Firefox pr_write挂钩。 dll注入,窗口挂钩

时间:2013-08-19 09:24:11

标签: c++ firefox hook dll-injection

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

我正在尝试创建Firefox钩子,它从PR_Write()Firefox方法收集数据(它位于nspr4.dll中)。 我google了很多,并尝试了很多方法,但不幸的是,当我注入钩子时,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()注入DLL。 DLL工作,我使用测试MessageBox来检查(但我不确定我是否正确指定了SetWindowsHookEx()的最后一个参数)。

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

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

也许有办法获取pr_write()地址,然后获取其调用堆栈(函数参数)并使用它们来调用我自己的函数?或者也许我应该尝试“使用MS Detours进行API挂钩”(再次我无法发布链接:<)

我该怎么办?

编辑我发现我的电脑上没有npsr4.dll。那么Firefox如何在没有这个lib的情况下构建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编译

1 个答案:

答案 0 :(得分:4)

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

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

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

3)使用WriteProcessMemory

将dll路径写入此分配的空间

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

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

6)现在您已经拥有了创建新远程线程的所有密钥,这些线程会将您的dll加载到Firefox的进程中。 您只需致电CreateRemoteThreadExlpStartAddress将地址LoadLibrarylpParameter指向您的dll路径字符串。

7)享受你的注射dll。

现在您的dll在进程内存中,您可以开始挂钩。以下是两种基本方法:

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

- 覆盖部分流程代码,使其跳转到您的功能中 使用VirtualProtect,您曾经反对删除所需代码部分的保护。 然后,您可以通过指向您的函数的CALLJUMP操作码更改当前指令。必须在函数开始时重写覆盖的指令,以保持实际流程的完整性。挂钩功能完成后,必须在覆盖指令后跳回。

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

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