Uninjected dll not completely released

c++ / delphi package - dll injection and api hooking
JohnStevenson
Posts: 27
Joined: Mon Jun 14, 2004 12:45 pm

Uninjected dll not completely released

Post 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!
madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Re: Uninjected dll not completely released

Post 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.
JohnStevenson
Posts: 27
Joined: Mon Jun 14, 2004 12:45 pm

Post 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.
madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Post 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.
JohnStevenson
Posts: 27
Joined: Mon Jun 14, 2004 12:45 pm

Post 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)!!
madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Post by madshi »

In which session is that running? The task manager can tell you that, I think.
JohnStevenson
Posts: 27
Joined: Mon Jun 14, 2004 12:45 pm

Post by JohnStevenson »

Zone Alarm is running in the current user session (ie User A in above scenarios).
madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Post 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.
JohnStevenson
Posts: 27
Joined: Mon Jun 14, 2004 12:45 pm

Post by JohnStevenson »

Yes, session id is 0.

I am hooking winsock connect.
madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Post 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?
JohnStevenson
Posts: 27
Joined: Mon Jun 14, 2004 12:45 pm

Post 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)
madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Post 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.
madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Post by madshi »

P.S: Currently I'm on journey, so it will take some time until I can check out ZoneAlarm myself...
JohnStevenson
Posts: 27
Joined: Mon Jun 14, 2004 12:45 pm

Post by JohnStevenson »

No problems. Thanks for all your help and your quick responses. Enjoy your trip...
madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Post 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:
Post Reply