[SOLVED] Hooking into just one system process

c++ / delphi package - dll injection and api hooking
Post Reply
blackpaw
Posts: 33
Joined: Mon Nov 05, 2007 1:08 am

[SOLVED] Hooking into just one system process

Post by blackpaw »

I want to inject a dll for hooking into just one process - spoolsv.ex (The Windows Print Spooler Service).

I don't think I need to setup a system wide hook for this - I just need to use

Code: Select all

InjectLibrary ("mydll.dll", processHandle)
?

Couple of questions

- I can just do this from a user mode app? preferably a service?

- How do I get the process handle of the spoolsv.exe process?


Will be using latest madHook code, signed etc. Will be running on 32/64 bit windows, from Vista versions onward.


Thanks - Lindsay
Last edited by blackpaw on Tue Jan 14, 2014 1:10 pm, edited 1 time in total.
blackpaw
Posts: 33
Joined: Mon Nov 05, 2007 1:08 am

Re: Hooking into just one system process

Post by blackpaw »

Further to this - I can successfully inject my DLL into spoolsv.exe on Windows 7 64bit - the inject library call returns true and I can see the DLL appear in the exe process using procmon.exe


However not having much luck with the HookAPI calls in the dll itself, they appear to succeed, but they never get called.

Code: Select all

// Chain Functions
DWORD (WINAPI *OrigStartDocPrinterW)(HANDLE hPrinter, DWORD Level, LPBYTE pDocInfo) = NULL;


// hooked functions
// SLPRINTHK3_API 
DWORD WINAPI OurStartDocPrinterW(HANDLE hPrinter, DWORD Level, LPBYTE pDocInfo)
{
	Log.ItemI(LOG_INFO | LOG_FORCE, L"print",L"StartDocPrinterW");
    DWORD result = OrigStartDocPrinterW(hPrinter, Level, pDocInfo);
    return result; 
}

extern "C" BOOL WINAPI DllMain(HANDLE hModule, DWORD fdwReason, LPVOID lpReserved)
{
    if (fdwReason == DLL_PROCESS_ATTACH)
    {      
		Log.Init(L"printhk3", true);
		Log.ItemI(LOG_INFO | LOG_FORCE, L"dllmain",L"InitializeMadCHook()");
        InitializeMadCHook();
		Log.ItemI(LOG_INFO | LOG_FORCE, L"dllmain",L"InitializeMadCHook() - done.");

        //spoolss.dll
        BOOL rc = HookAPI("spoolss.dll", "StartDocPrinterW", OurStartDocPrinterW, (PVOID*) &OrigStartDocPrinterW);
		if (rc)
			Log.ItemI(LOG_INFO | LOG_FORCE, L"dllmain",L"StartDocPrinterW - success");
		else
			Log.ItemI(LOG_INFO | LOG_FORCE, L"dllmain",L"StartDocPrinterW - failed");
    }
    else if (fdwReason == DLL_PROCESS_DETACH)
    {
		Log.ItemI(LOG_INFO | LOG_FORCE, L"dllmain",L"Unloading");
        FinalizeMadCHook();      
    }

    return true;
}
Concerningly, it doesn't seem to matter what parameters I pass to HookAPI - worng func name etc, it always succeeds.
madshi
Site Admin
Posts: 10754
Joined: Sun Mar 21, 2004 5:25 pm

Re: Hooking into just one system process

Post by madshi »

Sorry for the late reply, missed this thread for some reason (no notification from the forum this time).

Injection should work just fine, especially from a service, which has usually higher access rights/privileges than a normal user application. Seems you already solved the problem of getting a process handle? The usual way would be to enumerate the running processes and then call OpenProcess(). Enough privileges are needed for that to succeed.

HookAPI() succeeds even for APIs which don't exist - if the to-be-hooked dll is not loaded yet. In that situation madCodeHook has no way to double check whether the API really exists. So it returns true. The actual hooking is done (or attempted to be done) when the to-be-hooked dll is loaded. If the target dll is already loaded in the moment when you call HookAPI(), then HookAPI() should fail for non-existing APIs.

You could try loading the target dll yourself by using LoadLibrary(), so that you can be sure that HookAPI() returns success/failure correctly. I would recommend to do this only for testing, though.

My best guess would be that the APIs you've hooked are simply not called. You could double check by calling those APIs yourself from within your hook dll. Does the hook callback function get called then?
blackpaw
Posts: 33
Joined: Mon Nov 05, 2007 1:08 am

Re: Hooking into just one system process

Post by blackpaw »

madshi wrote:Sorry for the late reply, missed this thread for some reason (no notification from the forum this time).
No worries, thanks for getting back to me
Injection should work just fine, especially from a service, which has usually higher access rights/privileges than a normal user application. Seems you already solved the problem of getting a process handle? The usual way would be to enumerate the running processes and then call OpenProcess(). Enough privileges are needed for that to succeed.
Yes, that side of things is working well thanks - I cobbled togetehr some code that acquires a handle for any running process by module name, I can post it on the forum if you like, it works on 32/64 bit.
HookAPI() succeeds even for APIs which don't exist - if the to-be-hooked dll is not loaded yet. In that situation madCodeHook has no way to double check whether the API really exists. So it returns true. The actual hooking is done (or attempted to be done) when the to-be-hooked dll is loaded. If the target dll is already loaded in the moment when you call HookAPI(), then HookAPI() should fail for non-existing APIs.
Ah, that makes sense - thanks, I should have figured that out.
My best guess would be that the APIs you've hooked are simply not called. You could double check by calling those APIs yourself from within your hook dll. Does the hook callback function get called then?
I think you're right - using the same code to hook notepad worked as expected. From my reading of msdn I thought that spoolsv.exe called spoolss.dll to spools its jobs, but that doesn't appear to be the case :( Its a shame as I really want to just hook one central exe rather than every app on the system.

However all is not lost - spoolsv.exe does seem to call localspl.dll to do its jobs spooling to disk, shadowing all the print functions like "StartDocPrinter" with "Spl" prefixed. Initial tests look promising.


Alternatively, is it possible to inject into spoolsv.exe when it starts? it loads all the print monitor dlls on startup and I'd like to trap those dlls before it initialises them.

thanks.
madshi
Site Admin
Posts: 10754
Joined: Sun Mar 21, 2004 5:25 pm

Re: Hooking into just one system process

Post by madshi »

Injecting into a process when it starts is possible by one of the following two solutions:

(1) Either you need to hook the "parent" process (the one which will create the target process). Hook CreateProcessA/W or related APIs. Then you can inject your hook dll into the newly started process before it starts to run.

(2) Or use system wide DLL injection. You can use an include mask which only contains the one exe file you want to hook. The disadvantage of this solution is that you need to use an injection driver. See documentation.
blackpaw
Posts: 33
Joined: Mon Nov 05, 2007 1:08 am

Re: Hooking into just one system process

Post by blackpaw »

madshi wrote:(1) Either you need to hook the "parent" process (the one which will create the target process). Hook CreateProcessA/W or related APIs. Then you can inject your hook dll into the newly started process before it starts to
Interesting thought - it would be services.exe in this case.

Thanks for all the help, I think its pretty sorted out now.

Cheers.
Post Reply