我正在尝试在使用 microsoft visual studio 2010 编译的应用程序中挂钩一个函数,并从 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 或 GCC[4] __fastcall[5] 约定(又名 __msfastcall)传递适合 ECX 和 EDX 的前两个参数(从左到右评估)。剩余的参数从右到左推入堆栈。”
Borland fastcall 从左到右评估参数,它通过 EAX、EDX、ECX 传递三个参数。剩余的参数被压入堆栈,也是从左到右。 [6] 它是 Embarcadero Delphi 的 32 位编译器的默认调用约定,其中 >it 被称为寄存器。
取自: http ://en.wikipedia.org/wiki/X86_calling_conventions
这就是问题所在,borland fastcall 和microsoft __fastcall 是不同的。
所以我想我需要在 Hook 函数中使用一段汇编代码来对齐寄存器或其他东西,但我还不能解决这个问题。
任何帮助,将不胜感激。
Edit1:David Heffernan 回答部分有效。(它只在显示消息之前有效)
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.