Day 4 — I Built a Program That Caught a Reverse Shell
Source: Dev.to
Introduction
Until yesterday, my scripts were observers.
Today my computer started watching back—monitoring itself instead of scanning a target.
That’s actually what most real cybersecurity tools do.
Concept
Malware rarely announces itself. An attacker who compromises a machine needs communication (Command & Control callbacks, reverse shells).
All of these create an outbound network connection.
Instead of scanning attackers, I decided to monitor my own machine’s network connections in real time, essentially building a tiny Host Intrusion Detection System (HIDS) with Python.
Detection Logic
- Watch every active connection.
- Identify the process that opened it.
- Check destination IP and port.
- Alert if the behavior looks malicious.
Examples
- Browser → port 443 → normal.
- PDF reader → port 4444 → very suspicious.
Implementation
The Python library psutil provides access to operating‑system internals such as processes, memory, CPU, open ports, and network sockets.
import psutil
import time
import socket
import logging
logging.basicConfig(
filename="connection_alerts.log",
level=logging.WARNING,
format="%(asctime)s - %(message)s"
)
SUSPICIOUS_PORTS = {4444, 5555, 6666, 1337, 9001, 12345}
seen_connections = set()
connection_times = {}
ALERT_TIMEOUT = 60 # seconds
def resolve_ip(ip):
try:
return socket.gethostbyaddr(ip)[0]
except Exception:
return ip
print("Starting Network Monitoring")
while True:
for conn in psutil.net_connections(kind='inet'):
if conn.status != "ESTABLISHED":
continue
if not conn.raddr:
continue
remote_ip = conn.raddr.ip
remote_port = conn.raddr.port
if conn.pid:
try:
pname = psutil.Process(conn.pid).name()
except Exception:
pname = "UnknownProcess"
else:
pname = "Kernel/Hidden"
connection_id = f"{pname}-{remote_ip}-{remote_port}"
current_time = time.time()
# Cleanup old alerts
for cid in list(connection_times):
if current_time - connection_times[cid] > ALERT_TIMEOUT:
seen_connections.discard(cid)
del connection_times[cid]
if remote_port in SUSPICIOUS_PORTS:
if connection_id not in seen_connections:
seen_connections.add(connection_id)
connection_times[connection_id] = current_time
msg = f"[ALERT] Suspicious port connection! {pname} -> {resolve_ip(remote_ip)}:{remote_port}"
print(msg)
logging.warning(msg)
time.sleep(0.2)
Testing
Initial attempts
ping google.com→ no alerts (ping uses ICMP, not TCP).curl→ still no alerts because many connections open and close in milliseconds, making simple polling unreliable.
Simulating a reverse shell
# Terminal 1
nc -lvnp 4444
# Terminal 2
nc 127.0.0.1 4444
Output:
[ALERT] Suspicious port connection! nc -> 127.0.0.1:4444
The program detected the reverse shell, confirming that behavior‑based detection works.
Improvements
- Alert deduplication: The program initially printed dozens of alerts per second for a single persistent connection.
- Timeout logic: Added a 60‑second window to report each incident only once, reducing alert fatigue.
Lessons Learned
- ICMP vs. TCP monitoring: Different protocols require different observation methods.
- Process‑to‑network correlation is essential for contextual alerts.
- Polling is unreliable for security monitoring; real EDR tools use kernel‑level event hooks.
- Alert suppression is a core feature of SIEM systems.
- Signature‑based detection looks for known malware; behavior‑based detection looks for suspicious activity, which is harder for attackers to evade.
Future Work
Tomorrow I plan to monitor file modifications to detect ransomware‑like activity. If malware needs communication, ransomware needs to touch files—so watching file system changes will be the next logical step.