Understanding/Detecting Inline Hooks/ WinAPI Hooks (Ring3)

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

What is a Windows API?

It’s a set of functions and data structures that a Windows program can use to ask Windows to do something, like opening a file, displaying a message, etc.

Pretty much everything that a Windows program does involves calling various API functions.

Collectively, all the API functions that Windows makes available are called “The Windows API”.

The hook

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: a jmp instruction that jumps into our code at 0x0D000000. (There are other ways to place the hook such as with a push addr, 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 send() function.
  • Advapi32!CryptDecrypt – Used to decrypt encrypted data coming in from the recv() function.
  • User32!GetMessage – Shifu uses a hook here to intercept mouse click messages in order to take pictures of virtual keyboard clicks.
  • Kernel32!ExitProcess– Useful to prevent process from closing itself (bypassing game anticheats)

Detection

Here is a pseudocode of a simple solution, but not very effective if the attacker is a harduser. This following code will check if the prologue of api ExitProcess starts with 0xE9 (opcode JMP)

FARPROC Address = GetProcAddress(GetModuleHandle("kernel32.dll"),"ExitProcess");
if (*(BYTE*)Address == 0xE9)
{
 printf("Api hooked\n");//Do your thing
}

Thanks.

1 thought on “Understanding/Detecting Inline Hooks/ WinAPI Hooks (Ring3)”

Leave a Reply

Your email address will not be published. Required fields are marked *