4

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

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

  • 首先,我尝试不使用DLL,使用这种方法http://redkiing.wordpress.com/2012/04/30/firefox-formgrabber-iii-code-injection/(文章开头的来源)Firefox崩溃了创建远程进程()*

  • 我读到由于安全问题,CreateRemoteProcess() 在 Win7 上不起作用。我决定使用这种方法:http ://syprog.blogspot.com/2012/05/createremotethread-bypass-windows.html但它甚至没有加载我的 DLL。(来源在文章开头)

  • 然后我决定用 SetWindowsHookEx() 注入 DLL。DLL 工作,我使用测试 MessageBox 来检查(但我不确定我是否正确指定了 SetWindowsHookEx() 的最后一个参数)。

  • 我找到了带有 Firefox 示例的 Chrom 库(我不能发布超过 2 个链接,但谷歌:“chrom-lib”)。我将代码应用到我的 DLL,但是当我注入它时,Firefox 崩溃了。

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

也许有一种方法可以获取 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;
}

*我使用的是 Win8 x64,但钩子必须在 Vista/Win7/Win8 32 和 64 位下工作!我还在 Win7 x86 笔记本电脑上对其进行了测试。我用 Visual Studio 2012 编译

4

1 回答 1

5

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

1) 你OpenProcess用来获取火狐的进程HANDLE

2)您为 dll 的路径分配内存,用于VirtualAllocExFirefox 的进程

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

4) 你得到HANDLEdll kernel32.dll 使用GetModuleHandleA. 这个应该存在于每个 Windows 的进程中。kernel32.dll 包含窗口的核心 API 东西。

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

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

7) 享受您注入的 dll。

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

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

- 覆盖部分过程代码以使其在您的函数中跳转: 使用VirtualProtect,您一旦取消对您需要的代码部分的保护。CALL然后,您可以通过或JUMP指向您的函数的操作码更改当前指令。必须在函数开始时重写被覆盖的指令,以保持真实流程完整。在你的钩子函数之后,你必须在被覆盖的指令之后跳回来。

所有这些钩子技巧可能都需要一个称为蹦床的中间函数。此函数可能必须保存寄存器并稍后将它们加载回来。它还可以确保调用约定得到尊重。

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

于 2013-08-19T09:54:33.610 回答