def xinfo(clx, addr, n=4, is_regs=False): value = None _addr = 0 rstr = '' rstr += '0x{{:0{}x}}'.format(process.size_t * 2).format( addr) #hex(addr) sym = info.symbol(addr) if sym: rstr += '({})'.format(sym) if is_regs is False: rstr += ': ' _rstr = rstr try: for i in range(n): value = info.getsize_t(addr) if i != 0 or is_regs: rstr += " -> " _rstr = rstr _addr = addr addr = value if is_regs: info.getsize_t(value) rstr += '0x{{:0{}x}}'.format(process.size_t * 2).format(value) if is_regs is False: _rstr = rstr sym = info.symbol(value) if sym: rstr += '({})'.format(sym) # _addr=addr # addr=value except: if is_regs is False: fmt = '("{}")' else: fmt = '"{}"' try: cstr = pykd.loadCStr(_addr) if (cstr and value > 0x1f and ((ord(cstr[0]) < 0x7f) and (cstr[:1:] == '' or ord(cstr[:1:]) < 0x7f) and (cstr[1:2:] == '' or ord(cstr[1:2:]) < 0x7f))): rstr = _rstr + fmt.format( cstr.replace("\n", "\\n")[:process.size_t * 2 - 2:]) elif is_regs: rstr = _rstr + '0x{{:0{}x}}'.format( process.size_t * 2).format(value) except: # try: # wstr=pykd.loadUnicodeString(_addr) # if wstr: # rstr=_rstr+fmt.format(wstr[:process.size_t*2-2:]) # elif is_regs: # rstr=_rstr+'0x{{:0{}x}}'.format(process.size_t*2).format(value) # except: if value is not None and is_regs: rstr += '0x{{:0{}x}}'.format(process.size_t * 2).format(value) # pass return rstr
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 dereference(self, pointer, target_id=0): """ Recursively dereference a pointer for display """ fmt = ('<' if self.get_byte_order() == 'little' else '>') + {2: 'H', 4: 'L', 8: 'Q'}[self.get_addr_size()] addr = pointer chain = [] # recursively dereference for i in range(0, self.max_deref): try: [ptr] = pykd.loadPtrs(addr, 1) if ptr in chain: break chain.append(('pointer', addr)) addr = ptr except: log.exception("Dereferencing pointer 0x{:X}".format(addr)) break # get some info for the last pointer # first try to resolve a symbol context for the address if len(chain): p, addr = chain[-1] output = pykd.findSymbol(addr) sym = True try: # if there's no symbol found, pykd returns a hex string of the address if int(output, 16) == addr: sym = False log.debug("no symbol context") except: pass if sym: chain.append(('symbol', output.strip())) else: log.debug("no symbol context") mem = pykd.loadBytes(addr, 2) if mem[0] < 127: if mem[1] == 0: a = [] for i in range(0, self.max_string, 2): mem = pykd.loadBytes(addr + i, 2) if mem == [0, 0]: break a.extend(mem) output = array.array('B', a).tostring().decode('UTF-16').encode('latin1') chain.append(('unicode', output)) else: output = pykd.loadCStr(addr) chain.append(('string', output)) log.debug("chain: {}".format(chain)) return chain
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 get_string(ptr): """ try to get string from a pointer """ max_length = 30 try: s = pykd.loadCStr(ptr) if not all(c in string.printable for c in s): return None if len(s) > max_length: return s[:max_length:] + "..." else: return s except: return None
def examine_data(value, step=4): try: out = pykd.loadQWords(value,1)[0] if step==8 else pykd.loadDWords(value,1)[0] if self.is_address(out): return out except: return value str = pykd.loadCStr(value) #str = pykd.loadWStr(value) if is_printable(str): if len(str)<step: return "%x \"%s\"" % (out, str) return str return out
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 main(): nt_module = pykd.module("nt") ObpTypeDirectoryObject_addr = int(nt_module.ObpTypeDirectoryObject) ObpTypeDirectoryObject_value = pykd.loadQWords(ObpTypeDirectoryObject_addr, 1)[0] dict_entry_list = pykd.loadQWords(ObpTypeDirectoryObject_value, 37) print 'TypeName PoolTag PoolType' for dict_entry in dict_entry_list: if dict_entry == 0: continue type_obj_addr = pykd.loadQWords(dict_entry + 8, 1)[0] name_str = pykd.loadUnicodeString(type_obj_addr + 0x10) key_str = pykd.loadCStr(type_obj_addr + 0xc0) pool_type = pykd.loadDWords(type_obj_addr + 0x40 + 0x24, 1)[0] if pool_type == 1: pool_type = 'PagedPool' elif pool_type == 0x200: pool_type = 'NonPagedPoolNx' print '%s\n%s\n%s\n' % (name_str, key_str, pool_type)
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 testAmbiguousFieldAccess(self): derivedFiledVal = pykd.loadCStr( pykd.typedVar("g_fieldSameNameStruct").m_field) self.assertEqual(derivedFiledVal, "toaster")
def testBigCStr(self): self.assertEqual( 0x2000, len(pykd.loadCStr(pykd.ptrPtr(target.module.bigCStr)))) self.assertEqual( 0x2000, len(pykd.loadWStr(pykd.ptrPtr(target.module.bigWStr))))
def testCStr(self): self.assertEqual('Hello', pykd.loadCStr(target.module.helloStr)) self.assertEqual(u'Hello', pykd.loadWStr(target.module.helloWStr))
) == pykd.CPUType.AMD64 else pykd.typeInfo("Int4B") mallocProto = pykd.defineFunction(PVoid, pykd.callingConvention.NearC) mallocProto.append("size", size_t) malloc = pykd.typedVar( mallocProto, pykd.getOffset("malloc")) #getOffset("malloc") may take a long time # get a type of a std::string stringClass = pykd.typeInfo(fullStringClassName) # allocate memory buffer = malloc(stringClass.size()) # get a typed access to memory. As you may see the instance of the std::string is not initialized stringVar = pykd.typedVar(stringClass, buffer) # set up parameters for a constructor call. param = pykd.stackAlloc(100) pykd.writeCStr(param, "hello") # call ctor for initalizing. std::string has several forms of constructor so we need to note prototype ctor = stringVar.method(stringClassName, "Void(__thiscall)(Char*)") ctor(param) #check result: print(pykd.loadCStr(stringVar.c_str())) pykd.stackFree(100)
import pykd # Parsing the ProcessList with pykd if __name__ == "__main__": if not pykd.isWindbgExt(): print("Script cannot be launched outside Windbg") quit(0) pActiveProcessList = pykd.module("nt").PsActiveProcessHead # pActiveProcessList = pykd.getOffset("nt!PsActiveProcessHead") -> slower than using module("nt")... processList = pykd.typedVarList(pActiveProcessList, "nt!_EPROCESS", "ActiveProcessLinks") for i, process in enumerate(processList): pykd.dprint("Process " + str(i) + ":") name = pykd.loadCStr(process.ImageFileName) print(name)
def is_cstr(clx, addr): try: pykd.loadCStr(addr) except: return False return True
def get_xul_version(): version = pykd.loadCStr(pykd.module('xul').offset('gToolkitVersion')) return version
print("Script cannot be launched outside Windbg") quit(0) if len(sys.argv) < 2: print("Expecting process name as argument") quit(0) targetProcessName = sys.argv[1] pykd.dprintln("Target: " + targetProcessName) processList = pykd.typedVarList( pykd.module("nt").PsActiveProcessHead, "nt!_EPROCESS", "ActiveProcessLinks") for i, process in enumerate(processList): if pykd.loadCStr(process.ImageFileName) == targetProcessName: targetProcessList = pykd.module("nt").typedVar( "_LIST_ENTRY", process.ActiveProcessLinks) print("ActiveProcessLinks: 0x%08x" % process.ActiveProcessLinks) print(targetProcessList) #prevFlink = module("nt").typedVar("_LIST_ENTRY",targetProcessList.Blink) #nextBlink = module("nt").typedVar("_LIST_ENTRY",targetProcessList.Flink) print("prevFlink: 0x%08x" % pykd.ptrQWord(targetProcessList.Blink)) print("nextBlink: 0x%08x" % pykd.ptrQWord(targetProcessList.Flink + 8)) targetProcessBlink = targetProcessList.Blink pykd.writeQWords(targetProcessList.Blink, [targetProcessList.Flink]) pykd.writeQWords(targetProcessList.Flink, [targetProcessBlink]) pykd.writeQWords(process.ActiveProcessLinks,