@GadDLord의 How to change the implementation (detour) of an externally declared function을 기반으로 TScreen.GetWorkAreaRect에서 사용되는 SystemParametersInfoW를 연결할 수 있습니다. 죽은 링크를 막기 위해 코드 부분을 복사했습니다.
type
//strctures to hold the address and instructions to patch
TJumpOfs = Integer;
PPointer = ^Pointer;
PXRedirCode = ^TXRedirCode;
TXRedirCode = packed record
Jump: Byte;
Offset: TJumpOfs;
end;
PAbsoluteIndirectJmp = ^TAbsoluteIndirectJmp;
TAbsoluteIndirectJmp = packed record
OpCode: Word;
Addr: PPointer;
end;
var
DataCompareBackup: TXRedirCode; //Store the original address of the function to patch
//get the address of a procedure or method of a function
function GetActualAddr(Proc: Pointer): Pointer;
begin
if Proc <> nil then
begin
if (Win32Platform = VER_PLATFORM_WIN32_NT) and (PAbsoluteIndirectJmp(Proc).OpCode = $25FF) then
Result := PAbsoluteIndirectJmp(Proc).Addr^
else
Result := Proc;
end
else
Result := nil;
end;
//patch the original function or procedure
procedure HookProc(Proc, Dest: Pointer; var BackupCode: TXRedirCode);
var
n: {$IFDEF VER230}NativeUInt{$ELSE}DWORD{$ENDIF};
Code: TXRedirCode;
begin
Proc := GetActualAddr(Proc);
Assert(Proc <> nil);
//store the address of the original procedure to patch
if ReadProcessMemory(GetCurrentProcess, Proc, @BackupCode, SizeOf(BackupCode), n) then
begin
Code.Jump := $E9;
Code.Offset := PAnsiChar(Dest) - PAnsiChar(Proc) - SizeOf(Code);
//replace the target procedure address with the new one.
WriteProcessMemory(GetCurrentProcess, Proc, @Code, SizeOf(Code), n);
end;
end;
//restore the original address of the hooked function or procedure
procedure UnhookProc(Proc: Pointer; var BackupCode: TXRedirCode);
var
n: {$IFDEF VER230}NativeUInt{$ELSE}Cardinal{$ENDIF};
begin
if (BackupCode.Jump <> 0) and (Proc <> nil) then
begin
Proc := GetActualAddr(Proc);
Assert(Proc <> nil);
WriteProcessMemory(GetCurrentProcess, Proc, @BackupCode, SizeOf(BackupCode), n);
BackupCode.Jump := 0;
end;
end;
function MySystemParametersInfo(uiAction, uiParam: UINT;
pvParam: Pointer; fWinIni: UINT): BOOL; stdcall;
begin
Result := SystemParametersInfoA(uiAction, uiParam,pvParam,fWinIni);
if uiAction=SPI_GETWORKAREA then
begin
// Fake just for demo
TRect(pvParam^).Right := 1234;
end
end;
procedure TForm3.Button1Click(Sender: TObject);
begin
Caption := IntToStr(Screen.WorkAreaRect.Right)
end;
initialization
HookProc(@SystemParametersInfoW, @MySystemParametersInfo, DatacompareBackup);
finalization
UnHookProc(@SystemParametersInfoW, DatacompareBackup);
소스 코드를보고 교체해야 할 사항을 찾아 우회하십시오. 필요한 것을 수행하는 최저 수준의 기능을 우회하십시오. –