2011-09-28 17 views
11

L'unità FastCodePatch.pas funziona con la piattaforma Win32. Delphi XE2 supporta la piattaforma Win64, qualche idea su come far funzionare FastCodePatch nella piattaforma Win64?Come far funzionare FastCodePatch nella piattaforma Delphi XE2 Win64?

unit FastcodePatch; 

interface 

function FastcodeGetAddress(AStub: Pointer): Pointer; 
procedure FastcodeAddressPatch(const ASource, ADestination: Pointer); 

implementation 

uses 
    Windows; 

type 
    PJump = ^TJump; 
    TJump = packed record 
    OpCode: Byte; 
    Distance: Pointer; 
    end; 

function FastcodeGetAddress(AStub: Pointer): Pointer; 
begin 
    if PBYTE(AStub)^ = $E8 then 
    begin 
    Inc(Integer(AStub)); 
    Result := Pointer(Integer(AStub) + SizeOf(Pointer) + PInteger(AStub)^); 
    end 
    else 
    Result := nil; 
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 := Pointer(Integer(ADestination) - Integer(ASource) - 5); 

    FlushInstructionCache(GetCurrentProcess, ASource, SizeOf(TJump)); 
    VirtualProtect(ASource, Size, OldProtect, @OldProtect); 
    end; 
end; 

end. 

La soluzione fornita da Ville Krumlinde non funziona su 64 bit pacchetto. Funziona solo con l'applicazione .exe standalone.

risposta

4

Il seguente codice funziona sia per Win32 - Standalone e Package, Win64 - Standalone e pacchetto:

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

Questo è in realtà la risposta a una domanda diversa. Ville ha risposto alla tua domanda originale.Il patching delle funzioni nei pacchetti è un gioco diverso.Il codice che presenti è necessario anche su target a 32 bit. –

+0

Great code ! Confermo che funziona perfettamente con 'Delphi 10.1' (Berlin) con' Windows 7' a 32/64 bit, anche con 'DEP' abilitato. –

12

Per la funzione FastcodeAddressPatch, questa versione funziona sia a 32 che a 64 bit quando provo. La chiave sta cambiando il "puntatore" in "intero" perché l'istruzione di salto relativa Intel ($ E9) utilizza ancora un offset a 32 bit in modalità 64 bit.

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; 

io non sono sicuro di quello che l'altra funzione fa ma credo che dovrebbe essere simile a questo:

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

+1 Per essere chiari, la differenza è che la versione nella domanda utilizza un puntatore da 8 byte nel record TJump che non è corretto. –

+0

Aha, ora voglio rimuovere il mio upvote. 'Integer (ADestination) - Integer (ASource)' non può essere corretto su Win64. Devi usare 'NativeInt'. –

+0

@David: modificato in NativeInt nell'espressione. Il campo Distanza che è la destinazione dell'espressione deve essere a 32 bit, proprio come dici tu. –

Problemi correlati