Skip to content

Instantly share code, notes, and snippets.

@seclib
Created July 7, 2018 18:34
Show Gist options
  • Save seclib/a5da765a5dc9f07277e92fb976f9dfee to your computer and use it in GitHub Desktop.
Save seclib/a5da765a5dc9f07277e92fb976f9dfee to your computer and use it in GitHub Desktop.
Python malware extraction for 2018-07-05 HWP ROKRAT dropper
#extract malware from: 9e6ff58202f6c1bd2381e8209231efd0ef6855db59db975fb5b75041706ed104
import re
import sys
import zlib
import struct
import hashlib
import oledump
import olefile
import binascii
import cStringIO
from hexdump import hexdump
def md5(content):
return hashlib.md5(content).hexdigest()
def sha256(content):
return hashlib.sha256(content).hexdigest()
def writefile(filename,data):
with open(filename, 'wb') as f:
f.write(data)
def extract_payload(filename,postscript):
if re.search(' corpqe\. ',postscript):
print '[+] Found CVE-2017-8291 (reversed), attempting extraction...'
if re.search('adobeprint token 1 pop pop exch pop exec \x0a',postscript):
print '[+] Found PS prior to encoded shellcode and payload, extracting...'
enc_shellcode_payload = re.search('adobeprint token 1 pop pop exch pop exec \x0a(.+)$',postscript, re.DOTALL).group(1)
#simple size check
if len(enc_shellcode_payload) > 100:
key = ord(enc_shellcode_payload[0])
print '[+] XOR key for encoded shellcode and payload: 0x%02X' % key
enc_shellcode_payload = enc_shellcode_payload[1:]
dec_shellcode_payload = ''
for c in enc_shellcode_payload:
dec_shellcode_payload += chr(ord(c)^key)
dec_shellcode_payload = bytes(dec_shellcode_payload)
if re.search('\\x8b\\x04\\x24\\xc3\\xe8',dec_shellcode_payload, re.S):
print '[+] Found expected opcode bytes before encoded payload, extracting and decoding payload...'
payload_re = re.compile('\\x8b\\x04\\x24\\xc3\\xe8.{4}\\xc3(.{4})(.{4})')
payload_size = struct.unpack('<I',payload_re.search(dec_shellcode_payload).group(1))[0]
print '[+] Payload size: %i' % payload_size
key_payload = payload_re.search(dec_shellcode_payload).group(2)
print '[+] Payload 4-byte XOR key: 0x%02X%02X%02X%02X' % (ord(key_payload[0]),ord(key_payload[1]),ord(key_payload[2]),ord(key_payload[3]))
decoded = ''
payload_pos = payload_re.search(dec_shellcode_payload).span(2)[1]
encoded_payload = dec_shellcode_payload[payload_pos:payload_pos+payload_size]
for i in range(len(encoded_payload)):
decoded += chr(ord(encoded_payload[i])^ord(key_payload[i%4]))
else:
print '[!] Did not find the expected opcode bytes before encoded payload after decoding, exiting...'
sys.exit()
else:
print '[!] Did not find PS before encoded payload, exiting...'
sys.exit()
else:
print '[!] Did not find expected reversed ".eqproc", exiting...'
sys.exit()
md5_decoded = md5(decoded)
sha256_decoded = sha256(decoded)
decoded_filename = sha256_decoded
print '[+] Decoded payload hashes:'
print '%s' % md5_decoded
print '%s' % sha256_decoded
print '[+] Writing decoded file to: %s\n' % decoded_filename
with open(decoded_filename, 'wb') as f:
f.write(decoded)
def main():
#code taken from Didier Stevens oledump script
#https://raw.githubusercontent.com/DidierStevens/DidierStevensSuite/master/oledump.py
filename = sys.argv[1]
oStringIO = cStringIO.StringIO(open(filename, 'rb').read())
magic = oStringIO.read(6)
oStringIO.seek(0)
if magic[0:4] != oledump.OLEFILE_MAGIC:
print '[!] This only supports OLE, exiting...'
sys.exit()
ole = olefile.OleFileIO(oStringIO)
for orphan, fname, entry_type, stream in oledump.OLEGetStreams(ole):
if fname[0] == 'BinData':
if re.search('BIN00\d{2}\.[Ee]?[Pp][Ss]',fname[1]):
scriptname = fname[1]
if '.eps' in scriptname:
print '[+] Found EPS file: %s' % scriptname
elif '.ps' in scriptname:
print '[+] Found PS file: %s' % scriptname
try:
decompressed = zlib.decompress(stream, -15)
except Exception, e:
print '[!] Problem decompressing zlib stream, error:'
print e
extract_payload(filename,decompressed)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment