user2693835 user2693835 - 1 year ago 197
C++ Question

Firefox pr_write hook. dll injection, windows hooks

The problem was that the DLL which contains PR_Write() is called not npsr4.dll, but nss3.dll and hooks couldn't find GetProcAddress() from non-existing library.

I'm trying to create Firefox hook, which collects data from the PR_Write() Firefox method (it is located in nspr4.dll).
I googled much and tried many ways to do that, but unfortunately when I inject the hook, Firefox crashes.

  • Firstly, I tried not to use DLL, using this method (source at the beginning of the article) Firefox crashed at CreateRemoteProcess()*

  • I read that CreateRemoteProcess() doesn't work on Win7 because of security issues. I decided to use this method: But it didn't even load my DLL. (source at the beginning of the article)

  • Then I decided to inject the DLL with SetWindowsHookEx(). DLL worked, I used test MessageBox to check that (but I'm not sure if I specified the last parametr of SetWindowsHookEx() correctly).

  • I've found Chrom library with Firefox example (I cannot post more than 2 links but google: "chrom-lib"). I applied the code to my DLL, but when I inject it, Firefox crashes.

I don't know ASM, stack and memory managment well and I have no idea what is wrong and how to fix it. I only know I should use asm jump hook, but how?. I need a ready-to-use code :/

Maybe there is a way to get pr_write() address, then get its call stack (function arguments) and use them to call my own function? Or maybe I should try with "API Hooking with MS Detours" (again I cannot post link :< )

What should I do?

EDIT I nocticed that there is no npsr4.dll on my computer. So how does Firefox build HTTP request without this lib?

Current DLL code (Chrom-based with VirtualProtect() usage)

#define SIZE 6

struct Hook{

DWORD original_function;
DWORD destination_function;

BYTE original_bytes[SIZE];
BYTE JMP_instruction[SIZE];
DWORD original_protection, new_protection;


original_protection= PAGE_EXECUTE_READWRITE;
new_protection = PAGE_EXECUTE_READWRITE;



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),

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

// our overriding function
DWORD PR_Write_H (DWORD *fd, void *buf,DWORD amount){
// reset hooks, this will replace the jump instruction to original data
// 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
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

Answer Source

Here are the basic steps I use when injecting a dll:

1) You use OpenProcess in order to gets firefox's process HANDLE

2) You allocate memory for the path of your dll using VirtualAllocEx into firefox's process

3) You write the dll path into this allocated space using WriteProcessMemory

4) You get the HANDLE of the dll kernel32.dll using GetModuleHandleA. This one should be present in every windows's process. kernel32.dll contains window's core API stuff.

5) In this kernel32.dll you will find the function LoadLibrary that will help you loading your dll. Get its adress with GetProcAddress.

6) Now you have all the keys to create a new remote thread that will load your dll into firefox's process. You just call CreateRemoteThreadEx with lpStartAddress pointing to the address of LoadLibrary and lpParameter to your dll path string.

7) Enjoy your injected dll.

Now that your dll is in the process memory, you can start to hook. Here are two basic ways:

- On the Import Address Table (IAT): The import adress table is table that contain the adress of each external functions use by your module/process. In your case you want to change the adress of PR_Write by the adress of your manually created function. You must remove the memory page protection of the IAT using VirtualProtect. Now you can freely override the adress by your own.

- Override parts of the process code to make it jump in your functions: Using VirtualProtect, you once against remove the protection on the code parts you need. You then change the current instructions by the opcode of CALL or JUMP poiting to your function. The overrided instructions MUST be rewritten at the beggining of your function in order to keep the real flow intact. After your hook function, you must jump back after the overrided instruction.

All these hooks tricks may need a intermediate function called a trampoline. This function may have to save the registers and load them back later. It can also ensure that the calling conventions are respected.

When dealing with hooks, I would suggest to learn assembly and how to use debugging tools like OllyDbg.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download