从托管代码中挂钩 LoadLibrary 调用

发布于 2024-07-17 05:10:00 字数 429 浏览 8 评论 0原文

我们希望挂钩对 LoadLibrary 的调用,以便下载未找到的程序集。 我们有一个 ResolveAssembly 处理程序来处理托管程序集,但我们还需要处理非托管程序集。

我们尝试通过“Microsoft Windows 的编程应用程序”中指定的技术重写导入表来挂钩 LoadLibrary 调用,但是当我们调用 WriteProcessMemory() 时,我们收到权限被拒绝错误 (998)。 (是的,我们正在以提升的权限运行)

是否有人在加载 CLR 时成功地重写了导入表? 有人能指出我正确的方向吗?

更新:我们解决了权限被拒绝的问题,但现在当我们迭代混合程序集(托管+非托管)的导入表时,我们找到的唯一条目是 mscoree.dll。 有谁知道如何找到本地进口的吗? (我们正在使用 C++/CLI)。

We would like to hook calls to LoadLibrary in order to download assemblies that are not found. We have a handler for ResolveAssembly that handles the managed assemblies, but we also need to handle unmanaged assemblies.

We have attempted to hook LoadLibrary calls by re-writing the imports table via techniques specified in "Programming Applications for Microsoft Windows", but when we call WriteProcessMemory() we get a permission denied error (998). (Yes, we're running with elevated privs)

Has anyone succeeded in re-writing the imports table while the CLR is loaded? Can anyone point me in the right direction?

Update: We resolved the permission denied issue, but now when we iterate the Imports Table of a mixed assembly (managed + unmanaged), the only entry we find is mscoree.dll. Does anyone know how to find the native imports? (we're working in C++/CLI).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

用心笑 2024-07-24 05:10:00

我已经成功地从托管代码中挂钩。 不过,我是通过将非托管 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;
}

I have successfully hooked from Managed code. However, I did it by injecting an unmanaged DLL into the remote process and have it rewrite the import table in DllMain. You may want to consider this method.

Here is my hooking function:

//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;
}
你是年少的欢喜 2024-07-24 05:10:00

应该可以,但请尝试使用 detours (或免费的 N-CodeHook)。
Detours 几乎是检测 Win32 二进制文件的实际方法。

Should work, but try using detours (or the free N-CodeHook) instead.
Detours is almost the de-facto way of instrumenting Win32 binaries.

卸妝后依然美 2024-07-24 05:10:00

我们通过调用 VirtualProtect 解决了指定问题() 在调用 WriteProcessMemory() 之前,然后再次调用它以恢复保护级别。 这会暂时取消 IAT 所在内存的只读保护。 这对我们来说效果很好,并解决了调用 LoadLibrary() 时的问题。

现在,如果我能弄清楚为什么当非托管程序集链接到库(不是静态库)时不调用 LoadLibrary()...

顺便说一下,Detour 和 N-Code Hook 看起来都是不错的产品,而且很可能是我应该走的路,但我想避免添加第三个如果可能的话举行党大会。

We resolved the specified issue via a call to VirtualProtect() prior to calling WriteProcessMemory() and then call it again afterwards to restore the protection levels. This temporarily removes the read-only protection for the memory where the IAT resides. This works well for us and resolves the issue for when LoadLibrary() is called.

Now if I can just figure out why LoadLibrary() is not called when an unmanaged assembly links against a lib (not a static lib)...

By the way, Detour and N-Code Hook both look like nice products and are most likely the way I should go, but I would like to avoid adding a 3rd party assembly if possible.

魂归处 2024-07-24 05:10:00

最好的方法是挂钩 LoadLibrary/LoadLibraryEx,根据需要进行下载,并将下载的文件传递到链中。 但是,我担心在下载过程中会阻止 GUI。

The best way would be to hook LoadLibrary/LoadLibraryEx, do the download if needed, and pass the downloaded file down the chain. However, I'd be worried about blocking the GUI during that download.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文