Log in

View Full Version : Detouring DriverEntry / Self Debugging


naides
December 4th, 2006, 20:54
Sorry naides, I can't delete the first post in a split thread without deleting the whole thread
.. this shell must remain
Kayaker

blabberer
December 5th, 2006, 06:12
ok since we are talking about fooling things on the fly how does one accomplish trampolining a driver in disk (no not memory patching )
suppose we have a driver and we want to hardcode some trampoline in its driver entry (this buggers off after being called once never to be bothered again) what needs to be taken care off ??
(crc checks /release checksum others ?? what about the ubiquitous digital crap thats being tom tommed as if its cure for all ills in operating systems thats yet to see the light of day )
how do you add space to a driver for extra code i mean if the cave in question is small can an additional section whatever be added to it in the end ?? like in user mode i assume the base windoze loader is same so the concept should be same or am i being naive ?
i think i can edit peheaders section data to resemble exactly like loaded image this could yield a lot of space if the file alignment section alignment are different like in user mode (file align = 0x200 section align = 0x1000 we get 1400 bytes free without having to do anything except make file = image )

now drivers often dont use 0x200 and 0x1000 but have file align == image align and that too at probably 0x20 if my memory serves me right how could we generate extra space in these situations and if we are trampolining to a section at end will this section too get paged out along with the page where the original driver entry exists ??

now if we are trampolining successfully we need to do some usefull stuff
assume we need to log eax on every execution of our trampolined code

can we call _lwrite from c runtime (oh thats talking too primitive i mean here whats the bare minimum api/kapi/hack that could allow us to log to say some_foo.txt which we can open at leisure ?

assuming we opened NtCreatefile and use NtWriteFile to write and assuming it somehow succeds when do we close the handle to the file ?
do we have to open close on every loop ? coz after driver entry yields back to system i suppose it will never be called again and we cant issue a close
and this handle may be orphaned zombie ??? and would may be prevent us from reading it in notepad.exe ??

also is it possible to generate an universal position independent logging code

is it a fact that any and every dumb driver should import from ntoskrnl.exe ?
or can a no import driver work too ?

and can we scan its import table /? scan shadow table /? ssdt /? whetever it takes and for us to scan and fetch MMGetSystemRoutineAddress() apis start and use it to fetch all other concievable api address

also what care should be taken to possibly avoid or minimize bsods in the process of experimenting a trampoline on lets say trashing hal.dll or possibly ntoskrnl.exe itself (again no in memory patching i want to hard patch on disk and make the souped up driver load without problem and work like i want it to work without windows hampering me in the process)

i would settle for w2k with or without service packs(assuming its the most lenient for non ms persons playing gobbleydegook with its core drivers)

has anyone compiled several helloworld.sys and file compared them for differences between differnent builds (whats different in them except may be time and checksum )

what windows say if we change helloworld to hi world in hexeditor and force load it ?

all this must be accomplished without source all we have is a foo.sys and it does some magic and we want to log every step of it without involving a debugger (in fact nothing external should be involved all of it must be embedded inside and it should be stand alone )

whats the impact on performance of such a heavily patched driver


kayaker ? ? i know you must have a few pointers

Kayaker
December 6th, 2006, 21:48
Now what the heck are you up to Blabberer? That's OK, I think I know

I split this into a new thread since it's totally off topic from the original. That's a pretty cool idea, you want to morph a driver into a self-logging one?

It would probably be easier to do the detour dynamically, at least for drivers that load via ntoskrnl!IopLoadDriver. Much as I did in the Daemon Tools/SPTD thread, where you create a "wrapper" around the standard ntoskrnl DriverEntry loading routine.
http://woodmann.net/forum/showthread.php?t=9201

However this wouldn't apply to say boot loading drivers. That's an interesting idea then, to modify the file itself. One problem though would be if the driver does an internal checksum. As you say you have to update the PE.Checksum value any time you modify a driver file, but that's only to satisfy the PE loader. If the driver does its own checksum this probably wouldn't work (depends on how it's implemented). Btw, if you happen to have the SPTD driver in mind here (no, really!?), it does a full checksum hidden somewhere in its VM, so you're probably out of luck

The general idea sounds OK though, create a new section, change the Entry Point to your new section EP, do stuff, call the original DriverEntry with a CALL so it returns to your code, return control to the system. In essence create a wrapper like I did in that other thread. The only difference is that you'd need to hardcode the original DriverEntry EntryPoint address rather than getting it dynamically from the stack. Maybe something like:

Code:

__declspec(naked) DriverEntryDetour(){

///////////////////////////////////////////////

// Save the original DriverEntry parameters
// DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING RegistryPath)

_asm{
push dword ptr [esp+8]
pop pusRegistryPath_original

push dword ptr [esp+4]
pop pDriverObject_original

push dword ptr [esp]
pop ReturnAddress_DriverEntryDetour
}

///////////////////////////////////////////////

//... DO BAD STUFF...//

__asm
{
// Call orginal DriverEntry

push pusRegistryPath_original
push pDriverObject_original
call [DriverEntry_original] // hardcoded

mov DriverEntry_returnvalue, eax
}

///////////////////////////////////////////////

_asm{
mov eax, DriverEntry_returnvalue
push ReturnAddress_DriverEntryDetour
ret
}
}



As for the logging capabilities, if you have some driver code running in a new section I suppose you could run it as a debugger. You'd have to make sure your code isn't paged out as a regular INIT section would be. So what if you hooked Int3 and installed your own breakpoint handler. Then you changed the first byte of the original DriverEntry to 0xCC, saving the original byte of course. Then you call the original DriverEntry and let it run. Breakpoint hits, your Int3 ISR handles it, you check where it came from, you log 'whatever' if it's the BP you set, replace the byte, set a new 0xCC breakpoint on the very next instruction, IRETD without passing to the original Int3 handler, ad infinitum. I don't know about INT 3's purposely inserted to execute an SEH handler, as a debugger protection mechanism, you might have trouble with those or have to handle them differently.

Would it be slow? Sure, remember the BPRW Backtrace command? But that's not the point is it?

As for logging output to a text file, well this would be from within the Int3 handler so you'd have to be careful, but yeah there are file output strategies available. You could log to a circular buffer (which is what BPRW used) and occasionally dump it, that would probably be the most efficient. Or you could create a dedicated file output thread with PsCreateSystemThread and implement linked lists and spinlocks and such to output the file. This is what I did with a Softice kernel debugger extension and it worked well.

The big problem I see from all this (and I don't really know if any of it would work anyway), is the problem of writing the code. As you say you could probably fetch MmGetSystemRoutineAddress and work from there, doing it all in assembly.


The other idea I had though, instead of creating a new section and modifying the EP for the driver, you instead add a new *import module* entry to that section of the PE. This new module will be a kernel-mode dll which is automatically loaded when the driver is loaded (and unloaded in turn). As you're probably aware this is what I did as an example with my SysDasm driver, also mentioned in the above thread I linked to.

The SysDasm module loads as an export-only driver, but if you read the Intro.txt file I wrote that you can also write a kernel dll with functional entry/exit routines by adding PRIVATE exports declared as DllInitialize/DllUnload. This is all from
DLLs in Kernel Mode by Tim Roberts
http://www.wd-3.com/archive/KernelDlls.htm

Remember that such a kernel dll is loaded explicitly by the driver, just like ntoskrnl.exe / hal.dll. Now I'm not 100% sure, but *if* the DllInitialize routine is called and returns before the main DriverEntry routine, then you've got an opportunity to set up your Int3 handler/self debugger. (Does DLLMain for a usermode dll get called before the PE file first executes? should be the same principle)

Also, if the *image* of the original driver has been mapped before the dll modules are loaded, then you can also change the first byte of DriverEntry to 0xCC, priming your Int3 handler to begin its work.

If this worked you wouldn't have to worry about hardcoding anything or modifying the driver file other than inserting a new import entry, and you can write and compile a separate driver without the constraints of finding API offsets from within a code cave. I've got some thoughts about using your own Int0E and Int01 handlers instead (think ShadowWalker/OllyBone), but they're just fanciful concepts floating around at the moment

I'm sure there are plenty of holes in the logic so feel free to shoot them down.

Cheers,
Kayaker

blabberer
December 7th, 2006, 06:34
as usual nice insights and pretty neat explanations
thanks for summing it up nicely

as for whether usermode dlls dllinitilize is called before pe executes
yes it does execute before pe file gets any chance to execute anything

flow is like this for userland

tls callbacks of dlls
dll init of dll
tls callbacks of pe
then real pe gets a chance if it ever gets it

you can check the ntglobalflag plugin sources in stuph it has some examples
included

or google for brett-moores paper predeug (that effectively shows how to insert predebug.dll in import modules of an exe and get a commandprompt running before pe even starts to execute exactly like you suggest hardcoding the dll and loading it from path and letting winloader load this dumb dll modify whatever is to be modified reset the original kernel32.dll and unload it self and live happily ever after)


as to setting up int3 handlers isrs circular buffer etc i need to digest them before i could even think about logic holes so shooting them down (joking aint you ? ) is for laters

oh btw i never thought ill need to run my own debuggers
i was thinking in simple terms like complete hardcoded crap

suppose the original has
jmp dword ptr ds:[some const + r32*jmp table const] hard jump not conditional and no return to next valid instuction

what i was thinking was to insert

jmp someplace
malloc/valloc/rtlalloc/ some buff (assuming driver already imports them)
sprintf/wsprintf/some equivalent in kland/ (somebuff,formatstring,params)
ntcreatefile(//./??/somedir/mylog.txt)
ntwritefile(handle,somebuff)
ntclose()
free/vfree/rtlfree
execute original trashed instruction < should cycle upon itself isnt it ?

now thats lame logic wont work universally maybe it wouldnt even work at all

i was thinking of doing comapres on no debugger and with debugger on modified thingy so as to narrow things down some where some place things have got to diverge

sptd whois it a new kid in the block ? gotta find and rag
putting on my seniors cap