问题是包含 PR_Write() 的 DLL 不是 npsr4.dll,而是 nss3.dll 和 hooks 无法从不存在的库中找到 GetProcAddress()。
我正在尝试创建 Firefox 钩子(Hook),它从 PR_Write() Firefox 方法(它位于 nspr4.dll 中)收集数据。
我在谷歌上搜索了很多并尝试了很多方法来做到这一点,但不幸的是,当我注入(inject)钩子(Hook)时,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
,您曾经反对取消对您需要的代码部分的保护。
然后您通过指向您的函数的 CALL
或 JUMP
的操作码更改当前指令。重写的指令必须在你的函数开始时重写,以保持真实的流程完整。在你的钩子(Hook)函数之后,你必须在被覆盖的指令之后跳回去。
所有这些钩子(Hook)技巧可能需要一个称为蹦床的中间函数。此函数可能必须保存寄存器并稍后加载它们。它还可以确保遵守调用约定。
在处理钩子(Hook)时,我建议学习汇编以及如何使用 OllyDbg 之类的调试工具。
关于c++ - Firefox pr_write 钩子(Hook)。 dll注入(inject),windows钩子(Hook),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/18310423/