delphi - 如何保存原始函数的地址并稍后调用?

标签 delphi delphi-10-seattle ntdll api-hook

我正在尝试调用 api Hook 中的原始函数,以防止 dll 注入(inject) LdrLoadDll()函数,但每次当我尝试加载与过滤器不同的 dll 时,应用程序都会崩溃,并且无法调用原始函数。似乎我在钩子(Hook)之前保存“original_function”时犯了一些错误。

我正在 Windows 7 x64 上进行测试,在 32 位应用程序中注入(inject) 32 位 dll(代码如下)。

如何解决这个问题?

program Project1;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  Windows,
  SysUtils;

type
  NTSTATUS = Cardinal;
  PUNICODE_STRING = ^UNICODE_STRING;

  UNICODE_STRING = packed record
    Length: Word;
    MaximumLength: Word;
    Buffer: PWideChar;
  end;

const
  STATUS_ACCESS_DENIED = NTSTATUS($C0000022);

var
  Old_LdrLoadDll: function(szcwPath: PWideChar; dwFlags: DWORD;
    pUniModuleName: PUNICODE_STRING; pResultInstance: PPointer)
    : NTSTATUS; stdcall;

function LdrLoadDll(szcwPath: PWideChar; dwFlags: DWORD;
  pUniModuleName: PUNICODE_STRING; pResultInstance: PPointer)
  : NTSTATUS; stdcall;
begin
  Result := Old_LdrLoadDll(szcwPath, dwFlags, pUniModuleName, pResultInstance);
end;

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;
  NewCode.Offset := NativeInt(NewAddress) - NativeInt(OldAddress) -
    SizeOf(NewCode);
  PatchCode(OldAddress, NewCode, SizeOf(NewCode));
end;

function NewLdrLoadDll(szcwPath: PWideChar; dwFlags: DWORD;
  pUniModuleName: PUNICODE_STRING; pResultInstance: PPointer)
  : NTSTATUS; stdcall;
begin
  if (pos('111', pUniModuleName.Buffer) > 0) or
    (pos('222', pUniModuleName.Buffer) > 0) then

    Result := STATUS_ACCESS_DENIED
  else
    Result := LdrLoadDll(szcwPath, dwFlags, pUniModuleName, pResultInstance);
end;

begin
  @Old_LdrLoadDll := GetProcAddress(GetModuleHandle('ntdll.dll'), 'LdrLoadDll');
  try
    RedirectProcedure(GetProcAddress(GetModuleHandle('ntdll.dll'),
      'LdrLoadDll'), @NewLdrLoadDll);
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;

end.

最佳答案

我建议您不要使用自制的 Hook ,并为此获取现有的库。

Microsoft Detours现在是免费且开源的。由于它构建为 DLL,因此您可以将它与 Delphi 一起使用。

您将需要 C++ 编译器来从源代码构建它,但 Visual Studio Community 也是免费的。

关于delphi - 如何保存原始函数的地址并稍后调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54349288/

相关文章:

Delphi 7 软件包编辑器对应项

delphi - 如何使用Delphi IDE保存断点?

Delphi Seattle IDE - 方括号错误

delphi - 德尔福西雅图的 GCM,无 BAAS

multithreading - 新的Delphi TActivityIndi​​cator运行在主线程有什么用?

c - 获取内核对象窗口列表

delphi - delphi中将字符串字符转换为ascii

delphi - 控件 'xxx'没有父窗口

c# - 有人可以解释 RtlAdjustPrivilege

c# - 结构数组指针的问题