def test_calc_dmp(): with cuckoomem.from_file("tests/files/calc.dmp") as p: ppe = procmempe.from_memory(p, 0xd0000) assert p.regions == ppe.regions assert p.findmz(0x129abc) == 0xd0000 # Old/regular method with PE header. assert pe(p.readv(p.imgbase, 0x1000)).dos_header.e_lfanew == 0xd8 assert p.readv(p.imgbase + 0xd8, 4) == b"PE\x00\x00" assert pe(p).is32bit is True d = pe(p).optional_header.DATA_DIRECTORY[2] assert d.VirtualAddress == 0x59000 and d.Size == 0x62798 data = pe(p).resource(b"WEVT_TEMPLATE") assert data.startswith(b"CRIM") assert len(data) == 4750 assert len(ppe.pe.section(".text").get_data()) == 0x52e00
def decrypt_ransom_note(file): with open(file, 'rb') as f: try: pe = malduck.pe(f.read()) except: print("\t==> Error reading PE file!\n") return for res in resdb: crypted_buffer = pe.resource(res) if crypted_buffer != None: break if crypted_buffer != None: for key in keydb: decrypted_buffer = b'' for current_byte in range(0, len(crypted_buffer)): decrypted_buffer += bytes( [crypted_buffer[current_byte] ^ key[current_byte % 0x21]]) if b'DEAR' in decrypted_buffer: print(decrypted_buffer) break else: print("\t==> Expected resources not found!") return
def test_pe_header(): img = pe( base64(b""" TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEAAA4fug4AtAnNIbgBTM0hVGhpcyBwcm9ncmFtIGNhbm5vdCBiZSBydW4gaW4gRE9TIG1v ZGUuDQ0KJAAAAAAAAACCixJ5xup8KsbqfCrG6nwqz5LpKsfqfCrhLBEqxOp8KuEsByrU6nwqxup9 KnjqfCoF5SEqxep8KgXlIyrH6nwqBeVzKsXqfCrPkvUq2ep8Kti46CrH6nwqz5LtKsfqfCpSaWNo xup8KgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFBFAABMAQUAE5z9WAAAAAAAAAAA4AADAQsBCQAA bgAAACoAAAAAAADnEAAAABAAAACAAAAAAEAAABAAAAACAAAFAAAAAAAAAAUAAAAAAAAAAJAEAAAE AAAAAAAAAgAAgAAAEAAAEAAAAAAQAAAQAAAAAAAAEAAAAAAAAAAAAAAARIQAAMgAAAAAwAAAEAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAACAAACYAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALnRleHQAAADQ bAAAABAAAABuAAAABAAAAAAAAAAAAAAAAAAAIAAAYC5yZGF0YQAA/hIAAACAAAAAFAAAAHIAAAAA AAAAAAAAAAAAAEAAAEAuZGF0YQAAAGQKAAAAoAAAAAgAAACGAAAAAAAAAAAAAAAAAABAAADALmJz cwAAAAARBwAAALAAAAAIAAAAjgAAAAAAAAAAAAAAAAAAQAAAwC5yc3JjAAAAANADAADAAAAAzAMA AJYAAAAAAAAAAAAAAAAAAEAAAEAK """.strip())) assert img.dos_header.e_magic == 0x5a4d assert img.nt_headers.Signature == 0x4550 assert img.file_header.NumberOfSections == len(img.sections) assert img.sections[0].Name.strip(b"\x00") == b".text" assert img.sections[-1].get_file_offset() == 0x298 assert img.is32bit is True assert img.is64bit is False assert img.section(".text").VirtualAddress == 0x1000
def test_calc_exe(): p = pe(open("tests/files/calc.exe", "rb").read(), fast_load=False) assert p.is32bit is True data = p.resource(b"WEVT_TEMPLATE") assert data.startswith(b"CRIM") assert len(data) == 4750 icons = list(p.resources(b"RT_ICON")) assert len(icons) == 16 assert len(icons[0]) == 2664 assert len(icons[7]) == 2216 assert len(icons[11]) == 16936 bitmaps = list(p.resources(51209)) assert len(bitmaps) == 1 assert len(bitmaps[0]) == 22042
png_stego_xor = 0x61 url_xor = 0xC5 s = bytes('', 'latin1') #Change the User-Agent to look less suspicius headers = { 'User-Agent': 'cruloader' } # RC4 key offset at 0xC key_offset = 12 # RC4 key size key_size = 15 # RC4 decrypt the first layer of CruLoader p = pe(open(infile, "rb").read(), fast_load=False) get_rsrc = p.resource('RT_RCDATA') rc4_key = get_rsrc[key_offset:key_offset+key_size] encrypted = get_rsrc[28:] decrypted = rc4(rc4_key, encrypted) print("[+] Second layer unpacked") if decrypted[0:2].decode('latin1') != "MZ": print("[-] RC4 decryption failed") # Seems malduck ROL needs data type int according to the documentation else: convert_rol = (decrypted[0:]) for index,value in enumerate(convert_rol): a = rol(value, 4, bits=8) #convert back to bytes for malduck.xor
#!/usr/bin/env python3 #Todo Figure out how to ROL 4 with Python to then be able to XOR 0xC5 and find the Pastebin URL with regexp in Python import malduck import sys infile = sys.argv[1] outfile = infile + "_decrypted" # RC4 key offset at 0xC key_offset = 12 # RC4 key size key_size = 15 # RC4 decrypt the first layer of CruLoader p = malduck.pe(open(infile, "rb").read(), fast_load=False) get_rsrc = p.resource('RT_RCDATA') rc4_key = get_rsrc[key_offset:key_offset+key_size] encrypted = get_rsrc[28:] decrypted = malduck.rc4(rc4_key, encrypted) if decrypted[0:2].decode('latin1') != "MZ": print("RC4 decryption failed") else: with open (outfile, 'wb') as o: o.write(decrypted)
Emotet layer1 unpacker Packer uses RC4 crypto with a modulo of 0x12296 Key seems to be located in either the .rdata or .data section """ import malduck import sys infile = sys.argv[1] mod = 0x12296 with open(infile, 'rb') as f: a = f.read() p = malduck.pe(data=a) # Custom RC4 taken from https://gist.github.com/sysopfb/19aa8e0bdecde60662b7adecdc72b11f def decode_data(data, key, sz): S = list(range(sz)) S = [x & 0xff for x in S] j = 0 out = [] for i in range(sz): j = (j + S[i] + ord(key[i % len(key)])) % sz S[i], S[j] = S[j], S[i] i = j = 0 for char in data: i = (i + 1) % sz j = (j + S[i]) % sz
def test_ollydbg_exe(): p = pe(open("tests/files/ollydbg.exe", "rb").read(), fast_load=False) assert p.is32bit is True data = p.resource("DVCLAL") assert data.startswith(b"\xA2\x8C\xDF\x98") assert len(data) == 16