挂钩从注入的Delphi dll启用__fastcall的MSVC ++上制作的应用程序 [英] Hooking an App made on MSVC++ with __fastcall enabled from an injected Delphi dll

查看:133
本文介绍了挂钩从注入的Delphi dll启用__fastcall的MSVC ++上制作的应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在使用Microsoft Visual Studio 2010编译的应用程序中挂钩一个函数,并从delphi 2010 dll中启用了__fastcall,但是我不懂如何解决以下问题:

I am trying to hook a function within a application compiled with microsoft visual studio 2010, with __fastcall enabled from a delphi 2010 dll, but I am not to skilled to figure out how to detour the following problem:

C ++函数是:

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

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

I was trying something like that (using 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或GCC [4] __fastcall [5]约定(又名__msfastcall)传递适合ECX和EDX的前两个参数(从左到右评估).其余参数从右到左推入堆栈."

"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快速通话从左到右评估参数,它通过EAX,EDX,ECX传递三个参数.其余的参数也从左到右被压入堆栈.[6]这是Embarcadero Delphi的32位编译器的默认调用约定,其中>称为寄存器.

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 Delp where >it is known as register.

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

这是问题所在,borland fastcall和Microsoft __fastcall是不同的.

This is the problem, borland fastcall and microsoft __fastcall are different.

所以我认为我需要在Hook函数中使用一段汇编代码来对齐寄存器或其他内容,但是我还无法弄清楚.

So I'm thinking that I will need to use a piece of assembly code inside the Hook function to align registers or something, but I'm not able to figure this yet.

任何帮助将不胜感激.

David Heffernan Answer部分起作用.(仅在showmessage之前有效)

David Heffernan Answer works partially. (it only works until showmessage)

     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 ++函数正在 ECX EDX 中传递参数.因此,您只需要将它们复制到Delphi期望的寄存器中:分别为 EAX EDX .由于第二个参数已经在正确的寄存器中,因此您需要做的是:

The C++ function is passing parameters in ECX and EDX. So you just need to copy them to the registers that Delphi is expecting: EAX and EDX respectively. Since the second parameter is already in the right register all you need is this:

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 是您的挂钩函数.

I've done this in two functions so that I can write a pure asm only function that does the register swapping. We want pure asm to avoid all preamble. So, onTextMessageWrapper is your hook function.

还请注意,由于您使用的是Unicode Delphi,因此您将希望 PAnsiChar char * 匹配.

Note also that since you are using a Unicode Delp you will want PAnsiChar to match up with char*.

我所知道的有关调用约定的最佳参考是 Agner Fog .您将在此处找到所有血腥细节.重要的一点是,在Windows x86上,EAX,ECX和EDX寄存器是易失性或暂存寄存器.这意味着被调用者可以修改这些寄存器,而不必恢复它们.这就是为什么我在上面修改EAX而不花心地将其放回原处的原因.

The best reference I know for calling conventions is by Agner Fog. You'll find all the gory details there. One important point is that, on Windows x86, the EAX, ECX and EDX registers are volatile, or scratch registers. Which means that callees can modify those registers without having to restore them. Which is why I modify EAX above and do not bother to put it back.

这篇关于挂钩从注入的Delphi dll启用__fastcall的MSVC ++上制作的应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆