是否可以修補/重定向 RTL 中定義的記錄的任何方法?如果是,該怎么做?
我正在嘗試修補TValue.TryCast函式,我想將此函式重定向到我的函式定義,從那里跳轉到 orinal 函式,然后檢查其他內容并退出。
為了闡明這個話題,這就是我現在正在做的事情,但它沒有用。
我宣告:
type
TValueHelper = record helper for TValue
public
function TryCastFixed(ATypeInfo: PTypeInfo; out AResult: TValue): Boolean;
end;
var
TValueTryCastOrgAddr: Pointer;
function TValueHelper.TryCastFixed(ATypeInfo: PTypeInfo; out AResult: TValue): Boolean;
begin
asm
JMP TValueTryCastOrgAddr
end;
// fix for conversion from TValue
if not Result and (ATypeInfo <> Nil) and (ATypeInfo = System.TypeInfo(TValue)) then begin
AResult := TValue.From<TValue>(Self);
Exit(True);
end;
end;
然后有一個補丁的東西:
type
PAbsoluteIndirectJmp = ^TAbsoluteIndirectJmp;
TAbsoluteIndirectJmp = packed record
OpCode: Word; //$FF25(Jmp, FF /4)
Addr: ^Pointer;
end;
function WriteProtectedMemory(BaseAddress, Buffer: Pointer; Size: Cardinal; out WrittenBytes: Cardinal): Boolean;
var
OldProtect, Dummy: Cardinal;
begin
WrittenBytes := 0;
if Size > 0 then begin // VirtualProtect for DEP issues
OldProtect := 0;
Result := VirtualProtect(BaseAddress, Size, PAGE_EXECUTE_READWRITE, OldProtect);
if Result then try
Move(Buffer^, BaseAddress^, Size);
WrittenBytes := Size;
if OldProtect in [PAGE_EXECUTE, PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE, PAGE_EXECUTE_WRITECOPY] then
FlushInstructionCache(GetCurrentProcess, BaseAddress, Size);
finally
Dummy := 0;
VirtualProtect(BaseAddress, Size, OldProtect, Dummy);
end;
end;
Result := WrittenBytes = Size;
end;
function GetActualAddr(Proc: Pointer): Pointer;
begin
if Proc <> Nil then begin
if (PAbsoluteIndirectJmp(Proc).OpCode = $25FF) then
Result := PAbsoluteIndirectJmp(Proc).Addr^
else
Result := Proc;
end
else
Result := Nil;
end;
procedure RedirectFunction(OldP, DestP: Pointer);
type
TJump = packed record
Jmp: Byte; // $E9;
Offset: Integer;
end;
var
Jump: TJump;
WrittenBytes: Cardinal;
begin
if IsLibrary then
raise Exception.Create('RedirectFunction: Not allowed in a DLL');
//
OldP := GetActualAddr(OldP);
TValueTryCastOrgAddr := OldP;
DestP := GetActualAddr(DestP);
Jump.Jmp := $E9;
Jump.Offset := Integer(DestP) - Integer(OldP) - SizeOf(TJump);
WriteProtectedMemory(OldP, @Jump, SizeOf(TJump), WrittenBytes);
end;
procedure PatchTValueHelper_TryCast;
begin
RedirectFunction(@@TValue.TryCast, @@TValueHelper.TryCastFixed); // this is not working,
// as it can't access undeclared record, how to do it correctly?
end;
可以看出,代碼是由互聯網上的點點滴滴完成的,PatchTValueHelper_TryCast是我的主要問題。
如何在全球范圍內從此記錄中修補功能?
謝謝,內夫頓。
uj5u.com熱心網友回復:
首先要修補的代碼是這樣的:
RedirectFunction(@TValue.TryCast, @TValue.TryCastFixed);
但是你的TryCastFixed實作被破壞了,會導致堆疊溢位或更糟。重定向你做簡單的方式將 jmp 指令寫入TryCast. 這意味著每當您呼叫或跳轉到原始方法時,它都會跳轉到您的方法。如果您的方法向后跳,則您將無限回圈地來回跳躍。您的 jmp 指令也發生在編譯器創建的方法開始內已經執行的一些代碼之后。這意味著暫存器中的值可能不再相同,您不能在這里簡單地使用 jmp 指令。
如果您仍想使用原始方法,則需要使用 DDetours 或 madCodeHook 等庫(我假設還有其他方法)。
否則,我建議您只需將 RTL TryCast 中的代碼復制到您的例程中并添加修復程式,這樣您就可以擺脫重定向,因為那時您不再需要原始方法。
uj5u.com熱心網友回復:
你試過https://github.com/MahdiSafsafi/DDetours嗎?這是一個專門為掛鉤 Delphi 函式而設計的庫。免責宣告:我知道它是否可以攔截記錄輔助方法。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/493573.html
