2010-06-22 650 views
2

我想以與windbg的dt命令相同的方式轉儲結構的字段和偏移量。比方說,我想轉儲微軟公共符號中的_PEB結構(因爲windbg的DT命令起作用)。如何使用dbghlp和pdb獲取結構體的字段名稱和偏移

從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)); 

回答

3

我把它用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轉換標頭)。

+0

Oooops:上面的代碼在這一行中有一個錯誤: Win32Check(SymGetTypeInfo(Index,dwBaseAddress [0],pSymbol^.TypeIndex,TI_FINDCHILDREN,@ChildParams)); 調用者負責內存,所以我們需要爲TI_FINDCHILDREN_PARAMS結構的ChildId數組保留內存! – Remko 2010-06-23 12:26:08

0

我沒有這些東西完全是一個專家,但在C名字修飾前端下劃線有時應該成爲二進制格式的一部分。

如果您刪除了前導下劃線,它會起作用嗎?

+0

我試過已經試過,並沒有什麼區別。 如果我加載並執行例如notepad.exe,並指定WinMain作爲符號名稱,但它的工作原理儘管如此。 – Remko 2010-06-22 19:52:28

相關問題