The goal of DLL injection is to load a code into another running process’ address space. So how exactly do we go about accomplishing that? It turns out there are a couple of ways to do so in Windows. We are first going to examine “SetWindowsHookEx,” a method for creating hooks in Windows. If by the end of this post you are hungry for more, check out the references at the bottom. They helped me with a lot of the code and other information here.
The first thing to understand is how Windows hooks work and then how the Windows API method SetWindowsHookEx works. Hooks are a way to intercept events and act on them. There are many different types of hooks available. A few examples would include: WH_KEYBOARD and WH_MOUSE. These two can be used to monitor keyboard and mouse input respectively. There are also low level versions of both of those hook types. The important thing to understand about them is that every event that occurs will go through a hook chain. This chain has a series of procedures that will run on the event.
Here is the syntax from MSDN for a hook procedure:
The hook is called, performs whatever procedure it wants, then calls the next hook in the chain. According to Microsoft though, CallNextHookEx is only recommended and not required. So then it can be excluded so that the event isn’t seen by other hooks. Here is an example of a keylogger that uses Windows hooks. Compare the structure between the two. We can see that it hooks the process in the main method using SetWindowsHookEx and then for every event it outputs the keystroke and then calls the next hook in the chain.
Using SetWindowsHookEx to Inject a DLL
SetWindowsHookEx is how we put our own hook procedure into the hook chain. Here is the MSDN syntax for the method:
It takes the type of hook to be installed (idHook), the pointer to the procedure (lpfn), the handle to the DLL with the procedure (hMod), and finally the tread id to associate the hook to (dwThreadId). To get the pointer to the procedure we first need to load the DLL using the LoadLibrary method. This loads it into the address space of our exe. Then GetProcessAddress we are able to locate the address to the method that we want to use. Finally, we call SetWindowsHookEx and either wait for the event that we want or create our own using something like BroadcastSystemMessage. Once that event happens, Windows will load the DLL into the processes address space where it will be executed.
The following was adapted from code found here. First we load the DLL into the executable using LoadLibrary method. With GetProcAddress we get the address of the inject method from the DLL. Finally we set up a global hook (the parameter 0 will hook every thread in the current desktop) and wait for the program to be hooked.
In the DLL (adapted from here), we are setting up a Windows Socket to call out to a specific machine and sending a simple message.
Here we can see that the DLL called out to the other machine.
And here the DLL is loaded into a different process. Success!
This code does have issues though. We are setting up a global hook which means that any process that receives a key press will be hooked. In other words, we could end up injecting into something undesirable. Fortunately, it is quite possible to inject into a specific process. Here is a modified version that includes the necessary changes. This MSDN post helped me get some of the information I needed. This code adds some extra steps for targeted injection. First, it gets the process id to inject into. Using this it gets a thread id that is part of that process, since SetWindowsHookEx takes a thread id as the final parameter. Then it hooks our process and we wait.
This time we ran the DLL from the previous post.
Look at that! There is the message box running from the process we selected. Using Process Explorer we can see that the DLL is loaded into both Notepad++ and into the injector exe, which makes sense since the exe originally loads the DLL.
There are some limitations to hooking processes though. A process must have a Message Loop to be able to receive a message and thus be hooked. This limits our targets to primarily GUI based applications. SetWindowsHookEx also cannot be used on processes with a higher integrity level.
Reverse-Engineering Our Code
Here is what IDA gives us for the first injector.
This isn’t the whole graph of the process, but we can see the main portion of SetWindowsHookEx. First we load the inject.dll using LoadLibraryA. If you notice, param1 is used before each of the method calls. This is because that is the offset for the on the stack that it will save the first parameter. So we can see that it gets the address of the inject method (dllMethod) and then moves the handle to the DLL into param1 and calls GetProcAddress. Finally it loads all of the values for SetWindowsHookEx and calls it. Compare that to the second method.
There is really only one difference here, it moves the threadID variable that it got earlier into the fourth parameter spot on the stack and then calls SetWindowsHookEx. Not too bad is it? Coming up next we have the CreateRemoteThread method for injection. Keep hacking!