如何检测哪个钩子proc调用我的蹦床?

时间:2015-04-15 20:17:10

标签: delphi hook

我想对应用程序在dll中调用函数的次数进行一些分析 为了做到这一点,我将每个导出的函数挂钩在dll中 例如。如果我想跟踪user32.dll的呼叫,我需要挂钩830电话。

显然,我不想写830个蹦床功能,所以我提出了以下方案:

使用以下钩子功能:

var
  HookFunctionPtr: pointer = nil;

procedure HookFunction;
asm
  .NOFRAME
  CALL @@test  //5 bytes
@@Start0:
  ret; nop; nop  //3 bytes
  CALL @@test  //5 bytes
@@Start1: //Repeat this 1390 times.
  ret; nop; nop  //3 bytes
  //Examine the return address to see which call was hooked here.
@@Test:
  pop rax
  push rax
  push rcx
  mov rcx, qword ptr [HookFunctionPtr]
  add rcx,5
  sub rax,rcx
  shr rax,3 //divide by 8
  mov rcx,rax
  call HookFunction
  pop rcx
  ret
end;

procedure LogCalledFunction(DllEntry: Cardinal);
....

在进行挂钩时,我只需遍历dll pe-header以获取导出函数的地址。并在上面的函数内添加一个钩子 每个后续挂钩都高出8个字节。

我没有看到任何其他方式来判断哪个dll-entry导致了挂钩电话 有没有更好的方法来做到这一点,而无需重复相同的代码片数百次。

1 个答案:

答案 0 :(得分:1)

您必须为每个函数动态分配一个单独的存根,其中存根包含所需的上下文信息(DLL函数名称/ ID等)以及一些最小的代码,用一个额外的参数来调用您的真实蹦床在存根的上下文数据中。当您挂钩DLL函数时,您将使用存根作为钩子蹦床。当调用存根时,它会调用真实的trampoline,然后可以访问上下文数据。

这类似于Delphi的System.Classes.MakeObjectInstance()函数所使用的方法,该函数将TWndMethod包装在存根中以允许对象方法(最值得注意的是TWinControl.WndProc()TTimer.WndProc()方法)用作CreateWindow/Ex() / SetWindowLongPtr(GWL_WNDPROC)的Win32 API回调。当存根被Windows调用时,存根调用辅助函数(System.Classes.StdWndProc()),然后调用存根TWndMethod中指定的实际对象方法。

这允许一段代码处理任意数量的对象实例。你需要类似的东西。