def search_for_history_in_task_memory(self, malloc_tiny_list, pm_cr3, mempath): proc_pae = IA32PML4MemoryPae(FileAddressSpace(mempath), pm_cr3) history_list = [] ptr_size = 8 unpack_int = '=QQ' #print '' for vm_address in malloc_tiny_list: #print '[*] Search for keys in range 0x%.8x-0x%.8x'%(vm_address[0], vm_address[1]) for vm_offset in range(vm_address[0], vm_address[1], ptr_size*2): if proc_pae.is_valid_address(vm_offset): pointer_set = proc_pae.read(vm_offset, ptr_size*2) value = struct.unpack(unpack_int, pointer_set) # brute-force # value[0] = line pointer, value[1] = timestamp pointer if ((value[0] & value[1]) >= vm_address[0]) and ((value[0] & value[1]) < vm_address[1]): #print 'timestamp: %x, line: %x'%(value[1], value[0]) try: csharp = struct.unpack('c', proc_pae.read(value[1], 1))[0] except struct.error: continue if '#' == csharp: # timestamp signature #print 'got it' # get timestamp timebuf = '' linebuf = '' temp_list = [] for byte in range(value[1]+1, vm_address[1], 1): # remove singature '#' buf = proc_pae.read(byte, 1) if struct.unpack('b', buf)[0] == 0: break timebuf += struct.unpack('c', buf)[0] if timebuf != '': for byte in range(value[0], vm_address[1], 1): buf = proc_pae.read(byte, 1) try: if struct.unpack('b', buf)[0] == 0: break linebuf += struct.unpack('c', buf)[0] except struct.error: continue temp_list.append(long(timebuf)) temp_list.append(linebuf) history_list.append(temp_list) #print history_list return history_list
def search_for_keys_in_task_memory(self, malloc_tiny_list, pm_cr3, mempath): proc_pae = IA32PML4MemoryPae(FileAddressSpace(mempath), pm_cr3) candidate_key_list = [] ptr_size = 0 unpack_int = '' if self.arch == 32: ptr_size = 4 unpack_int = '=I' elif self.arch == 64: ptr_size = 8 unpack_int = '=Q' else: ptr_size = 4 unpack_int = '=I' print '' for vm_address in malloc_tiny_list: print '[*] Search for keys in range 0x%.8x-0x%.8x' % ( vm_address[0], vm_address[1]), for vm_offset in range(vm_address[0], vm_address[1], ptr_size): if proc_pae.is_valid_address(vm_offset): signature = proc_pae.read(vm_offset, ptr_size) if KEY_SIZE == struct.unpack( unpack_int, signature )[0]: # find specific hex code(0x00000018) #print signature.encode('hex') key_buf = proc_pae.read(vm_offset + ptr_size, ptr_size) key_buf_ptr = struct.unpack(unpack_int, key_buf)[0] if key_buf_ptr >= vm_address[ 0] and key_buf_ptr <= vm_address[ 1]: # check vma between vm.start and vm.stop candidate_key = proc_pae.read( key_buf_ptr, KEY_SIZE) candidate_key_list.append( candidate_key) # append to candidate key list print 'complete. master key candidates : %d' % len( candidate_key_list) return candidate_key_list
def get_proc_dump(self, vm_list, vm_struct, process_name, mempath): pm_cr3 = self.get_proc_cr3(vm_list, vm_struct) print '[+] Resetting the Page Mapping Table: 0x%x' % pm_cr3 proc_pae = IA32PML4MemoryPae(FileAddressSpace(mempath), pm_cr3) print '[+] Process Dump Start' for vme_info in vm_list: #print proc_pae.vtop(vme_info[0]) #print vme_info[1] nop_code = 0x00 pk_nop_code = struct.pack('=B', nop_code) nop = pk_nop_code * 0x1000 file = open('%s-%x-%x' % (process_name, vme_info[0], vme_info[1]), mode="wb") nop_flag = 0 for i in range(vme_info[0], vme_info[1], 0x1000): raw_data = 0x00 if not (proc_pae.is_valid_address(i)): if nop_flag == 1: raw_data = nop file.write(raw_data) continue raw_data = proc_pae.read(i, 0x1000) if raw_data is None: if nop_flag == 1: raw_data = nop file.write(raw_data) continue file.write(raw_data) nop_flag = 1 file.close() size = os.path.getsize('%s-%x-%x' % (process_name, vme_info[0], vme_info[1])) if size == 0: os.remove('%s-%x-%x' % (process_name, vme_info[0], vme_info[1])) else: print ' [-] [DUMP] Image Name: %s-%x-%x' % ( process_name, vme_info[0], vme_info[1]) print '[+] Process Dump End' return
def search_for_keys_in_task_memory(self, vmaddr, pm_cr3, mempath): proc_pae = IA32PML4MemoryPae(FileAddressSpace(mempath), pm_cr3) print '[*] Search for keys in range 0x%.8x-0x%.8x'%(vmaddr[0], vmaddr[1]) if proc_pae.is_valid_address(vmaddr[0]): fvVer = struct.unpack('=I', proc_pae.read(vmaddr[0], 4))[0] # maybe 2 keylen = struct.unpack('=I', proc_pae.read(vmaddr[0]+4, 4))[0] # maybe 0x10 if not keylen == 0x10: return Key = struct.unpack('=16s', proc_pae.read(vmaddr[0]+8, keylen))[0] # maybe 0x10 Vmk1 = proc_pae.read(vmaddr[0]+0x90, 16) Vmk2 = proc_pae.read(vmaddr[0]+0x430+0x90, 16) if not Key or Key != Vmk1[:keylen]: return if Vmk1 == Vmk2: self.candidate_key_list.append(proc_pae.read(vmaddr[0]+0x90, 16*11))
def get_mach_dump(self, vm_list, vm_struct, pid_process_name, mempath, pm_cr3): #print '[+] Resetting the Page Mapping Table: 0x%x'%pm_cr3 # init page table procmem = IA32PML4MemoryPae(FileAddressSpace(mempath), pm_cr3) dump_start = 0 mach_vme_list = [] for vme_info in vm_list: if procmem.is_valid_address(vme_info[0]): mach_header = _procmemcpy(procmem, vme_info[0], _MACH_HEADER) else: continue if mach_header.MH_MAGIC_X86 == mach_header.magic and FILE_MACH_EXECUTE == int(mach_header.filetype): print ' [-] Find 32 bit Mach-O signature at %.8x'%vme_info[0] self.mach_32bit = 1 elif mach_header.MH_MAGIC_X64 == mach_header.magic and FILE_MACH_EXECUTE == int(mach_header.filetype): print ' [-] Find 64 bit Mach-O signature at %.8x'%vme_info[0] self.mach_32bit = 0 else: print ' [-] Invalid Header at %.8x'%vme_info[0] continue fileoff = vme_info[0] # dump start offset dump_start = vme_info[0] # get load command offset loadcmdoff = 0 if self.mach_32bit: loadcmdoff = fileoff + sizeof(_MACH_HEADER) else: loadcmdoff = fileoff + sizeof(_MACH_HEADER_64) #loadcommand_offset = file_offset+SIZEOFMACHOHEADER for cmdcount in xrange(0, mach_header.ncmds): if self.mach_32bit: segment_command = _procmemcpy(procmem, loadcmdoff, _SEGMENT_COMMAND) else: segment_command = _procmemcpy(procmem, loadcmdoff, _SEGMENT_COMMAND_64) if str(segment_command.segname).split('\x00')[0] == '__PAGEZERO': self.difference = fileoff - segment_command.vmsize loadcmdoff = loadcmdoff + segment_command.cmdsize continue if segment_command.cmd == TYPE_SEGMENT or segment_command.cmd == TYPE_SEGMENT64: if str(segment_command.segname).split('\x00')[0] == '__PAGEZERO': self.difference = fileoff - segment_command.vmsize loadcmdoff = loadcmdoff + segment_command.cmdsize continue #mach_vme_info = [] vmstart = segment_command.vmaddr+self.difference vmend = segment_command.vmsize+segment_command.vmaddr+self.difference mach_vme_list.append([vmstart, vmend]) loadcmdoff = loadcmdoff + segment_command.cmdsize break dumpfilename = '%s-%x'%(pid_process_name, dump_start) file = open(dumpfilename, mode="wb") for vme in mach_vme_list: print ' [-] from %.8x to %.8x'%(vme[0], vme[1]) nop_code = 0x00 pk_nop_code = struct.pack('=B', nop_code) nop = pk_nop_code*0x1000 nop_flag = 1 writebuf = '' for i in xrange(vme[0], vme[1], 0x1000): raw_data = 0x00 if not(procmem.is_valid_address(i)): if nop_flag == 1: raw_data = nop writebuf += raw_data continue raw_data = procmem.read(i, 0x1000) if raw_data is None: if nop_flag == 1: raw_data = nop writebuf += raw_data continue writebuf += raw_data nop_flag = 1 file.write(writebuf[:vme[1] - vme[0]]) file.close() print ' [-] [DUMP] Image Name: %s-%x'%(pid_process_name, dump_start) print '[+] Process Dump End' self.reloc(dumpfilename) return
def get_mach_dump(self, vm_list, vm_struct, pid_process_name, mempath, pm_cr3): #print '[+] Resetting the Page Mapping Table: 0x%x'%pm_cr3 proc_pae = IA32PML4MemoryPae(FileAddressSpace(mempath), pm_cr3) #print '[+] Process Dump Start' MH_MAGIC_X86 = 'feedface' MH_MAGIC_X64 = 'feedfacf' MACHHEADER_32 = 'IIIIIII' SIZEOFMACHOHEADER_32 = 28 # bytes MACHHEADER_64 = 'IIIIIIII' SIZEOFMACHOHEADER_64 = 32 # bytes MACHHEADER = MACHHEADER_32 SIZEOFMACHOHEADER = SIZEOFMACHOHEADER_32 COMMAND_32 = 'II16sIIII' COMMAND_64 = 'II16sQQQQ' SIZEOFCOMMAND_32 = 40 # bytes SIZEOFCOMMAND_64 = 56 # bytes TYPE_SEGMENT = 0x01 TYPE_SEGMENT64 = 0x19 FILE_MACH_EXECUTE = 0x02 dump_start = 0 difference = 0 mach_vme_list = [] for vme_info in vm_list: try: machoheader_t = proc_pae.read( vme_info[0], SIZEOFMACHOHEADER) # read 0x1c bytes machoheader = struct.unpack(MACHHEADER, machoheader_t) except: continue strHex = '%x' % machoheader[0] if MH_MAGIC_X86 == strHex and FILE_MACH_EXECUTE == machoheader[3]: print ' [-] Find 32 bit Mach-O signature at %.8x' % vme_info[0] COMMAND = COMMAND_32 SIZEOFCOMMAND = SIZEOFCOMMAND_32 MACHHEADER = MACHHEADER_32 SIZEOFMACHOHEADER = SIZEOFMACHOHEADER_32 elif MH_MAGIC_X64 == strHex and FILE_MACH_EXECUTE == machoheader[3]: print ' [-] Find 64 bit Mach-O signature at %.8x' % vme_info[0] COMMAND = COMMAND_64 SIZEOFCOMMAND = SIZEOFCOMMAND_64 MACHHEADER = MACHHEADER_64 SIZEOFMACHOHEADER = SIZEOFMACHOHEADER_64 else: continue file_offset = vme_info[0] dump_start = file_offset loadcommand_offset = file_offset + SIZEOFMACHOHEADER for num_load_command in range(0, machoheader[4]): loadcommand_t = proc_pae.read(loadcommand_offset, SIZEOFCOMMAND) # 'II16sII' loadcommand = struct.unpack(COMMAND, loadcommand_t) if loadcommand[2].split('\x00')[0] == '__PAGEZERO': difference = dump_start - loadcommand[4] loadcommand_offset = loadcommand_offset + loadcommand[1] continue if loadcommand[0] == TYPE_SEGMENT or loadcommand[ 0] == TYPE_SEGMENT64: if loadcommand[2].split('\x00')[0] == '__PAGEZERO': difference = dump_start - loadcommand[4] loadcommand_offset = loadcommand_offset + loadcommand[1] continue mach_vme_info = [] mach_vme_info.append(loadcommand[3] + difference) mach_vme_info.append(loadcommand[6] + loadcommand[3] + difference) mach_vme_list.append(mach_vme_info) loadcommand_offset = loadcommand_offset + loadcommand[1] break file = open('%s-%x' % (pid_process_name, dump_start), mode="wb") for mach_vme_info in mach_vme_list: print ' [-] from %.8x to %.8x' % (mach_vme_info[0], mach_vme_info[1]) nop_code = 0x00 pk_nop_code = struct.pack('=B', nop_code) nop = pk_nop_code * 0x1000 nop_flag = 0 writebuf = '' for i in range(mach_vme_info[0], mach_vme_info[1], 0x1000): raw_data = 0x00 if not (proc_pae.is_valid_address(i)): if nop_flag == 1: raw_data = nop writebuf += raw_data continue raw_data = proc_pae.read(i, 0x1000) if raw_data is None: if nop_flag == 1: raw_data = nop writebuf += raw_data continue writebuf += raw_data nop_flag = 1 file.write(writebuf[:mach_vme_info[1] - mach_vme_info[0]]) file.close() print ' [-] [DUMP] Image Name: %s-%x' % (pid_process_name, dump_start) print '[+] Process Dump End' return