我们想挂钩调用LoadLibrary以下载未找到的程序集。我们有一个处理托管程序集的ResolveAssembly处理程序,但我们还需要处理非托管程序集。
我们尝试通过在“Microsoft Windows编程应用程序”中指定的技术重写导入表来挂钩LoadLibrary调用,但是当我们调用WriteProcessMemory()时,我们得到一个权限被拒绝错误(998)。 (是的,我们正在提升私人权利)
在加载CLR时,有没有人成功重写导入表?有人能指出我正确的方向吗?
更新:我们解决了权限被拒绝的问题,但现在当我们迭代混合程序集的Imports表(托管+非托管)时,我们找到的唯一条目是mscoree.dll。有谁知道如何找到原生进口? (我们正在使用C ++ / CLI )。
答案 0 :(得分:10)
我已成功连接托管代码。但是,我是通过将一个非托管DLL注入远程进程并让它重写DllMain中的导入表来实现的。您可能需要考虑这种方法。
这是我的挂钩功能:
//structure of a function to hook
struct HookedFunction {
public:
LPTSTR moduleName;
LPTSTR functionName;
LPVOID newfunc;
LPVOID* oldfunc;
};
BOOL Hook(HMODULE Module, struct HookedFunction Function) {
//parse dos header
IMAGE_DOS_HEADER* dos_header = (IMAGE_DOS_HEADER*)Module;
if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) return 0; //not a dos program
//parse nt header
IMAGE_NT_HEADERS* nt_header = (IMAGE_NT_HEADERS*)(dos_header->e_lfanew + (SIZE_T)Module);
if (nt_header->Signature != IMAGE_NT_SIGNATURE) return 0; //not a windows program
//optional header (pretty much not optional)
IMAGE_OPTIONAL_HEADER optional_header = nt_header->OptionalHeader;
if (optional_header.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) return 0; //no optional header
IMAGE_IMPORT_DESCRIPTOR* idt_address = (IMAGE_IMPORT_DESCRIPTOR*)(optional_header.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress + (SIZE_T)Module);
if (!optional_header.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size) return 0; //no import table
//enumerate the import dlls
BOOL hooked = false;
for(IMAGE_IMPORT_DESCRIPTOR* i = idt_address; i->Name != NULL; i++)
//check the import filename
if (!_stricmp(Function.moduleName, (char*)(i->Name + (SIZE_T)Module)))
//enumerate imported functions for this dll
for (int j = 0; *(j + (LPVOID*)(i->FirstThunk + (SIZE_T)Module)) != NULL; j++)
//check if the function matches the function we are looking for
if (!_stricmp(Function.functionName, (char*)(*(j + (SIZE_T*)(i->OriginalFirstThunk + (SIZE_T)Module)) + (SIZE_T)Module + 2) )) {
//replace the function
LPVOID* memloc = j + (LPVOID*)(i->FirstThunk + (SIZE_T)Module);
if (*memloc != Function.newfunc) { //not already hooked
DWORD oldrights;
DWORD newrights = PAGE_READWRITE;
VirtualProtect(memloc, sizeof(LPVOID), newrights, &oldrights);
if (Function.oldfunc && !*Function.oldfunc)
*Function.oldfunc = *memloc;
*memloc = Function.newfunc;
VirtualProtect(memloc, sizeof(LPVOID), oldrights, &newrights);
}
hooked = true;
}
return hooked;
}
答案 1 :(得分:7)
应该有效,但请尝试使用detours(或免费的N-CodeHook) Detours几乎是用于检测Win32二进制文件的事实上的方式。
答案 2 :(得分:2)
我们在调用WriteProcessMemory()之前通过调用 VirtualProtect() 解决了指定的问题,然后再次调用它以恢复保护级别。这会暂时删除IAT所在内存的只读保护。这对我们很有用,并解决了调用LoadLibrary()时的问题。
现在,如果我可以弄清楚当非托管程序集链接到lib(不是静态库)时,为什么不调用LoadLibrary()...
顺便说一句,Detour和N-Code Hook看起来都很好看,很可能是我应该去的方式,但我想尽可能避免添加第三方组装。
答案 3 :(得分:0)
最好的方法是挂钩LoadLibrary / LoadLibraryEx,根据需要进行下载,然后将下载的文件传递给链。但是,我担心在下载期间阻止GUI。