问题是包含 PR_Write() 的 DLL 不是 npsr4.dll,而是 nss3.dll 和 hooks 无法从不存在的库中找到 GetProcAddress()。

我正在尝试创建 Firefox 钩子(Hook),它从 PR_Write() Firefox 方法(它位于 nspr4.dll 中)收集数据。
我在谷歌上搜索了很多并尝试了很多方法来做到这一点,但不幸的是,当我注入(inject)钩子(Hook)时,Firefox 崩溃了。

  • 首先,我尝试不使用DLL,使用这个方法http://redkiing.wordpress.com/2012/04/30/firefox-formgrabber-iii-code-injection/(文章开头的来源)Firefox crashed at CreateRemoteProcess()*
  • 我读到 CreateRemoteProcess() 由于安全问题在 Win7 上不起作用。我决定使用这个方法: http://syprog.blogspot.com/2012/05/createremotethread-bypass-windows.html 但它甚至没有加载我的 DLL。 (来源在文章开头)
  • 然后我决定用 SetWindowsHookEx() 注入(inject) DLL。 DLL 工作,我使用测试 MessageBox 来检查(但我不确定我是否正确指定了 SetWindowsHookEx() 的最后一个参数)。
  • 我找到了带有 Firefox 示例的 Chrom 库(我不能发布超过 2 个链接,但 google:“chrom-lib”)。我将代码应用于我的 DLL,但是当我注入(inject)它时,Firefox 崩溃了。

  • 我不太了解 ASM、堆栈和内存管理,也不知道出了什么问题以及如何解决。我只知道我应该使用 asm jump hook,但是怎么用呢?我需要一个现成的代码:/

    也许有一种方法可以获取 pr_write() 地址,然后获取其调用堆栈(函数参数)并使用它们来调用我自己的函数?或者也许我应该尝试使用“API Hooking with MS Detours”(同样我无法发布链接:
    我应该怎么办?

    编辑 我注意到我的电脑上没有 npsr4.dll。那么火狐如何在没有这个库的情况下构建 HTTP 请求呢?

    当前 DLL 代码(基于 Chrom 的 VirtualProtect() 用法)
    #define SIZE 6
    
    struct Hook{
    
        DWORD original_function;
        DWORD destination_function;
    
        BYTE original_bytes[SIZE];
        BYTE JMP_instruction[SIZE];
        DWORD original_protection, new_protection;
    
        Hook(){
    
        original_protection= PAGE_EXECUTE_READWRITE;
        new_protection = PAGE_EXECUTE_READWRITE;
    
        }
    
        ~Hook(){
    
        memcpy((void*) original_function, original_bytes, SIZE);
    
        }
    
        int Initialize(char * function, char * module_name, void * destination_function_ptr)
        {
            original_function = (DWORD)GetProcAddress(GetModuleHandle(module_name),
                                 function);
    
            destination_function = (DWORD) destination_function_ptr;
    
            if (original_function==NULL){
                return FALSE;}
    
            return TRUE;
        }
    
        int Start()
        {
            BYTE JMP_temporary[SIZE] = {0xE9, 0x90, 0x90, 0x90, 0x90, 0xC3};
    
            memcpy(JMP_instruction, JMP_temporary, SIZE);
    
            DWORD JMP_size = ((DWORD)destination_function - (DWORD)original_function - 5);
    
            VirtualProtect((LPVOID)original_function, SIZE, PAGE_EXECUTE_READWRITE, &original_protection);
    
            MessageBox(NULL,"Works", ":D",0);
    
            memcpy(original_bytes,(void*)original_function, SIZE);
    
            memcpy(&JMP_instruction[1], &JMP_size, 4);
    
            memcpy((void*)original_function, JMP_instruction, SIZE);
    
            VirtualProtect((LPVOID)original_function, SIZE, original_protection, NULL);
    
            return TRUE;
        }
    
        int Reset(){
    
            VirtualProtect((LPVOID)original_function, SIZE, new_protection, NULL);
    
            memcpy((void*)original_function, original_bytes, SIZE);
    
            return TRUE;
        }
    
        int Place_Hook(){
    
            memcpy((void*)original_function, JMP_instruction, SIZE);
    
            VirtualProtect((LPVOID)original_function, SIZE, original_protection, NULL);
    
            return TRUE;
        }
    
    };
    
    //...
    
    Hook Firefox; // use chrom library
    
    DWORD PR_Write_H (DWORD *fd,  void *buf,DWORD amount); // this is our overiding-function
    typedef DWORD (*prWrite)(DWORD*,void*,DWORD); // defination of our original function
    
    prWrite prw = NULL; // create a orginal function, we later point this to orginal function
                        // address
    
    // example test function
    int write_log(char * log, char * data)
    {
        ofstream fout("D:\\log2.txt", ios::app);fout << data;fout.close();
        return TRUE;
    }
    
    void create_hooks() //this is called when DLL is initialized
    {
        // Override PR_Write function in nspr4.dll with our PR_Write_H,
        // Note nspr4.dll must already be
        // loaded in process space
        Firefox.Initialize("PR_Write", "nspr4.dll", PR_Write_H);
    
        // Write jump instruction on orginal function address
        Firefox.Start();
    }
    
    // our overriding function
    DWORD PR_Write_H (DWORD *fd,  void *buf,DWORD amount){
        // reset hooks, this will replace the jump instruction to original data
        Firefox.Reset();
        // point prw(function) to original function
        prw = (prWrite)Firefox.original_function;
        // log the headers
        write_log(log_file, (char*) buf);
        // call the real PR_Write function
        DWORD ret = prw(fd, buf, amount);
        // again place the jump instruction on the original function
        Firefox.Place_Hook();
        return ret;
    }
    

    最佳答案

    以下是我在注入(inject) dll 时使用的基本步骤:

    1) 您使用 OpenProcess 来获取 Firefox 的进程 HANDLE
    2)您使用VirtualAllocEx为您的dll路径分配内存到Firefox的进程中

    3)您使用WriteProcessMemory将dll路径写入这个分配的空间

    4) 使用 HANDLE 获取 dll kernel32.dll 的 GetModuleHandleA 。这个应该存在于每个窗口的进程中。 kernel32.dll 包含窗口的核心 API 内容。

    5) 在这个 kernel32.dll 中,你会发现函数 LoadLibrary 将帮助你加载你的 dll。使用 GetProcAddress 获取它的地址。

    6) 现在您拥有了创建新远程线程的所有 key ,该线程会将您的 dll 加载到 Firefox 的进程中。
    您只需调用 CreateRemoteThreadEx,其中 lpStartAddress 指向 LoadLibrary 的地址,lpParameter 指向您的 dll 路径字符串。

    7) 享受你注入(inject)的 dll。

    现在您的 dll 已在进程内存中,您可以开始 Hook 了。这里有两种基本方法:

    - 在导入地址表 (IAT) 上:
    导入地址表是包含模块/进程使用的每个外部函数的地址的表。
    在您的情况下,您希望通过手动创建的函数的地址更改 PR_Write 的地址。您必须使用 VirtualProtect 删除 IAT 的内存页保护。现在您可以自由地覆盖您自己的地址。

    - 覆盖部分流程代码以使其跳转到您的函数中:
    使用 VirtualProtect ,您曾经反对取消对您需要的代码部分的保护。
    然后您通过指向您的函数的 CALLJUMP 的操作码更改当前指令。重写的指令必须在你的函数开始时重写,以保持真实的流程完整。在你的钩子(Hook)函数之后,你必须在被覆盖的指令之后跳回去。

    所有这些钩子(Hook)技巧可能需要一个称为蹦床的中间函数。此函数可能必须保存寄存器并稍后加载它们。它还可以确保遵守调用约定。

    在处理钩子(Hook)时,我建议学习汇编以及如何使用 OllyDbg 之类的调试工具。

    关于c++ - Firefox pr_write 钩子(Hook)。 dll注入(inject),windows钩子(Hook),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/18310423/

    10-17 02:46