我想加载不同于应用程序工作目录中存在的DLL版本。为此,我需要挂钩LoadLibrary调用,以便当应用程序调用加载DLL时,我可以透明地用更新版本的DLL替换它。我尝试使用NCodeHook并在我的DLL中使用以下代码,我使用NInjectLib注入到应用程序中,但在加载kernel32.dll时它崩溃了。任何人都可以告诉我这是否是正确的注入电话的方式,还是有其他选择。
// CodeHook.cpp : Defines the entry point for the DLL application.
//
#include "stdafx.h"
#include <NCodeHookInstantiation.h>
#include "CodeHook.h"
#ifdef _MANAGED
#pragma managed(push, off)
#endif
typedef HMODULE (WINAPI *LoadLibraryFPtr)(LPCTSTR dllName);
#pragma data_seg("SHARED")
LoadLibraryFPtr origFunc = NULL;
#pragma data_seg()
#pragma comment(linker, "/section:SHARED,RWS")
HMODULE WINAPI LoadLibraryHook(LPCTSTR dllName)
{
if (origFunc != NULL)
{
return origFunc(dllName);
}
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
CODEHOOK_API void Initialize (void)
{
NCodeHookIA32 nch;
origFunc = nch.createHookByName("kernel32.dll", "LoadLibrary", LoadLibraryHook);
}
#ifdef _MANAGED
#pragma managed(pop)
#endif
答案 0 :(得分:3)
我不知道NCodeHook库,但要知道的一件重要事情是LoadLibrary函数实际上有两个版本:LoadLibraryA(LPCSTR)
和LoadLibraryW(LPCWSTR)
。确保挂钩正确的并使用适当的函数定义。您可能还需要挂钩LoadLibraryExA / LoadLibraryExW
Detours是一个更广为人知的API挂钩库。另请参阅this article了解更多挂钩技巧。
答案 1 :(得分:0)
当使用手写的挂钩/绕行库时,我在kernel32.dll
遇到类似的崩溃问题。我在discussion pages的MinHook library中找到了对问题的一个很好的解释:
据我所知,你的绕行库没有考虑到它试图挂钩的函数是使用短跳操作码实现的可能性(显然LoadLibrary(Ex)W
是以这种方式实现的)。这将导致在挂钩期间需要替换的不同字节。
使用MinHook挂钩LoadLibrary
和朋友为我工作:
HMODULE WINAPI LoadLibraryA_replacement(_In_ LPCTSTR lpFileName)
{
// do your stuff
return loadLibraryA_original(lpFileName);
}
bool installLoadLibraryHook()
{
// Initialize MinHook.
if (MH_Initialize() != MH_OK)
return false;
if (MH_CreateHook(&LoadLibraryA, &LoadLibraryA_replacement,
reinterpret_cast<LPVOID*>(&loadLibraryA_original)) != MH_OK)
return false;
if (MH_EnableHook(&LoadLibraryA) != MH_OK)
return false;
// same for LoadLibraryW, LoadLibraryExW, LoadLibraryExA
return true;
}
答案 2 :(得分:-1)
API挂钩有很多陷阱。我不知道有关NCodeHook实现的细节,但如果API挂钩代码没有正确处理不可写页面,则可能会出现问题。可以假设该库将调用VirtualProtect
并且操作系统将正确处理写入时复制,但很难说。
我同意评论,这可能不是解决您问题的最佳方法。 API挂钩依赖于应用程序二进制接口,该接口最多是准文档。我不建议将其用于生产用途的商业应用程序。
并排程序集肯定是有用的,因为强名称消除了有关需要加载哪个DLL的任何含糊之处。或者,考虑将LoadLibraryEx
与DLL的绝对路径和LOAD_WITH_ALTERED_SEARCH_PATH
标志一起使用。