def aplib_compdecsingle(data): import aplib c = aplib.compress(data) compressed = c.do() d = aplib.decompress(compressed) decompressed , consumed = d.do() return compressed, decompressed
def parse_ini(file_data, ADDON_MAGIC=["JF", "J1"]): pe = pefile.PE(data=file_data) #if len(sys.argv) > 2: # ADDON_MAGIC = [sys.argv[2]] #else: # ADDON_MAGIC = ["JF", "J1"] file_data = pe.get_memory_mapped_image() for magic in ADDON_MAGIC: index = 0 for i in range(2): temp = file_data[index:].find(magic) if temp != -1: index += temp ( magicVal, flags, section, offset, length, ) = struct.unpack_from('<IIIII', file_data[index:]) if section in JOINER_SECTIONS.keys(): handler = handlers[JOINER_SECTIONS[section]] compressed_data = file_data[offset:offset + length] uncompressed = aplib.decompress(compressed_data).do() handler(uncompressed[0]) else: print("UNKNOWN SECTION: " + hex(section)) index += 1 else: break
def decrypt_payload(encrypted_addr, rc4key, encrypted_size, unpacked_size, entry_point, relocs, relocs_size): buffer = bytearray(encrypted_size) for i in range(len(buffer)): buffer[i] = Byte(encrypted_addr + i) decrypted = rc4crypt(buffer, rc4key) unpacked = decompress(str(decrypted)).do() # checking for free segment address seg_start = 0x10000000 while SegName(seg_start) != '': seg_start += 0x10000000 AddSeg(seg_start, seg_start + unpacked_size, 0, 1, idaapi.saRelPara, idaapi.scPub) # copying data to new segment data = unpacked[0] for i in range(len(data)): PatchByte(seg_start + i, ord(data[i])) fix_payload_relocs_and_import(seg_start, relocs) MakeFunction(seg_start + entry_point) return
def convert_pubkey(data): pub = aplib.decompress(data).do()[0] bit = struct.unpack_from('<I', pub)[0] mod = pub[4:(bit / 8) + 4] exp = pub[(bit / 8) + 4:] mod = int(binascii.hexlify(mod), 16) exp = int(binascii.hexlify(exp), 16) keypub = RSA.construct((mod, long(exp))) pempub = keypub.exportKey('PEM') return ((keypub, pempub))
def decompress_that_shit(buffer, output='config.txt'): # AWFUL hack because of aplib bug with `str` and offset... forced to use `file` instead. temp_file = tempfile.TemporaryFile(mode='w+b') # Skip 12 first bytes (4 bytes for XOR key, 4 for compressed size and 4 for uncompressed size) temp_file.write(buffer[12:]) temp_file.seek(0) cleartext = decompress(temp_file).do() temp_file.close() print('[I] Decoded configuration:\n\t %s' % str(cleartext)) with open(output, 'wb') as f: print("[I] Saving decoded configuration into '%s'" % output) f.write(str(cleartext))
def DecompressThisShit(buffer): #On bypass les 12 premiers bytes 4 pour la clef xor 4 pour la taille de #config compresser 4 pour la taille de la config decompresser open("config.raw","wb").write(str(buffer[12:])) resource = open("config.raw","rb") com=decompress(resource).do() os.remove("config.raw") print "Config decoded! Save in config.txt." print str(com) open("config.txt","wb").write(str(com))
def extract_candidate(blob, offset): """Attempt to decrypt candidate and test DOS header Args: blob (string): binary string of the blob to search offset (int): offset in the blob (candidate start) Returns: string: extracted PE file (none if no PE is extracted) """ try: candidate = blob[offset:] ptext = aplib.decompress(candidate).do()[0] # If this is a valid PE file find the length and trim it # If it's not valid pefile will throw and error and we will # return None pe = pefile.PE(data=ptext) # Remove overlay return pe.trim() except Exception as e: return None
def decoder(data): global TEST config = {} #data = open(sys.argv[1], 'rb').read() #Check if need to memory map if data[0x400:0x500] != '\x00' * 0x100 and data[:2] == 'MZ': pe = pefile.PE(data=data) data = pe.get_memory_mapped_image() blob = find_xor_table(data) print(blob) #off = data.find('\x00\x00WD') #blob = data[off-2:] l = struct.unpack_from('<I', blob)[0] config['CONF_VAL'] = blob[4:6] blob = blob[8:] + '\x00\x00\x00\x00' #blob = blob[8:l] xor_hash = struct.unpack_from('<I', blob)[0] client_ini_data = None keypub = None #A list of tuples (need_decoded_flag, data, crc_hash) decoded_data = [] while xor_hash != 0: blob = blob[4:] ( val2, xorval, val3, ) = struct.unpack_from('<III', blob) decompress_flag = xorval & 1 blob = blob[12:] crc_hash = xorval ^ xor_hash offset = xorval ^ val3 l = xorval ^ val2 if crc_hash in JOINER_SECTIONS.keys(): print(JOINER_SECTIONS[crc_hash]) handler = handlers[JOINER_SECTIONS[crc_hash]] if JOINER_SECTIONS[crc_hash] == "CRC_PUBLIC_KEY": sect_data = data[offset:offset + l] (keypub, pempub) = handler(sect_data) elif JOINER_SECTIONS[crc_hash] == "CRC_CLIENT_INI": client_ini_data = data[offset:offset + l] else: if JOINER_SECTIONS[crc_hash] in handlers.keys(): handler = handlers[JOINER_SECTIONS[crc_hash]] sect_data = data[offset:offset + l] config.update(handler(sect_data)) else: print("CRC_HASH: " + hex(crc_hash)) print("XOR_VAL: " + hex(xorval)) sect_data = data[offset:offset + l] #Data with decompress flag is decompressed if decompress_flag == 1: sect_data = aplib.decompress(sect_data).do()[0] decoded_data.append((False, sect_data, crc_hash)) #Else it's got the RSAPublicDecrypt + serpent + decompress else: decoded_data.append((True, sect_data, crc_hash)) print("Length: " + hex(xorval ^ val2)) print("offset: " + hex(xorval ^ val3)) xor_hash = struct.unpack_from('<I', blob)[0] #Sort the list first so smallest data goes first that way we always have pub key before modules decoded_data.sort(key=lambda tup: len(tup[1])) mod_num = 1 for item in decoded_data: flag = item[0] temp = item[1] hash = item[2] if flag == False: if struct.unpack_from('<I', temp)[0] == 1024: #pub key (keypub, pempub) = convert_pubkey(temp, False) else: config.update({hex(hash): temp}) else: #Module? if len(temp) > 0x500: temp = gozi_decode_sect(keypub, temp) off = temp.find('M8Z') if off != -1: temp = aplib.decompress(temp[off:]).do()[0] config.update({'DLL_' + str(mod_num): decoder(temp)}) mod_num += 1 #ini params? else: client_ini_data = temp if type(keypub) != type(None): print("Pub key: " + pempub) config.update({'PUB_KEY': pempub}) if client_ini_data != None: config.update(client_init_parse(keypub, client_ini_data)) return (config)
def parse_wordlist(data): out = aplib.decompress(data).do()[0] return ({"WORD_LIST": out})
if len(sys.argv) > 2: ADDON_MAGIC = [sys.argv[2]] else: ADDON_MAGIC = ["JF", "J1"] file_data = pe.get_memory_mapped_image() for magic in ADDON_MAGIC: index = 0 for i in range(3): temp = file_data[index:].find(magic) if temp != -1: index += temp (magicVal,offset,length,section) = struct.unpack_from('<IIII', file_data[index:]) if section in JOINER_SECTIONS.keys(): handler = handlers[JOINER_SECTIONS[section]] compressed_data = file_data[offset:offset+length] try: uncompressed = aplib.decompress(compressed_data).do() handler(uncompressed[0]) except: pass else: print("UNKNOWN SECTION: " +hex(section)) index += 1 else: break
table256[counter] = table256[muddle] table256[muddle] = swap counter = 0 muddle = 0 for i in range(len(buf)): counter += 1 counter %= 256 muddle = (table256[counter] + muddle) %256 swap = table256[counter] table256[counter] = table256[muddle] table256[muddle] = swap buf[i] ^= table256[(table256[muddle] + table256[counter]) % 256] return "".join([chr(x) for x in buf]) dec = xorDecodeString_3(data, key) innerKey = dec[:7] dec2 = xorDecodeString_3(dec[7:], innerKey) md5Checksum = dec2[:32] compressedSize = struct.unpack("<I", "".join(dec2[32:36]))[0] decompressedSize = struct.unpack("<I", "".join(dec2[36:40]))[0] aplibCompressedBuf = dec2[40:] decompressedBuf = aplib.decompress(aplibCompressedBuf).do() print len(decompressedBuf[0]) print decompressedBuf[1] fp_out = open(sys.argv[2], 'wb') fp_out.write(decompressedBuf[0]) fp_out.close()
def parse_ini(file_data, ADDON_MAGIC=["JJ", "JF", "J1"]): ret_val = {} try: pe = pefile.PE(data=file_data) file_data = pe.get_memory_mapped_image() except: file_data = bytearray( binascii.unhexlify( '4d5a90000300000004000000ffff0000b800000000000000400000000000000000000000000000000000000000000000000000000000000000000000' ) + file_data[60:]) pe_offset = struct.unpack_from('<I', file_data[60:])[0] file_data[pe_offset] = 'P' file_data[pe_offset + 1] = 'E' file_data = str(file_data) try: pe = pefile.PE(data=file_data) except: print("Bad PE file") return (ret_val) #if len(sys.argv) > 2: # ADDON_MAGIC = [sys.argv[2]] #else: # ADDON_MAGIC = ["JF", "J1"] ver = gozi_version.get_gozi_ver(data) if ver != None: ret_val["VER"] = str(ver) for magic in ADDON_MAGIC: index = 0 for i in range(3): temp = file_data[index:].find(magic) if temp != -1: index += temp ( magicVal, offset, length, section, ) = struct.unpack_from('<IIII', file_data[index:]) if length > len(file_data): ( magicVal, flags, section, offset, length, ) = struct.unpack_from('<IIIII', file_data[index:]) if section in JOINER_SECTIONS.keys(): print("offset: " + str(offset)) handler = handlers[JOINER_SECTIONS[section]] compressed_data = file_data[offset:offset + length] #open(str(section), 'wb').write(compressed_data) if len(compressed_data) > 0: uncompressed = "" try: uncompressed = aplib.decompress( compressed_data).do() uncompressed = uncompressed[0] print("Calling handler") ret = handler(uncompressed) if ret != None: ret_val.update(ret) except: print("SECTION:" + hex(section) + ":DECOMPRESS FAILURE Size:" + str(len(compressed_data))) ret = handler(compressed_data) if ret != None: ret_val.update(ret) else: try: compressed_data = file_data[offset:offset + length] #open(hex(section)+'_blahblah.bin', 'wb').write(compressed_data) uncompressed = aplib.decompress(compressed_data).do() if uncompressed[0][:2] == 'MZ': ret = loader_dll_parse(uncompressed[0]) if ret != None: ret_val.update(ret) else: print("UNKNOWN SECTION: " + hex(section)) except: print("UNKNOWN SECTION: " + hex(section)) index += 1 else: break print(ret_val) return ret_val
def decompress_config(): global FULL_CONFIG, DECOMPRESSED_CONFIG DECOMPRESSED_CONFIG = FULL_CONFIG[0x104:] # extract compressed config DECOMPRESSED_CONFIG = decompress(bytearray(DECOMPRESSED_CONFIG))
t = "" while i < len(blob): if not (j % 2): i += 2 t += blob[i] i += 1 j += 1 key = None for poss_decode in possible_decodes: s = solve_ta505crypter(t, poss_decode) if s.check() == sat: m = s.model() for d in m.decls(): if d.name() == 'xor1': key = m[d].as_long() if key: out = "" for i in range(len(t) / 4): temp = struct.unpack_from('<I', t[i * 4:])[0] temp ^= key temp = rol(temp, 4) temp += 2004318072 out += struct.pack('<I', temp & 0xffffffff) open(sys.argv[1] + '_decodedObject', 'wb').write(out) if out[:3] == 'M8Z': print("Decompressing") out2 = aplib.decompress(out).do() open(sys.argv[1] + '_decompressed', 'wb').write(out2[0])
exit() # -------------------------------------------------------------------------- # Step 5: Decompress plaintext # -------------------------------------------------------------------------- print '[+] Decompressing plaintext ...' if plain[20] == 'P' and plain[21] == 'p' and plain[22] == 'X': print '[+] PpX signature found.' else: print '[!] Warning. PpX signature not found. Continuing anyways...' # Drop the first 20 bytes plain = plain[20:] decompressed_plain = aplib.decompress(plain).do() print '[+] Deflating: %d -> %d bytes ...' % (len(plain), len(decompressed_plain[0])) print '[+] Decompressed registry data: %s ...' % ' '.join( '%02X' % ord(x) for x in decompressed_plain[0][:32]) if decompressed_plain[0][0:4] == 'PX\x00\x00': print '[+] PX signature found: ' else: print '[!] Error. Not a PX file' with open('%s_decrypted' % filename, 'wb') as fp: fp.write(decompressed_plain[0]) print '[+] Program finished. Bye bye :)'
def parse_joinned_data(self, data): data = self.pe_magic_check(data) config_data = [] fnames = [] for m in re.finditer(magic + "\x00.", data): xor_dword = 0 magic_dword = data[m.start():m.start() + 4] if (magic_dword[0:1] == "J1" or magic_dword[3] == "\0"): (flags, crc32_name, addr, size) = unpack_from("<LLLL", data, m.start() + 4) print( "[+] magic: {0} flags: 0x{1:X} crc32_name: 0x{2:X} addr: 0x{3:X} size: 0x{4:X}" .format(repr(magic_dword), flags, crc32_name, addr, size)) elif (magic_dword[0:1] == "JJ" or (ord(magic_dword[3]) & 1) == 1): (xor_dword, crc32_name, addr, size) = unpack_from("<LLLL", data, m.start() + 4) print( "[+] magic: {0} xor: 0x{1:X} crc32_name: 0x{2:X} addr: 0x{3:X} size: 0x{4:X}" .format(repr(magic_dword), xor_dword, crc32_name, addr, size)) else: break if size > 0x80000: print("[!] size is too large, skipped this entry") continue try: offset = addr except: print("[!] This PE is old Ursnif (not DreamBot)") (addr, size, crc32_name, flags) = unpack_from("<LLLL", data, m.start() + 4) print( "[+] magic: {0} addr: 0x{1:X} size: 0x{2:X} crc32_name: 0x{3:X} flags: 0x{4:X}" .format(repr(magic_dword), addr, size, crc32_name, flags)) offset = addr try: joined_res = data[offset:offset + size] dec_data = aplib.decompress(joined_res).do()[0] except: pe = pefile.PE(data=data) offset = pe.get_offset_from_rva(addr) joined_res = data[offset:offset + size] dec_data = aplib.decompress(joined_res).do()[0] #print("[!] Cann't decode data.") #continue if (xor_dword != 0): mod_data = "" for i in range(min(4, size + 1)): mod_data += chr( ord(dec_data[i]) ^ ((xor_dword >> 8 * i) & 0xff)) if (size >= 4): mod_data += dec_data[4:] dec_data = mod_data if crc32_name in (0x4f75cea7, 0x9e154a0c): fname = "ursnif_client32.bin" open(fname, "wb").write(dec_data) print("[+] dumped 32 bit client dll: {0}".format(fname)) fnames.append(dec_data) elif crc32_name in (0x90f8aab4, 0x41982e1f): fname = "ursnif_client64.bin" open(fname, "wb").write(dec_data) print("[+] dumped 64 bit client dll: {0}".format(fname)) # fnames.append(fname) elif crc32_name in (0xe1285e64, ): fname = "ursnif_public_key.bin" open(fname, "wb").write(dec_data) print("[+] dumped public key: {0}".format(fname)) elif crc32_name in (0xd722afcb, 0x8365b957, 0x8fb1dde1): fname = "ursnif_st_config.bin" open(fname, "wb").write(dec_data) print("[+] dumped static config: {0}".format(fname)) config_data.append(self.parse_config(dec_data)) else: fname = "ursnif_" + hex(addr) + "_ap32_dec.bin" open(fname, "wb").write(dec_data) print("[+] dumped: {0}".format(fname)) for fname in fnames: config_data = self.parse_joinned_data(fname) return config_data
def calculate(self): if not has_yara: debug.error("Yara must be installed for this plugin") if not has_yara: debug.error("Aplib must be installed for this plugin") addr_space = utils.load_as(self._config) os, memory_model = self.is_valid_profile(addr_space.profile) if not os: debug.error("This command does not support the selected profile.") rules = yara.compile(sources=ursnif_sig) for task in self.filter_tasks(tasks.pslist(addr_space)): scanner = malfind.VadYaraScanner(task=task, rules=rules) for hit, address in scanner.scan(): vad_base_addr, end = self.get_vad_base(task, address) proc_addr_space = task.get_process_address_space() data = proc_addr_space.zread(vad_base_addr, end - vad_base_addr) config_data = [] mz_magic = unpack_from("=2s", data, 0x0)[0] nt_magic = unpack_from("<H", data, 0x3c)[0] if mz_magic == "\x00\x00": data = "\x4d\x5a" + data[2:] data = data[:nt_magic] + "\x50\x45" + data[nt_magic + 2:] fnames = [] for m in re.finditer(magic + "\x00.", data): xor_dword = 0 magic_dword = data[m.start():m.start() + 4] if (magic_dword[0:1] == "J1" or magic_dword[3] == "\0"): (flags, crc32_name, addr, size) = unpack_from("<LLLL", data, m.start() + 4) print( "[+] magic: {0} flags: 0x{1:X} crc32_name: 0x{2:X} addr: 0x{3:X} size: 0x{4:X}\n" .format(repr(magic_dword), flags, crc32_name, addr, size)) elif (magic_dword[0:1] == "JJ" or (ord(magic_dword[3]) & 1) == 1): (xor_dword, crc32_name, addr, size) = unpack_from("<LLLL", data, m.start() + 4) print( "[+] magic: {0} xor: 0x{1:X} crc32_name: 0x{2:X} addr: 0x{3:X} size: 0x{4:X}\n" .format(repr(magic_dword), xor_dword, crc32_name, addr, size)) else: raise ValueError("Unknown joiner header") if size > 0x80000: print("[!] size is too large, skipped this entry\n") continue try: offset = addr except: print("[!] This PE is old Ursnif (not DreamBot)\n") (addr, size, crc32_name, flags) = unpack_from("<LLLL", data, m.start() + 4) print( "[+] magic: {0} addr: 0x{1:X} size: 0x{2:X} crc32_name: 0x{3:X} flags: 0x{4:X}\n" .format(repr(magic_dword), addr, size, crc32_name, flags)) offset = addr joined_res = data[offset:offset + size] try: dec_data = aplib.decompress(joined_res).do()[0] except: print("[!] Cann't decode data.\n") continue if (xor_dword != 0): mod_data = "" for i in range(min(4, size + 1)): mod_data += chr( ord(dec_data[i]) ^ ((xor_dword >> 8 * i) & 0xff)) if (size >= 4): mod_data += dec_data[4:] dec_data = mod_data if crc32_name in (0x4f75cea7, 0x9e154a0c): fname = "ursnif_client32.bin" open(fname, "wb").write(dec_data) print("[+] dumped 32 bit client dll: {0}\n".format( fname)) fnames.append(fname) elif crc32_name in (0x90f8aab4, 0x41982e1f): fname = "ursnif_client64.bin" open(fname, "wb").write(dec_data) print("[+] dumped 64 bit client dll: {0}\n".format( fname)) # fnames.append(fname) elif crc32_name in (0xe1285e64, ): fname = "ursnif_public_key.bin" open(fname, "wb").write(dec_data) print("[+] dumped public key: {0}\n".format(fname)) elif crc32_name in (0xd722afcb, 0x8365b957, 0x8fb1dde1): fname = "ursnif_st_config.bin" open(fname, "wb").write(dec_data) print("[+] dumped static config: {0}\n".format(fname)) config_data.append(self.parse_config(dec_data)) else: fname = "ursnif_" + hex(addr) + "_ap32_dec.bin" open(fname, "wb").write(dec_data) print("[+] dumped: {0}".format(fname)) for fname in fnames: parse_joinned_data(fname, magic) yield task, vad_base_addr, end, hit, memory_model, config_data break