there is a non exported function in ntoskrnl.exe called ioploaddriver. bpx that api. keep in mind that you need to load the nms (softice propriatary pdb format) to find this import. in my rustock.b paper i have written a detailed step-by-step guide how to do this.
windbg should do this without problems.
you can also try to install a callback with PsSetLoadImageNotifyRoutine and then initiate a debugger break
> frankboldewin: there is a non exported function in ntoskrnl.exe called ioploaddriver. bpx that api. keep in mind that you need to load the nms (softice propriatary pdb format) to find this import. in my rustock.b paper i have written a detailed step-by-step guide how to do this.
>
> windbg should do this without problems.
>
> you can also try to break on pssetimagenotifyroutine
A driver is a modified PE file. There is no exported DriverEntry symbol and you can name the function anything you want. There's a special section, INIT, that contains the DriverEntry code that is called when the driver is loaded. The start address within the INIT section is contained in the PE section "OPTIONAL" and is labeled "AddressOfEntryPoint". Find the load address of the driver, add the offset from the start address, and set a hw breakpoint.
You can also set a conditional breakpoint based on the name of the driver as it's being loaded.
# how to break at DriverEntry for _any_ driver without syms
there are many ways to do this.
1) patch the driver and insert CCh code at DriverEntry.
it doesn't work for signed driver and causes a lot of problems:
how to bypass unhanded exception.
2) break on IoCreateDevice or any other API-function called by the driver;
it works, but causes many false positive alarm;
it doesn't work at all if the driver doesn't call any API function in DriverEntry;
3) break on unexported internal kernel function ioploaddriver
it works, but requests pdb-symbols;
4) well, the simplest method is:
a) create your own driver and place int 03 at the DriverEntry;
b) load it and catch the exception in the debugger;
c) unroll stack and see which functions was called before;
/* in my case - W2KSP0 - this is internal function placed at 804D9281h */
d) set break on 804D9281h and reload driver
(need reboot, if don't want to bypass the unhanded exception)
e) catch the debugger pop-up and trace 804D9281h
utill you see CALL [EAX+2Ch] or something like that.
does it look familiar? I mean 2Ch constant. this is offset of the EntryPoint!
f) save address of the CALL [EAX+2Ch] (in my case it's 804A442Eh).
well, every time you want to pop-up at the DriverEntry,
just break on 804A442Eh.
the point is: this address will be always the same
(of course if you don't install/uninstall Service Pack)
CALL [EAX+2Ch] passes control to the DriverEntry.
ok, there is a better solution:
1) write your own demo driver (see bellow);
2) put CCh (int 03) into DriverEntry;
3) load the driver;
4) wait until the debugger pops-up;
5) trace code until you return to the mother-function;
6) this function is internal _IoLoadDriver procedure; /* but it doesn't matter at all */
7) see the instruction above: "CALL [EAX+2Ch]", where EAX -> "PE", 2Ch is an offset of the DriverEntry;
8) remember the address of the CALL [EAX+2Ch], it various from one version of the kernel to another, but for certain version (your version) it's always the same. (for W2KSP0 RUS it's 804A442Eh);
9) since, "CALL [EAX+2Ch]" immediately passes control to the DriveEntry this is best solution to break on it and have a fun.
now, the demo-driver:
---------------------
.686
.model flat, stdcall
.code
DriverEntry proc
int 03
nop
mov eax, 0C0000182h; STATUS_DEVICE_CONFIGURATION_ERROR
ret
DriverEntry endp
end DriverEntry
and now how to make it (you must to have NTDDK):
------------------------------------------------
ml.exe /nologo /c /coff demo.asm
link.exe /nologo /driver /base:0x10000 /align:32 /out:demo.sys /subsystem:native demo.obj