Tip: Hook IE & Explorer w/ fake BHO

c++ / delphi package - dll injection and api hooking
Post Reply
bigfreak
Posts: 4
Joined: Tue Apr 19, 2005 8:13 pm

Tip: Hook IE & Explorer w/ fake BHO

Post by bigfreak »

Getting access to another process to hook it is often tricky. Granted if you have control over when it's launched, you can launch it pre-injected with madshi's CreateProcess stuff. In some cases, you don't have that luxury. Sometimes, you're stuck with a process that's already running or a process who's launch you can't control. If you want to hook these processes, you'd normally have to have your exe file running, detect when the target process is running and then inject your dll into it. This is messy and having another process floating around feels sloppy.

There is good news, however, if you want to hook explorer.exe and/or iexplore.exe, it's easy to do with a BHO.

First you need to make a GUID -- it's not hard. Next, you need to make some registry entries:

First, the BHO entry

Code: Select all

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Browser Helper Objects\{00000000-0000-0000-0000-000000000000}
Next, you need the CLSID to back it up

Code: Select all

[HKEY_CLASSES_ROOT\CLSID\{00000000-0000-0000-0000-000000000000}]

[HKEY_CLASSES_ROOT\CLSID\{00000000-0000-0000-0000-000000000000}\InprocServer32]
@="C:\\Program Files\\MyHooksDir\\LoadMyHook.dll"
"ThreadingModel"="Apartment"
In both cases, you need to replace "00000000-0000-0000-0000-000000000000" with your GUID

Next we need to code the "LoadMyHook.dll"

Code: Select all

#include <windows.h>

static HMODULE ModuleFromAddress(PVOID pv) 
{
	MEMORY_BASIC_INFORMATION mbi;

	return ((::VirtualQuery(pv, &mbi, sizeof(mbi)) != 0) 
	        ? (HMODULE) mbi.AllocationBase : NULL);
}

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpvReserved)
{
	//returning false causes us to be unloaded
	BOOL bRet = FALSE;
	BOOL bHookOnlyIE = TRUE;  // set to false if you want to hook Explorer too
    if(dwReason == DLL_PROCESS_ATTACH)
    {
        if(bHookOnlyIE)
        {
    		TCHAR exeFileName[MAX_PATH];
    		if(GetModuleFileName(NULL, exeFileName, MAX_PATH) == 0)
    			return bRet;
    		//backup until we find the name of the exe
    		TCHAR* pChar = NULL;
    		for(int i=wcslen(exeFileName); (i>=0) &&
    			(exeFileName[i]!='\\'); i--)
    		{
    			//convert the exe filename to uppercase while we're at it.
    			if((exeFileName[i] >= 'a') && (exeFileName[i] <= 'z'))
    			{
    				exeFileName[i] -= 'a' - 'A';
    			}
    			//get the address of this char
    			pChar = &exeFileName[i];
    		}
    		if(wcscmp(pChar, L"IEXPLORE.EXE") != 0)
    		{
    			//this isn't IE (could be explorer.exe or anything else)
    			return bRet;
    		}
    	}

		//This is the IE process

		//see if MyHook is loaded already
		if(GetModuleHandle(L"MyHook.DLL") != NULL)
		{
			//it's already loaded and doing it's job
			return bRet;
		}

		//we need to launch MyHook.dll with LoadLibrary() before IE shuts us down for not being a
		//  true BHO

		//Before we can launch MyHook.dll, it would be nice to know the full path to it :D

		//get the filename of this DLL
		TCHAR fileName[MAX_PATH];
		if(GetModuleFileName(ModuleFromAddress(DllMain), fileName, MAX_PATH) == 0)
			return bRet;

		//strip off the dll filename leaving us with a path
		for(i=wcslen(fileName); (i>=0) &&
			(fileName[i]!='\\'); i--)
		{
			fileName[i] = 0;
		}

		//we make the assumption that MyHook.dll and this DLL are in the same dir
		wcscat(fileName, L"MyHook.dll");

		//Locked a Loaded. Let 'er Rip.  :D
		if(LoadLibrary(fileName) == NULL)
		{
			MessageBox(NULL, L"Unable to Load Hook!", L"MyHook - LoadMyHook.dll", MB_OK);
		}
	}
	return bRet;
}
As you can tell, my DLLMain alawys returns FALSE. This casuses IE and explorer to unload the "LoadMyHook.dll" file.

The real action takes place in MyHook.dll. The fear I had when I first coded this is that IE would eject the DLL when it turned out not to be a BHO. This is why the loader dll only launches the dll that does the hooking. Because IE and explorer both keep the fake BHO dll loaded, it's "possible" to do all all your hooking with one dll. I personally think it's safer using two dlls. There isn't any chance of being ejected by the host process.

Also, you'll see that I'm checking to see if I'm running in IE. For my project, I didn't want to hook explorer and doing so caused me problems when I wanted to update or uninstall my dlls. If you only want to hook explorer, you can do the same thing and look for "EXPLORER.EXE".

Also note that I'm using wide (unicode) versions of the APIs. Converting the code back to ansi will take a little effort, but it shouldn't be hard. I personally feel a little more comfortable knowing if someone sticks my app in a folder that has Chinese or Japanese characters in it, it'll still work. :)

Anyway, I though I'd share my method for hooking IE (and explorer if you want). It suites my needs well.

EDIT = spelling.
tetrasync
Posts: 11
Joined: Tue May 17, 2005 8:09 am

Post by tetrasync »

good stuff man! thanks alot
bigfreak
Posts: 4
Joined: Tue Apr 19, 2005 8:13 pm

Post by bigfreak »

I'm glad you found it useful. There are a lot of neat applications for it.

API hooking is a lot of fun and, thanks to madshi, it's easy. I only wish I had more time on my hands to "play" with other apps.
Post Reply