Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ember.js/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 从卸载模块的PDB中提取结构信息_C_Windows_Windbg_Pdb Files_Dbghelp - Fatal编程技术网

C 从卸载模块的PDB中提取结构信息

C 从卸载模块的PDB中提取结构信息,c,windows,windbg,pdb-files,dbghelp,C,Windows,Windbg,Pdb Files,Dbghelp,我正在尝试编写一个WinDbg调试器扩展,它可以在实时远程目标和崩溃转储上工作。该扩展通过结构偏移沿不透明内存块向下移动并将其不同区域投射到已知对象来分析该内存块 这些结构会在版本之间更改字段/字段顺序,因此我无法在调试器扩展本身中硬编码(或包含标题)。相反,我想从我有私有符号的PDB中提取结构信息 当在pdb/映像位于已加载模块列表中的实时目标上使用此功能时,效果非常好,我可以使用类似于在类的结构中获取字段的函数 GetFieldOffset("MyClass!MyNestedClass",

我正在尝试编写一个WinDbg调试器扩展,它可以在实时远程目标和崩溃转储上工作。该扩展通过结构偏移沿不透明内存块向下移动并将其不同区域投射到已知对象来分析该内存块

这些结构会在版本之间更改字段/字段顺序,因此我无法在调试器扩展本身中硬编码(或包含标题)。相反,我想从我有私有符号的PDB中提取结构信息

当在pdb/映像位于已加载模块列表中的实时目标上使用此功能时,效果非常好,我可以使用类似于在类的结构中获取字段的函数

GetFieldOffset("MyClass!MyNestedClass", "m_Struct", &offsetInClass);

GetFieldData(offsetInClass + classAddr, "MyClass!_MY_STRUCT", "FieldInStruct",
             sizeof(ULONG), &myFieldValue);
我的问题:当我在加载的模块列表中没有该模块时(无论是在错误的上下文中,还是在分析崩溃转储),我无法使用上述功能

在我分析的内存区域的开头,我存储了pdb GUID和年龄。使用它,我可以使用在我的符号路径/符号缓存中找到我的pdb的路径

所以我有我的特定pdb实例的路径,但我不确定从这里走到哪里。通过查看exposed by DbgHelp.dll,我看不到任何明显的使用此pdb文件获取类型信息的方法。函数(如)需要模块库,而“我的模块”未加载且无法加载。我只需要结构中字段的字节偏移量。有什么想法吗


谢谢

调试接口访问SDK提供用于直接使用PDB的API:


DIA2Dump示例功能齐全,演示了如何提取类型信息

下面的
POC代码
展示了如何使用
diasdk

//脆弱代码小心处理

#include "typefrompdb.h"
int main(int argc, char* argv[]) {
    USAGE;
    swprintf(pdb, MAX_PATH,L"%S",argv[1]);
    swprintf(type, MAX_PATH,L"%S",argv[2]);
    result = CoInitialize(NULL);
    result = CoCreateInstance( CLSID_DiaSource,NULL, 
        CLSCTX_INPROC_SERVER,__uuidof( IDiaDataSource ),(void **) &pSource);
    result = pSource->loadDataFromPdb(pdb);
    SHOUT("%s 2find %S %d\n",(result==S_OK)?"succeded":"failed",pdb,__LINE__);
    result = pSource->openSession(&pSession);
    result = pSession->get_globalScope(&pSymbol);
    result = pSymbol->findChildren(SymTagUDT,type,nsNone,&pEnumsymbols);
    result = pEnumsymbols->get_Count(&count);   
    result = pEnumsymbols->Next(1,&pSymudt,&noofsymret);
    SHOUT("%s 2find %S %d\n",(result==S_OK)?"succeded":"failed",type,__LINE__);
    result = pSymudt->get_name(udtname);
    result = pSymudt->findChildren(SymTagNull,NULL,nsNone,&pEnumsymbols);
    result = pEnumsymbols->get_Count(&count);
    SHOUT("no of members in struct %S is  0X%X %d\n",type,count,__LINE__);
    wprintf(L"\nstruct %s {\nType Leng Tags Name  \n",*udtname);
    for (LONG i =0 ; i< count; i++)     {
        result = pEnumsymbols->Next(1,&pSymchild,&noofsymret);            
        result = pSymchild->get_name(childname);
        result = pSymchild->get_type(&pSymtags);
        result = pSymtags->get_symTag(&dwtag);
        result = pSymtags->get_length(&len);
        result = pSymtags->get_baseType(&basetype);
        wprintf(L"0x%.2X 0x%.2I64X 0x%.2X %s\n",basetype,len,dwtag,*childname);
    }    return 0; }
测试用例的结果

/* handling errors/releasing memory BSTRS pointers  closing handles using 
sensible coding standards using dynamic allocations replacing ansi with unicode
etc etc etc should be implemented POC CODE not meant for blind copy pasting 
typical test case is typefrompdb.exe ntdll.pdb _DRIVER_OBJECT */
#include <stdio.h>
#include <Windows.h>
#include <Dia2.h>    // set INCLUDE=diasdkdir\inc
#include <atlbase.h> // vs 2010 express edition used with wdk 7600 
#include <atlcom.h>  // set INCLUDE=C:\WinDDK\7600.16385.1\inc\atl71
#include <dbghelp.h> // set INCLUDE=windbg\sdk\inc
#define SHOUT(...) if(result!=S_OK){printf(__VA_ARGS__);exit(0);\
        }else{printf(__VA_ARGS__);}
#define USAGE if (argc != 3) { printf( \
    "usage %s %s %s\n",argv[0],"file.pdb","typename"); return 0;}
HRESULT                 result              = E_FAIL;
IDiaDataSource          *pSource            = NULL;
IDiaSession             *pSession           = NULL;
IDiaSymbol              *pSymbol,*pSymchild = NULL;
IDiaEnumSymbols         *pEnumsymbols       = NULL;
wchar_t                 pdb[500], type[500] = {0};
BSTR        childname[0x100],udtname[0x100] = {0};
LONG                    count               = 0;
ULONG                   noofsymret          = 0;
DWORD               dwtag,basetype          = 0;
ULONGLONG               len                 = 0;
CComPtr< IDiaSymbol >   pSymudt;
CComPtr< IDiaSymbol >   pSymtags;
typefrompdb.exe
usage typefrompdb.exe file.pdb typename  
typefrompdb.exe ntd dr
failed 2find ntd 11

typefrompdb.exe ntdll.pdb _driver_object
succeded 2find ntdll.pdb 11
failed 2find _driver_object 17

typefrompdb.exe ntdll.pdb _DRIVER_OBJECT
succeded 2find ntdll.pdb 11
succeded 2find _DRIVER_OBJECT 17
no of members in struct _DRIVER_OBJECT is  0XF 21    
struct _DRIVER_OBJECT {
Type Leng Tags Name
0x06 0x02 0x10 Type
0x06 0x02 0x10 Size
0x00 0x04 0x0E DeviceObject
0x0E 0x04 0x10 Flags
0x00 0x04 0x0E DriverStart
0x0E 0x04 0x10 DriverSize
0x00 0x04 0x0E DriverSection
0x00 0x04 0x0E DriverExtension
0x00 0x08 0x0B DriverName
0x00 0x04 0x0E HardwareDatabase
0x00 0x04 0x0E FastIoDispatch
0x00 0x04 0x0E DriverInit
0x00 0x04 0x0E DriverStartIo
0x00 0x04 0x0E DriverUnload
0x00 0x70 0x0F MajorFunction
grep -iE "btint|btulong|btnotype" cvconst.h
    btNoType = 0,
    btInt = 6,
    btULong = 14,

grep -i -A 35 "enum symtagenum" cvconst.h 
| awk "{ if ( NR==0x0B || NR==0x0E || NR==0x0F || NR==0x10 ) print $0 }"
    SymTagAnnotation,
    SymTagUDT,
    SymTagEnum,
    SymTagFunctionType,
典型测试用例的结果解释

/* handling errors/releasing memory BSTRS pointers  closing handles using 
sensible coding standards using dynamic allocations replacing ansi with unicode
etc etc etc should be implemented POC CODE not meant for blind copy pasting 
typical test case is typefrompdb.exe ntdll.pdb _DRIVER_OBJECT */
#include <stdio.h>
#include <Windows.h>
#include <Dia2.h>    // set INCLUDE=diasdkdir\inc
#include <atlbase.h> // vs 2010 express edition used with wdk 7600 
#include <atlcom.h>  // set INCLUDE=C:\WinDDK\7600.16385.1\inc\atl71
#include <dbghelp.h> // set INCLUDE=windbg\sdk\inc
#define SHOUT(...) if(result!=S_OK){printf(__VA_ARGS__);exit(0);\
        }else{printf(__VA_ARGS__);}
#define USAGE if (argc != 3) { printf( \
    "usage %s %s %s\n",argv[0],"file.pdb","typename"); return 0;}
HRESULT                 result              = E_FAIL;
IDiaDataSource          *pSource            = NULL;
IDiaSession             *pSession           = NULL;
IDiaSymbol              *pSymbol,*pSymchild = NULL;
IDiaEnumSymbols         *pEnumsymbols       = NULL;
wchar_t                 pdb[500], type[500] = {0};
BSTR        childname[0x100],udtname[0x100] = {0};
LONG                    count               = 0;
ULONG                   noofsymret          = 0;
DWORD               dwtag,basetype          = 0;
ULONGLONG               len                 = 0;
CComPtr< IDiaSymbol >   pSymudt;
CComPtr< IDiaSymbol >   pSymtags;
typefrompdb.exe
usage typefrompdb.exe file.pdb typename  
typefrompdb.exe ntd dr
failed 2find ntd 11

typefrompdb.exe ntdll.pdb _driver_object
succeded 2find ntdll.pdb 11
failed 2find _driver_object 17

typefrompdb.exe ntdll.pdb _DRIVER_OBJECT
succeded 2find ntdll.pdb 11
succeded 2find _DRIVER_OBJECT 17
no of members in struct _DRIVER_OBJECT is  0XF 21    
struct _DRIVER_OBJECT {
Type Leng Tags Name
0x06 0x02 0x10 Type
0x06 0x02 0x10 Size
0x00 0x04 0x0E DeviceObject
0x0E 0x04 0x10 Flags
0x00 0x04 0x0E DriverStart
0x0E 0x04 0x10 DriverSize
0x00 0x04 0x0E DriverSection
0x00 0x04 0x0E DriverExtension
0x00 0x08 0x0B DriverName
0x00 0x04 0x0E HardwareDatabase
0x00 0x04 0x0E FastIoDispatch
0x00 0x04 0x0E DriverInit
0x00 0x04 0x0E DriverStartIo
0x00 0x04 0x0E DriverUnload
0x00 0x70 0x0F MajorFunction
grep -iE "btint|btulong|btnotype" cvconst.h
    btNoType = 0,
    btInt = 6,
    btULong = 14,

grep -i -A 35 "enum symtagenum" cvconst.h 
| awk "{ if ( NR==0x0B || NR==0x0E || NR==0x0F || NR==0x10 ) print $0 }"
    SymTagAnnotation,
    SymTagUDT,
    SymTagEnum,
    SymTagFunctionType,
编辑
我从来都不确定这是一个答案这更像是一个测试或实验在使用dia sdk
symloadmodel使用硬编码为0x1000000的任意地址
您可以看到,在平台sdk示例中的
DBH src
中,相同src的编译二进制文件在windbg安装中可用

C:\Program Files\Microsoft SDKs\Windows\v7.1\Samples\winbase\debug\dbh


//global
DWORD64 gDefaultBaseForVirtualMods;

BOOL init()
{
    int i;

    *gModName = 0;
    gBase = 0;;
    gDefaultBaseForVirtualMods = 0x1000000;

else if (!_tcsicmp(ext, _T(".pdb"))) 
{
    addr = gDefaultBaseForVirtualMods;
    dontopen = true;
} else {
    addr = gDefaultBase;
}


C:\>dbh XXXXXXX\ntdll.pdb t _DRIVER_OBJECT

   name : _DRIVER_OBJECT
   addr :        0
   size : a8
  flags : 0
   type : 1
modbase :  1000000
  value :        0
    reg : 0
  scope : SymTagNull (0)
    tag : SymTagUDT (b)
  index : 1

C:\>
无论如何
我要重申,您不应该在windbg扩展中使用dbghelp函数
,请阅读以下链接上的说明(编写wdbg扩展/dbgeng扩展/engextcpp函数,该函数声明不支持在windbg扩展中使用dbghelp函数

Note   You must not attempt to call any DbgHelp or ImageHlp routines from any debugger extension. Calling these routines is not supported and may cause a variety of problems. 


卸载的模块在转储中没有相关的CvRecord,因此内存将不可用。当您尝试查看地址中的数据时,windbg将显示???,当您尝试读取带有自定义扩展名的任何内容时,windbg将显示为true(请参阅MINIDUMP_模块和MINIDUMP_Unload_模块)dbghelp.chm中的结构请注意,不建议直接在windbg扩展中使用dbghelp函数,而是使用dbgeng提供的包装器Idebug****或engextcpp框架。这些包装器正确访问底层数据(缓存数据、实时数据等)我将接受这一点,因为您投入了大量的精力,但事实证明,有一种简单得多的方法,只使用dbghelp(当然是diah2的通用包装,但直接使用更健壮)。显然,使用具有任意基址和PDB路径的SymLoadModule就足够了。漂亮!