Page 1 of 2

Uninjected dll not completely released

Posted: Mon Jun 14, 2004 1:51 pm
by JohnStevenson
Hi Madshi
Great products - thanks.

I have a problem when I uninject my dll, as it does not always seem to be completely released. Here is the scenario:

Dll injection/uninjection is performed by a service application, which my program controls using SendIpcMessage. I use (Un)InjectLibrarySessionW, having obtained the session id with GetCurrentSessionId. The dll is injected from my program's main form Create procedure, and uninjected from its Destroy procedure. The service application logs its events so I can see that the dll is being successfully (un)injected. And my program does what it's supposed to do, so I know everything is working.

If I want to uninstall/update my program, my installer makes sure my program is not running, stops the service and then deletes/replaces the files. However, I keep getting "Access Denied" errors when the installer attemps to delete or overwrite the injection dll. But this only happens if my program has been automatically started from the user's Start Up folder!

If I start the program normally then stop it, I can delete the dll. But if it has been auto started I cannot, unless I log off then back on.

I can get round this problem by calling the dll injection later in my program (ie not in FormCreate but as the result of a user action), but I cannot work out why this is happening. Any ideas?

This does not happen on Win 98SE or Win2000, but only on XP. I've tested it on 2 XP machines with the same results.

Incidentally, with fast-user switching, things get really confused:

If User 1 auto-starts the program then the dll cannot be deleted by User 1 or any subsequent user.

However, if User 1 does not auto-start the program but User 2 does, both User 1 and User 2 CAN delete the dll!

Re: Uninjected dll not completely released

Posted: Tue Jun 15, 2004 10:00 am
by madshi
JohnStevenson wrote:I use (Un)InjectLibrarySessionW, having obtained the session id with GetCurrentSessionId.
Who calls GetCurrentSessionId? Your application or the service?
JohnStevenson wrote:If I start the program normally then stop it, I can delete the dll. But if it has been auto started I cannot, unless I log off then back on.
Could you please log with which session id you're injecting and uninjecting in the problematic situations? Maybe that helps us tracking down the problem.

Posted: Tue Jun 15, 2004 2:26 pm
by JohnStevenson
Hi Madshi

Firstly, my application calls GetCurrentSessionId.

Secondly:

Auto-start scenario
I log on as User A. My application auto-starts
- service log reports: Injection succeeded Id:0 (where Id is result of
GetCurrentSessionId called from application)

I close application manually.
- service log reports: Uninjection succeeded Id:0

I run install program and get Access Denied error for injection dll.

Manual start scenario
I log on as User A. I start my application manually
- service log reports: Injection succeeded Id:0

I close application manually.
- service log reports: Uninjection succeeded Id:0

I run install program and injection dll is replaced successfully.


Note that both scenarios start from a fresh boot-up. Also, if after the Auto-start scenario, I disable my application's auto-start and log-off User A, then when I log back on the behaviour is as the Manual start scenario.

FYI
My service records all session ids and their injected state, so it can
clean up any injected sessions on shutdown. If I create a scenario where
my application does not uninject the session on closing, the service log reports a successful uninjection on service shutdown (both from the install program and from the Services window). However, this does not solve my problem.

Hope this helps.

Posted: Tue Jun 15, 2004 2:41 pm
by madshi
Hmmmm... Sounds alright to me.

Could you please try this one?

http://madshi.net/KernelMonitor.zip

Just start it and click on your hook dll. Then the monitor will show which processes still have the hook dll loaded. Hopefully that helps us further. It seems that uninjection fails to uninject the dll from some processes. The question is from which and why...

P.S: Please don't use this KernelMonitor in win9x. Theoretically it works there, but in practise it likes to bluescreen win9x. Have to work on that. It works more or less stable in winNT, though.

Posted: Tue Jun 15, 2004 3:54 pm
by JohnStevenson
Ha!

In the Auto-start scenario one process still has the hook dll loaded after uninjection, and that's Zone Alarm (zapro.exe Version 4.0.123.12)!!

Posted: Tue Jun 15, 2004 5:03 pm
by madshi
In which session is that running? The task manager can tell you that, I think.

Posted: Tue Jun 15, 2004 5:23 pm
by JohnStevenson
Zone Alarm is running in the current user session (ie User A in above scenarios).

Posted: Tue Jun 15, 2004 5:40 pm
by madshi
So that's session 0 in your case, too? So uninjection *should* work? Which APIs are you hooking? It might be that uninjection doesn't uninject the dll from ZoneAlarm, because madCodeHook thinks that one of the API hook callback functions is still "in use" (thinking that it's still in use may be correct or not, it's hard to say). If the hook dll would be uninjected while a hook API callback is still in use, ZoneAlarm would crash.

Posted: Tue Jun 15, 2004 6:04 pm
by JohnStevenson
Yes, session id is 0.

I am hooking winsock connect.

Posted: Tue Jun 15, 2004 6:23 pm
by madshi
So probably madCodeHook seems to think that your "connectCallback" function is still in use. I'm not sure why, though. Please try this: Remove the HookAPI call. Does uninjecting work successfully then?

Posted: Tue Jun 15, 2004 7:15 pm
by JohnStevenson
No, uninjecting does not work with the HookApi call removed from the dll (and neither does my application, obviously!). ZA is still the culprit.

I notice that ZA loads after my application has auto-started, and this seems to be part of the problem:

For example, I disabled my application's auto-start and log on. I then shut down ZA, and start my application. Then I restart ZA. When I close my application, ZA still has the hook dll loaded.

Conversely, if I start my application after ZA has started then everything if fine.

(This would explain why in the Auto-start scenario the call to inject from FormCreate causes a problem - before ZA has loaded - whereas the call to inject from a subsequent user action - after ZA has loaded - is fine)

Posted: Tue Jun 15, 2004 7:42 pm
by madshi
That's really strange. I've no explanation for that right now. I'll probably give ZoneAlarm a try on my XP PC somewhen later and see whether I can reproduce the problem you're describing. However, I guess that this is a kind of ZoneAlarm protection or something like that and I'm not sure whether there's a way to solve it.

Anyway, you will have to deal with the possibility of the hook dll not being able to be uninjected from every process. As I said, madCodeHook sometimes doesn't allow uninjecting, if it thinks that a hook callback function is still in use in a specific process. So there is no guarantee that uninjecting always works for all processes.

Posted: Tue Jun 15, 2004 7:42 pm
by madshi
P.S: Currently I'm on journey, so it will take some time until I can check out ZoneAlarm myself...

Posted: Tue Jun 15, 2004 7:53 pm
by JohnStevenson
No problems. Thanks for all your help and your quick responses. Enjoy your trip...

Posted: Sat Jun 26, 2004 11:51 am
by madshi
Sorry for the delay in replying.

Ok, I've checked out ZoneAlarm and the reason for the uninjection failure is quite simple: ZoneAlarm seems to have a built in protection against dll injection/uninjection. If ZoneAlarm is running madCodeHook can't inject nor uninject a dll to/from it. The only thing that is working is the automatic injection into newly created processes, which is done by a little kernel mode driver in the NT family.

That means, if you first start your program and then ZoneAlarm, madCodeHook's kernel mode driver does its job and ZoneAlarm gets your hook dll injected. But if you first start ZoneAlarm and then your program, madCodeHook tries to create a remote thread in the context of ZoneAlarm which is supposed to load the dll. But somehow ZoneAlarm blocks that. Same thing with uninjecting: ZoneAlarm again blocks that.

:cry: