我正在使用以下例程来修补RTL中的函数.
procedure PatchCode(const AddrProc: Pointer; const CodeSize: NativeUInt;
const Code: Pointer);
var
OldProtect: Cardinal;
begin
VirtualProtect(AddrProc, CodeSize, PAGE_EXECUTE_READWRITE, OldProtect);
Move(Code^, AddrProc^, CodeSize);
VirtualProtect(AddrProc, CodeSize, OldProtect, OldProtect);
end;
Run Code Online (Sandbox Code Playgroud)
但是当我调整我的补丁方法时,它们的大小会发生变化,导致这样的代码破坏:
//PatchRedirect calls PatchCode internally
PatchRedirect(AddrGetMem,{codesize = }17, @RedirectGetMem, JUMPS_GETMEM);
Run Code Online (Sandbox Code Playgroud)
有没有办法在编译时或运行时确定方法的大小?(任何一个都很好).
我希望有一个通用的解决方案,但如果它只适用于asm例程,那对我的目的来说很好.
使用案例
一个用例就是FillChar的更快版本.
99%的时间FillChar用作a ZeroMem.所以我补丁System.ZeroMem:
xor r8,r8
jmp FastFillChar;
Run Code Online (Sandbox Code Playgroud)
我修补System.FillChar与
movzx R8,R8b
mov r9,$0101010101010101
imul r8,r9
jmp FastFillChar
Run Code Online (Sandbox Code Playgroud)
这样我可以使99%的情况下FillChar更快一点.
或者,如果有人打扰实际使用zeromem
更新
感谢Rudy我认为我有一个适用于有限子集的解决方案.
有没有办法获得程序的大小?
如果您有权访问源代码,是的.
Delphi将生成的例程代码放在与该implementation部分中声明的顺序相同的顺序中.
只要您尝试修补的目标代码和从中获取补丁的源代码使用相同的参数进行编译{$CODEALIGN n}就没有问题.
对于Win32,默认值为4,Win32 RTL使用对齐4进行编译.Win64 RTL的代码对齐方式为{$CodeAlign 16}.
只要代码和补丁收件人中的代码对齐匹配,以下代码就可以正常工作:
ProcSize:= NativeInt(@Routine2) - NativeInt(@Routine1);
PatchCode(@Routine1, ProcSize, @System.Something);
Run Code Online (Sandbox Code Playgroud)
任何对齐nops只会增加到下一个倍数的大小,$CodeAlign并且目标代码以相同的方式对齐,所以你应该没问题.
显然,Routine1最好是非常简短,否则你会遇到麻烦,也许在修补if之前断言@dest不是一个裸Jmp到其他一些例程是个好主意ProcSize > $CodeAlign.
| 归档时间: |
|
| 查看次数: |
254 次 |
| 最近记录: |