Unusual reboot by hooking ZwUnloadDriver

Today I was experimenting with hooking functionality of device driver I had written.It was amazing that I could hook even ZwLoadDriver and ZwUnloadDriver without any problem.But When I tried stopping the driver it resulted in system crash and then reboot.The same didnot happen when I hooked ZwLoadDriver alone.
Anybody knows the reason why?

Maybe, because your driver hooks unloading of itself :slight_smile:

–pa

Pavel,

Your answer is probably correct, ZwUnload is in the roughly 10% of
the calls that require special work to hook. A more interesting
question is why is the OP hooking this in the first place,
PsSetLoadImageNotifyRoutine’s callback will handle most users needs on
this.

Don Burn (MVP, Windows DKD)
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

“xxxxx@fastmail.fm” wrote in message
news:xxxxx@ntdev:

> Maybe, because your driver hooks unloading of itself :slight_smile:
>
> --pa

>>PsSetLoadImageNotifyRoutine’s

Worth to mention number of subscribers are limited, and if I would be the bad guy, I would fill it all to prevent others from registering notification callback :slight_smile:

The restriction by Microsoft is stupid, they literally have a counter to
check if the linked list of calls gets more than 8. Of course if you
are the bad guy you are also monitoring the SSDT and eliminating the
OP’s hook. If you want to claim we should not use something because it
can be attacked, then give up on computers period.

Don Burn (MVP, Windows DKD)
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

xxxxx@shcherbyna.com” wrote in message
news:xxxxx@ntdev:

> >>PsSetLoadImageNotifyRoutine’s
>
> Worth to mention number of subscribers are limited, and if I would be the bad guy, I would fill it all to prevent others from registering notification callback :slight_smile:

Nope.

I just want to say that OP has to check for return value of the function and if it is STATUS_INSUFFICIENT_RESOURCES do something else.

The unload routine for the driver is called before unloading the driver.
So, in the unload routine I had written I unhooked the ZwUnloadDriver routine inside it.Is it causing this side effect?Where should I unhook the ZwUnloadDriver routine then.Is there a way of calling any routine just before Unload is called?

xxxxx@hotmail.com wrote:

The unload routine for the driver is called before unloading the driver.
So, in the unload routine I had written I unhooked the ZwUnloadDriver routine inside it.Is it causing this side effect?

Think about how this works.

Device manager decides it needs to unload your driver. It calls
ZwUnloadDriver, but because you have hoooked it, the call goes to your
hook instead. The call stack goes:

device manager
–> your hook
–> ZwUnloadDriver
–> your driver’s unload routine

Your unload routine undoes the hook. Now, you return, ZwUnloadDriver
then removes your driver from memory and returns. When it returns, the
address it pops from the stack is an address inside your hook routine,
but that address now points into empty space, because your driver has
been unloaded.

Working around this kind of issue requires careful magic. If your
unload hook detects that the hooking driver is being unloaded, then it
needs to fix up the stack so that it looks like the hook never
happened. That requires assembly coding.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

> Working around this kind of issue requires careful magic. If your unload hook detects that the hooking

driver is being unloaded, then it needs to fix up the stack so that it looks like the hook never happened.
That requires assembly coding.

You make an assumption that, at the time of unloading a driver, you will be still the first one in a call chain that you have hooked…

However, taking into the account that the above is not guaranteed to be the case, you need another workaround. Basically, you have to ensure that the pointer that you have registered in a call chain will stay valid until the reboot. It has to point not to your actual code but to a chunk of unpaged memory (IIRC, memory in unpaged pool is executable) loaded with machine instructions that make a jump or call to your code. When you unload your driver you will update this chunk in such way that it points to the original callee, rather than your code. However, this chunk has to stay, and a pointer to it has to remain in a call chain - otherwise you have a good chance to crash after having unloaded your driver…

Anton Bassov

Thanks for clarification.Now I understood why the system use to crash everytime I used to unload my driver.
I was thinking for a solution for this problem besides assembly programming.Is there any way to call a routine or function that does the unhooking just before the unload routine is invoked so that my driver can unload safely using the unhooked ZwUnloadDriver?

xxxxx@hotmail.com wrote:

Thanks for clarification.Now I understood why the system use to crash everytime I used to unload my driver.
I was thinking for a solution for this problem besides assembly programming.Is there any way to call a routine or function that does the unhooking just before the unload routine is invoked so that my driver can unload safely using the unhooked ZwUnloadDriver?

There is no way to do this safely. Did you read Anton’s reply
yesterday? He is quite correct. If someone else happens to hook the
same API after you, that driver will save your handler’s address in
their private memory. There is no way to fix that. Thus, the address
you shove into the hook must be valid forever.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

>>Is there any way to call a routine or function that does the unhooking just before the unload routine is invoked so that my driver can unload safely using the unhooked ZwUnloadDriver?

And how on the earth they know about the function address to restore (you took the IAT, hook it, may be some one hooked it before you, may be not). Its you who has the last address so its you who can restore it.

I have not seen such a weird requirement. Its like sitting on a branch of tree, cutting that same branch and asking can some one switch me to some other branch before gravity starts acting on my bottom.