2012-01-23 2 views
17

일부 수정을 통해 직접 처리 할 수 ​​있도록 루틴 호출을 패치하고 싶습니다. 리소스 로더를 작성 중입니다. Delphi의 LoadResourceModule과 InitInheritedComponent 루틴을 내 패치로 패치하고 싶습니다. 내가 MadEcept.pas 단위에서 PatchAPI 호출을 확인했지만 내 프로젝트에 사용할 수 있다면 그것을 알아낼 수 없습니다. 이에델파이에 패치 루틴 호출

모든 포인터는 매우 도움이 될 것입니다 ...> MyCustomResourceModule -> LoadResourceModule - -> 점프에

나는 런타임 통화에서

내 EXE 같은 것을 원한다.

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 비트 코드를 작동

+3

이이 질문을 확인 detour''라고 [외부에서 선언 된 함수의 구현 (우회)를 변경하는 방법 (http://stackoverflow.com/questions/6905287/ 구현 방법 - 외부에서 선언 된 기능의 우회 방법) – RRUZ

+0

방금 ​​같은 생각을하고있었습니다. 따라서이 기술을 사용하면 구성 요소 스트리밍에 코드를 추가 할 수 있습니다 (DFM에서 코드 추가). 응용 프로그램) 메커니즘에? 따라서 예를 들어, 중고 컴포넌트 클래스를 로깅하거나 품질 보증 (BDE 클래스를 사용하지 마십시오! 또는 컴포넌트 X의 이전 버전)을 사용할 수 있습니다. – mjn

+2

@mjn 더 쉽게 수행 할 수있는 다른 확장 점이 있습니다. 예 :'TReader.OnFindComponentClass'. 패치 코드는 다른 사람이 작업을 완료 할 수 없을 때 항상 최후의 수단이어야합니다. –

답변

16

는 다음 코드를 사용합니다. 또한 이전 함수와 새 함수가 동일한 실행 모듈에있는 경우 64 비트 코드에서도 작동합니다. 그렇지 않으면 점프 거리가 32 비트 정수의 범위를 초과 할 수 있습니다.

두 사람의 주소가 얼마나 멀리 떨어져 있는지에 관계없이 누군가가 64 비트 주소 공간에서 근무하는 대안을 제공 할 수 있다면 매우 흥미 롭습니다.

+6

리디렉션을 unpatch *하거나 응용 프로그램을 닫을 때 코드가 끊어지지 않도록하는 것이 좋습니다. 리디렉션 된 호출이 만들어 질 수 있습니다 (예 : RTL 또는 리디렉션 장치 앞에로드 된 다른 장치). 그리고 점프합니다 일부 초기화되지 않은 코드. –

+0

@Arnaud 사실 일 수 있습니다. 이 모든 사용 내 모든 호출이 이루어지기 전에 리디렉션 또는 부작용이없는 루틴 및 unpatching 상관 관계가 없습니다. –

+0

@DavidHeffernan 그냥 생각을 위해 어떻게 내가 이전 프로 시저 호출 할 수 기본 그 값에 대해 작업하십시오. 위의 코드에서 새 루틴으로 이동하기 위해 이전 루틴의 주소를 덮어 씁니다. MyLoadResourceModule과 같은 것은 내부적으로 LoadResourceModule을 사용하여 추가 작업을 수행합니다 .... –

7

이미 Delphi detours library이 있습니다.

델파이 본론 도서관

는 .IT 쉬운 삽입하는 방법과 제거 후크를 제공 델파이 및 Windows API 함수를 후크 할 수 있도록 라이브러리입니다.

특징 :

  • 지원 x86 및 x64 아키텍처.
  • 트램펄린 기능을 통해 원래 기능 호출 허용.
  • 멀티 훅 지원.
  • COM/인터페이스/win32api 지원.
  • COM vtable 패치 지원.
  • 완전 스레드 안전 코드 후킹 및 언 후킹.
  • 지원 후킹 개체 메서드.
  • 지원되는 Delphi 7/2005-2010/XE-XE7.
  • 나사로/FPC를 지원합니다.
  • 64 비트 주소가 지원됩니다.
  • 라이브러리는 외부 라이브러리를 사용하지 않습니다.
  • 라이브러리는 언제든지 후크를 삽입하고 제거 할 수 있습니다.
  • 라이브러리에는 asm 명령어 (x86 & x64)를 디코딩 할 수있는 InstDecode 라이브러리가 들어 있습니다.
3

필자는 David Heffernan의 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; 
관련 문제