How to make FastCodePatch work in Delphi XE2 Win64 platform?

前端 未结 2 2019
星月不相逢
星月不相逢 2021-02-08 05:10

Unit FastCodePatch.pas works in Win32 platform. Delphi XE2 supports Win64 platform, any ideas how to make FastCodePatch works in Win64 platform?

unit FastcodePa         


        
相关标签:
2条回答
  • 2021-02-08 05:30

    For the FastcodeAddressPatch-function, this version works both in 32-bit and 64-bit when I try. The key is changing "pointer" to "integer" because the Intel relative jump-instruction ($E9) still use an 32-bit offset in 64-bit mode.

    type
      PJump = ^TJump;
      TJump = packed record
        OpCode: Byte;
        Distance: integer;
      end;
    
    procedure FastcodeAddressPatch(const ASource, ADestination: Pointer);
    const
      Size = SizeOf(TJump);
    var
      NewJump: PJump;
      OldProtect: Cardinal;
    begin
      if VirtualProtect(ASource, Size, PAGE_EXECUTE_READWRITE, OldProtect) then
      begin
        NewJump := PJump(ASource);
        NewJump.OpCode := $E9;
        NewJump.Distance := NativeInt(ADestination) - NativeInt(ASource) - Size;
    
        FlushInstructionCache(GetCurrentProcess, ASource, SizeOf(TJump));
        VirtualProtect(ASource, Size, OldProtect, @OldProtect);
      end;
    end;
    
    procedure Test;
    begin
      MessageBox(0,'Original','',0);
    end;
    
    procedure NewTest;
    begin
      MessageBox(0,'Patched','',0);
    end;
    
    procedure TForm5.FormCreate(Sender: TObject);
    begin
      FastcodeAddressPatch(@Test,@NewTest);
      Test;
    end;
    

    I'm not sure what the other function does but I'm guessing it should be like this:

    function FastcodeGetAddress(AStub: Pointer): Pointer;
    begin
      if PBYTE(AStub)^ = $E8 then
      begin
        Inc(NativeInt(AStub));
        Result := Pointer(NativeInt(AStub) + SizeOf(integer) + PInteger(AStub)^);
      end
      else
        Result := nil;
    end;
    
    0 讨论(0)
  • 2021-02-08 05:33

    The following code works for both Win32 - Standalone and Package, Win64 - Standalone and Package:

    type
      TNativeUInt = {$if CompilerVersion < 23}Cardinal{$else}NativeUInt{$ifend};
    
      PJump = ^TJump;
      TJump = packed record
        OpCode: Byte;
        Distance: integer;
      end;
    
    function GetActualAddr(Proc: Pointer): Pointer;
    type
      PAbsoluteIndirectJmp = ^TAbsoluteIndirectJmp;
      TAbsoluteIndirectJmp = packed record
        OpCode: Word;   //$FF25(Jmp, FF /4)
        Addr: Cardinal;
      end;
    var J: PAbsoluteIndirectJmp;
    begin
      J := PAbsoluteIndirectJmp(Proc);
      if (J.OpCode = $25FF) then
        {$ifdef Win32}Result := PPointer(J.Addr)^{$endif}
        {$ifdef Win64}Result := PPointer(TNativeUInt(Proc) + J.Addr + 6{Instruction Size})^{$endif}
      else
        Result := Proc;
    end;
    
    procedure FastcodeAddressPatch(const ASource, ADestination: Pointer);
    const
      Size = SizeOf(TJump);
    var
      NewJump: PJump;
      OldProtect: Cardinal;
      P: Pointer;
    begin
      P := GetActualAddr(ASource);
      if VirtualProtect(P, Size, PAGE_EXECUTE_READWRITE, OldProtect) then
      begin
        NewJump := PJump(P);
        NewJump.OpCode := $E9;
        NewJump.Distance := TNativeUInt(ADestination) - TNativeUInt(P) - Size;
    
        FlushInstructionCache(GetCurrentProcess, P, SizeOf(TJump));
        VirtualProtect(P, Size, OldProtect, @OldProtect);
      end;
    end;
    
    0 讨论(0)
提交回复
热议问题