Easyhook:如何从使用 LoadLibrary 加载的 DLL 挂钩函数
Easyhook: How to hook a function from a DLL loaded with LoadLibrary
我已经使用 EasyHook 一段时间了,并且在静态链接 DLL 方面非常成功。现在,我尝试使用与静态链接的 DLL 相同的方法从从主机应用程序动态加载的 DLL 中挂接一个函数。
在这种情况下,挂钩无法正常工作。尝试创建挂钩时出现以下异常:
System.DllNotFoundException: The given library is not loaded into the current process.
异常非常正确地指出库尚未加载,但是Host/hooked进程将在ns/ms之后加载它] 开始之后(这完全没关系)。
我在 Internet 上搜索的教程和结果仅涉及挂接静态链接的 DLL。我还没有找到任何关于动态加载的 DLL 的信息。想到的一种解决方案:挂钩 LoadLibrary
和 GetProcAddress
并等待正确的 winapi 调用进行所需的替换。
是否有任何other/an更简单的方法从动态加载的 DLL 挂钩函数?
有一个限制:外部程序不能更改为以静态方式使用 DLL。
为了促进可能的解决方案,这里有一些片段显示了我想要挂钩的内容:
首先,这是我要替换的带有AddIntegers
函数的DLL(代码在Delphi)
library Calculate;
function AddIntegers(_a, _b: integer): integer; stdcall;
begin
Result := _a + _b;
end;
exports
AddIntegers;
begin
end.
其次,这是使用导出的 AddIntegers
函数使用上述 DLL 的程序。
program HostConsole;
{$APPTYPE CONSOLE}
uses
Winapi.Windows, System.SysUtils;
var
n1, n2, sum: Int32;
// Variables for DLL Loading
h: HMODULE;
AddIntegers: function(_a, _b: integer): integer; stdcall;
begin
try
// Load Library
h := LoadLibrary('Calculate.dll');
if h = 0 then
begin;
raise Exception.Create('Cannot load DLL');
end;
// Load function
AddIntegers := GetProcAddress(h, 'AddIntegers');
if not Assigned(AddIntegers) then
begin
raise Exception.Create('Cannot find function');
end;
Write('Enter first number: ');
Readln(n1);
Write('Enter second number: ');
Readln(n2);
// To the calculation
sum := AddIntegers(n1, n2);
Writeln('The sum is ', sum);
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
// Unload Library
FreeLibrary(h);
Readln;
end.
我花了一些时间,但我终于想通了:只有当它在那里时,你才能挂钩它。只要模块未加载,就无法挂钩它。
如何加载模块?
根据问题中的代码,LoadLibrary()
使模块可用。这意味着,为了获得模块可用的第一个时间点,您需要挂钩 LoadLibrary()
!
挂钩LoadLibrary()
如果有人正在寻找调用该函数的方法,这里有一种可能的方法:
[UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Unicode, SetLastError = true)]
delegate IntPtr LoadLibrary_Delegate(string lpFileName);
[DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern IntPtr LoadLibrary(string lpFileName);
IntPtr LoadLibrary_Hook(string lpFileName)
{
IntPtr result = LoadLibrary(lpFileName);
if (lpFileName == "<FILENAME HERE>")
{
// Apply hook
}
return result;
}
既然您知道何时加载库,就可以挂钩它的函数了。您现在还可以挂钩与已检查库一起静态加载的任何函数。
提示:在我的实际用例中,.dll
在启动后立即加载,并在应用程序终止后释放。如果多次加载和卸载库,则应检查是否存在内存泄漏。是的,EasyHook 可能不知道挂钩的库已卸载。
我已经使用 EasyHook 一段时间了,并且在静态链接 DLL 方面非常成功。现在,我尝试使用与静态链接的 DLL 相同的方法从从主机应用程序动态加载的 DLL 中挂接一个函数。
在这种情况下,挂钩无法正常工作。尝试创建挂钩时出现以下异常:
System.DllNotFoundException: The given library is not loaded into the current process.
异常非常正确地指出库尚未加载,但是Host/hooked进程将在ns/ms之后加载它] 开始之后(这完全没关系)。
我在 Internet 上搜索的教程和结果仅涉及挂接静态链接的 DLL。我还没有找到任何关于动态加载的 DLL 的信息。想到的一种解决方案:挂钩 LoadLibrary
和 GetProcAddress
并等待正确的 winapi 调用进行所需的替换。
是否有任何other/an更简单的方法从动态加载的 DLL 挂钩函数?
有一个限制:外部程序不能更改为以静态方式使用 DLL。
为了促进可能的解决方案,这里有一些片段显示了我想要挂钩的内容:
首先,这是我要替换的带有AddIntegers
函数的DLL(代码在Delphi)
library Calculate;
function AddIntegers(_a, _b: integer): integer; stdcall;
begin
Result := _a + _b;
end;
exports
AddIntegers;
begin
end.
其次,这是使用导出的 AddIntegers
函数使用上述 DLL 的程序。
program HostConsole;
{$APPTYPE CONSOLE}
uses
Winapi.Windows, System.SysUtils;
var
n1, n2, sum: Int32;
// Variables for DLL Loading
h: HMODULE;
AddIntegers: function(_a, _b: integer): integer; stdcall;
begin
try
// Load Library
h := LoadLibrary('Calculate.dll');
if h = 0 then
begin;
raise Exception.Create('Cannot load DLL');
end;
// Load function
AddIntegers := GetProcAddress(h, 'AddIntegers');
if not Assigned(AddIntegers) then
begin
raise Exception.Create('Cannot find function');
end;
Write('Enter first number: ');
Readln(n1);
Write('Enter second number: ');
Readln(n2);
// To the calculation
sum := AddIntegers(n1, n2);
Writeln('The sum is ', sum);
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
// Unload Library
FreeLibrary(h);
Readln;
end.
我花了一些时间,但我终于想通了:只有当它在那里时,你才能挂钩它。只要模块未加载,就无法挂钩它。
如何加载模块?
根据问题中的代码,LoadLibrary()
使模块可用。这意味着,为了获得模块可用的第一个时间点,您需要挂钩 LoadLibrary()
!
挂钩LoadLibrary()
如果有人正在寻找调用该函数的方法,这里有一种可能的方法:
[UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Unicode, SetLastError = true)]
delegate IntPtr LoadLibrary_Delegate(string lpFileName);
[DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern IntPtr LoadLibrary(string lpFileName);
IntPtr LoadLibrary_Hook(string lpFileName)
{
IntPtr result = LoadLibrary(lpFileName);
if (lpFileName == "<FILENAME HERE>")
{
// Apply hook
}
return result;
}
既然您知道何时加载库,就可以挂钩它的函数了。您现在还可以挂钩与已检查库一起静态加载的任何函数。
提示:在我的实际用例中,.dll
在启动后立即加载,并在应用程序终止后释放。如果多次加载和卸载库,则应检查是否存在内存泄漏。是的,EasyHook 可能不知道挂钩的库已卸载。