def main(pepath): # Extract debug infos from PE. guid, pdb_filename = get_external_codeview(pepath) print("PE debug infos : %s, %s" % (pdb_filename, guid)) # Extract corresponding PDB. pdbpath = os.path.join(os.path.dirname(pepath), pdb_filename) p = pdbparse.parse(pdbpath, fast_load=True) pdb = p.streams[pdbparse.PDB_STREAM_PDB] pdb.load() guidstr = ( u'%08x%04x%04x%s%x' % (pdb.GUID.Data1, pdb.GUID.Data2, pdb.GUID.Data3, binascii.hexlify(pdb.GUID.Data4).decode('ascii'), pdb.Age)).upper() print("PDB Guid : %s" % (guidstr)) if guid != guidstr: print(u'pdb not for this exe') sys.exit(-1) else: dbi = p.streams[pdbparse.PDB_STREAM_DBI] dbi.load() for (i, fns) in enumerate(dbi.modules): module_name = dbi.DBIExHeaders[i].objName.decode('ascii') print("[%d] DBI Module : %s" % (i, module_name)) for fn in fns: print(u'\t%s' % fn) print(u'-')
def read_symbols(filename, base_address=0): pdb = pdbparse.parse(filename) try: sects = pdb.STREAM_SECT_HDR_ORIG.sections omap = pdb.STREAM_OMAP_FROM_SRC except AttributeError as e: # In this case there is no OMAP, so we use the given section # headers and use the identity function for omap.remap print("NO OMAP!") sects = pdb.STREAM_SECT_HDR.sections omap = DummyOmap() gsyms = pdb.STREAM_GSYM for sym in gsyms.globals: try: off = sym.offset virt_base = sects[sym.segment - 1].VirtualAddress nm = cstring(sects[sym.segment - 1].Name) yield (sym.name, base_address + omap.remap(off + virt_base), sym.symtype, nm) except IndexError as e: pass # print ("Skipping %s, segment %d does not exist" % (sym.name,sym.segment-1), file=sys.stderr) except AttributeError as e: pass
def main(): option_list = [ make_option('-b', '--bin', dest = 'bin', default = None, help = 'DmaBackdoorHv_x64.efi binary file path'), make_option('-p', '--pdb', dest = 'pdb', default = None, help = 'DmaBackdoorHv_x64.pdb debug symbols file path'), make_option('-o', '--output', dest = 'output', default = None, help = 'file path to save extracted backdoor code') ] parser = OptionParser(option_list = option_list) options, args = parser.parse_args() if options.bin is None or options.pdb is None or options.output is None: print('Insufficient arguments, try --help') return -1 print('[+] Loading debug symbols from %s' % options.pdb) # load debug symbols file pdb = pdbparse.parse(options.pdb) # obtain needed symbols bd_start = symbol_offset(pdb, BACKDOOR_START) bd_end = symbol_offset(pdb, BACKDOOR_END) if bd_start is None: print('ERROR: Symbol %s() is not found' % BACKDOOR_START) return -1 if bd_end is None: print('ERROR: Symbol %s() is not found' % BACKDOOR_END) return -1 assert bd_end > bd_start print('[+] %s() symbol offset is 0x%x' % (BACKDOOR_START, bd_start)) print('[+] %s() symbol offset is 0x%x' % (BACKDOOR_END, bd_end)) with open(options.bin, 'rb') as fd: # read backdoor body from the binary fd.seek(bd_start) data = fd.read(bd_end - bd_start) with open(options.output, 'wb') as fd: # write backdoor body to the output file fd.write(data) print('[+] %d bytes of backdoor body written into the %s' % (len(data), options.output)) return 0
def main(pepath): # Extract debug infos from PE. guid, pdb_filename = get_external_codeview(pepath) print("PE debug infos : %s, %s" % (pdb_filename, guid)) # Extract corresponding PDB. pdbpath = os.path.join(os.path.dirname(pepath), pdb_filename) p = pdbparse.parse(pdbpath, fast_load = True) pdb = p.streams[pdbparse.PDB_STREAM_PDB] pdb.load() guidstr = (u'%08x%04x%04x%s%x' % (pdb.GUID.Data1, pdb.GUID.Data2, pdb.GUID.Data3, binascii.hexlify( pdb.GUID.Data4).decode('ascii'), pdb.Age)).upper() print("PDB Guid : %s" % (guidstr)) if guid != guidstr: print(u'pdb not for this exe') sys.exit(-1) else: dbi = p.streams[pdbparse.PDB_STREAM_DBI] dbi.load() for (i, fns) in enumerate(dbi.modules): module_name = dbi.DBIExHeaders[i].objName.decode('ascii') print("[%d] DBI Module : %s" % (i, module_name)) for fn in fns: print(u'\t%s' % fn) print(u'-')
def _pdb_hash(filename): pdb = pdbparse.parse(filename, fast_load=True) pdb.STREAM_PDB.load() guid = pdb.STREAM_PDB.GUID guid_str = "%.8X%.4X%.4X%s" % (guid.Data1, guid.Data2, guid.Data3, guid.Data4.encode("hex").upper()) return "%s%s" % (guid_str, pdb.STREAM_PDB.Age)
def getAllOffsets(filesLocation): allOffsets32 = [] allOffsets64 = [] for ntos in glob(filesLocation + os.sep + "ntoskrnl*.exe"): offsets = Offsets(ntos) # 1. Get Ntos version versionInfo = win32api.GetFileVersionInfo(ntos, "\\") offsets.version = [ versionInfo["FileVersionMS"] >> 16, versionInfo["FileVersionMS"] & 0xFF, versionInfo["FileVersionLS"] >> 16, versionInfo["FileVersionLS"] & 0xFF, ] print "Parsing file: %s of version %s" % (ntos, repr(offsets.version)) # 2. Get PDB pdb_file = checkout_pdb(ntos) if None == pdb_file: print "Failed to get PDB for %s" % ntos continue pdb = pdbparse.parse(pdb_file) types = pdb.streams[2].types.values() # 3. Find intresting offsets try: prcbDataOffset = getOffset(types, "_KPCR", "PrcbData") except: if "x86" in ntos: prcbDataOffset = 0x120 elif "x64" in ntos: prcbDataOffset = 0x180 else: raise Exception("WTF") offsets.kthread = prcbDataOffset + getOffset(types, "_KPRCB", "CurrentThread") if "x86" in ntos: offsets.ktrap_frame_size = 0x8C # 0x29c - I can't recall where this 0x29c came from, but it's wrong elif "x64" in ntos: offsets.ktrap_frame_size = getStructSize(types, "_KTRAP_FRAME") else: raise Exception("WTF") offsets.eflags = getOffset(types, "_KTRAP_FRAME", "EFlags") offsets.ThreadListEntry = getOffset(types, "_ETHREAD", "ThreadListEntry") offsets.Teb = getOffset(types, "_KTHREAD", "Teb") offsets.CrossThreadFlags = getOffset(types, "_ETHREAD", "CrossThreadFlags") offsets.InitialStack = getOffset(types, "_KTHREAD", "InitialStack") offsets.TrapFrame = getOffset(types, "_KTHREAD", "TrapFrame") offsets.Cid = getOffset(types, "_ETHREAD", "Cid") offsets.PreviousMode = getOffset(types, "_KTHREAD", "PreviousMode") offsets.DirectoryTableBase = getOffset(types, "_KPROCESS", "DirectoryTableBase") offsets.ThreadListHead = getOffset(types, "_EPROCESS", "ThreadListHead") # 4. Generate code if "x86" in ntos: allOffsets32.append(offsets) elif "x64" in ntos: allOffsets64.append(offsets) else: raise Exception("WTF") return (allOffsets32, allOffsets64)
def get_functions(pdb_file): """Get the offset for the functions we are interested in""" methods = {'ssl3_new': 0, 'ssl3_free': 0, 'ssl3_connect': 0, 'ssl3_read_app_data': 0, 'ssl3_write_app_data': 0} try: # Do this the hard way to avoid having to load # the types stream in mammoth PDB files pdb = pdbparse.parse(pdb_file, fast_load=True) pdb.STREAM_DBI.load() pdb._update_names() pdb.STREAM_GSYM = pdb.STREAM_GSYM.reload() if pdb.STREAM_GSYM.size: pdb.STREAM_GSYM.load() pdb.STREAM_SECT_HDR = pdb.STREAM_SECT_HDR.reload() pdb.STREAM_SECT_HDR.load() # These are the dicey ones pdb.STREAM_OMAP_FROM_SRC = pdb.STREAM_OMAP_FROM_SRC.reload() pdb.STREAM_OMAP_FROM_SRC.load() pdb.STREAM_SECT_HDR_ORIG = pdb.STREAM_SECT_HDR_ORIG.reload() pdb.STREAM_SECT_HDR_ORIG.load() except AttributeError: pass try: sects = pdb.STREAM_SECT_HDR_ORIG.sections omap = pdb.STREAM_OMAP_FROM_SRC except AttributeError: sects = pdb.STREAM_SECT_HDR.sections omap = DummyOmap() gsyms = pdb.STREAM_GSYM if not hasattr(gsyms, 'globals'): gsyms.globals = [] #names = [] for sym in gsyms.globals: try: name = sym.name.lstrip('_') #names.append(name) if name in methods: off = sym.offset virt_base = sects[sym.segment-1].VirtualAddress addr = omap.remap(off+virt_base) if methods[name] == 0: methods[name] = addr else: methods[name] = -1 except IndexError: pass except AttributeError: pass #with open('names.txt', 'wb') as f_out: # for name in names: # f_out.write(name + "\n") return methods
def main(pdbfilepath): pdb = pdbparse.parse(pdbfilepath, fast_load = True) if len(sys.argv) > 2: streams = [pdb.streams[int(i)] for i in sys.argv[2:]] else: streams = pdb.streams for stream in streams: ofname = basename(pdb.fp.name) + ('.%03d' % stream.index) with open(ofname, 'wb') as f: f.write(stream.data)
def get_pdb_hash(pdbfilepath): ''' 获取 PDB 文件的哈希值 ''' if not is_file_exists(pdbfilepath): return None p = pdbparse.parse(pdbfilepath, fast_load = True) pdb = p.streams[pdbparse.PDB_STREAM_PDB] pdb.load() guidstr = (u'%08x%04x%04x%s%x' % (pdb.GUID.Data1, pdb.GUID.Data2, pdb.GUID.Data3, binascii.hexlify( pdb.GUID.Data4).decode('ascii'), pdb.Age)).upper() return guidstr
def main(pdbfilepath): pdb = pdbparse.parse(pdbfilepath, fast_load=True) if len(sys.argv) > 2: streams = [pdb.streams[int(i)] for i in sys.argv[2:]] else: streams = pdb.streams print(pdbfilepath) for stream in streams: if stream.index == 1: raw = stream.data[12:28] print(hex2guid(raw)) if stream.index == 1: break
def dump_types(pdbFile, filename): pdb = pdbparse.parse(pdbFile) #call the parse function in __init__ of the pdbparse library structs = [ s for s in pdb.streams[2].types.values() if (s.leaf_type == "LF_STRUCTURE" or s.leaf_type == "LF_UNION") and not s.prop.fwdref ] FILE=open(filename, "w"); #open filename in write mode FILE.write(pdbFile[:-4] +' (pdb file)' + "\n") # put the OS version at the top of the file! for s in structs: FILE.write(s.name + "," + s.name + "," + ("%#x" % s.size) + "," + "struct\n") for f in s.fieldlist.substructs: tpname =get_tpname(f.index) FILE.write(s.name + "," + f.name + "," + str(hex(f.offset)) + "," + "%s" % (tpname) + "\n") FILE.close()
def update(self, file_path, binary, base_addr): self._base_addr = base_addr if not file_path: return data = "" with open(file_path, "rb") as fin: data = fin.read() if not data[:15] == b"Microsoft C/C++" or pdbparse is None: return try: pdb = pdbparse.parse(file_path) self._parseSymbols(pdb) except Exception as exc: LOGGER.error("Failed parsing \"%s\" with exception type: %s" % (file_path, type(exc)))
def dump_types(pdbFile, filename): print pdbFile+"\t"+filename #pdb = pdbparse.parse(filename) pdb = pdbparse.parse(pdbFile) #call the parse function in __init__ of the pdbparse library structs = [ s for s in pdb.streams[2].types.values() if (s.leaf_type == "LF_STRUCTURE" or s.leaf_type == "LF_UNION") and not s.prop.fwdref ] FILE=open(filename, "w"); #open filename in write mode FILE.write(pdbFile[:-4] +' (pdb file)' + "\n") # put the OS version at the top of the file! for s in structs: FILE.write(s.name + "," + s.name + "," + ("%#x" % s.size) + "," + "struct\n") for f in s.fieldlist.substructs: tpname =get_tpname(f.index) FILE.write(s.name + "," + f.name + "," + str(hex(f.offset)) + "," + "%s" % (tpname) + "\n") FILE.close()
def update(self, binary_info): self._base_addr = binary_info.base_addr if not binary_info.file_path: return data = "" with open(binary_info.file_path, "rb") as fin: data = fin.read(16) self._parseOep(data) if data[:15] != b"Microsoft C/C++" or pdbparse is None: return try: pdb = pdbparse.parse(binary_info.file_path) self._parseSymbols(pdb) except Exception as exc: LOGGER.error("Failed parsing \"%s\" with exception type: %s", binary_info.file_path, type(exc))
def _hash_info(self, pdbfile, imgbase=0): def _sym_name(sym): try: return sym.name except AttributeError: return "" pdb_file_name = self._get_pdb_filename() self.logverbose("Using PDB file: {0}".format(pdb_file_name)) pdb = pdbparse.parse(self._get_pdb_filename()) try: sects = pdb.STREAM_SECT_HDR_ORIG.sections omap = pdb.STREAM_OMAP_FROM_SRC except AttributeError as err: # In this case there is no OMAP, so we use the given section # headers and use the identity function for omap.remap sects = pdb.STREAM_SECT_HDR.sections omap = DummyOmap() g_HashTable_p = 0 g_HashTableSize_p = 0 g_CacheHeap_p = 0 for sym in pdb.STREAM_GSYM.globals: if _sym_name(sym).endswith("g_HashTable"): off = sym.offset virt_base = sects[sym.segment-1].VirtualAddress g_HashTable_p = imgbase+omap.remap(off+virt_base) if _sym_name(sym).endswith("g_HashTableSize"): off = sym.offset virt_base = sects[sym.segment-1].VirtualAddress g_HashTableSize_p = imgbase+omap.remap(off+virt_base) if _sym_name(sym).endswith("g_CacheHeap"): off = sym.offset virt_base = sects[sym.segment-1].VirtualAddress g_CacheHeap_p = imgbase+omap.remap(off+virt_base) return g_HashTable_p, g_HashTableSize_p, g_CacheHeap_p
def formatStructs(pdbfile, fields): """Format the requested structures from a given .pdb file. @param pdbfile: name of .pdb file @param fields: requested fields (as struct.field strings) @return: string representation of the desired structures """ pdb = pdbparse.parse(pdbfile) structs = collections.defaultdict(list) for fieldspec in fields: struct, dot, field = fieldspec.strip().partition('.') if field == "": if struct not in structs: structs[struct] = list() else: structs[struct].append(field) pdbStructs = pdb.STREAM_TPI.structures structSpecs = [ formatStruct(pdbStructs[structName], structFields) for structName, structFields in structs.items() ] return "\n\n".join(structSpecs)
def _get_srvtrans_symbol(self, pdbfile, imgbase): pdb = pdbparse.parse(pdbfile, fast_load=True) pdb.STREAM_DBI.load() pdb._update_names() pdb.STREAM_GSYM = pdb.STREAM_GSYM.reload() pdb.STREAM_GSYM.load() pdb.STREAM_OMAP_FROM_SRC = pdb.STREAM_OMAP_FROM_SRC.reload() pdb.STREAM_OMAP_FROM_SRC.load() pdb.STREAM_SECT_HDR_ORIG = pdb.STREAM_SECT_HDR_ORIG.reload() pdb.STREAM_SECT_HDR_ORIG.load() sects = pdb.STREAM_SECT_HDR_ORIG.sections omap = pdb.STREAM_OMAP_FROM_SRC gsyms = pdb.STREAM_GSYM srv_trans_pointer = "SrvTransaction2DispatchTable" for sym in gsyms.globals: if srv_trans_pointer.lower() in sym.name.lower(): virt_base = sects[sym.segment - 1].VirtualAddress sym_rva = omap.remap(sym.offset + virt_base) return sym_rva return ''
def main(filename, base_address): pdb = pdbparse.parse(filename) imgbase = int(base_address, 0) try: sects = pdb.STREAM_SECT_HDR_ORIG.sections omap = pdb.STREAM_OMAP_FROM_SRC except AttributeError as e: # In this case there is no OMAP, so we use the given section # headers and use the identity function for omap.remap sects = pdb.STREAM_SECT_HDR.sections omap = DummyOmap() gsyms = pdb.STREAM_GSYM for sym in gsyms.globals: try: off = sym.offset virt_base = sects[sym.segment - 1].VirtualAddress nm = cstring(sects[sym.segment - 1].Name) print("%s,%#x,%d,%s" % (sym.name, imgbase + omap.remap(off + virt_base), sym.symtype, nm)) except IndexError as e: print("Skipping %s, segment %d does not exist" % (sym.name, sym.segment - 1), file = sys.stderr) except AttributeError as e: pass
def memb_str(memb): off = memb.offset tpname = get_tpname(memb.index) return "%#x: %s (%s)" % (off, memb.name, tpname) def struct_pretty_str(lf): return (lf.name + (", %#x bytes\n " % lf.size) + "\n ".join(memb_str(s) for s in lf.fieldlist.substructs)) def enum_pretty_str(enum): enumerated = [] utypename = get_tpname(enum.utype) for e in enum.fieldlist.substructs: e_val = -1 if e.enum_value == '\xff' else e.enum_value enumerated.append("%s = %d" % (e.name, e_val)) return (enum.name + (" (%s)\n " % utypename) + "\n ".join(enumerated)) pdb = pdbparse.parse(sys.argv[1]) structs = [ s for s in pdb.streams[2].types.values() if (s.leaf_type == "LF_STRUCTURE" or s.leaf_type == "LF_UNION") and not s.prop.fwdref ] enums = [ e for e in pdb.streams[2].types.values() if e.leaf_type == "LF_ENUM" and not e.prop.fwdref ] print "******* Structures *******" for s in structs: print struct_pretty_str(s) print "******* Enumerations *******" for e in enums: print enum_pretty_str(e)
import os import sys import pdbparse from pdbparse.peinfo import * from binascii import hexlify if __name__ == u"__main__": pepath = sys.argv[1] pdbinfo = get_external_codeview(pepath) pdbpath = os.path.join(os.path.dirname(pepath), pdbinfo[1]) print(pdbinfo[1]) print(pdbinfo[0]) p = pdbparse.parse(pdbpath, fast_load=True) pdb = p.streams[pdbparse.PDB_STREAM_PDB] pdb.load() guidstr = ( u"%08x%04x%04x%s%x" % (pdb.GUID.Data1, pdb.GUID.Data2, pdb.GUID.Data3, pdb.GUID.Data4.encode("hex"), pdb.Age) ).upper() print(guidstr) if pdbinfo[0] != guidstr: print(u"pdb not for this exe") else: dbi = p.streams[pdbparse.PDB_STREAM_DBI] dbi.load() i = 0
class DummyOmap(object): def remap(self, addr): return addr def cstring(str): return str.split('\0')[0] parser = OptionParser() (opts, args) = parser.parse_args() if len(args) != 2: parser.error("Need filename and base address") pdb = pdbparse.parse(args[0]) imgbase = int(args[1], 0) try: sects = pdb.STREAM_SECT_HDR_ORIG.sections omap = pdb.STREAM_OMAP_FROM_SRC except AttributeError as e: # In this case there is no OMAP, so we use the given section # headers and use the identity function for omap.remap sects = pdb.STREAM_SECT_HDR.sections omap = DummyOmap() gsyms = pdb.STREAM_GSYM for sym in gsyms.globals: try: off = sym.offset
def main(): import platform genfile = 'csrss_offsets.h' me = os.path.basename(__file__) f = open(genfile, 'w') f.write('// This file was generated by a tool. Do not edit it manually!\n') f.write('// To regenerate it, please run ' + me + '\n\n') if platform.machine().endswith('64'): f.write( '// This header is generated to target 64-bit Windows including SysWoW64\n\n' ) else: f.write( '// This header is generated to target 32-bit Windows ONLY\n\n') f.write('#pragma once\n\n') if platform.machine().endswith('64'): f.write('#ifdef _WIN64\n\n') ntdll_pdb = handle_pe("C:\\Windows\\system32\\ntdll.dll") sys.stderr.write("Loading symbols for %s...\n" % ntdll_pdb) pdb = pdbparse.parse(ntdll_pdb, fast_load=True) addrs = symbol_addresses(pdb) rva_CsrServerApiRoutine_x64 = addrs['CsrServerApiRoutine'] rva_RtlpEnvironLookupTable_x64 = addrs['RtlpEnvironLookupTable'] f.write( '// RVA of CsrServerApiRoutine up to RtlpEnvironLookupTable in System32\\ntdll.exe\n' ) f.write('#define csrDataRva_x64 ' + hex(rva_CsrServerApiRoutine_x64) + '\n') f.write('// RtlpEnvironLookupTable = ' + hex(rva_RtlpEnvironLookupTable_x64) + '\n') f.write('#define csrDataSize_x64 ' + hex(rva_RtlpEnvironLookupTable_x64 - rva_CsrServerApiRoutine_x64) + '\n') f.write('\n') f.write('#else\n\n') ntdll_pdb = handle_pe("C:\\Windows\\SysWOW64\\ntdll.dll") sys.stderr.write("Loading symbols for %s...\n" % ntdll_pdb) pdb = pdbparse.parse(ntdll_pdb, fast_load=True) addrs = symbol_addresses(pdb) rva_CsrServerApiRoutine = addrs['_CsrServerApiRoutine'] rva_RtlpEnvironLookupTable = addrs['_RtlpEnvironLookupTable'] f.write('// WoW64 ntdll.dll\n') f.write( '// RVA of _CsrServerApiRoutine up to _RtlpEnvironLookupTable in SysWOW64\\ntdll.dll\n' ) f.write('#define csrDataRva_x86 ' + hex(rva_CsrServerApiRoutine) + '\n') f.write('// RtlpEnvironLookupTable = ' + hex(rva_RtlpEnvironLookupTable) + '\n') f.write('#define csrDataSize_x86 ' + hex(rva_RtlpEnvironLookupTable - rva_CsrServerApiRoutine) + '\n') f.write('\n') f.write( '// RVA of CsrServerApiRoutine up to RtlpEnvironLookupTable in System32\\ntdll.exe\n' ) f.write('#define csrDataRva_wow64 ' + hex(rva_CsrServerApiRoutine_x64) + '\n') f.write('// RtlpEnvironLookupTable = ' + hex(rva_RtlpEnvironLookupTable_x64) + '\n') f.write('#define csrDataSize_wow64 ' + hex(rva_RtlpEnvironLookupTable_x64 - rva_CsrServerApiRoutine_x64) + '\n') f.write('\n') f.write('#endif\n') else: f.write('#ifdef WIN64\n\n') f.write('#error 64-bit csrss offsets missing; please consult ' + me + '\n') f.write('#define csrDataRva_x64 0\n') f.write('#define csrDataSize_x64 0\n') f.write('#define csrDataRva_wow64 0\n') f.write('#define csrDataSize_wow64 0\n') f.write('\n') f.write('#else\n\n') ntdll_pdb = handle_pe("C:\\Windows\\system32\\ntdll.dll") sys.stderr.write("Loading symbols for %s...\n" % ntdll_pdb) pdb = pdbparse.parse(ntdll_pdb, fast_load=True) addrs = symbol_addresses(pdb) rva_CsrServerApiRoutine = addrs['CsrServerApiRoutine'] rva_RtlpEnvironLookupTable = addrs['RtlpEnvironLookupTable'] f.write( '// RVA of CsrServerApiRoutine up to RtlpEnvironLookupTable in System32\\ntdll.exe\n' ) f.write('#define csrDataRva_x86 ' + hex(rva_CsrServerApiRoutine) + '\n') f.write('// RtlpEnvironLookupTable = ' + hex(rva_RtlpEnvironLookupTable) + '\n') f.write('#define csrDataSize_x86 ' + hex(rva_RtlpEnvironLookupTable - rva_CsrServerApiRoutine) + '\n') f.write('\n') f.write('// WoW64 not supported on native 32-bit platform\n') f.write('#define csrDataRva_wow64 0\n') f.write('#define csrDataSize_wow64 0\n') f.write('\n') f.write('#endif\n') f.close() print 'Successfully generated ' + genfile
def make_pdb_profile(filepath): filepath = filepath + ".pdb" pdb = pdbparse.parse(filepath) try: sects = pdb.STREAM_SECT_HDR_ORIG.sections omap = pdb.STREAM_OMAP_FROM_SRC except AttributeError as e: # In this case there is no OMAP, so we use the given section # headers and use the identity function for omap.remap sects = pdb.STREAM_SECT_HDR.sections omap = DummyOmap() gsyms = pdb.STREAM_GSYM profile = {"$FUNCTIONS": {}, "$CONSTANTS": {}, "$STRUCTS": {}} struct_specs = { structName: process_struct(pdb.STREAM_TPI.structures[structName]) for structName in pdb.STREAM_TPI.structures.keys() } for structName, structFields in struct_specs.items(): profile["$STRUCTS"][structName] = structFields for sym in gsyms.globals: try: off = sym.offset sym_name = sym.name virt_base = sects[sym.segment - 1].VirtualAddress mapped = omap.remap(off + virt_base) is_function = (sym.symtype & 2) == 2 except IndexError as e: # skip symbol because segment was not found continue except AttributeError as e: # missing offset in symbol? continue if sym_name.startswith("?"): sym_name = undname(sym_name) if is_function: profile["$FUNCTIONS"][sym_name] = mapped else: profile["$CONSTANTS"][sym_name] = mapped guid = pdb.STREAM_PDB.GUID guid_str = "%.8X%.4X%.4X%s" % (guid.Data1, guid.Data2, guid.Data3, guid.Data4.hex().upper()) symstore_hash = "%s%s" % (guid_str, pdb.STREAM_PDB.Age) base_fn = os.path.splitext(os.path.basename(filepath))[0] profile["$METADATA"] = { "GUID_AGE": symstore_hash, "PDBFile": os.path.basename(filepath), "ProfileClass": base_fn[0].upper() + base_fn[1:].lower(), "Timestamp": pdb.STREAM_PDB.TimeDateStamp.replace( tzinfo=None).strftime("%Y-%m-%d %H:%M:%SZ"), "Type": "Profile", "Version": pdb.STREAM_PDB.Version } print(json.dumps(profile, indent=4, sort_keys=True))
from pdbparse.omap import Omap class DummyOmap(object): def remap(self, addr): return addr def cstring(str): return str.split('\0')[0] parser = OptionParser() (opts, args) = parser.parse_args() if len(args) != 2: parser.error("Need filename and base address") pdb = pdbparse.parse(args[0]) imgbase = int(args[1], 0) try: sects = pdb.STREAM_SECT_HDR_ORIG.sections omap = pdb.STREAM_OMAP_FROM_SRC except AttributeError as e: # In this case there is no OMAP, so we use the given section # headers and use the identity function for omap.remap sects = pdb.STREAM_SECT_HDR.sections omap = DummyOmap() gsyms = pdb.STREAM_GSYM for sym in gsyms.globals: try:
def __init__(self, mods): self.addrs = {} self._cache = {} not_found = [] for pdbname,base in mods: pdbbase = ".".join(os.path.basename(pdbname).split('.')[:-1]) if not os.path.exists(pdbname): print "WARN: %s not found" % pdbname not_found.append( (base, pdbbase) ) continue #print "Loading symbols for %s..." % pdbbase try: # Do this the hard way to avoid having to load # the types stream in mammoth PDB files pdb = pdbparse.parse(pdbname, fast_load=True) pdb.STREAM_DBI.load() pdb._update_names() pdb.STREAM_GSYM = pdb.STREAM_GSYM.reload() if pdb.STREAM_GSYM.size: pdb.STREAM_GSYM.load() pdb.STREAM_SECT_HDR = pdb.STREAM_SECT_HDR.reload() pdb.STREAM_SECT_HDR.load() # These are the dicey ones pdb.STREAM_OMAP_FROM_SRC = pdb.STREAM_OMAP_FROM_SRC.reload() pdb.STREAM_OMAP_FROM_SRC.load() pdb.STREAM_SECT_HDR_ORIG = pdb.STREAM_SECT_HDR_ORIG.reload() pdb.STREAM_SECT_HDR_ORIG.load() except AttributeError, e: pass #except Exception, e: # print "WARN: error %s parsing %s, skipping" % (e,pdbbase) # not_found.append( (base, pdbbase) ) # continue try: sects = pdb.STREAM_SECT_HDR_ORIG.sections omap = pdb.STREAM_OMAP_FROM_SRC except AttributeError as e: # In this case there is no OMAP, so we use the given section # headers and use the identity function for omap.remap sects = pdb.STREAM_SECT_HDR.sections omap = DummyOmap() gsyms = pdb.STREAM_GSYM if not hasattr(gsyms, 'globals'): gsyms.globals = [] last_sect = max(sects, key=attrgetter('VirtualAddress')) limit = base + last_sect.VirtualAddress + last_sect.Misc.VirtualSize self.addrs[base,limit] = {} self.addrs[base,limit]['name'] = pdbbase self.addrs[base,limit]['addrs'] = [] for sym in gsyms.globals: if not hasattr(sym, 'offset'): continue off = sym.offset try: virt_base = sects[sym.segment-1].VirtualAddress except IndexError: continue mapped = omap.remap(off+virt_base) + base self.addrs[base,limit]['addrs'].append((mapped,sym.name)) self.addrs[base,limit]['addrs'].sort(key=itemgetter(0))
def make_pdb_profile(filepath, dll_origin_path=None, dll_path=None, dll_symstore_hash=None): pdb = pdbparse.parse(filepath) try: sects = pdb.STREAM_SECT_HDR_ORIG.sections omap = pdb.STREAM_OMAP_FROM_SRC except AttributeError: # In this case there is no OMAP, so we use the given section # headers and use the identity function for omap.remap sects = pdb.STREAM_SECT_HDR.sections omap = DummyOmap() gsyms = pdb.STREAM_GSYM profile = {"$FUNCTIONS": {}, "$CONSTANTS": {}, "$STRUCTS": {}} struct_specs = { name: info for name, info in traverse_tree(pdb.STREAM_TPI.structures.values()) } for structName, structFields in struct_specs.items(): if structFields != [0, {}]: profile["$STRUCTS"][structName] = structFields mapped_syms = {"$CONSTANTS": {}, "$FUNCTIONS": {}} for sym in gsyms.globals: try: off = sym.offset sym_name = sym.name virt_base = sects[sym.segment - 1].VirtualAddress mapped = omap.remap(off + virt_base) if (sym.symtype & 2) == 2: target_key = "$FUNCTIONS" else: target_key = "$CONSTANTS" except IndexError: # skip symbol because segment was not found continue except AttributeError: # missing offset in symbol? continue sym_name = Demangler().DemangleName(sym_name) if sym_name not in mapped_syms[target_key]: mapped_syms[target_key][sym_name] = list() mapped_syms[target_key][sym_name].append(mapped) for target_key, sym_dict in mapped_syms.items(): for sym_name, value_set in sym_dict.items(): ndx = 0 for mapped in sorted(value_set): if ndx == 0: next_sym_name = sym_name else: next_sym_name = "{}_{}".format(sym_name, ndx) ndx += 1 profile[target_key][next_sym_name] = mapped del mapped_syms pdb_symstore_hash = make_symstore_hash(pdb.STREAM_PDB) base_filename = os.path.splitext(os.path.basename(filepath))[0] profile["$METADATA"] = { "DLL_GUID_AGE": dll_symstore_hash, "GUID_AGE": pdb_symstore_hash, "PDBFile": os.path.basename(filepath), "ProfileClass": base_filename[0].upper() + base_filename[1:].lower(), "Timestamp": pdb.STREAM_PDB.TimeDateStamp.replace( tzinfo=None).strftime("%Y-%m-%d %H:%M:%SZ"), "Type": "Profile", "Version": pdb.STREAM_PDB.Version, } # Additional metadata requested by the ApiVectors developers profile["$EXTRAS"] = {} if dll_origin_path: profile["$EXTRAS"]["DLLPath"] = str(dll_origin_path) if dll_path: try: pe = pefile.PE(dll_path, fast_load=True) profile["$EXTRAS"]["ImageBase"] = hex(pe.OPTIONAL_HEADER.ImageBase) except AttributeError: # I think that DLLs have some sanity and the optional header is # always present. Ignore this error if it happens pass return json.dumps(profile, indent=4, sort_keys=True)
def __init__(self, filename: str): self._filename = filename logger.info("Parsing PDB...") self._pdb = pdbparse.parse(filename) self._seen_ctypes: Set[str] = set([])
def add_debug_symbols(self, db, addr_space, mod): def is_valid_debug_dir(debug_dir, image_base, addr_space): return debug_dir != None and debug_dir.AddressOfRawData != 0 and addr_space.is_valid_address(image_base + debug_dir.AddressOfRawData) and addr_space.is_valid_address(image_base + debug_dir.AddressOfRawData + debug_dir.SizeOfData - 1) mod_path = self.module_path(mod) mod_name = self.module_name(mod) module_id = self.module_id(db, mod) image_base = mod.DllBase debug_dir = mod.get_debug_directory() if not is_valid_debug_dir(debug_dir, image_base, addr_space): # No joy in this process space return if debug_dir.Type != 2: # IMAGE_DEBUG_TYPE_CODEVIEW return debug_data = addr_space.zread(image_base + debug_dir.AddressOfRawData, debug_dir.SizeOfData) if debug_data[:4] == 'RSDS': guid, filename = pdbparse.peinfo.get_rsds(debug_data) elif debug_data[:4] == 'NB10': guid, filename = pdbparse.peinfo.get_nb10(debug_data) else: debug.warning("'{0}' is an unknown CodeView section".format(debug_data[:4])) return if filename == '': return # We have valid CodeView debugging information, so try and download PDB file from a symbol server saved_mod_path = tempfile.gettempdir() + os.sep + guid if self.do_download(db, module_id, guid, filename): if not os.path.exists(saved_mod_path): os.makedirs(saved_mod_path) self.download_pdbfile(db, guid.upper(), module_id, filename, saved_mod_path) # At this point, and if all has gone well, known co-ords should be: mod; image_base; guid; filename pdbname = saved_mod_path + os.sep + filename if not os.path.exists(pdbname): shutil.rmtree(saved_mod_path) debug.warning("Symbols for module {0} (in {1}) not found".format(mod.BaseDllName, filename)) return try: # Do this the hard way to avoid having to load # the types stream in mammoth PDB files pdb = pdbparse.parse(pdbname, fast_load=True) pdb.STREAM_DBI.load() # As pdbparse doesn't add STREAM_FPO_STRINGS to parent, do it manually if pdb.STREAM_DBI.DBIDbgHeader.snNewFPO != -1: pdb.add_supported_stream("STREAM_FPO_STRINGS", pdb.STREAM_DBI.DBIDbgHeader.snNewFPO+1, pdbparse.PDBFPOStrings) except AttributeError: pass try: pdb._update_names() pdb.STREAM_GSYM = pdb.STREAM_GSYM.reload() pdb.STREAM_GSYM.load() pdb.STREAM_SECT_HDR = pdb.STREAM_SECT_HDR.reload() pdb.STREAM_SECT_HDR.load() # These are the dicey ones pdb.STREAM_OMAP_FROM_SRC = pdb.STREAM_OMAP_FROM_SRC.reload() pdb.STREAM_OMAP_FROM_SRC.load() pdb.STREAM_SECT_HDR_ORIG = pdb.STREAM_SECT_HDR_ORIG.reload() pdb.STREAM_SECT_HDR_ORIG.load() except AttributeError: pass try: # Ensure FPO streams are loaded pdb.STREAM_FPO = pdb.STREAM_FPO.reload() pdb.STREAM_FPO.load() pdb.STREAM_FPO_NEW = pdb.STREAM_FPO_NEW.reload() pdb.STREAM_FPO_NEW.load() pdb.STREAM_FPO_STRINGS = pdb.STREAM_FPO_STRINGS.reload() pdb.STREAM_FPO_STRINGS.load() pdb.STREAM_FPO_NEW.load2() # inject program strings except AttributeError: pass except construct.adapters.ConstError as err: # TODO: fix actual PDB parsing failure issue! debug.warning("Ignoring PDB parsing failure of {0}/{1}: {2}".format(guid.upper(), filename, err.message)) db.execute("""SELECT pdb.id FROM mod_pdb INNER JOIN pdb ON pdb_id=pdb.id WHERE module_id=? AND guid=? AND file=? """, (module_id, str(guid.upper()).rstrip('\0'), str(filename).rstrip('\0'))) row = db.fetchone() assert(row != None) pdb_id = row[0] self.process_gsyms(db, pdb, pdb_id, module_id, guid, filename) try: self.process_fpo(db, pdb, pdb_id, module_id, guid, filename) except AttributeError: pass try: self.process_fpov2(db, pdb, pdb_id, module_id, guid, filename) except AttributeError: pass shutil.rmtree(saved_mod_path) debug.info("Removed directory {0} and its contents".format(saved_mod_path)) self._sym_db_conn.commit()
tpname = '<unk. type>' if off is not None: return "%#x: %s (%s)" % (off, memb.name, tpname) else: return "<unk. offset>: %s (%s)" % (getattr(memb, 'name', '<unnamed>'), tpname) def struct_pretty_str(lf): return (lf.name + (", %#x bytes\n " % lf.size) + "\n ".join(memb_str(s) for s in lf.fieldlist.substructs)) def enum_pretty_str(enum): enumerated = [] utypename = get_tpname(enum.utype) for e in enum.fieldlist.substructs: e_val = -1 if e.enum_value == '\xff' else e.enum_value enumerated.append("%s = %d" % (e.name, e_val)) return (enum.name + (" (%s)\n " % utypename) + "\n ".join(enumerated)) pdb = pdbparse.parse(sys.argv[1], load_type_info=True) structs = [ s for s in pdb.streams[2].types.values() if (s.leaf_type == "LF_STRUCTURE" or s.leaf_type == "LF_UNION") and not s.prop.fwdref ] enums = [ e for e in pdb.streams[2].types.values() if e.leaf_type == "LF_ENUM" and not e.prop.fwdref ] print "******* Structures *******" for s in structs: print struct_pretty_str(s) print "******* Enumerations *******" for e in enums: print enum_pretty_str(e)
addrs = [ SyscallTable(0, 0, 0), SyscallTable(0, 0, 0), ] values = [ SyscallTable(0, 0, 0), SyscallTable(0, 0, 0), ] if len(sys.argv) != 3: print("usage: %s <exe> <pdb>" % sys.argv[0], file = sys.stderr) sys.exit(1) pe = PE(sys.argv[1]) pdb = pdbparse.parse(sys.argv[2]) sects = pdb.STREAM_SECT_HDR_ORIG.sections gsyms = pdb.STREAM_GSYM omap = pdb.STREAM_OMAP_FROM_SRC omap_rev = pdb.STREAM_OMAP_TO_SRC for tbl, addr in zip(names, addrs): for sym in gsyms.globals: if not hasattr(sym, 'offset'): continue try: virt_base = sects[sym.segment - 1].VirtualAddress except IndexError: continue off = sym.offset if tbl.ServiceTable in sym.name:
sys.exit(1) mods = [ (sys.argv[i],sys.argv[i+1],int(sys.argv[i+2])) for i in range(1,len(sys.argv)-2,3) ] addrs = {} # Set this to the first PDB section that contains section headers # Common bases: # ntdll: 8 # ntoskrnl: 10 # BASE = for pdbname,basestr,BASE in mods: pdbbase = os.path.basename(pdbname).split('.')[0] print "Loading symbols for %s..." % pdbbase pdb = pdbparse.parse(pdbname) base = int(basestr,0) sects = Sections.parse(pdb.streams[BASE].data) orig_sects = Sections.parse(pdb.streams[BASE+3].data) gsyms = pdb.streams[pdb.streams[3].gsym_file] omap = Omap(pdb.streams[BASE+2].data) omap_rev = Omap(pdb.streams[BASE+1].data) last_sect = max(sects, key=attrgetter('VirtualAddress')) limit = base + last_sect.VirtualAddress + last_sect.Misc.VirtualSize addrs[base,limit] = {} addrs[base,limit]['name'] = pdbbase addrs[base,limit]['addrs'] = [] for sym in gsyms.globals: off = sym.offset
def make_pdb_profile(filepath): pdb = pdbparse.parse(filepath) try: sects = pdb.STREAM_SECT_HDR_ORIG.sections omap = pdb.STREAM_OMAP_FROM_SRC except AttributeError: # In this case there is no OMAP, so we use the given section # headers and use the identity function for omap.remap sects = pdb.STREAM_SECT_HDR.sections omap = DummyOmap() gsyms = pdb.STREAM_GSYM profile = {"$FUNCTIONS": {}, "$CONSTANTS": {}, "$STRUCTS": {}} struct_specs = { name: info for name, info in traverse_tree(pdb.STREAM_TPI.structures.values()) } for structName, structFields in struct_specs.items(): if structFields != [0, {}]: profile["$STRUCTS"][structName] = structFields mapped_syms = {"$CONSTANTS": {}, "$FUNCTIONS": {}} for sym in gsyms.globals: try: off = sym.offset sym_name = sym.name virt_base = sects[sym.segment - 1].VirtualAddress mapped = omap.remap(off + virt_base) if (sym.symtype & 2) == 2: target_key = "$FUNCTIONS" else: target_key = "$CONSTANTS" except IndexError: # skip symbol because segment was not found continue except AttributeError: # missing offset in symbol? continue sym_name = Demangler().DemangleName(sym_name) if sym_name not in mapped_syms[target_key]: mapped_syms[target_key][sym_name] = list() mapped_syms[target_key][sym_name].append(mapped) for target_key, sym_dict in mapped_syms.items(): for sym_name, value_set in sym_dict.items(): ndx = 0 for mapped in sorted(value_set): if ndx == 0: next_sym_name = sym_name else: next_sym_name = '{}_{}'.format(sym_name, ndx) ndx += 1 profile[target_key][next_sym_name] = mapped del mapped_syms guid = pdb.STREAM_PDB.GUID guid_str = "%.8X%.4X%.4X%s" % (guid.Data1, guid.Data2, guid.Data3, guid.Data4.hex().upper()) symstore_hash = "%s%s" % (guid_str, pdb.STREAM_PDB.Age) base_fn = os.path.splitext(os.path.basename(filepath))[0] profile["$METADATA"] = { "GUID_AGE": symstore_hash, "PDBFile": os.path.basename(filepath), "ProfileClass": base_fn[0].upper() + base_fn[1:].lower(), "Timestamp": pdb.STREAM_PDB.TimeDateStamp.replace( tzinfo=None).strftime("%Y-%m-%d %H:%M:%SZ"), "Type": "Profile", "Version": pdb.STREAM_PDB.Version } return json.dumps(profile, indent=4, sort_keys=True)
def add_debug_symbols(self, db, addr_space, mod): def is_valid_debug_dir(debug_dir, image_base, addr_space): return debug_dir != None and debug_dir.AddressOfRawData != 0 and addr_space.is_valid_address( image_base + debug_dir.AddressOfRawData) and addr_space.is_valid_address( image_base + debug_dir.AddressOfRawData + debug_dir.SizeOfData - 1) mod_path = self.module_path(mod) mod_name = self.module_name(mod) module_id = self.module_id(db, mod) image_base = mod.DllBase debug_dir = mod.get_debug_directory() if not is_valid_debug_dir(debug_dir, image_base, addr_space): # No joy in this process space return if debug_dir.Type != 2: # IMAGE_DEBUG_TYPE_CODEVIEW return debug_data = addr_space.zread(image_base + debug_dir.AddressOfRawData, debug_dir.SizeOfData) if debug_data[:4] == 'RSDS': guid, filename = pdbparse.peinfo.get_rsds(debug_data) elif debug_data[:4] == 'NB10': guid, filename = pdbparse.peinfo.get_nb10(debug_data) else: debug.warning("'{0}' is an unknown CodeView section".format( debug_data[:4])) return if filename == '': return # We have valid CodeView debugging information, so try and download PDB file from a symbol server saved_mod_path = tempfile.gettempdir() + os.sep + guid if self.do_download(db, module_id, guid, filename): if not os.path.exists(saved_mod_path): os.makedirs(saved_mod_path) self.download_pdbfile(db, guid.upper(), module_id, filename, saved_mod_path) # At this point, and if all has gone well, known co-ords should be: mod; image_base; guid; filename pdbname = saved_mod_path + os.sep + filename if not os.path.exists(pdbname): shutil.rmtree(saved_mod_path) debug.warning( "Symbols for module {0} (in {1}) not found".format( mod.BaseDllName, filename)) return try: # Do this the hard way to avoid having to load # the types stream in mammoth PDB files pdb = pdbparse.parse(pdbname, fast_load=True) pdb.STREAM_DBI.load() # As pdbparse doesn't add STREAM_FPO_STRINGS to parent, do it manually if pdb.STREAM_DBI.DBIDbgHeader.snNewFPO != -1: pdb.add_supported_stream( "STREAM_FPO_STRINGS", pdb.STREAM_DBI.DBIDbgHeader.snNewFPO + 1, pdbparse.PDBFPOStrings) except AttributeError: pass try: pdb._update_names() pdb.STREAM_GSYM = pdb.STREAM_GSYM.reload() pdb.STREAM_GSYM.load() pdb.STREAM_SECT_HDR = pdb.STREAM_SECT_HDR.reload() pdb.STREAM_SECT_HDR.load() # These are the dicey ones pdb.STREAM_OMAP_FROM_SRC = pdb.STREAM_OMAP_FROM_SRC.reload() pdb.STREAM_OMAP_FROM_SRC.load() pdb.STREAM_SECT_HDR_ORIG = pdb.STREAM_SECT_HDR_ORIG.reload() pdb.STREAM_SECT_HDR_ORIG.load() except AttributeError: pass try: # Ensure FPO streams are loaded pdb.STREAM_FPO = pdb.STREAM_FPO.reload() pdb.STREAM_FPO.load() pdb.STREAM_FPO_NEW = pdb.STREAM_FPO_NEW.reload() pdb.STREAM_FPO_NEW.load() pdb.STREAM_FPO_STRINGS = pdb.STREAM_FPO_STRINGS.reload() pdb.STREAM_FPO_STRINGS.load() pdb.STREAM_FPO_NEW.load2() # inject program strings except AttributeError: pass except construct.adapters.ConstError as err: # TODO: fix actual PDB parsing failure issue! debug.warning( "Ignoring PDB parsing failure of {0}/{1}: {2}".format( guid.upper(), filename, err.message)) db.execute( """SELECT pdb.id FROM mod_pdb INNER JOIN pdb ON pdb_id=pdb.id WHERE module_id=? AND guid=? AND file=? """, (module_id, str( guid.upper()).rstrip('\0'), str(filename).rstrip('\0'))) row = db.fetchone() assert (row != None) pdb_id = row[0] self.process_gsyms(db, pdb, pdb_id, module_id, guid, filename) try: self.process_fpo(db, pdb, pdb_id, module_id, guid, filename) except AttributeError: pass try: self.process_fpov2(db, pdb, pdb_id, module_id, guid, filename) except AttributeError: pass shutil.rmtree(saved_mod_path) debug.info("Removed directory {0} and its contents".format( saved_mod_path)) self._sym_db_conn.commit()
dest="width", help="set pointer width for PDB's target architecture", type="int", default=None) opts, args = parser.parse_args() ctype = themes[opts.theme] ptr_str = theme_func[opts.theme]["ptr_str"] fptr_str = theme_func[opts.theme]["fptr_str"] if opts.fwdrefs: struct_pretty_str = struct_pretty_str_fwd else: struct_pretty_str = struct_pretty_str_nofwd if opts.fwdrefs: pdb = pdbparse.parse(args[0], fast_load=True) pdb.streams[2].load(elim_fwdrefs=False) else: pdb = pdbparse.parse(args[0]) # Determine the pointer width, set global ARCH_PTR_SIZE if opts.width: ARCH_PTR_SIZE = opts.width else: # TODO: this causes a ConstError occassionally (can't be reliably # reproduced). try: ##pdb.STREAM_DBI.load() # sets global ARCH_PTR_SIZE if pdb.STREAM_DBI.machine in ('IMAGE_FILE_MACHINE_I386'):
import os import sys import pdbparse from pdbparse.peinfo import * from binascii import hexlify if __name__ == u'__main__': pepath = sys.argv[1] pdbinfo = get_external_codeview(pepath) pdbpath = os.path.join(os.path.dirname(pepath), pdbinfo[1]) print(pdbinfo[1]) print(pdbinfo[0]) p = pdbparse.parse(pdbpath, fast_load=True) pdb = p.streams[pdbparse.PDB_STREAM_PDB] pdb.load() guidstr = (u'%08x%04x%04x%s%x' % ( pdb.GUID.Data1, pdb.GUID.Data2, pdb.GUID.Data3, pdb.GUID.Data4.encode('hex'), pdb.Age )).upper() print(guidstr) if pdbinfo[0] != guidstr: print(u'pdb not for this exe') else: dbi = p.streams[pdbparse.PDB_STREAM_DBI] dbi.load()
help="emit forward references", default=False) opts,args = parser.parse_args() ctype = themes[opts.theme] ptr_str = theme_func[opts.theme]["ptr_str"] fptr_str = theme_func[opts.theme]["fptr_str"] if opts.fwdrefs: struct_pretty_str = struct_pretty_str_fwd else: struct_pretty_str = struct_pretty_str_nofwd #dc ** duh ** #filename = r'd:\PDBs\6.1.0#1055\VPAdmin.pdb' filename = args[0] if opts.fwdrefs: pdb = pdbparse.parse(filename, fast_load=True) pdb.streams[2].load(elim_fwdrefs=False) else: pdb = pdbparse.parse(filename) if opts.fwdrefs: fwdrefs = [ s for s in pdb.streams[2].types.values() if (s.leaf_type == "LF_STRUCTURE" or s.leaf_type == "LF_UNION") and s.prop.fwdref ] print "/******* Forward Refs *******/" for f in fwdrefs: print "struct %s;" % mangle(f.name) print "typedef struct %s %s;" % (mangle(f.name), demangle(f.name)) print # Reload the file without fwdrefs as it messes up type sizes pdb = pdbparse.parse(filename) structs = [ s for s in pdb.streams[2].types.values() if (s.leaf_type == "LF_STRUCTURE" or s.leaf_type == "LF_UNION") and not s.prop.fwdref ]
dest = "width", help = "set pointer width for PDB's target architecture", type = "int", default = None) opts, args = parser.parse_args() ctype = themes[opts.theme] ptr_str = theme_func[opts.theme]["ptr_str"] fptr_str = theme_func[opts.theme]["fptr_str"] if opts.fwdrefs: struct_pretty_str = struct_pretty_str_fwd else: struct_pretty_str = struct_pretty_str_nofwd if opts.fwdrefs: pdb = pdbparse.parse(args[0], fast_load = True) pdb.streams[2].load(elim_fwdrefs = False) else: pdb = pdbparse.parse(args[0]) # Determine the pointer width, set global ARCH_PTR_SIZE if opts.width: ARCH_PTR_SIZE = opts.width else: # TODO: this causes a ConstError occassionally (can't be reliably # reproduced). try: ##pdb.STREAM_DBI.load() # sets global ARCH_PTR_SIZE if pdb.STREAM_DBI.machine in ('IMAGE_FILE_MACHINE_I386'):
#!/usr/bin/env python from os.path import basename import pdbparse import sys pdb = pdbparse.parse(sys.argv[1], fast_load=True) if len(sys.argv) > 2: streams = [ pdb.streams[int(i)] for i in sys.argv[2:] ] else: streams = pdb.streams for stream in streams: ofname = basename(pdb.fp.name) + ('.%03d' % stream.index) f = open(ofname, 'w') f.write(stream.data) f.close()
def __init__(self, mods): self.addrs = {} self._cache = {} not_found = [] for pdbname, base in mods: pdbbase = ".".join(os.path.basename(pdbname).split('.')[:-1]) if not os.path.exists(pdbname): print "WARN: %s not found" % pdbname not_found.append((base, pdbbase)) continue #print "Loading symbols for %s..." % pdbbase try: # Do this the hard way to avoid having to load # the types stream in mammoth PDB files pdb = pdbparse.parse(pdbname, fast_load=True) pdb.STREAM_DBI.load() pdb._update_names() pdb.STREAM_GSYM = pdb.STREAM_GSYM.reload() if pdb.STREAM_GSYM.size: pdb.STREAM_GSYM.load() pdb.STREAM_SECT_HDR = pdb.STREAM_SECT_HDR.reload() pdb.STREAM_SECT_HDR.load() # These are the dicey ones pdb.STREAM_OMAP_FROM_SRC = pdb.STREAM_OMAP_FROM_SRC.reload() pdb.STREAM_OMAP_FROM_SRC.load() pdb.STREAM_SECT_HDR_ORIG = pdb.STREAM_SECT_HDR_ORIG.reload() pdb.STREAM_SECT_HDR_ORIG.load() except AttributeError, e: pass #except Exception, e: # print "WARN: error %s parsing %s, skipping" % (e,pdbbase) # not_found.append( (base, pdbbase) ) # continue try: sects = pdb.STREAM_SECT_HDR_ORIG.sections omap = pdb.STREAM_OMAP_FROM_SRC except AttributeError as e: # In this case there is no OMAP, so we use the given section # headers and use the identity function for omap.remap sects = pdb.STREAM_SECT_HDR.sections omap = DummyOmap() gsyms = pdb.STREAM_GSYM if not hasattr(gsyms, 'globals'): gsyms.globals = [] last_sect = max(sects, key=attrgetter('VirtualAddress')) limit = base + last_sect.VirtualAddress + last_sect.Misc.VirtualSize self.addrs[base, limit] = {} self.addrs[base, limit]['name'] = pdbbase self.addrs[base, limit]['addrs'] = [] for sym in gsyms.globals: if not hasattr(sym, 'offset'): continue off = sym.offset try: virt_base = sects[sym.segment - 1].VirtualAddress except IndexError: continue mapped = omap.remap(off + virt_base) + base self.addrs[base, limit]['addrs'].append((mapped, sym.name)) self.addrs[base, limit]['addrs'].sort(key=itemgetter(0))
addrs = [ SyscallTable(0, 0, 0), SyscallTable(0, 0, 0), ] values = [ SyscallTable(0, 0, 0), SyscallTable(0, 0, 0), ] if len(sys.argv) != 3: print("usage: %s <exe> <pdb>" % sys.argv[0], file=sys.stderr) sys.exit(1) pe = PE(sys.argv[1]) pdb = pdbparse.parse(sys.argv[2]) sects = pdb.STREAM_SECT_HDR_ORIG.sections gsyms = pdb.STREAM_GSYM omap = pdb.STREAM_OMAP_FROM_SRC omap_rev = pdb.STREAM_OMAP_TO_SRC for tbl, addr in zip(names, addrs): for sym in gsyms.globals: if not hasattr(sym, 'offset'): continue try: virt_base = sects[sym.segment - 1].VirtualAddress except IndexError: continue off = sym.offset if tbl.ServiceTable in sym.name: