Advertisement
darienhuss

Python malware extraction for 2018-07-05 HWP Lazarus

Jul 5th, 2018
1,590
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.15 KB | None | 0 0
  1. #extract malware from: 6f1bddb3aa221635adfd8b1c465da64ab436648e3c14e44ccd118e96af50e5d7
  2. import re
  3. import sys
  4. import zlib
  5. import struct
  6. import hashlib
  7. import oledump
  8. import olefile
  9. import binascii
  10. import cStringIO
  11.  
  12. from Crypto.Cipher import AES
  13. def md5(content):
  14.     return hashlib.md5(content).hexdigest()
  15.  
  16. def sha256(content):
  17.     return hashlib.sha256(content).hexdigest()
  18.  
  19. def writefile(filename,data):
  20.     with open(filename, 'wb') as f:
  21.         f.write(data)
  22.  
  23. def aes_decrypt(encr,key,iv):
  24.     cipher = AES.new(key, AES.MODE_CBC, iv)
  25.     return cipher.decrypt(encr)
  26.  
  27. def extract_payload(filename,postscript):
  28.    
  29.     if re.search('/FontSize <[A-F0-9]{8}>',postscript) and re.search(' def <[a-f0-9]{100,}>',postscript):
  30.         print '[+] Found 4-byte XOR encoded PostScript, continuing...'
  31.         key = re.search('/FontSize <([A-F0-9]{8})>',postscript).group(1).decode('hex')
  32.         postscript_encoded = re.search(' def <([a-f0-9]{100,})>',postscript).group(1).decode('hex')
  33.         postscript_decoded = ''
  34.         for i in range(len(postscript_encoded)):
  35.             postscript_decoded += chr(ord(postscript_encoded[i]) ^ ord(key[i%4]))
  36.  
  37.         if re.search('/shellcode <[a-f0-9]{100,}>',postscript_decoded):
  38.             print '[+] Found hex-encoded shellcode in decoded PostScript, searching for AES key/IV...'
  39.             shellcode = re.search('/shellcode <([a-f0-9]{100,})>',postscript_decoded).group(1).decode('hex')
  40.             if re.search('(?:\\xC7\\x45.(.{4}))(?:\\xC7\\x45.(.{4}))(?:\\xC7\\x45.(.{4}))(?:\\xC7\\x45.(.{4}))(?:\\xC7\\x45.(.{4}))(?:\\xC7\\x45.(.{4}))(?:\\xC7\\x45.(.{4}))(?:\\xC7\\x45.(.{4})).{6,10}\\xAA\\xC5\\xE2\\x5D.{6,12}\\xEE\\x95\\xB6\\x50.{6,12}\\xAE\\x87\\x92\\x3F',shellcode):
  41.                 print '[+] Found expected hashed WinAPIs trailing the AES key/IV, searching for key/IV'
  42.                 key_iv_segments = re.search('(?:\\xC7\\x45.(.{4}))(?:\\xC7\\x45.(.{4}))(?:\\xC7\\x45.(.{4}))(?:\\xC7\\x45.(.{4}))(?:\\xC7\\x45.(.{4}))(?:\\xC7\\x45.(.{4}))(?:\\xC7\\x45.(.{4}))(?:\\xC7\\x45.(.{4})).{6,10}\\xAA\\xC5\\xE2\\x5D.{6,12}\\xEE\\x95\\xB6\\x50.{6,12}\\xAE\\x87\\x92\\x3F',shellcode, re.S).groups()
  43.                 aes_key = ''
  44.                 aes_iv = ''
  45.                 for i in range(4):
  46.                     aes_key += key_iv_segments[i]
  47.                 for i in range(4,8):
  48.                     aes_iv += key_iv_segments[i]
  49.                 return aes_key,aes_iv
  50.             else:
  51.                 print '[!] Did not find the expected hashed WinAPIs trailing the AES key/IV, try searching for bytes: C745E46578706C or C745B068707377 to find the function with the AES key/IV'
  52.         else:
  53.             print '[!] Did not find expected hex-encoded shellcode, exiting...'
  54.             sys.exit()
  55.     else:
  56.         print '[!] Did not find expected 4-byte XOR PostScript, exiting...'
  57.         sys.exit()
  58.  
  59.     md5_decoded = md5(decoded)
  60.     sha256_decoded = sha256(decoded)
  61.     decoded_filename = sha256_decoded
  62.  
  63.     print '[+] Decoded payload hashes:'
  64.     print '%s' % md5_decoded
  65.     print '%s' % sha256_decoded
  66.     print '[+] Writing decoded file to: %s\n' % decoded_filename
  67.     with open(decoded_filename, 'wb') as f:
  68.         f.write(decoded)
  69.  
  70. def main():
  71.     #code taken from Didier Stevens oledump script
  72.     #https://raw.githubusercontent.com/DidierStevens/DidierStevensSuite/master/oledump.py
  73.     filename = sys.argv[1]
  74.     oStringIO = cStringIO.StringIO(open(filename, 'rb').read())
  75.     magic = oStringIO.read(6)
  76.     oStringIO.seek(0)
  77.     if magic[0:4] != oledump.OLEFILE_MAGIC:
  78.         print '[!] This only supports OLE, exiting...'
  79.         sys.exit()
  80.     ole = olefile.OleFileIO(oStringIO)
  81.     for orphan, fname, entry_type, stream in oledump.OLEGetStreams(ole):
  82.         if fname[0] == 'BinData':
  83.             if re.search('BIN00\d{2}\.[Ee]?[Pp][Ss]',fname[1]):
  84.                 scriptname = fname[1]
  85.                 if '.eps' in scriptname:
  86.                     print '[+] Found EPS file: %s' % scriptname
  87.                 elif '.ps' in scriptname:
  88.                     print '[+] Found PS file: %s' % scriptname
  89.                 try:
  90.                     decompressed = zlib.decompress(stream, -15)
  91.                 except Exception, e:
  92.                     print '[!] Problem decompressing zlib stream, error:'
  93.                     print e
  94.                     sys.exit()
  95.                 aes_key, aes_iv = extract_payload(filename,decompressed)
  96.                 print '[+] Found AES key: %s' % "".join("{:02x}".format(c) for c in bytearray(aes_key))
  97.                 print '[+] Found AES IV: %s' % "".join("{:02x}".format(c) for c in bytearray(aes_iv))
  98.             if re.search('BIN00\d{2}\.[bB][mM][pP]',fname[1]):
  99.                 print '[+] Found BMP'
  100.                 stego_bmp = zlib.decompress(stream, -15)
  101.  
  102.     if re.search('F0und3g9',stego_bmp):
  103.         print '[+] Found expected magic bytes (F0und3g9) prior to encrypted implants, extracting payloads now'
  104.         x86_size_loc = re.search('F0und3g9',stego_bmp).span()[1]
  105.         x86_size = struct.unpack('<I',stego_bmp[x86_size_loc:x86_size_loc+4])[0]
  106.         x86_loc = x86_size_loc + 4
  107.         x86_encrypted = stego_bmp[x86_loc:x86_loc+x86_size]
  108.         x86_decrypted = aes_decrypt(x86_encrypted,aes_key,aes_iv)
  109.  
  110.         md5_x86 = md5(x86_decrypted)
  111.         sha256_x86 = sha256(x86_decrypted)
  112.  
  113.         x64_size_loc = x86_loc+x86_size
  114.         x64_size = struct.unpack('<I',stego_bmp[x64_size_loc:x64_size_loc+4])[0]
  115.         x64_loc = x64_size_loc+4
  116.         x64_encrypted = stego_bmp[x64_loc:x64_loc+x64_size]
  117.         x64_decrypted = aes_decrypt(x64_encrypted,aes_key,aes_iv)
  118.  
  119.         md5_x64 = md5(x64_decrypted)
  120.         sha256_x64 = sha256(x64_decrypted)
  121.  
  122.         print '[+] Decrypted file info:'
  123.         print 'x86.bin|%s' % md5_x86
  124.         print 'x86.bin|%s' % sha256_x86
  125.         print 'x64.bin|%s' % md5_x64
  126.         print 'x64.bin|%s\n' % sha256_x64
  127.         print '[+] Writing x86.bin to: %s' % sha256_x86
  128.         with open(sha256_x86, 'wb') as f:
  129.             f.write(x86_decrypted)
  130.         print '[+] Writing x64.bin to: %s' % sha256_x64
  131.         with open(sha256_x64, 'wb') as f:
  132.             f.write(x64_decrypted)
  133.  
  134.  
  135.  
  136. if __name__ == '__main__':
  137.     main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement