visual-studio-2010 - 通过注入(inject)的 Delphi dll 启用 __fastcall 来 Hook 在 MSVC++ 上制作的应用程序

标签 visual-studio-2010 delphi assembly hook delphi-2010

我试图在使用 microsoft Visual Studio 2010 编译的应用程序中 Hook 一个函数,并从 delphi 2010 dll 启用 __fastcall,但我不熟练如何解决以下问题:

C++ 函数是:

     void __fastcall function(int arg1; char* arg2);

我正在尝试类似的事情(使用 uallHook):

    var FTextMessage : procedure(Modo: integer; Msg: pchar); register;
    procedure onTextMessage(Modo: integer; Msg: pchar); register;
    begin
      ShowMessage(inttostr(Modo) + ' - ' + string(Msg));
      FTextMessage(Modo, Msg);
    end;
    begin
    HookCode(Ptr($574210), @onTextMessage, @FTextMessage);
    end.

这会导致调试/崩溃。

所以,我发现:

"Microsoft or GCC[4] __fastcall[5] convention (aka __msfastcall) passes the first two arguments (evaluated left to right) that fit into ECX and EDX. Remaining arguments are pushed onto the stack from right to left."

Borland fastcall Evaluating arguments from left to right, it passes three arguments via EAX, EDX, ECX. Remaining arguments are pushed onto the stack, also left to right.[6] It is the default calling convention of the 32 bit compiler of Embarcadero Delphi, where >it is known as register.

摘自: http://en.wikipedia.org/wiki/X86_calling_conventions

这就是问题所在,borland fastcall 和 microsoft __fastcall 是不同的。

所以我想我需要在 Hook 函数中使用一段汇编代码来对齐寄存器或其他东西,但我还无法弄清楚这一点。

如有任何帮助,我们将不胜感激。

编辑1: 大卫·赫弗南的答案部分有效。 (它只在显示消息之前有效)

     var FTextMessage : procedure(Modo: integer;Msg: PAnsiChar); register;

     procedure onTextMessage(Modo: integer;Msg: PAnsiChar); register;
     begin
       ShowMessage(inttostr(Modo) + ' - ' + string(Msg));
       asm
         MOV ECX,Modo
         MOV EDX,Msg
         JMP FTextMessage
       end;  // I got a crash trying or without trying to restore the registers before executing the JMP FTextMessage
     //  FTextMessage(Modo,Msg); // < Also this method doesnt work either, if I call the Original function from here (without executing asm code above) i got a crash too. (this is what i was meaning with "to correct the registers")
     end;

     procedure onTextMessageWrapper(Modo: Integer;Msg: PAnsiChar); register;
     asm
       MOV EDX,ECX  // < Moving ECX to EDX, I'm able to Access Modo and Msg correctly in onTextMessage procedure.
       JMP onTextMessage
     end;

     begin
       HookCode(Ptr($574210), @onTextMessageWrapper, @FTextMessage);
     end.

最佳答案

C++ 函数正在 ECXEDX 中传递参数。因此,您只需将它们分别复制到 Delphi 所需的寄存器:EAXEDX 即可。由于第二个参数已经在正确的寄存器中,因此您所需要的就是:

procedure onTextMessage(Modo: Integer; Msg: PAnsiChar); register;
begin
  ...
end;

procedure onTextMessageWrapper(Modo: Integer; Msg: PAnsiChar); register;
asm
  MOV EAX,ECX
  JMP onTextMessage
end;

我在两个函数中完成了此操作,以便我可以编写一个纯 asm 函数来进行寄存器交换。我们想要纯 asm 以避免所有前导码。所以,onTextMessageWrapper 是你的钩子(Hook)函数。

另请注意,由于您使用的是 Unicode Delphi,因此您将希望 PAnsiCharchar* 匹配。

我所知道的有关调用约定的最佳引用是 Agner Fog 。你会在那里找到所有血淋淋的细节。重要的一点是,在 Windows x86 上,EAX、ECX 和 EDX 寄存器是 volatile 寄存器或暂存寄存器。这意味着被调用者可以修改这些寄存器而无需恢复它们。这就是为什么我修改了上面的EAX并且懒得把它放回去。

关于visual-studio-2010 - 通过注入(inject)的 Delphi dll 启用 __fastcall 来 Hook 在 MSVC++ 上制作的应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13703303/

相关文章:

assembly - x86组装极限新手查询: "invalid instruction operands"?

c++ - 如何从 Windows 中的 Image 对象获取像素信息?

delphi - 确定要包含的 Delphi 运行时包

c++ - malloc导致内存泄漏

delphi - delphi中如何检测修饰键?

Delphi - 带有变体部分的记录

assembly - DOS 可执行文件中的 "MZ" header 及其对堆栈的影响

assembly - 汇编语言中的数字地址

c++ - 如何最好地组织 Visual Studio 2010 C++ 中的依赖项?

C++ Visual Studio .exe 消失