delphi monkeypatching

Llamada de rutina de parche en Delphi



monkeypatching (3)

Quiero parchar una llamada de rutina para poder manejarlo yo mismo con algunas modificaciones. Estoy escribiendo un cargador de recursos. Quiero parchear las rutinas LoadResourceModule y InitInheritedComponent de Delphi con las mías. Revisé la llamada de PatchAPI en la unidad MadExcept.pas, pero no pude determinar si puedo usar eso para mi proyecto.

Quiero algo como

mi exe en tiempo de ejecución llama -> LoadResourceModule -> salta a -> MyCustomResourceModule ...

Cualquier sugerencia sobre esto sería muy útil.


Yo uso el siguiente código:

procedure PatchCode(Address: Pointer; const NewCode; Size: Integer); var OldProtect: DWORD; begin if VirtualProtect(Address, Size, PAGE_EXECUTE_READWRITE, OldProtect) then begin Move(NewCode, Address^, Size); FlushInstructionCache(GetCurrentProcess, Address, Size); VirtualProtect(Address, Size, OldProtect, @OldProtect); end; end; type PInstruction = ^TInstruction; TInstruction = packed record Opcode: Byte; Offset: Integer; end; procedure RedirectProcedure(OldAddress, NewAddress: Pointer); var NewCode: TInstruction; begin NewCode.Opcode := $E9;//jump relative NewCode.Offset := NativeInt(NewAddress)-NativeInt(OldAddress)-SizeOf(NewCode); PatchCode(OldAddress, NewCode, SizeOf(NewCode)); end;

Implementarás tu gancho / parche / desvío llamando a RedirectProcedure :

RedirectProcedure(@LoadResourceModule, @MyLoadResourceModule);

Esto funcionará para el código de 32 bits. También funcionará para el código de 64 bits siempre que las funciones antiguas y nuevas residan en el mismo módulo ejecutable. De lo contrario, la distancia de salto puede exceder el rango de un entero de 32 bits.

Me interesaría mucho si alguien pudiera proporcionar una alternativa que funcionara para el espacio de direcciones de 64 bits, independientemente de lo lejos que estuvieran las dos direcciones.


Modifiqué el código de David Heffernan para soporte de 64 bits y salto indirecto a métodos en un BPL. Con la ayuda de: http://chee-yang.blogspot.com.tr/2008/11/hack-into-delphi-class.html

type PAbsoluteIndirectJmp = ^TAbsoluteIndirectJmp; TAbsoluteIndirectJmp = packed record OpCode: Word; // $FF25(Jmp, FF /4) Addr: DWORD; // 32-bit address // in 32-bit mode: it is a direct jmp address to target method // in 64-bit mode: it is a relative pointer to a 64-bit address used to jmp to target method end; PInstruction = ^TInstruction; TInstruction = packed record Opcode: Byte; Offset: Integer; end; function GetActualAddr(Proc: Pointer): Pointer; begin Result := Proc; if Result <> nil then if PAbsoluteIndirectJmp(Result)^.OpCode = $25FF then // we need to understand if it is proc entry or a jmp following an address {$ifdef CPUX64} Result := PPointer( NativeInt(Result) + PAbsoluteIndirectJmp(Result)^.Addr + SizeOf(TAbsoluteIndirectJmp))^; // in 64-bit mode target address is a 64-bit address (jmp qword ptr [32-bit relative address] FF 25 XX XX XX XX) // The address is in a loaction pointed by ( Addr + Current EIP = XX XX XX XX + EIP) // We also need to add (instruction + operand) size (SizeOf(TAbsoluteIndirectJmp)) to calculate relative address // XX XX XX XX + Current EIP + SizeOf(TAbsoluteIndirectJmp) {$else} Result := PPointer(PAbsoluteIndirectJmp(Result)^.Addr)^; // in 32-bit it is a direct address to method {$endif} end; procedure PatchCode(Address: Pointer; const NewCode; Size: Integer); var OldProtect: DWORD; begin if VirtualProtect(Address, Size, PAGE_EXECUTE_READWRITE, OldProtect) then //FM: remove the write protect on Code Segment begin Move(NewCode, Address^, Size); FlushInstructionCache(GetCurrentProcess, Address, Size); VirtualProtect(Address, Size, OldProtect, @OldProtect); // restore write protection end; end; procedure RedirectProcedure(OldAddress, NewAddress: Pointer); var NewCode: TInstruction; begin OldAddress := GetActualAddr(OldAddress); NewCode.Opcode := $E9;//jump relative NewCode.Offset := NativeInt(NewAddress) - NativeInt(OldAddress) - SizeOf(NewCode); PatchCode(OldAddress, NewCode, SizeOf(NewCode)); end;


Ya hay una biblioteca de desvíos de Delphi para esto.

La Biblioteca Delphi Detours es una biblioteca que le permite enlazar las funciones delphi y API de Windows. Proporciona una manera fácil de insertar y quitar el gancho.

Caracteristicas :

  • Admite la arquitectura x86 y x64.
  • Permitir llamar a la función original a través de la función Trampoline.
  • Soporte para Multi Hook.
  • Compatibilidad con COM / Interfaces / win32api.
  • Soporte de parcheo Vtable.
  • Codificación y desenganche de código totalmente seguro para subprocesos.
  • Soporte de gancho Método de objeto.
  • Compatible con Delphi 7 / 2005-2010 / XE-XE7.
  • Soporte Lazarus / FPC.
  • La dirección de 64 bit es compatible.
  • La biblioteca no usa ninguna biblioteca externa.
  • La biblioteca puede insertar y quitar el gancho en cualquier momento.
  • La biblioteca contiene la biblioteca InstDecode, que le permite decodificar instrucciones asm (x86 y x64).