c++ - Firefox pr_write 钩子(Hook)。 dll 注入(inject),Windows 钩子(Hook)

标签 c++ firefox hook dll-injection

问题是包含 PR_Write() 的 DLL 调用的不是 npsr4.dll,而是 nss3.dll 和 Hook 无法从不存在的库中找到 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 在 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。那么如果没有这个库,Firefox 是如何构建 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;
}

*I'm using Win8 x64 but the hook must work at Vista/Win7/Win8 32 and 64 bit! I also tested it at Win7 x86 laptop. I compile with Visual Studio 2012

最佳答案

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

1) 您使用 OpenProcess为了获取 Firefox 的进程 HANDLE

2) 使用 VirtualAllocEx 为 dll 的路径分配内存进入 Firefox 的进程

3) 使用 WriteProcessMemory 将 dll 路径写入此分配空间

4) 你得到 HANDLE使用 GetModuleHandleA 的 dll kernel32.dll .这个应该出现在每个窗口的进程中。 kernel32.dll 包含窗口的核心 API 内容。

5) 在这个 kernel32.dll 中你会找到函数 LoadLibrary这将帮助您加载您的 dll。使用 GetProcAddress 获取其地址.

6) 现在您拥有了创建新远程线程的所有关键,该线程会将您的 dll 加载到 Firefox 的进程中。 你只要打电话CreateRemoteThreadExlpStartAddress指向LoadLibrary的地址和 lpParameter到您的 dll 路径字符串。

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

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

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

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

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

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

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

相关文章:

git - Powershell 在 TortoiseGit Hook 中不返回任何内容

C++ 疯狂 typedef : what is the point of allowing this syntax by the Standard?

c++ - 从double转换为__m128

javascript - Animate scrolltop 不适用于 chrome 但适用于 firefox

javascript - Selenium:多浏览器并行测试

html - <thead> 的垂直边框颜色不同于 <table> 边框的其余部分 - 渗入下方的水平边框 - Firefox colspan 问题

hook - 安卓应用程序: java/JNI call hooking strategies

windows - 从 Windows 窗体读取文本

c++ - Boost 将派生类反序列化为基类指针

c++ - 使用 qExec 创建 Qt 测试套件