Ever wonder how malware is able to harvest credentials from within web browsers? The most popular method is a Man-in-The-Browser (MiTB) attack known as inline hooking (sometimes referred to as detours). Inline hooks are incredibly versatile and very common in malware. With inline hooks, malware can become puppetmaster of any process, manipulating it into doing whatever the malware author pleases. Let’s see how they do it.
How do you get your code into the target process?
The first step in inline hooking is to get your code to run inside the target process. This process is known as injection.
There are several common injection methods that we see in the wild. For our example, we use
VirtualAllocEx to create a memory region inside of Firefox at
CreateRemoteThread would then be used to begin execution inside of Firefox in the
0x0D000000 region in order to set the hooks and to take care of initialization. (The actual injection process is an intricate topic on its own and is outside the scope of this post.) Here is what our injected code block looks like. The highlighted areas will become clearer as we go on.
There are four parts to the inline hook: the hook, the malicious code (which is filled with NOPs here), the execution of trampled bytes, and the return.
The hook, sometimes referred to as the trampoline, is analogous to a traffic officer redirecting traffic to another location. For our example, we will be hooking the
send() function from the ws2_32 library. Below is a picture of the first few instructions in the
ws2_32!send function as it appears normally. In order to place the hook, we need to overwrite some existing instructions in the function. The green box highlights the bytes that we will overwrite.
Notice that five bytes are going to be overwritten. This is the exact number of bytes needed for our hook:
jmp instruction that jumps into our code at
0x0D000000. (There are other ways to place the hook such as with a
ret instruction combination.) Here is the same
send() function after the hook is placed:
The malicious code
Now that execution flow has been redirected to our injected code, registers must be saved to ensure that we do not crash when we return execution to the
send() function. In 32-bit processes, we can save all of the registers with the
pusha instruction. When the malicious code is finished executing, the
popad instruction will restore all the registers to the state they were in when the
send() call was initially executed. Now that we are in control of the
send() function, we must come up with something interesting to do. One thing we could do is to look and see if a POST request is being sent and send that data back to our command and control in hopes it will contain login credentials.
The execution of trampled bytes and the return
After we have done something useful with our malicious code, we have to make sure our process returns to the exact same state it was in before our hook took over. First, we use the
popad instruction to restore all of our registers. Remember those five bytes we trampled over when we set the hook? Those original instructions still need to be run, so they were copied to the end of the malicious code during the hooking process so that they seamlessly run after the registers are restored. Lastly, we jump home safely into the send function + 0x05 (the length of our hook).
Putting it all together
Let’s take one more look at everything we did to get the full picture. Follow the arrows to see the flow of execution for a normal, unhooked
send() function in Firefox:
After injecting our detour, the flow of execution now looks like this:
Reasons for hooking API calls
You can probably think of a reason to hook every API call imaginable. Here are a few:
urlmon!URLDownloadToFile- Used to intercept downloaded files. Shifu hooks this function in every process in order to prevent new malware from downloading.
ws2_32!send- Used to capture POST credentials from unencrypted traffic.
GetHostByName- Shifu hooks this function in order to ignore traffic to its command and control sites.
ws2_32!recv- Used to capture incoming packet data from unencrypted traffic.
Advapi32!CryptEncrypt- Used for capturing data before it gets encrypted because it won’t be plain text when it goes out the
Advapi32!CryptDecrypt- Used to decrypt encrypted data coming in from the
User32!GetMessage- Shifu uses a hook here to intercept mouse click messages in order to take pictures of virtual keyboard clicks.
Automatically Expose Inline Hooks
With our automated TBMTM Cloud Sandbox, we automatically detect and unravel suspicious inline hooks. Our interactive reports allow you to drill down through each hooked process, module, and function. Here is an example showing Internet Explorer getting hooked:
We even provide easy access to the injected code if you wish to analyze it further yourself. You can see it in action here in this 90-second video:
If you are interested in seeing our TBMTM Cloud Sandbox in action for yourself, request a free trial now!