def listCreateProcess(): try: print '-'*10+'CreateProcess'+'-'*10 notifyaddr=pykd.getOffset('nt!PspCreateProcessNotifyRoutine') count=pykd.getOffset('nt!PspCreateProcessNotifyRoutineCount') count=pykd.ptrPtr(count) try: excount=pykd.getOffset('nt!PspCreateProcessNotifyRoutineExCount') except: excount=0 count+=excount if is_2000(): for i in xrange(count): funcaddr=pykd.ptrPtr(notifyaddr+i*g_mwordsize)&0xffffffffffffff8 symbolname=pykd.findSymbol(source) print 'routine:%x %s' % (funcaddr, symbolname) else: if pykd.is64bitSystem(): for i in xrange(count): funcaddr=pykd.ptrPtr(notifyaddr+i*g_mwordsize)&0xffffffffffffff8 symbolname=pykd.findSymbol(funcaddr) print 'routine:%x %s' % (funcaddr, symbolname) else: for i in xrange(count): routine_block=pykd.ptrPtr(notifyaddr+i*g_mwordsize)&0xffffffffffffff8 funcaddr=pykd.ptrPtr(routine_block+g_mwordsize) symbolname=pykd.findSymbol(funcaddr) print 'routine:%x %s' % (funcaddr, symbolname) except Exception, err: print traceback.format_exc()
def listCmpCallback(): try: notifyaddr=pykd.getOffset('nt!CmpCallBackVector') count=pykd.getOffset('nt!CmpCallBackCount') count=pykd.ptrPtr(count) print '-'*10+'CmpCallback'+'-'*10 if is_2000(): for i in xrange(count): funcaddr=pykd.ptrPtr(notifyaddr+i*g_mwordsize)&0xffffffffffffff8 symbolname=pykd.findSymbol(source) print 'routine:%x %s' % (funcaddr, symbolname) else: if pykd.is64bitSystem(): for i in xrange(count): funcaddr=pykd.ptrPtr(notifyaddr+i*g_mwordsize)&0xffffffffffffff8 symbolname=pykd.findSymbol(funcaddr) print 'routine:%x %s' % (funcaddr, symbolname) else: for i in xrange(count): routine_block=pykd.ptrPtr(notifyaddr+i*g_mwordsize)&0xffffffffffffff8 funcaddr=pykd.ptrPtr(routine_block+g_mwordsize) symbolname=pykd.findSymbol(funcaddr) print 'routine:%x %s' % (funcaddr, symbolname) except Exception, err: print traceback.format_exc()
def listCreateProcess(): try: print '-' * 10 + 'CreateProcess' + '-' * 10 notifyaddr = pykd.getOffset('nt!PspCreateProcessNotifyRoutine') count = pykd.getOffset('nt!PspCreateProcessNotifyRoutineCount') count = pykd.ptrPtr(count) try: excount = pykd.getOffset('nt!PspCreateProcessNotifyRoutineExCount') except: excount = 0 count += excount if is_2000(): for i in xrange(count): funcaddr = pykd.ptrPtr(notifyaddr + i * g_mwordsize) & 0xffffffffffffff8 symbolname = pykd.findSymbol(source) print 'routine:%x %s' % (funcaddr, symbolname) else: if pykd.is64bitSystem(): for i in xrange(count): funcaddr = pykd.ptrPtr(notifyaddr + i * g_mwordsize) & 0xffffffffffffff8 symbolname = pykd.findSymbol(funcaddr) print 'routine:%x %s' % (funcaddr, symbolname) else: for i in xrange(count): routine_block = pykd.ptrPtr( notifyaddr + i * g_mwordsize) & 0xffffffffffffff8 funcaddr = pykd.ptrPtr(routine_block + g_mwordsize) symbolname = pykd.findSymbol(funcaddr) print 'routine:%x %s' % (funcaddr, symbolname) except Exception, err: print traceback.format_exc()
def hookHandlerNative(): """Address of the func name as returned by getMethodName is pointed by EAX+0x08 However, unlike the published AVM source code claims, setNative function in the NPSWF32 has an additional check before the correct function address is assigned to the MethodInfo object. That logic is reimplemented here.""" global GBP address = pykd.ptrPtr(pykd.reg("eax")+0x8) comp_byte = pykd.ptrByte(pykd.ptrPtr(pykd.reg("esp")+0x18) + 0x38) if comp_byte > 0: nativefunc = pykd.ptrPtr(pykd.reg("esi")+0x28) else: nativefunc = pykd.ptrPtr(pykd.reg("esi")+0x24) if pykd.isValid(address): methodName = pykd.loadCStr(address) if pykd.isValid(nativefunc): print "[^] NATIVE METHOD: at 0x%x \t offset: 0x%x \tName: %s" % \ (nativefunc,nativefunc-NPS['base_addr'], methodName.decode("utf-8","replace")) if NPS["TraceNative"] and methodName not in GBP['BP_FUNCS'] and\ methodName not in GBP['BP_RFUNCS']: if NPS["Debug"]: print "[Debug] Setting bp for tracing on 0x%x" % nativefunc GBP[nativefunc] = pykd.setBp(nativefunc, lambda: functionHandler(methodName)) func_breakpoints(methodName.decode("utf-8","replace"), nativefunc) else: print "[!] No native function found. Something is likely wrong!!!" return pykd.executionStatus.NoChange
def listShutdown(): try: print '-' * 10 + 'Shutdown' + '-' * 10 IRP_MJ_SHUTDOWN = 0x10 #define IRP_MJ_SHUTDOWN 0x10 head = pykd.getOffset('nt!IopNotifyShutdownQueueHead') next = head while 1: next = pykd.ptrPtr(next) if next == head: break try: deviceobjectaddr = pykd.ptrPtr(next + g_mwordsize * 2) deviceobject = pykd.typedVar('nt!_DEVICE_OBJECT', deviceobjectaddr) driverobject = pykd.typedVar('nt!_DRIVER_OBJECT', int(deviceobject.DriverObject)) funcaddr = pykd.ptrPtr(driverobject.MajorFunction + g_mwordsize * IRP_MJ_SHUTDOWN) symbolname = pykd.findSymbol(funcaddr) print 'routine:%x %s' % (funcaddr, symbolname) except Exception, err: pass except Exception, err: print traceback.format_exc()
def listCmpCallback(): try: notifyaddr = pykd.getOffset('nt!CmpCallBackVector') count = pykd.getOffset('nt!CmpCallBackCount') count = pykd.ptrPtr(count) print '-' * 10 + 'CmpCallback' + '-' * 10 if is_2000(): for i in xrange(count): funcaddr = pykd.ptrPtr(notifyaddr + i * g_mwordsize) & 0xffffffffffffff8 symbolname = pykd.findSymbol(source) print 'routine:%x %s' % (funcaddr, symbolname) else: if pykd.is64bitSystem(): for i in xrange(count): funcaddr = pykd.ptrPtr(notifyaddr + i * g_mwordsize) & 0xffffffffffffff8 symbolname = pykd.findSymbol(funcaddr) print 'routine:%x %s' % (funcaddr, symbolname) else: for i in xrange(count): routine_block = pykd.ptrPtr( notifyaddr + i * g_mwordsize) & 0xffffffffffffff8 funcaddr = pykd.ptrPtr(routine_block + g_mwordsize) symbolname = pykd.findSymbol(funcaddr) print 'routine:%x %s' % (funcaddr, symbolname) except Exception, err: print traceback.format_exc()
def enter_call_back(self): self.condition = False time = datetime.datetime.now() current_free_size = (hex(pykd.ptrMWord(pykd.reg("esp") + 0xC))).replace('L', '') # logging everything except Free[0] if (current_free_size != "0x0"): self.condition = True self.out = str(time) self.out += ", RtlFreeHeap(" if arch_bits == 32: esp = pykd.reg(stack_pointer) self.out += hex(pykd.ptrPtr(esp + 4)) + " , " self.out += hex(pykd.ptrMWord(esp + 0x8)) + " , " self.out += hex(pykd.ptrPtr(esp + 0xC)) + ") = " else: self.out += hex(pykd.reg("rcx")) + " , " self.out += hex(pykd.reg("rdx")) + " , " self.out += hex(pykd.reg("r8")) + ") = " if self.bp_end == None: disas = pykd.dbgCommand("uf ntdll!RtlFreeHeap").split('\n') for i in disas: if 'ret' in i: self.ret_addr = format64(i.split()[0]) break self.bp_end = pykd.setBp(int(self.ret_addr, 16), self.return_call_back) return False
def allocServedFixedMallocOutOfLineAlloc(allocsize, ret): """Callback invoked just before the FixedMalloc OutOfLine function returns. EAX will store the allocation address""" global GBP allocaddress = pykd.reg("eax") # If allocsize is greater than 0x7f0 the allocation will be served by # FixedMalloc::LargeAlloc if allocsize <= 0x7f0: if GBP["START_ALLOC_MONITOR"]: returned_allocsize = pykd.ptrPtr((allocaddress & 0xfffff000)+0x12) # FixedAlloc allocator allocator = pykd.ptrPtr((allocaddress & 0xfffff000)+0x1C) # FixedAlloc.h#L120 # GCHeap *m_heap; //The heap from which we # //obtain memory # int m_heapPartition; //The heap partition from which we # //obtain memory # uint32_t m_itemsPerBlock; //Number of items that fit in a block # uint32_t m_itemSize; //Size of each individual item # FixedBlock* m_firstBlock; //First block on list of free blocks # FixedBlock* m_lastBlock; //Last block on list of free blocks # FixedBlock* m_firstFree; //The lowest priority block that has # //free items # size_t m_numBlocks; //Number of blocks owned by this # //allocator if IsheapIsolVersion(): heapPartition = pykd.ptrPtr(allocator+0x4) else: heapPartition = "NotImplemented" kSizeClass = kSizeClassIndex[((allocsize+7)>>3)] MMgc_FixedMalloc_obj =\ allocator - kSizeClass*NPS["FixedAllocSafeSize"] -\ NPS["m_allocs_offset"] if NPS['ffmsize']: if NPS['ffmsize'] == returned_allocsize: print "[FixedMalloc::OutOfLineAlloc] Requested Allocation \ of size:0x%x Returned allocation of size:0x%x at address:0x%x \ (MMgc::FixedMalloc Instance: 0x%x HeapPartition: %s)" % (allocsize, returned_allocsize, allocaddress, MMgc_FixedMalloc_obj, heapPartition) else: print "[FixedMalloc::OutOfLineAlloc] Requested Allocation of \ size:0x%x Returned allocation of size:0x%x at address:0x%x \ (MMgc::FixedMalloc Instance: 0x%x HeapPartition: %s)" % (allocsize, returned_allocsize, allocaddress, MMgc_FixedMalloc_obj, heapPartition) GBP["AllocHistory"][allocaddress] = pykd.dbgCommand("kv") +\ "\n\n" +\ "\n\nRAW Stack data in case FPO is in place:\n\n" +\ pykd.dbgCommand("dps esp L100") # Delete the breakpoint del GBP[ret] return pykd.executionStatus.NoChange
def listIopTimer(): try: print '-' * 10 + 'IopTimer' + '-' * 10 head = pykd.getOffset('nt!IopTimerQueueHead') next = head while 1: next = pykd.ptrPtr(next) if next == head: break funcaddr = pykd.ptrPtr(next + g_mwordsize * 2) symbolname = pykd.findSymbol(funcaddr) print 'routine:%x %s' % (funcaddr, symbolname) except Exception, err: print traceback.format_exc()
def listSeFileSystem(): try: print '-' * 10 + 'SeFileSystem' + '-' * 10 head = pykd.getOffset('nt!SeFileSystemNotifyRoutinesHead') next = head while 1: next = pykd.ptrPtr(next) if not next: break funcaddr = pykd.ptrPtr(next + g_mwordsize) symbolname = pykd.findSymbol(funcaddr) print 'routine:%x %s' % (funcaddr, symbolname) except Exception, err: print traceback.format_exc()
def listBugCheckReasonCallback(): try: print '-' * 10 + 'BugCheckReasonCallback' + '-' * 10 head = pykd.getOffset('nt!KeBugCheckReasonCallbackListHead') next = head while 1: next = pykd.ptrPtr(next) if next == head: break funcaddr = pykd.ptrPtr(next + g_mwordsize * 2) symbolname = pykd.findSymbol(funcaddr) print 'routine:%x %s' % (funcaddr, symbolname) except Exception, err: print traceback.format_exc()
def listBugCheckReasonCallback(): try: print '-'*10+'BugCheckReasonCallback'+'-'*10 head=pykd.getOffset('nt!KeBugCheckReasonCallbackListHead') next=head while 1: next=pykd.ptrPtr(next) if next==head: break funcaddr=pykd.ptrPtr(next+g_mwordsize*2) symbolname=pykd.findSymbol(funcaddr) print 'routine:%x %s' % (funcaddr, symbolname) except Exception, err: print traceback.format_exc()
def listSeFileSystem(): try: print '-'*10+'SeFileSystem'+'-'*10 head=pykd.getOffset('nt!SeFileSystemNotifyRoutinesHead') next=head while 1: next=pykd.ptrPtr(next) if not next: break funcaddr=pykd.ptrPtr(next+g_mwordsize) symbolname=pykd.findSymbol(funcaddr) print 'routine:%x %s' % (funcaddr, symbolname) except Exception, err: print traceback.format_exc()
def listIopTimer(): try: print '-'*10+'IopTimer'+'-'*10 head=pykd.getOffset('nt!IopTimerQueueHead') next=head while 1: next=pykd.ptrPtr(next) if next==head: break funcaddr=pykd.ptrPtr(next+g_mwordsize*2) symbolname=pykd.findSymbol(funcaddr) print 'routine:%x %s' % (funcaddr, symbolname) except Exception, err: print traceback.format_exc()
def enter_call_back(self,bp): self.out = "RtlFreeHeap(" if arch_bits == 32: esp = pykd.reg(stack_pointer) self.out += hex(pykd.ptrPtr(esp + 4)) + " , " self.out += hex(pykd.ptrMWord(esp + 0x8)) + " , " self.out += hex(pykd.ptrPtr(esp + 0xC)) + ") = " else: self.out += hex(pykd.reg("rcx")) + " , " self.out += hex(pykd.reg("rdx")) + " , " self.out += hex(pykd.reg("r8")) + ") = " if self.bp_end == None: self.ret_addr = pykd.dbgCommand("dd esp L1").split()[1] self.bp_end = pykd.setBp(int(self.ret_addr, 16), self.return_call_back) return False
def listPlugPlay(): try: print '-' * 10 + 'PlugPlay' + '-' * 10 table = pykd.getOffset('nt!IopDeviceClassNotifyList') for i in xrange(13): head = table + g_mwordsize * i * 2 next = head while 1: next = pykd.ptrPtr(next) if next == head: break funcaddr = pykd.ptrPtr(next + g_mwordsize * 5) symbolname = pykd.findSymbol(funcaddr) print 'routine:%x %s' % (funcaddr, symbolname) except Exception, err: print traceback.format_exc()
def _meta_object_addr_of_frame(frame): ax32serv = module('Ax32Serv') element_type = _element_type_of_raw_frame(frame) element_id = _element_id_of_raw_frame(frame) base_offset = 0 first_lvl_offset = 72 second_lvl_offset = 0 if element_type == ElementType.xpp_table: base_offset = ax32serv.offset('tableObj') second_lvl_offset = (element_id % 2500) * 8 elif element_type == ElementType.xpp_class: base_offset = ax32serv.offset('classObj') second_lvl_offset = (element_id % 2500) * 8 else: return 0 return ptrPtr(ptrPtr(base_offset + first_lvl_offset) + second_lvl_offset)
def listModuleByLdrHash(eprocessaddr): modulelist = {} try: cmdline = '.process /P %x;.reload;' % eprocessaddr r = pykd.dbgCommand(cmdline) try: LdrpHashTable = pykd.getOffset('ntdll!LdrpHashTable') except: print 'get LdrpHashTable symbol fail, maybe ldr is null' return [] if int(LdrpHashTable) != 0: for i in xrange(26): listhead = LdrpHashTable + i * 2 * g_mwordsize hashlink = listhead while 1: hashlink = pykd.ptrPtr(hashlink) if hashlink == listhead: break ldr = pykd.containingRecord(hashlink, 'nt!_LDR_DATA_TABLE_ENTRY', 'HashLinks') if int(ldr) not in modulelist: info = ModuleInfo() if info.init1(ldr): modulelist[int(ldr)] = info except Exception, err: print traceback.format_exc()
def listModuleByLdrHash(eprocessaddr): modulelist = {} try: cmdline = ".process /P %x;.reload;" % eprocessaddr r = pykd.dbgCommand(cmdline) try: LdrpHashTable = pykd.getOffset("ntdll!LdrpHashTable") except: print "get LdrpHashTable symbol fail, maybe ldr is null" return [] if int(LdrpHashTable) != 0: for i in xrange(26): listhead = LdrpHashTable + i * 2 * g_mwordsize hashlink = listhead while 1: hashlink = pykd.ptrPtr(hashlink) if hashlink == listhead: break ldr = pykd.containingRecord(hashlink, "nt!_LDR_DATA_TABLE_ENTRY", "HashLinks") if int(ldr) not in modulelist: info = ModuleInfo() if info.init1(ldr): modulelist[int(ldr)] = info except Exception, err: print traceback.format_exc()
def testCompare(self): self.assertTrue( pykd.compareMemory(target.module.helloStr, pykd.ptrPtr(target.module.strArray), 5)) self.assertFalse( pykd.compareMemory(target.module.helloStr, target.module.helloWStr, 5))
def inspectDispatchRoutine(driverobjectaddr=None): try: if driverobjectaddr: driverinfo=DriverInfo() if not driverinfo.init1(driverobjectaddr): print 'fail to get driver info' return driverlist=[driverinfo] else: driverlist=listDriverByDirectoryObject() for driverinfo in driverlist: try: startaddr=driverinfo.baseaddr endaddr=driverinfo.baseaddr+driverinfo.modulesize driverobjectaddr=driverinfo.driverobjectaddr driverobject=pykd.typedVar('nt!_DRIVER_OBJECT', driverobjectaddr) print '='*10, 'drvobj:%x %s' % (driverobjectaddr,driverinfo.filepath),'='*10 for i in xrange(28): funcaddr=pykd.ptrPtr(driverobject.MajorFunction+i*g_mwordsize) symbolname=pykd.findSymbol(funcaddr) if funcaddr<startaddr or funcaddr>=endaddr: if symbolname.find('+')!=-1: print '%d %s %x %s maybe hooked!!!!!' % (i, MajorFunction[i], funcaddr, symbolname) else: print '%d %s %x %s' % (i, MajorFunction[i], funcaddr, symbolname) else: print '%d %s %x %s' % (i, MajorFunction[i], funcaddr, symbolname) except Exception, err: print traceback.format_exc() except Exception, err: print traceback.format_exc()
def allocServedFixedMallocLargeAlloc(req_size, ret, FixedMalloc): """Callback invoked just before the FixedMalloc Large function returns. EAX will store the allocation address""" global GBP # FixedMalloc::InitInstance # this->m_heap = MMgc::GCHeap; # this->m_largeAllocHeapPartition = fixedPartitionMap[partition]; # m_largeAllocHeapPartition is at offset + 0x4 if IsheapIsolVersion(): Partition = pykd.ptrPtr((FixedMalloc+0x4)) else: Partition = "NotImplemented" if GBP["START_ALLOC_MONITOR"]: returned_allocsize = ((req_size + 0xfff)>>0xC)*0x1000 if NPS['ffmsize']: if NPS['ffmsize'] == returned_allocsize: print "[FixedMalloc::LargeAlloc] Requested Allocation of \ size:0x%x Returned allocation of size:0x%x at address:0x%x FixedMalloc:0x%x \ Partition: %s" %\ (req_size, returned_allocsize, pykd.reg("eax"), FixedMalloc, Partition) else: print "[FixedMalloc::LargeAlloc] Requested Allocation of \ size:0x%x Returned allocation of size:0x%x at address:0x%x FixedMalloc:0x%x \ Partition: %s" %\ (req_size, returned_allocsize, pykd.reg("eax"), FixedMalloc, Partition) GBP["AllocHistory"][pykd.reg("eax")] = pykd.dbgCommand("kv") +\ "\n\nRAW Stack data in case FPO is in place:\n\n" +\ pykd.dbgCommand("dps esp L100") return pykd.executionStatus.NoChange
def listPlugPlay(): try: print '-'*10+'PlugPlay'+'-'*10 table=pykd.getOffset('nt!IopDeviceClassNotifyList') for i in xrange(13): head=table+g_mwordsize*i*2 next=head while 1: next=pykd.ptrPtr(next) if next==head: break funcaddr=pykd.ptrPtr(next+g_mwordsize*5) symbolname=pykd.findSymbol(funcaddr) print 'routine:%x %s' % (funcaddr, symbolname) except Exception, err: print traceback.format_exc()
def enter_call_back(self): self.condition = False time = datetime.datetime.now() current_alloc_size = (hex(pykd.ptrMWord(pykd.reg("esp") + 0xC))).replace('L', '') if (current_alloc_size == alloc_size) or "null" in alloc_size: self.condition = True self.out = str(time) self.out += ", RtlAllocateHeap(" if arch_bits == 32: esp = pykd.reg("esp") self.out += hex(pykd.ptrPtr(esp + 4)) + " , " self.out += hex(pykd.ptrMWord(esp + 0x8)) + " , " self.out += hex(pykd.ptrMWord(esp + 0xC)) + ") = " else: self.out += hex(pykd.reg("rcx")) + " , " self.out += hex(pykd.reg("rdx")) + " , " self.out += hex(pykd.reg("r8")) + ") = " if self.condition: disas = pykd.dbgCommand("uf ntdll!RtlAllocateHeap").split('\n') for i in disas: if 'ret' in i: self.ret_addr = format64(i.split()[0]) break self.bp_end = pykd.setBp(int(self.ret_addr, 16), self.return_call_back) return False
def InitTracer(): global DriverObject global ImageBase global NtImageEnd NtModule = pykd.module("nt") NtImageBase = NtModule.begin() NtImageEnd = NtModule.end() pykd.dbgCommand("ba e1 IopLoadDriver+4bd") pykd.dbgCommand("ba e1 IopLoadDriver+4c2") pykd.go() while(1): regPath = pykd.dbgCommand("du /c40 @rdx+10") if "VmpDriver.vmp" in regPath: print "[*] Find VMP Driver" DriverObject = pykd.reg("rcx") print "\t[-] Driver Object : 0x{:X}".format(DriverObject) ImageBase =pykd.ptrPtr(DriverObject+0x18) # DriverObject.DriverStart print "\t[-] ImageBase Address : 0x{:X}".format(ImageBase) VMPTracingSub.GetSectionInfo(ImageBase) EntryPoint = ImageBase + VMPTracingSub.EntryPoint_Off strEntryPoint = hex(EntryPoint).rstrip("L") pykd.dbgCommand("ba e1 "+strEntryPoint) pykd.go() pykd.dbgCommand("bc 2") return pykd.go()
def inspectSSDT(): kernelbase=g_kernelbase KeServiceDescriptorTable=pykd.getOffset('nt!KeServiceDescriptorTable') KiServiceTable=pykd.ptrPtr(KeServiceDescriptorTable) serviceCount=pykd.ptrMWord(KeServiceDescriptorTable+2*g_mwordsize) print 'nt!KeServiceDescriptorTable:0x%x' % KeServiceDescriptorTable print 'nt!KiServiceTable:0x%x' % KiServiceTable print 'serviceCount:0x%x(%d)' % (serviceCount, serviceCount) ssdttable=pykd.loadPtrs(KiServiceTable, serviceCount) table_rva=(KiServiceTable-kernelbase) print 'KiServiceTable rva:0x%x' % table_rva filedata=open(g_kernelpath, 'rb').read() pe = pefile.PE(data=filedata, fast_load=True) if pe.DOS_HEADER.e_magic!=0X5A4D or pe.NT_HEADERS.Signature!=0x4550: raise Exception("%s is not a pe file" % filepath) table_fileoffset=pe.get_offset_from_rva(table_rva) print 'KiServiceTable file offset:0x%x' % table_fileoffset d=filedata[table_fileoffset:table_fileoffset+g_mwordsize*serviceCount] number=0 for i in xrange(serviceCount): source=binascii.b2a_hex(d[i*g_mwordsize:(i+1)*g_mwordsize][::-1]) source=pykd.addr64(int(source, 16))-pykd.addr64(pe.OPTIONAL_HEADER.ImageBase)+kernelbase symbolname=pykd.findSymbol(source) current=ssdttable[i] if source==current: print 'source:0x%x current:0x%x %s' % (source, current, symbolname) else: hooksymbolname=pykd.findSymbol(current) print 'source:0x%x %s <-> current:0x%x %s hooked!!!!!!!' % (source, symbolname, current, hooksymbolname) number+=1 print 'hooked function number:', number
def enter_call_back(self, bp): self.out = "RtlFreeHeap(" if arch_bits == 32: esp = pykd.reg(stack_pointer) self.out += hex(pykd.ptrPtr(esp + 4)) + " , " self.out += hex(pykd.ptrMWord(esp + 0x8)) + " , " self.out += hex(pykd.ptrPtr(esp + 0xC)) + ") = " else: self.out += hex(pykd.reg("rcx")) + " , " self.out += hex(pykd.reg("rdx")) + " , " self.out += hex(pykd.reg("r8")) + ") = " if self.bp_end == None: self.ret_addr = pykd.dbgCommand("dd esp L1").split()[1] self.bp_end = pykd.setBp(int(self.ret_addr, 16), self.return_call_back) return False
def return_call_back(self): esp = pykd.reg(stack_pointer) self.out += hex(pykd.reg(return_reg)) self.out += " - From: " + (hex(pykd.ptrPtr(esp))).replace('L', '') print(self.out) if logging: log.write(self.out + "\n") return False
def enter_call_back(self, bp): self.out = "RtlAllocateHeap(" esp = pykd.reg("esp") self.out += hex(pykd.ptrPtr(esp + 4)) + " , " self.out += hex(pykd.ptrMWord(esp + 0x8)) + " , " self.out += hex(pykd.ptrMWord(esp + 0xC)) + ") = " if self.bp_end == None: self.ret_addr = pykd.dbgCommand("dd esp L1").split()[1] self.bp_end = pykd.setBp(int(self.ret_addr, 16), self.return_call_back) return False
def enter_call_back(self, bp): self.out = "RtlFreeHeap(" if arch_bits == 32: esp = pykd.reg(stack_pointer) self.out += hex(pykd.ptrPtr(esp + 4)) + " , " self.out += hex(pykd.ptrMWord(esp + 0x8)) + " , " self.out += hex(pykd.ptrPtr(esp + 0xC)) + ") = " else: self.out += hex(pykd.reg("rcx")) + " , " self.out += hex(pykd.reg("rdx")) + " , " self.out += hex(pykd.reg("r8")) + ") = " if self.bp_end == None: disas = pykd.dbgCommand("uf ntdll!RtlFreeHeap").split("\n") for i in disas: if "ret" in i: self.ret_addr = i.split()[0] break self.bp_end = pykd.setBp(int(self.ret_addr, 16), self.return_call_back) return False
def hookHandlerInterp(): """...""" global GBP # address of the func name as returned by getMethodName address = pykd.ptrPtr(pykd.reg("eax")+0x8) if pykd.isValid(address): methodName = pykd.loadCStr(address) GBP['INTERP_RET'] = pykd.setBp((NPS["SetInterpRet"]-4), lambda: hookHandlerInterpRet(methodName)) return pykd.executionStatus.NoChange
def enter_call_back(self): self.out = 'RtlFreeHeap(' if arch_bits == 32: esp = pykd.reg(stack_pointer) self.out += hex(pykd.ptrPtr(esp + 4)) + " , " self.out += hex(pykd.ptrMWord(esp + 0x8)) + " , " self.out += hex(pykd.ptrPtr(esp + 0xC)) + ") = " else: self.out += hex(pykd.reg("rcx")) + " , " self.out += hex(pykd.reg("rdx")) + " , " self.out += hex(pykd.reg("r8")) + ") = " if self.bp_end == None: disas = pykd.dbgCommand("uf ntdll!RtlFreeHeap").split('\n') for i in disas: if 'ret' in i: self.ret_addr = i.split()[0] break self.bp_end = pykd.setBp(pykd.expr(self.ret_addr), self.return_call_back) return False
def return_call_back(self): #returns a BOOLEAN which is a byte under the hood if self.condition: esp = pykd.reg(stack_pointer) ret_val = hex(pykd.reg("al")) self.out += ret_val self.out += " - From: " + (hex(pykd.ptrPtr(esp))).replace('L', '') print(self.out) if logging: log.write(self.out + "\n") return False
def listFsNotifyChange(): try: print '-'*10+'FsNotifyChange'+'-'*10 head=pykd.getOffset('nt!IopFsNotifyChangeQueueHead') next=head while 1: next=pykd.ptrPtr(next) if next==head: break dirverobjectaddr=pykd.ptrPtr(next+g_mwordsize*2) funcaddr=pykd.ptrPtr(next+g_mwordsize*3) try: driverobject=pykd.typedVar('nt!_DRIVER_OBJECT', dirverobjectaddr) drivername=pykd.loadUnicodeString(driverobject.DriverName) except Exception, err: drivername='' symbolname=pykd.findSymbol(funcaddr) print 'routine:%x %s driver:%s' % (funcaddr, symbolname, drivername) except Exception, err: print traceback.format_exc()
def listFsNotifyChange(): try: print '-' * 10 + 'FsNotifyChange' + '-' * 10 head = pykd.getOffset('nt!IopFsNotifyChangeQueueHead') next = head while 1: next = pykd.ptrPtr(next) if next == head: break dirverobjectaddr = pykd.ptrPtr(next + g_mwordsize * 2) funcaddr = pykd.ptrPtr(next + g_mwordsize * 3) try: driverobject = pykd.typedVar('nt!_DRIVER_OBJECT', dirverobjectaddr) drivername = pykd.loadUnicodeString(driverobject.DriverName) except Exception, err: drivername = '' symbolname = pykd.findSymbol(funcaddr) print 'routine:%x %s driver:%s' % (funcaddr, symbolname, drivername) except Exception, err: print traceback.format_exc()
def allocServedHeapAllocSystem(): """Callback invoked when HeapAlloc is called.""" global GBP if GBP["START_ALLOC_MONITOR"]: # LPVOID WINAPI HeapAlloc( # _In_ HANDLE hHeap, # _In_ DWORD dwFlags, # _In_ SIZE_T dwBytes # ); size = pykd.ptrPtr(pykd.reg("esp")+0xC) heap = pykd.ptrPtr(pykd.reg("esp")+0x4) tid = pykd.getCurrentThreadId() if NPS['ihsize']: if NPS['ihsize'] == size: # Setup a breakpoint on the return address GBP["HeapAllocRet"] = pykd.setBp(pykd.ptrPtr(pykd.reg("esp")), lambda: allocServedHeapAllocSystemRet(size, heap, tid)) else: # Setup a breakpoint on the return address GBP["HeapAllocRet"] = pykd.setBp(pykd.ptrPtr(pykd.reg("esp")), lambda: allocServedHeapAllocSystemRet(size, heap, tid)) return pykd.executionStatus.NoChange
def hookHandlerJit(): """Unlike setNative, setJit is a fairly simple in that the GprMethodProc parameted contains the resolved address of the jitted function. We simply need to read that register value.""" global GBP # address of the func name as returned by getMethodName address = pykd.ptrPtr(pykd.reg("eax")+0x8) # address of the jitted function jitfunc = pykd.ptrPtr(pykd.reg("esp")+0x28) if pykd.isValid(address): methodName = pykd.loadCStr(address) if pykd.isValid(jitfunc): print "[&] JITTED METHOD: at 0x%x \t offset: 0x%x \t\tName: %s" %\ (jitfunc,0,methodName.decode("utf-8","replace")) if NPS["TraceJit"] and methodName not in GBP['BP_FUNCS'] and\ methodName not in GBP['BP_RFUNCS']: if NPS["Debug"]: print "[Debug] Setting bp for tracing on 0x%x" % jitfunc GBP[jitfunc] = pykd.setBp(jitfunc, lambda: functionHandler(methodName)) func_breakpoints(methodName.decode("utf-8","replace"), jitfunc) else: print "[!] No jitted function found. Something is likely wrong!!!" return pykd.executionStatus.NoChange
def listShutdown(): try: print '-'*10+'Shutdown'+'-'*10 IRP_MJ_SHUTDOWN=0x10 #define IRP_MJ_SHUTDOWN 0x10 head=pykd.getOffset('nt!IopNotifyShutdownQueueHead') next=head while 1: next=pykd.ptrPtr(next) if next==head: break try: deviceobjectaddr=pykd.ptrPtr(next+g_mwordsize*2) deviceobject=pykd.typedVar('nt!_DEVICE_OBJECT', deviceobjectaddr) driverobject=pykd.typedVar('nt!_DRIVER_OBJECT', int(deviceobject.DriverObject)) funcaddr=pykd.ptrPtr(driverobject.MajorFunction+g_mwordsize*IRP_MJ_SHUTDOWN) symbolname=pykd.findSymbol(funcaddr) print 'routine:%x %s' % (funcaddr, symbolname) except Exception, err: pass except Exception, err: print traceback.format_exc()
def allocServedGCAlloc(req_size, ret, GCAlloc, Partition): """Callback invoked just before the GCAlloc function returns. EAX will store the allocation address""" global GBP allocaddress = pykd.reg("eax") GCAllocBase = pykd.ptrPtr((allocaddress & 0xfffff000)+0xC) returned_allocsize = pykd.ptrPtr((allocaddress & 0xfffff000)+0x4) if GBP["START_ALLOC_MONITOR"]: if NPS['fgcsize']: if NPS['fgcsize'] == returned_allocsize: print "[GCAlloc::Alloc] Requested allocation 0x%x Returned \ allocation of size:0x%x at address: 0x%x: HeapPartition: %s" %\ (req_size, returned_allocsize, allocaddress, Partition) else: print "[GCAlloc::Alloc] Requested allocation 0x%x Returned \ allocation of size:0x%x at address: 0x%x HeapPartition: %s" %\ (req_size, returned_allocsize, allocaddress, Partition) GBP["AllocHistory"][allocaddress] = pykd.dbgCommand("kv") +\ "\n\nRAW Stack data in case FPO is in place:\n\n" +\ pykd.dbgCommand("dps esp L100") # Delete the breakpoints del GBP["GCAllocBPs"][ret] return pykd.executionStatus.NoChange
def enter_call_back(self,bp): self.out = "RtlAllocateHeap(" esp = pykd.reg("esp") self.out += hex(pykd.ptrPtr(esp + 4)) + " , " self.out += hex(pykd.ptrMWord(esp + 0x8)) + " , " self.out += hex(pykd.ptrMWord(esp + 0xC)) + ") = " if self.bp_end == None: disas = pykd.dbgCommand("uf ntdll!RtlAllocateHeap").split('\n') for i in disas: if 'ret' in i: self.ret_addr = i.split()[0] break self.bp_end = pykd.setBp(int(self.ret_addr, 16), self.return_call_back) return False
def _cb_CIasin_pentium4(self, bp): sp = pykd.reg("esp") # reversed this a while a go now bridge = pykd.loadCStr((pykd.ptrPtr(sp + 0x78) + 0xb)) print("(+) DEBUG ASIN: %s" % bridge) if self.bp_end_asin is None: disas = pykd.dbgCommand("uf %x" % self.asin_addr).split('\n') for i in disas: if 'ret' in i: self.ret_addr = i.split()[0] break self.bp_end_asin = pykd.setBp(int(self.ret_addr, 16), self.return_call_back) return False
def allocHandlerGCAlloc(rets): """Callback invoked when a GC allocation is requested. The function sets a breakpoint on the addresses within the function where the allocation address is returned.""" global GBP req_size = pykd.ptrPtr(pykd.reg("esi")+0x20) GCAlloc = pykd.reg("ecx") #MMgc::GCAlloc::GCAlloc #mov esi, ecx #... #mov ecx, [esp+10h+SmallGCAllocHeapPartition] #mov [esi+38h], edx #mov [esi+3Ch], ecx ; 0x3c is the partition index #mov [esi+30h], eax if IsheapIsolVersion(): Partition = pykd.ptrPtr(pykd.reg("esi")+0x3c) else: Partition = "NotImplemented" for ret in findAllocRets('GCAlloc::Alloc', func_sigs_ends['GCAllocEnd'], ["\xC2", "\x04", "\x00"]): GBP["GCAllocBPs"][ret] = pykd.setBp(ret, lambda: allocServedGCAlloc(req_size, ret, GCAlloc, Partition)) return pykd.executionStatus.NoChange
def rewrite_filename(): """ Overwrite the terminating NUL-byte for the first filename. This effectively concatenates the first two filenames. """ this = pykd.reg("ecx") buf = pykd.ptrPtr(this + 1036) buf_size = pykd.ptrDWord(this + 1040) files = list(Path().iterdir()) files_hdr = len(files) * 4 * 2 files_len = files_hdr + sum(len(x.name) + 1 for x in files) if files_len == buf_size: names = pykd.loadBytes(buf + files_hdr, buf_size - files_hdr) for i, byte in enumerate(names): if byte == 0: pykd.writeBytes(buf + files_hdr + i, [0x41]) break
#!/usr/bin/env python # -*- coding: utf-8 -* # author: SAI import os,sys,time import traceback import pykd from common import * mmhighestuseraddress=pykd.ptrPtr(pykd.getOffset('nt!MmHighestUserAddress')) class ProcessInfo(object): def init(self, eprocessobj): try: if eprocessobj.ObjectTable<mmhighestuseraddress or eprocessobj.VadRoot<mmhighestuseraddress or eprocessobj.QuotaBlock<mmhighestuseraddress: return False self.eprocessaddr=int(eprocessobj) self.pid=int(eprocessobj.UniqueProcessId) self.parentpid=int(eprocessobj.InheritedFromUniqueProcessId) self.peb=int(eprocessobj.Peb) filepath=pykd.loadUnicodeString(eprocessobj.SeAuditProcessCreationInfo.ImageFileName.Name) filepath=revise_filepath(filepath) name=pykd.loadChars(eprocessobj.ImageFileName, 16) if name.startswith('\x00'): name='' name=name.strip('\x00') self.filepath, self.name=guess_filepath(filepath, name) return True except Exception, err: print traceback.format_exc() return False
def _meta_object_name_of_frame(frame): name_addr = ptrPtr(_meta_object_addr_of_frame(frame) + 16) if isValid(name_addr): return loadWStr(name_addr) else: return ''
def _method_name_of_raw_frame(frame): name_addr = ptrPtr(frame.stackOffset + 8) return loadWStr(name_addr)
def inspectIatEatHook(modulelist, eprocessaddr=None, targetmodulebase=None): try: if eprocessaddr: cmdline='.process /P /r %x' % eprocessaddr r=pykd.dbgCommand(cmdline) importfunctable=[] exportfunctable={} for mo in modulelist: modulepath=mo.filepath modulename=mo.name.lower() s=os.path.splitext(modulename) if len(s)>=2: modulebasename=s[0] else: modulebasename=modulename baseaddr=mo.baseaddr if not os.path.exists(modulepath): continue elif not baseaddr: continue filedata=open(modulepath, 'rb').read() pe = pefile.PE(data=filedata, fast_load=True) if pe.DOS_HEADER.e_magic!=0X5A4D or pe.NT_HEADERS.Signature!=0x4550: raise Exception("%s is not a pe file" % modulepath) pe.parse_data_directories(pefile.DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_EXPORT']) if hasattr(pe,'DIRECTORY_ENTRY_EXPORT'): exporttable=pe.DIRECTORY_ENTRY_EXPORT for i in exporttable.symbols: funcoffset=pe.get_rva_from_offset(i.address_offset) funcaddr=baseaddr+i.address #print hex(baseaddr+funcoffset) ,hex(funcaddr) info=ExportFuncInfo(i.name, modulename, baseaddr, funcaddr, funcoffset, i.ordinal, i.forwarder) exportfunctable[funcaddr]=info pe.parse_data_directories(pefile.DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_IMPORT']) if hasattr(pe,'DIRECTORY_ENTRY_IMPORT'): importtable=pe.DIRECTORY_ENTRY_IMPORT for importitem in importtable: importname=importitem.dll for i in importitem.imports: #thunkvalue=i.bound iatoffset=i.address-pe.OPTIONAL_HEADER.ImageBase+baseaddr funcname=i.name #print '%s %s %x %x %s' % (importname, funcname, baseaddr, iatoffset, i.ordinal) info=ImportFuncInfo(funcname, modulename, importname, baseaddr, iatoffset, i.ordinal) importfunctable.append(info) #for info in exportfunctable.values(): # print info.funcname, hex(info.funcaddr) #return #inspect export table for info in exportfunctable.values(): if not targetmodulebase or (targetmodulebase==info.baseaddr): sourceoffsetvalue=info.funcaddr-info.baseaddr try: currentoffsetvalue=pykd.ptrDWord(info.funcoffset+info.baseaddr) except Exception, err: print 'EATHOOK:(%s!%s) baseaddr:%x offset:%x value:%x<->????????' % (info.modulename, info.funcname, info.baseaddr, info.funcoffset, sourceoffsetvalue) continue if sourceoffsetvalue!=currentoffsetvalue: print 'EATHOOK:(%s!%s) baseaddr:%x offset:%x value:%x<->%x' % (info.modulename, info.funcname, info.baseaddr, info.funcoffset, sourceoffsetvalue, currentoffsetvalue) print 'inspect EATHOOK completely' #inspect import table for i in importfunctable: if not targetmodulebase or (targetmodulebase==i.baseaddr): try: currentfuncaddr=pykd.ptrPtr(i.iatoffset) except Exception, err: if i.ordinal: #by ordinal print 'IATHOOK:(source:%s import:idx:%s!%d)<->????????' % (i.sourcemodulename, i.importmodulename,i.ordinal) else: #by name print 'IATHOOK:(source:%s import:%s!%s)<->????????' % (i.sourcemodulename, i.importmodulename,i.funcname) continue if not exportfunctable.get(currentfuncaddr): hookfuncname=pykd.findSymbol(currentfuncaddr) if i.ordinal: #by ordinal print 'IATHOOK:(source:%s import:%s!idx:%d)<->%x(%s)' % (i.sourcemodulename, i.importmodulename,i.ordinal, currentfuncaddr, hookfuncname) else: #by name print 'IATHOOK:(source:%s import:%s!%s)<->%x(%s)' % (i.sourcemodulename, i.importmodulename,i.funcname, currentfuncaddr, hookfuncname)
def inspectMsgHook(): msglist=[] try: gSharedInfo=pykd.getOffset('win32k!gSharedInfo') serverinfo=pykd.ptrPtr(gSharedInfo) aheList=pykd.ptrPtr(gSharedInfo+g_mwordsize) if is_2000() or is_xp(): count=pykd.ptrPtr(serverinfo+g_mwordsize*2) else: count=pykd.ptrPtr(serverinfo+g_mwordsize*1) for i in xrange(count): entry=aheList+i*3*g_mwordsize phook=pykd.ptrPtr(entry) #head type=pykd.ptrByte(entry+2*g_mwordsize) if type!=5: continue try: handle=pykd.ptrPtr(phook) msgtype=pykd.ptrPtr(phook+6*g_mwordsize) funcoffset=pykd.ptrPtr(phook+7*g_mwordsize) flags=pykd.ptrPtr(phook+8*g_mwordsize) if flags&1: bGlobal=1 else: bGlobal=0 pti=pykd.ptrPtr(phook+2*g_mwordsize) threadobjectaddr=pykd.ptrPtr(pti) threadobject=pykd.typedVar('nt!_ETHREAD', threadobjectaddr) pid=int(threadobject.Cid.UniqueProcess) tid=(threadobject.Cid.UniqueThread) try: processobject=pykd.typedVar('nt!_EPROCESS', threadobject.ThreadsProcess) except Exception, err: processobject=pykd.typedVar('nt!_EPROCESS', threadobject.Tcb.Process) processpath=pykd.loadUnicodeString(processobject.SeAuditProcessCreationInfo.ImageFileName.Name) msginfo=MsgInfo(handle=handle, pid=pid, tid=tid, msgtype=msgtype, funcoffset=funcoffset, bGlobal=bGlobal, processpath=processpath) msglist.append(msginfo) except Exception, err: print err
def listSocket(): try: r=pykd.dbgCommand('.reload tcpip.sys') if is_2000(): print 'no support' elif is_xp() or is_2003(): AddrObjTable=pykd.getOffset('tcpip!AddrObjTable') AddrObjTable=pykd.ptrPtr(AddrObjTable) AddrObjTableSize=pykd.getOffset('tcpip!AddrObjTableSize') AddrObjTableSize=pykd.ptrPtr(AddrObjTableSize) print '='*20 print 'AddrObjTable:%x AddrObjTableSize:%d' % (AddrObjTable, AddrObjTableSize) if pykd.is64bitSystem(): Next_offset=0 localIP_offset=0x58 #4bytes LocalPort_offset=0x5c#2bytes Protocol_offset=0x5e #2bytes pid_offset=0x238 #4bytes else: if is_xp(): Next_offset=0 localIP_offset=0x2c #4bytes LocalPort_offset=0x30#2bytes Protocol_offset=0x32 #2bytes pid_offset=0x148 #4bytes elif is_2003(): Next_offset=0 localIP_offset=0x30 #4bytes LocalPort_offset=0x34#2bytes Protocol_offset=0x36 #2bytes pid_offset=0x14c #4bytes print 'local remote protocol pid' for i in xrange(AddrObjTableSize): obj=pykd.ptrPtr(AddrObjTable+i*g_mwordsize) while obj!=0: LocalIP=pykd.ptrMWord(obj+localIP_offset) LocalPort=pykd.ptrWord(obj+LocalPort_offset) LocalPort=socket.htons(LocalPort) Protocol=pykd.ptrWord(obj+Protocol_offset) pid=pykd.ptrMWord(obj+pid_offset) Protocol=g_protocols.get(Protocol) print '%16s:%5d *.* %10s %d' % (socket.inet_ntoa(struct.pack('I', LocalIP)), LocalPort, Protocol, pid) obj=pykd.ptrPtr(obj+Next_offset) print '='*20 TCBTable=pykd.getOffset('tcpip!TCBTable') TCBTable=pykd.ptrPtr(TCBTable) MaxHashTableSize=pykd.getOffset('tcpip!MaxHashTableSize') MaxHashTableSize=pykd.ptrPtr(MaxHashTableSize) print 'TCBTable:%x MaxHashTableSize:%d' % (TCBTable, MaxHashTableSize) Next_offset=0 RemoteIP_offset=0x0c#4bytes LocalIP_offset=0x10#4bytes RemotePort_offset=0x14#2bytes LocalPort_offset=0x16 #2bytes pid_offset=0x18 #4bytes print 'local remote protocol pid' for i in xrange(MaxHashTableSize): obj=pykd.ptrPtr(TCBTable+i*g_mwordsize) while obj!=0: RemoteIP=pykd.ptrMWord(obj+RemoteIP_offset) LocalIP=pykd.ptrMWord(obj+LocalIP_offset) RemotePort=pykd.ptrWord(obj+RemotePort_offset) RemotePort=socket.htons(RemotePort) LocalPort=pykd.ptrWord(obj+LocalPort_offset) LocalPort=socket.htons(LocalPort) pid=pykd.ptrMWord(obj+pid_offset) print '%16s:%5d %16s:%5d TCP %d' % (socket.inet_ntoa(struct.pack('I', LocalIP)), LocalPort, socket.inet_ntoa(struct.pack('I', RemoteIP)), RemotePort, pid) obj=pykd.ptrPtr(obj+Next_offset) else: print 'no support' except Exception, err: print err