Ejemplo n.º 1
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'-')
Ejemplo n.º 2
0
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
Ejemplo n.º 3
0
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
Ejemplo n.º 4
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'-')
Ejemplo n.º 5
0
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)
Ejemplo n.º 6
0
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)
Ejemplo n.º 7
0
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
Ejemplo n.º 8
0
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)
Ejemplo n.º 9
0
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
Ejemplo n.º 10
0
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
Ejemplo n.º 11
0
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()
Ejemplo n.º 12
0
 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)))
Ejemplo n.º 13
0
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()
Ejemplo n.º 14
0
 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))
Ejemplo n.º 15
0
    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
Ejemplo n.º 16
0
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)
Ejemplo n.º 17
0
    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 ''
Ejemplo n.º 18
0
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
Ejemplo n.º 19
0
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)
Ejemplo n.º 20
0
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)
Ejemplo n.º 21
0
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
Ejemplo n.º 22
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
Ejemplo n.º 23
0
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
Ejemplo n.º 24
0
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))
Ejemplo n.º 25
0
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))
Ejemplo n.º 27
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)
Ejemplo n.º 28
0
 def __init__(self, filename: str):
     self._filename = filename
     logger.info("Parsing PDB...")
     self._pdb = pdbparse.parse(filename)
     self._seen_ctypes: Set[str] = set([])
Ejemplo n.º 29
0
  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()
Ejemplo n.º 30
0
        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)
Ejemplo n.º 31
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:
Ejemplo n.º 32
0
    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
Ejemplo n.º 33
0
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)
Ejemplo n.º 34
0
    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()
Ejemplo n.º 35
0
                      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'):
Ejemplo n.º 36
0
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()
Ejemplo n.º 37
0
                      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 ]
Ejemplo n.º 38
0
        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'):
Ejemplo n.º 39
0
#!/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()
Ejemplo n.º 40
0
    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))
Ejemplo n.º 41
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: