Created
July 7, 2018 18:34
-
-
Save seclib/a5da765a5dc9f07277e92fb976f9dfee to your computer and use it in GitHub Desktop.
Python malware extraction for 2018-07-05 HWP ROKRAT dropper
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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