首頁>Program>source

我具有第三方功能

function DataCompare(const S1, S2: string; APartial: Boolean): Boolean;
begin
   ...
end;

它在另一个第三方單元中使用。

我希望在執行時用另一个新的實現替換函式體。

這可能吗? 我猜將需要一些破解(例如VirtualMemoryUnprotect).非常欢迎使用非彙編程式解決方案。

最新回復
  • 6月前
    1 #

    是的,您可以使用 ReadProcessMemoryWriteProcessMemory 用於修補当前程序代碼的函式.基本上,您会获得要修補的過程或函式的地址,然後在新過程的地址中插入一个Jump指令。

    檢查此代碼

    Uses
      uThirdParty; //this is the unit where the original DataCompare function is declarated
    type
      //strctures to hold the address and instructions to patch
      TJumpOfs = Integer;
      PPointer = ^Pointer;
      PXRedirCode = ^TXRedirCode;
      TXRedirCode = packed record
        Jump: Byte;
        Offset: TJumpOfs;
      end;
      PAbsoluteIndirectJmp = ^TAbsoluteIndirectJmp;
      TAbsoluteIndirectJmp = packed record
        OpCode: Word;
        Addr: PPointer;
      end;
    var
     DataCompareBackup: TXRedirCode; //Store the original address of the function to patch
    
    //this is the implementation of the new function
    function DataCompareHack(const S1, S2: string; APartial: Boolean): Boolean;
    begin
      //here write your own code
    end;
    //get the address of a procedure or method of a function 
    function GetActualAddr(Proc: Pointer): Pointer;
    begin
      if Proc <> nil then
      begin
        if (Win32Platform = VER_PLATFORM_WIN32_NT) and (PAbsoluteIndirectJmp(Proc).OpCode = $25FF) then
          Result := PAbsoluteIndirectJmp(Proc).Addr^
        else
          Result := Proc;
      end
      else
        Result := nil;
    end;
    //patch the original function or procedure
    procedure HookProc(Proc, Dest: Pointer; var BackupCode: TXRedirCode);
    var
      n: {$IFDEF VER230}NativeUInt{$ELSE}DWORD{$ENDIF};
      Code: TXRedirCode;
    begin
      Proc := GetActualAddr(Proc);
      Assert(Proc <> nil);
      //store the address of the original procedure to patch
      if ReadProcessMemory(GetCurrentProcess, Proc, @BackupCode, SizeOf(BackupCode), n) then
      begin
        Code.Jump := $E9;
        Code.Offset := PAnsiChar(Dest) - PAnsiChar(Proc) - SizeOf(Code);
        //replace the target procedure address  with the new one.
        WriteProcessMemory(GetCurrentProcess, Proc, @Code, SizeOf(Code), n);
      end;
    end;
    //restore the original address of the hooked function or procedure
    procedure UnhookProc(Proc: Pointer; var BackupCode: TXRedirCode);
    var
      n: {$IFDEF VER230}NativeUInt{$ELSE}Cardinal{$ENDIF};
    begin
      if (BackupCode.Jump <> 0) and (Proc <> nil) then
      begin
        Proc := GetActualAddr(Proc);
        Assert(Proc <> nil);
        WriteProcessMemory(GetCurrentProcess, Proc, @BackupCode, SizeOf(BackupCode), n);
        BackupCode.Jump := 0;
      end;
    end;
    //Patch the original procedure or function
    procedure HookDataCompare;
    begin
      //look how is passed the address of the original procedure (including the unit name)
      HookProc(@uThirdParty.DataCompare, @DataCompareHack, DataCompareBackup);
    end;
    //restore the address of the original procedure or function
    procedure UnHookDataCompare;
    begin
      UnhookProc(@uThirdParty.DataCompare, DataCompareBackup);
    end;
    
    initialization
     HookDataCompare;
    finalization
     UnHookDataCompare;
    end.
    

    現在,每次執行應用程式並致電 DataCompare 功能完成後,將執行跳轉指令(至新地址),从而匯致 DataCompareHack

  • 6月前
    2 #

    我认為JCL對此有一些實用工具...我自己没有使用過,但是快速瀏覽了一下,下面的內容很有希望:

    jclSysUtils.WriteProtectedMemory()
    jclPeImage.TJclPeMapImgHooks.ReplaceImport()
    

    我覺得该死 演示如何使用它们。

    jclHookExcept.JclHookExceptions()

相似問題

  • c++:用constexpr查詢表
  • string:用Java反轉给定的句子