3

有没有办法访问包含在可执行文件中的绝地调试信息(JDBG)?

Microsoft 调试工具已将我指向二进制文件中的堆栈链,我想知道这些偏移量对应的方法/过程/函数:

user32.dll!SendMessageA+0x4c
StackOverflow.exe+0x179263
StackOverflow.exe+0x2315b5
StackOverflow.exe+0x1fc82
StackOverflow.exe+0x50388
StackOverflow.exe+0x541fe
user32.dll!gapfnScSendMessage+0x332

显然我在打电话SendMessage,但我不知道从哪里来。可执行文件是使用嵌入在可执行文件中的 Jcl 调试信息构建的;但我不知道如何阅读它。

查看 中的一些函数和类JclDebug.pas,一切似乎都是为了获取当前进程内部的调试信息,例如:

function GetLocationInfo(const Addr: Pointer; var Info: TJclLocationInfo): Boolean;

在我当前进程的地址空间中获取一个地址。它找出HMODULE地址所在的位置,例如:

  • 堆栈溢出.exe
  • GDI32.dll
  • USER32.dll
  • 内核基础.dll
  • dwmapi.dll
  • UxTheme.dll

我在想我可以使用LoadLibrary(返回一个HMODULE)来手动加载一个模块,然后将它提供给一些通过模块图像挖掘以获取调试信息的类:

module := LoadLibrary('C:\Users\Ian\Desktop\StackOverflow.exe');

TJclDebugInfoList = class(TObjectList)
private
   function GetItemFromModule(const Module: HMODULE): TJclDebugInfoSource;
   ...
protected
   function CreateDebugInfo(const Module: HMODULE): TJclDebugInfoSource;
   ...
end;

除非它受到保护。

我正在尝试(希望)我可以编写一个工具来选择二进制文件(*.exe),输入地址,然后返回

  • 功能
  • 方法
  • 文件
  • 电话号码

的偏移量。

例如

[002315B5] FMain.TfrmMain.lvQuestions (Line 158, "FMain.pas" + 1) + $11

可能的?


编辑:我的第一个粗略和现成的方法是提取压缩map文件,以便我可以查看它。但它没有保存为资源():

在此处输入图像描述

虽然通用工具会更有用:

在此处输入图像描述


更新

我尝试使用TJclDebugInfoList;我意识到数组属性ItemFromModule将访问受保护的方法:

function GetModuleLocationInfo(filename: string; Addr: Pointer): TJclLocationInfo;
var
   module: HMODULE;
   infoList: TJclDebugInfoList;
   infoSource: TJclDebugInfoSource;

   Address: Pointer;
   locationInfo: TJclLocationInfo;
   AddressOffset: Integer;
begin
   module := LoadLibrary(filename);
   if module = 0 then
      RaiseLastWin32Error;
   try
      infoList := TJclDebugInfoList.Create;
      try
         infoSource := infoList.ItemFromModule[module];
         if source = nil then
            raise Exception.Create('Could not find debug info source for module '+IntToStr(module));
         if not source.GetLocationInfo(Addr, {var}locationInfo) then
            raise Exception.Create('Could not get location info for address $'+IntToHex(Integer(Address), 8));

         Result := locationInfo;
      finally
         infoList.Free;
      end;
   finally
      FreeLibrary(module);
   end;
end;

除了其中一个TJclDebugInfoSource后代类中的代码尝试将其假定为虚拟地址的内容转换为偏移地址时出现下溢。

4

3 回答 3

2

使用从. TJclDebugInfoBinary_ 然后调用它。无论如何,这一切都会完成,除了它有一些帮助方法将地址从当前地址空间映射到它们对应的模块,而当您手动执行此操作时,您必须已经知道地址属于哪个模块。(但是故障转储已经告诉了你那部分,所以你不需要列表类的帮助。)HModuleLoadLibraryGetLocationInfoTJclDebugInfoList

您可能必须修改地址,因为崩溃时模块的基地址与您加载时的基地址不同LoadLibrary

JCL 调试信息不​​存储在资源中。它存储在名为 JCLDEBUG 的 PE 部分中。请参阅JclDebug.pasPeMapImgFindSection32中和PeMapImgFindSectionFromModule的用法。

于 2011-05-17T18:00:48.477 回答
1

我前段时间做了一个这样的工具,不知道能不能找回来,但至少有可能:-)

另一方面,我使用 jclDebug.pas 制作了几个工具,现在我记得:我对其进行了一些更改以使“离线”堆栈跟踪成为可能。你可以看看这些:

实时进程堆栈查看器: http ://code.google.com/p/asmprofiler/wiki/ProcessStackViewer

Minidump 阅读器(使用离线阅读 .map 或来自 exe 的嵌入式 jdbg 信息): http ://code.google.com/p/asmprofiler/source/browse/#svn%2Ftrunk%2FMiniDumpReader

于 2011-05-18T06:36:01.057 回答
1

这是代码可以提供有关模块中地址的调试信息

function GetModuleLocationInfo(filename: string; AddressOffset: Pointer; AssumeOffsetIsRelativeToStartOfCodeSection: Boolean=False): TJclLocationInfo;
var
    module: HMODULE;
    infoList: TJclDebugInfoList;
    infoSource: TJclDebugInfoSource;

    Address: Pointer;
    locationInfo: TJclLocationInfo;
begin
    //Code is public domain. No attribution required.
    module := LoadLibrary(PChar(filename));
    if module = 0 then
        RaiseLastWin32Error;
    try
        infoList := TJclDebugInfoList.Create;
        try
            infoSource := infoList.ItemFromModule[module];
            if infoSource = nil then
                raise Exception.Create('Could not find debug info source for module '+IntToStr(module));

            DWORD(Address) := DWORD(AddressOffset) + DWORD(module) + DWORD(ModuleCodeOffset);
            if not infoSource.GetLocationInfo(Address, {var}locationInfo) then
                raise Exception.Create('Could not get location info for address $'+IntToHex(Integer(Address), 8));

            Result := locationInfo;
        finally
            infoList.Free;
        end;
    finally
        FreeLibrary(module);
    end;
end;

还有一个实际示例,来自 Process Explorer 的偏移量:

在此处输入图像描述

GetModuleLocationInfo('C:\Program Files (x86)\Avatar\HelpDesk.exe', 0xdcb17);

返回:

TJclLocationInfo
   Address: $266CB17
   UnitName: 'BalloonHint'
   ProcedureName: 'TBalloonHint.SetVisible'
   OffsetFromProcName: 83
   LineNumber: 281
   OffsetFromLineNumber: 0
   SourceName: 'BalloonHint.pas'
   DebugInfo: $1F25C74

或者采用 JclDebug 的风格:

[0266CB17] BalloonHint.TBalloonHint.SetVisible(第 281 行,“BalloonHint.pas”)+ $0

于 2011-10-27T16:15:54.500 回答