How do I prevent DLL injection

Viewed 46103

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.

8 Answers

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.

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.

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.

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.

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...

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 (DEP). 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 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

Related