views:

1689

answers:

7

So the other day, I saw this:

http://www.edgeofnowhere.cc/viewtopic.php?p=2483118

and it goes over three different methods of DLL injection. How would I prevent these from the process? Or at a bare minimum, how do I prevent the first one?

I was thinking maybe a Ring 0 driver might be the only way to stop all three, but I'd like to see what the community thinks.

+2  A: 

The best way would be to ensure no untrusted process gets Administrator access, or runs as the same user account as your application. Without this access, code injection into your application is not possible; and once such a process gets that access, it can cause all kinds of mischief without needing to inject itself into another process - the injection just makes it easier to hide.

bdonlan
Yeah... that's not helpful. How could I put the process under a new user account from within the process?
Clark Gaebel
+2  A: 

Why do you want to prevent this? Is it an actual 'business' need, or are you just interested in a 'hack' to oppose the 'hack'

If the user rights permit this, it's by design - the OS provides the facility to all users that you, the administrator of the system have assigned to the accounts under which they run.

Raymond Chen's going to be linking here soon...

Ruben Bartelink
DLL Injection is common practice in game hacking. I am just playing with ways to prevent it. And, in turn, ways to get around those. How about we stop questioning the morality of the question and answer it instead?
Clark Gaebel
Not questioning morality at all. The more information available on both sides of hte equation, the better. My point was that the facility is an intentionally provided OS feature, and hence isnt actually something thats "not supposed to happen". Any attempt to prevent it is thus more a 'hack' than 'circumventing' in the first place. But my main aim was to confirm that one was looking to enter an arms race versus thinking that this is something that one normally adjusts at the app level. Clearly you are, so that's clarified...
Ruben Bartelink
+9  A: 

The best technical solution would be to do something that causes the loader code to not be able to run properly after your process initializes. One way of doing this is by taking the NT loader lock, which will effectively prevent any loader action from taking place. Other options include patching the loader code directly in memory to make calls to LoadLibrary fail for the attacker (e.g. insert an int3 breakpoint and self-debug to handle expected cases)..

But speaking as a hacker (one who admins the site you linked to, in fact), you're not going to ever stop people from getting code into your process, one way or another. LoadLibrary just happens to be a handy shortcut, but there are tons of different ways to load code manually that you could never hope to stop entirely, short of some extremely involved ring0 code. And even if you do go to ring0, the hackers will be right there beside you.

Also, there are plenty of legitimate uses for DLL injection. Theme programs, accessibility tools, and various programs that extend OS functionality can all potentially use DLL injection to give added functionality to any program.

Cthulhon
Albeit true that it will be impossible to stop ALL hackers, I just want to stop those three listed techniques. These are the most command, and technique one is use almost exclusively but the majority of leechers and script kiddies. Just FYI, the code is within an injected dll, so all I want to do is make sure that once I'm in, no one else can get in.
Clark Gaebel
Mind you, the Loader Lock is a global resource, and seizing it (is|should be) grounds for immediate termination.
MSalters
A: 

I'm not intimately familiar with the Windows API, but I can give you some more generalized pointers:

  1. See if you can use Windows Data Execution Prevention (DPE). It will probably not work for all (read: most) situations, because the process outlined in your link is a valid process from the OS's standpoint. Defense in depth though

  2. Ensure that your process methods assert security permissions throughout the application

  3. Statically allocate your memory space so that any new threads spawned into it will either fail or overwrite existing memory space; you'll need probably a hefty chunk of logic to detect and correct for this though.

  4. Factor your code into a device driver or some other low-level type process that you can get covered under the Windows File Protection umbrella.

Just saw Cthulon's answer (nice name, btw!) and I'm afraid he's probably correct: anyone who wants to perform code injection on your application will find a way to do so. The steps above might merely make it a bit more difficult.

Hope this helps

Josh E
A: 

Just brief thoughts for discussion :)

Using a code cave to inject a CRC check into your own code will perhaps slow down others from using other code caves.

Polling the process module list for unknown dll's being loaded might help with slowing down people just injecting any old thing with attach thread and message hooks.

Greg Domjan
+1  A: 

Are you looking for a Ring3 solution then? If so, you're wanting to build additional functionality into the system that is not currently ( at least to my knowledge ) provided out-of-the-box, so it will require some bit of work. Also, this is possible from a driver, in fact most of your AV software performs this type of activity regularly.

As for stopping the above methods from user-mode, it gets a bit trickier since you can't just register yourself as a call back to process creation or DLL loading. You can, however, if you assume your process has started before theirs, hook CreateRemoteThread and similar functions globally and perform this type of checking yourself.

So in effect you'd want to check where CreateRemoteThread wants to create a thread and return an error if you're not happy with it.

This would negate the first two methods. For the third method, if you have valid hashes of the original program on disk, then you could always check the hash before loading it. If you're without hashes, you could at least just check some of the simple places someone would add that type of code and look for DLLs you don't expect to be there (e.g. the IAT, or run strings).

It's not fool-proof, but it appears to give the functionality you requested.

mrduclaw
A: 

How to defend against those 3 techniques:

CreateRemoteThread

You can prevent the first technique (CreateRemoteThread which calls LoadLibrary) by hooking LoadLibrary. In your hook you check against a list of DLL names that you know are part of the process and that may be loaded, or you can check against a list of known DLLs you don't want to load.

When you find a DLL you don't want to load SetLastError(ERROR_ACCESS_DENIED) then return NULL. I set the last error so that people that write code looking for an error code get one. This appears to work, perhaps a different code may be more appropriate.

That will stop the DLL from loading.

SetWindowsHookEx

I think the same technique for CreateRemoteThread blocking will work for SetWindowsHookEx, but only if you can get your hook installed before the SetWindowsHookEx technique has started loading its code (which is typically when the first Window is created in an app - so early in its lifetime).

Code Cave

Nice technique. Not seen that before. You can defend against this, but you'll have to hook the LoadLibrary entry point (not the IAT table) as the Code Cave calls LoadLibrary directly.

As the author of the article commented - there are many ways you can be attacked and you probably will have a hard time defeating them all. But often you only want to defend against certain DLL loads (such as a particular 3rd party DLL that is incompatible with your software because the 3rd party DLL wasn't written properly to accomodate the fact that another hook may also be present, so you block it from loading).

Stephen Kellett