Как изменить реализацию (обход) функции, объявленной извне

У меня есть сторонняя функция

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

Он используется в другом стороннем подразделении.

Я хочу заменить тело функции во время выполнения другой новой реализацией.

Это возможно? Я предполагаю, что потребуется какой-то хак (ala VirtualMemoryUnprotect). Неассемблерное решение очень приветствуется.

Да, вы можете это сделать, используя функции ReadProcessMemory и WriteProcessMemory для исправления кода текущего процесса. В принципе, вы получаете адрес процедуры или функции для исправления, а затем вставляете инструкцию перехода в адрес новой процедуры.

Проверьте этот код

 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 .

Я думаю, что у JCL есть некоторые утилиты для такого рода вещей … Я не использовал его сам, но имел быстрый взгляд, и следующие пункты выглядели многообещающими:

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

Я думаю, что jclHookExcept.JclHookExceptions() демонстрирует, как их использовать.

  • C вызовы функции: Понимание правила «неявного int»
  • Функция триггера jquery, когда элемент находится в viewport
  • Есть ли встроенный просмотрщик функций экспорта DLL?
  • «Срок службы» строкового литерала в C
  • Как строки передаются в .NET?
  • Как вернуть строковое значение из функции Bash
  • Определить имена таблиц и столбцов в качестве аргументов в функции plpgsql?
  • функциональный интерфейс, который ничего не принимает и ничего не возвращает
  • Инструменты для получения графического графика вызова функции кода
  • Макро против функции в C
  • Зачем использовать именованные функциональные выражения?
  • Interesting Posts
    Давайте будем гением компьютера.