如何使用 dbghlp 和 pdb 获取结构体的字段名称和偏移量

发布于 2024-09-07 05:58:18 字数 2865 浏览 7 评论 0原文

我想以与 Windbg 的 dt 命令相同的方式转储结构的字段和偏移量。举例来说,我想转储 Microsoft 公共符号中的 _PEB 结构(因为 Windbg 的 DT 命令有效)。

从 MSDN 文档中,我了解到 SymFromName 函数应该能够执行此操作,下面是我尝试过的代码,该代码在 SymFromName 上失败,并显示 LastError 126(找不到指定的模块)。 从注册的回调中,我得到以下输出:

CBA_SET_OPTIONS
CBA_SET_OPTIONS
CBA_SET_OPTIONS
CBA_EVENT: code 0 desc DBGHELP: Symbol Search Path: symsrv*symsrv.dll*C:\Symbols*http://msdl.microsoft.com/download/symbols

DBGHELP: Symbol Search Path: symsrv*symsrv.dll*C:\Symbols*http://msdl.microsoft.com/download/symbols

CBA_DEFERRED_SYMBOL_LOAD_START: C:\Windows\Sysnative\ntdll.dll
CBA_DEFERRED_SYMBOL_LOAD_PARTIAL: C:\Windows\Sysnative\ntdll.dll
CBA_EVENT: code 0 desc DBGHELP: No header for C:\Windows\Sysnative\ntdll.dll.  Searching for image on disk

DBGHELP: No header for C:\Windows\Sysnative\ntdll.dll.  Searching for image on disk

CBA_EVENT: code 0 desc DBGHELP: C:\Windows\Sysnative\ntdll.dll - OK

DBGHELP: C:\Windows\Sysnative\ntdll.dll - OK

CBA_DEFERRED_SYMBOL_LOAD_COMPLETE: C:\Windows\Sysnative\ntdll.dll
CBA_EVENT: code 0 desc DBGHELP: ntdll - public symbols  
         C:\Symbols\ntdll.pdb\823B51C37A764AF7BA1558B42B627FAC2\ntdll.pdb

DBGHELP: ntdll - public symbols  
         C:\Symbols\ntdll.pdb\823B51C37A764AF7BA1558B42B627FAC2\ntdll.pdb

代码:

const
  Index: THandle =1;
  Size = (SizeOf(SYMBOL_INFO)-1 + MAX_SYM_NAME * SizeOf(TCHAR) + SizeOf(ULONG64) -1) div SizeOf(ULONG64);
var
  Symbol: String;
  Filename: String;
  Path: String;
  dwBaseAddress: DWORD;
  im: IMAGEHLP_MODULE64;
  Buffer: array[0..Size] of ULONG64;
  pSymbol: PSYMBOL_INFO;
  SymbolName: array[0..MAX_SYM_NAME-1] of Char;
begin
  ZeroMemory(@SymbolName, SizeOf(SymbolName));
  SymbolName := '_PEB';
  Filename := 'C:\Windows\Sysnative\ntdll.dll';
  Path := 'symsrv*symsrv.dll*C:\Symbols*http://msdl.microsoft.com/download/symbols';

  { Initialize }
  Win32Check(SymInitialize(Index, nil, False));
  { Register callback to get some debug info }
  Win32Check(SymRegisterCallback64(Index, DbgHelpCallback, 0));

  { Set Options }
  SymSetOptions(SymGetOptions or SYMOPT_UNDNAME);
  SymSetOptions(SymGetOptions or SYMOPT_DEBUG);
  SymSetOptions(SymGetOptions or SYMOPT_LOAD_ANYTHING);

  { Set Symbol Path }
  Win32Check(SymSetSearchPathW(Index, PChar(Path)));

  { Load Module }
  dwBaseAddress := SymLoadModuleExW(Index, 0, PChar(Filename), nil, 0, 0, nil, 0);
  Win32Check(dwBaseAddress > 0);

  ZeroMemory(@im, SizeOf(im));
  im.SizeOfStruct := SizeOf(im);
  Win32Check(SymGetModuleInfoW64(Index, dwBaseAddress, im));

  ZeroMemory(@Buffer, SizeOf(Buffer));
  pSymbol := PSYMBOL_INFO(@Buffer);
  pSymbol^.SizeOfStruct := SizeOf(SYMBOL_INFO);
  pSymbol^.MaxNameLen := MAX_SYM_NAME;

  Win32Check(SymFromNameW(Index, Symbolname, pSymbol));

  Win32Check(SymUnloadModule64(Index, dwBaseAddress));
  Win32Check(SymCleanup(Index));

I would like to dump the fields and offsets of structures in the same way as windbg's dt command. Let's say for example I would like to dump the _PEB structure which is in the Microsoft Public symbols (since windbg's DT command works).

From MSDN documentation I understood that the SymFromName function should be able to do this, below the is the code I've tried that fails on SymFromName with LastError 126 (The specified module could not be found).
From the registered Callback I get the following output:

CBA_SET_OPTIONS
CBA_SET_OPTIONS
CBA_SET_OPTIONS
CBA_EVENT: code 0 desc DBGHELP: Symbol Search Path: symsrv*symsrv.dll*C:\Symbols*http://msdl.microsoft.com/download/symbols

DBGHELP: Symbol Search Path: symsrv*symsrv.dll*C:\Symbols*http://msdl.microsoft.com/download/symbols

CBA_DEFERRED_SYMBOL_LOAD_START: C:\Windows\Sysnative\ntdll.dll
CBA_DEFERRED_SYMBOL_LOAD_PARTIAL: C:\Windows\Sysnative\ntdll.dll
CBA_EVENT: code 0 desc DBGHELP: No header for C:\Windows\Sysnative\ntdll.dll.  Searching for image on disk

DBGHELP: No header for C:\Windows\Sysnative\ntdll.dll.  Searching for image on disk

CBA_EVENT: code 0 desc DBGHELP: C:\Windows\Sysnative\ntdll.dll - OK

DBGHELP: C:\Windows\Sysnative\ntdll.dll - OK

CBA_DEFERRED_SYMBOL_LOAD_COMPLETE: C:\Windows\Sysnative\ntdll.dll
CBA_EVENT: code 0 desc DBGHELP: ntdll - public symbols  
         C:\Symbols\ntdll.pdb\823B51C37A764AF7BA1558B42B627FAC2\ntdll.pdb

DBGHELP: ntdll - public symbols  
         C:\Symbols\ntdll.pdb\823B51C37A764AF7BA1558B42B627FAC2\ntdll.pdb

The Code:

const
  Index: THandle =1;
  Size = (SizeOf(SYMBOL_INFO)-1 + MAX_SYM_NAME * SizeOf(TCHAR) + SizeOf(ULONG64) -1) div SizeOf(ULONG64);
var
  Symbol: String;
  Filename: String;
  Path: String;
  dwBaseAddress: DWORD;
  im: IMAGEHLP_MODULE64;
  Buffer: array[0..Size] of ULONG64;
  pSymbol: PSYMBOL_INFO;
  SymbolName: array[0..MAX_SYM_NAME-1] of Char;
begin
  ZeroMemory(@SymbolName, SizeOf(SymbolName));
  SymbolName := '_PEB';
  Filename := 'C:\Windows\Sysnative\ntdll.dll';
  Path := 'symsrv*symsrv.dll*C:\Symbols*http://msdl.microsoft.com/download/symbols';

  { Initialize }
  Win32Check(SymInitialize(Index, nil, False));
  { Register callback to get some debug info }
  Win32Check(SymRegisterCallback64(Index, DbgHelpCallback, 0));

  { Set Options }
  SymSetOptions(SymGetOptions or SYMOPT_UNDNAME);
  SymSetOptions(SymGetOptions or SYMOPT_DEBUG);
  SymSetOptions(SymGetOptions or SYMOPT_LOAD_ANYTHING);

  { Set Symbol Path }
  Win32Check(SymSetSearchPathW(Index, PChar(Path)));

  { Load Module }
  dwBaseAddress := SymLoadModuleExW(Index, 0, PChar(Filename), nil, 0, 0, nil, 0);
  Win32Check(dwBaseAddress > 0);

  ZeroMemory(@im, SizeOf(im));
  im.SizeOfStruct := SizeOf(im);
  Win32Check(SymGetModuleInfoW64(Index, dwBaseAddress, im));

  ZeroMemory(@Buffer, SizeOf(Buffer));
  pSymbol := PSYMBOL_INFO(@Buffer);
  pSymbol^.SizeOfStruct := SizeOf(SYMBOL_INFO);
  pSymbol^.MaxNameLen := MAX_SYM_NAME;

  Win32Check(SymFromNameW(Index, Symbolname, pSymbol));

  Win32Check(SymUnloadModule64(Index, dwBaseAddress));
  Win32Check(SymCleanup(Index));

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

岛徒 2024-09-14 05:58:30

我并不是这些方面的专家,但 C 名称修改中的前导下划线有时应该是二进制格式的一部分。

如果删除前导下划线,它会起作用吗?

I'm not exactly an expert in these things, but the leading underscore in C namemangling is sometimes supposed to be part of the binary format.

Does it work if you remove the leading underscore?

瞄了个咪的 2024-09-14 05:58:28

我通过使用 SymGetTypeFromName 获取符号索引,然后使用 SymGetTypeInfo 获取详细信息来使其工作:

const
  Index: THandle =1;
  Size = (SizeOf(SYMBOL_INFO)-1 + MAX_SYM_NAME * SizeOf(TCHAR) + SizeOf(ULONG64) -1) div SizeOf(ULONG64);
var
  Filename: String;
  Path: String;
  dwBaseAddress: array[0..0] of DWORD;
  im: IMAGEHLP_MODULE64;
  Buffer: array[0..Size] of ULONG64;
  pSymbol: PSYMBOL_INFO;
  SymbolName: array[0..MAX_SYM_NAME-1] of Char;
  i: Integer;
  ChildParams: TI_FINDCHILDREN_PARAMS;
  dwOffset: DWORD;
  pSymName: PChar;
begin
  ZeroMemory(@SymbolName, SizeOf(SymbolName));
  SymbolName := '_PEB';
  Filename := 'C:\Windows\System32\ntdll.dll';
  Path := 'symsrv*symsrv.dll*C:\Symbols*http://msdl.microsoft.com/download/symbols';

  { Initialize }
  Win32Check(SymInitialize(Index, nil, False));
  { Register callback to get some debug info }
  Win32Check(SymRegisterCallback64(Index, DbgHelpCallback, 0));

  { Set Options }
  SymSetOptions(SymGetOptions or SYMOPT_UNDNAME);
  SymSetOptions(SymGetOptions or SYMOPT_DEBUG);
  SymSetOptions(SymGetOptions or SYMOPT_LOAD_ANYTHING);

  { Set Symbol Path }
  Win32Check(SymSetSearchPathW(Index, PChar(Path)));

  { Load Module }
  dwBaseAddress[0] := SymLoadModuleExW(Index, 0, PChar(Filename), nil, 0, 0, nil, 0);

  ZeroMemory(@im, SizeOf(im));

  im.SizeOfStruct := SizeOf(im);
  for i := 0 to Length(dwBaseAddress)-1 do
  begin
    SymGetModuleInfoW64(Index, dwBaseAddress[i], im);
  end;

  ZeroMemory(@Buffer, SizeOf(Buffer));
  pSymbol := PSYMBOL_INFO(@Buffer);
  pSymbol^.SizeOfStruct := SizeOf(SYMBOL_INFO);
  pSymbol^.MaxNameLen := MAX_SYM_NAME;
  { Get Type Info by Symbol Name (we need the index) }
  Win32Check(SymGetTypeFromNameW(Index, dwBaseAddress[0], SymbolName, pSymbol));

  { Get Child Count }
  ZeroMemory(@ChildParams, SizeOf(ChildParams));
  Win32Check(SymGetTypeInfo(Index, dwBaseAddress[0], pSymbol^.TypeIndex, TI_GET_CHILDRENCOUNT, @ChildParams.Count));

  { Get Child Info }
  // TODO: Caller must reserve memory for the ChildId array (Count * SizeOf(ULONG))
  Win32Check(SymGetTypeInfo(Index, dwBaseAddress[0], pSymbol^.TypeIndex, TI_FINDCHILDREN, @ChildParams));
  for i := ChildParams.Start to ChildParams.Count - 1 do
  begin
    { Get Child Name }
    Win32Check(SymGetTypeInfo(Index, dwBaseAddress[0], {pSymbol^.TypeIndex + }ChildParams.ChildId[i], TI_GET_SYMNAME, @pSymName));
    { Get Child Offset }
    Win32Check(SymGetTypeInfo(Index, dwBaseAddress[0], {pSymbol^.TypeIndex + }ChildParams.ChildId[i], TI_GET_OFFSET, @dwOffset));
    Memo1.Lines.Add(Format('+0x%.3x %s', [dwOffset, pSymName]));
    LocalFree(Cardinal(pSymName));
  end;

  for i := 0 to Length(dwBaseAddress)-1 do
  begin
    Win32Check(SymUnloadModule64(Index, dwBaseAddress[i]));
  end;
  Win32Check(SymCleanup(Index));
end;

这是输出:

+0x000 InheritedAddressSpace
+0x001 ReadImageFileExecOptions
+0x002 BeingDebugged
+0x003 BitField
+0x003 ImageUsesLargePages
+0x003 IsProtectedProcess
+0x003 IsLegacyProcess
+0x003 IsImageDynamicallyRelocated
+0x003 SkipPatchingUser32Forwarders
+0x003 SpareBits
+0x004 Mutant
+0x008 ImageBaseAddress
+0x00C Ldr
+0x010 ProcessParameters
+0x014 SubSystemData
+0x018 ProcessHeap
+0x01C FastPebLock
+0x020 AtlThunkSListPtr
+0x024 IFEOKey
+0x028 CrossProcessFlags
+0x028 ProcessInJob
+0x028 ProcessInitializing
+0x028 ProcessUsingVEH
+0x028 ProcessUsingVCH
+0x028 ProcessUsingFTH
+0x028 ReservedBits0
+0x02C KernelCallbackTable
+0x02C UserSharedInfoPtr
+0x030 SystemReserved
+0x034 AtlThunkSListPtr32
+0x038 ApiSetMap
+0x03C TlsExpansionCounter
+0x040 TlsBitmap
+0x044 TlsBitmapBits
+0x04C ReadOnlySharedMemoryBase
+0x050 HotpatchInformation
+0x054 ReadOnlyStaticServerData
+0x058 AnsiCodePageData
+0x05C OemCodePageData
+0x060 UnicodeCaseTableData
+0x064 NumberOfProcessors
+0x068 NtGlobalFlag
+0x070 CriticalSectionTimeout
+0x078 HeapSegmentReserve
+0x07C HeapSegmentCommit
+0x080 HeapDeCommitTotalFreeThreshold
+0x084 HeapDeCommitFreeBlockThreshold
+0x088 NumberOfHeaps
+0x08C MaximumNumberOfHeaps
+0x090 ProcessHeaps
+0x094 GdiSharedHandleTable
+0x098 ProcessStarterHelper
+0x09C GdiDCAttributeList
+0x0A0 LoaderLock
+0x0A4 OSMajorVersion
+0x0A8 OSMinorVersion
+0x0AC OSBuildNumber
+0x0AE OSCSDVersion
+0x0B0 OSPlatformId
+0x0B4 ImageSubsystem
+0x0B8 ImageSubsystemMajorVersion
+0x0BC ImageSubsystemMinorVersion
+0x0C0 ActiveProcessAffinityMask
+0x0C4 GdiHandleBuffer
+0x14C PostProcessInitRoutine
+0x150 TlsExpansionBitmap
+0x154 TlsExpansionBitmapBits
+0x1D4 SessionId
+0x1D8 AppCompatFlags
+0x1E0 AppCompatFlagsUser
+0x1E8 pShimData
+0x1EC AppCompatInfo
+0x1F0 CSDVersion
+0x1F8 ActivationContextData
+0x1FC ProcessAssemblyStorageMap
+0x200 SystemDefaultActivationContextData
+0x204 SystemAssemblyStorageMap
+0x208 MinimumStackCommit
+0x20C FlsCallback
+0x210 FlsListHead
+0x218 FlsBitmap
+0x21C FlsBitmapBits
+0x22C FlsHighIndex
+0x230 WerRegistrationData
+0x234 WerShipAssertPtr
+0x238 pContextData
+0x23C pImageHeaderHash
+0x240 TracingFlags
+0x240 HeapTracingEnabled
+0x240 CritSecTracingEnabled
+0x240 SpareTracingBits

现在进入下一步:使用 Delphi 2010 的 RTTI 并使用此机制来比较偏移量(这对我有帮助)转换 Jedi ApiLib 的标头)。

I got it to work by using SymGetTypeFromName to get the Symbol Index and then use SymGetTypeInfo to get the details:

const
  Index: THandle =1;
  Size = (SizeOf(SYMBOL_INFO)-1 + MAX_SYM_NAME * SizeOf(TCHAR) + SizeOf(ULONG64) -1) div SizeOf(ULONG64);
var
  Filename: String;
  Path: String;
  dwBaseAddress: array[0..0] of DWORD;
  im: IMAGEHLP_MODULE64;
  Buffer: array[0..Size] of ULONG64;
  pSymbol: PSYMBOL_INFO;
  SymbolName: array[0..MAX_SYM_NAME-1] of Char;
  i: Integer;
  ChildParams: TI_FINDCHILDREN_PARAMS;
  dwOffset: DWORD;
  pSymName: PChar;
begin
  ZeroMemory(@SymbolName, SizeOf(SymbolName));
  SymbolName := '_PEB';
  Filename := 'C:\Windows\System32\ntdll.dll';
  Path := 'symsrv*symsrv.dll*C:\Symbols*http://msdl.microsoft.com/download/symbols';

  { Initialize }
  Win32Check(SymInitialize(Index, nil, False));
  { Register callback to get some debug info }
  Win32Check(SymRegisterCallback64(Index, DbgHelpCallback, 0));

  { Set Options }
  SymSetOptions(SymGetOptions or SYMOPT_UNDNAME);
  SymSetOptions(SymGetOptions or SYMOPT_DEBUG);
  SymSetOptions(SymGetOptions or SYMOPT_LOAD_ANYTHING);

  { Set Symbol Path }
  Win32Check(SymSetSearchPathW(Index, PChar(Path)));

  { Load Module }
  dwBaseAddress[0] := SymLoadModuleExW(Index, 0, PChar(Filename), nil, 0, 0, nil, 0);

  ZeroMemory(@im, SizeOf(im));

  im.SizeOfStruct := SizeOf(im);
  for i := 0 to Length(dwBaseAddress)-1 do
  begin
    SymGetModuleInfoW64(Index, dwBaseAddress[i], im);
  end;

  ZeroMemory(@Buffer, SizeOf(Buffer));
  pSymbol := PSYMBOL_INFO(@Buffer);
  pSymbol^.SizeOfStruct := SizeOf(SYMBOL_INFO);
  pSymbol^.MaxNameLen := MAX_SYM_NAME;
  { Get Type Info by Symbol Name (we need the index) }
  Win32Check(SymGetTypeFromNameW(Index, dwBaseAddress[0], SymbolName, pSymbol));

  { Get Child Count }
  ZeroMemory(@ChildParams, SizeOf(ChildParams));
  Win32Check(SymGetTypeInfo(Index, dwBaseAddress[0], pSymbol^.TypeIndex, TI_GET_CHILDRENCOUNT, @ChildParams.Count));

  { Get Child Info }
  // TODO: Caller must reserve memory for the ChildId array (Count * SizeOf(ULONG))
  Win32Check(SymGetTypeInfo(Index, dwBaseAddress[0], pSymbol^.TypeIndex, TI_FINDCHILDREN, @ChildParams));
  for i := ChildParams.Start to ChildParams.Count - 1 do
  begin
    { Get Child Name }
    Win32Check(SymGetTypeInfo(Index, dwBaseAddress[0], {pSymbol^.TypeIndex + }ChildParams.ChildId[i], TI_GET_SYMNAME, @pSymName));
    { Get Child Offset }
    Win32Check(SymGetTypeInfo(Index, dwBaseAddress[0], {pSymbol^.TypeIndex + }ChildParams.ChildId[i], TI_GET_OFFSET, @dwOffset));
    Memo1.Lines.Add(Format('+0x%.3x %s', [dwOffset, pSymName]));
    LocalFree(Cardinal(pSymName));
  end;

  for i := 0 to Length(dwBaseAddress)-1 do
  begin
    Win32Check(SymUnloadModule64(Index, dwBaseAddress[i]));
  end;
  Win32Check(SymCleanup(Index));
end;

and this is the output:

+0x000 InheritedAddressSpace
+0x001 ReadImageFileExecOptions
+0x002 BeingDebugged
+0x003 BitField
+0x003 ImageUsesLargePages
+0x003 IsProtectedProcess
+0x003 IsLegacyProcess
+0x003 IsImageDynamicallyRelocated
+0x003 SkipPatchingUser32Forwarders
+0x003 SpareBits
+0x004 Mutant
+0x008 ImageBaseAddress
+0x00C Ldr
+0x010 ProcessParameters
+0x014 SubSystemData
+0x018 ProcessHeap
+0x01C FastPebLock
+0x020 AtlThunkSListPtr
+0x024 IFEOKey
+0x028 CrossProcessFlags
+0x028 ProcessInJob
+0x028 ProcessInitializing
+0x028 ProcessUsingVEH
+0x028 ProcessUsingVCH
+0x028 ProcessUsingFTH
+0x028 ReservedBits0
+0x02C KernelCallbackTable
+0x02C UserSharedInfoPtr
+0x030 SystemReserved
+0x034 AtlThunkSListPtr32
+0x038 ApiSetMap
+0x03C TlsExpansionCounter
+0x040 TlsBitmap
+0x044 TlsBitmapBits
+0x04C ReadOnlySharedMemoryBase
+0x050 HotpatchInformation
+0x054 ReadOnlyStaticServerData
+0x058 AnsiCodePageData
+0x05C OemCodePageData
+0x060 UnicodeCaseTableData
+0x064 NumberOfProcessors
+0x068 NtGlobalFlag
+0x070 CriticalSectionTimeout
+0x078 HeapSegmentReserve
+0x07C HeapSegmentCommit
+0x080 HeapDeCommitTotalFreeThreshold
+0x084 HeapDeCommitFreeBlockThreshold
+0x088 NumberOfHeaps
+0x08C MaximumNumberOfHeaps
+0x090 ProcessHeaps
+0x094 GdiSharedHandleTable
+0x098 ProcessStarterHelper
+0x09C GdiDCAttributeList
+0x0A0 LoaderLock
+0x0A4 OSMajorVersion
+0x0A8 OSMinorVersion
+0x0AC OSBuildNumber
+0x0AE OSCSDVersion
+0x0B0 OSPlatformId
+0x0B4 ImageSubsystem
+0x0B8 ImageSubsystemMajorVersion
+0x0BC ImageSubsystemMinorVersion
+0x0C0 ActiveProcessAffinityMask
+0x0C4 GdiHandleBuffer
+0x14C PostProcessInitRoutine
+0x150 TlsExpansionBitmap
+0x154 TlsExpansionBitmapBits
+0x1D4 SessionId
+0x1D8 AppCompatFlags
+0x1E0 AppCompatFlagsUser
+0x1E8 pShimData
+0x1EC AppCompatInfo
+0x1F0 CSDVersion
+0x1F8 ActivationContextData
+0x1FC ProcessAssemblyStorageMap
+0x200 SystemDefaultActivationContextData
+0x204 SystemAssemblyStorageMap
+0x208 MinimumStackCommit
+0x20C FlsCallback
+0x210 FlsListHead
+0x218 FlsBitmap
+0x21C FlsBitmapBits
+0x22C FlsHighIndex
+0x230 WerRegistrationData
+0x234 WerShipAssertPtr
+0x238 pContextData
+0x23C pImageHeaderHash
+0x240 TracingFlags
+0x240 HeapTracingEnabled
+0x240 CritSecTracingEnabled
+0x240 SpareTracingBits

Now on to the next step: use Delphi 2010's RTTI and use this mechanism to compare offsets (this helps me converting headers for the Jedi ApiLib).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文