Подтвердить что ты не робот

Патч обычный вызов в delphi

Я хочу исправить обычный вызов, чтобы иметь возможность обрабатывать его сам с некоторыми изменениями. Я пишу загрузчик ресурсов. Я хочу исправить Delphi LoadResourceModule и InitInheritedComponent с моим. Я проверил PatchAPI-вызов в блоке MadExcept.pas, но не смог понять, могу ли я использовать его для моего проекта.

Мне нужно что-то вроде

мой exe при вызовах во время выполнения → LoadResourceModule → перейти в → MyCustomResourceModule...

Любые указатели на это будут очень полезны.

4b9b3361

Ответ 1

Я использую следующий код:

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;

Вы выполнили бы свой крюк/патч/обход, вызвав RedirectProcedure:

RedirectProcedure(@LoadResourceModule, @MyLoadResourceModule);

Это будет работать для 32-битного кода. Он также будет работать для 64-битного кода при условии, что как старые, так и новые функции находятся в одном и том же исполняемом модуле. В противном случае расстояние перехода может превышать диапазон 32-битного целого.

Мне было бы очень интересно, если бы кто-то мог предоставить альтернативу, которая работала для 64-битного адресного пространства, независимо от того, насколько далеко друг от друга были два адреса.

Ответ 2

Для этого уже существует Delphi обходная библиотека.

Библиотека Delphi Detours - это библиотека, позволяющая подключать delphi и API окон. Он обеспечивает простой способ вставки и удалите крючок.

Особенности:

  • Поддержка архитектуры x86 и x64.
  • Разрешить вызов исходной функции через функцию Trampoline.
  • Поддержка Multi Hook.
  • Поддержка COM/интерфейсов/win32api.
  • Поддержка COM vtable patching.
  • Полностью потокобезопасный код для подключения и отцепления.
  • Поддержка метода привязки объектов.
  • Поддерживается Delphi 7/2005-2010/XE-XE7.
  • Поддержка Lazarus/FPC.
  • Поддерживается 64-разрядный адрес.
  • Библиотека не использует внешнюю библиотеку.
  • Библиотека может вставлять и удалять крючок в любое время.
  • Библиотека содержит библиотеку InstDecode, которая позволяет вам декодировать инструкции asm (x86 и x64).

Ответ 3

Я изменил код Дэвида Хеффернана на 64-битную поддержку и косвенный переход к методам в BPL. С некоторой помощью: 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;