API Hooking in Assembly
Sunday, November 24, 2013 | Author: Deep Flash
I wanted to write an article which discusses in depth the method used for hooking the entry point of an API. This method is often used in malwares to alter the behavior of some APIs. Usually the Networking APIs imported from ws2_32.dll, wininet.dll are hooked in this way.

As an example I have taken the Win32/Gepys virus family. The code examples are in assembly. This will help in understanding clearly the method used for hooking.

In order to hook the entry point of the API we need the following:

1. API Address. This can be retrieved by calling GetProcAddress() on the API.
2. Buffer: This buffer will be used to store the first few opcodes of the API along with the jump trampoline. You can get this buffer by calling VirtualAlloc().
3. Malicious Subroutine: This is the subroutine which we want to execute before executing the main API. It will be invoked each time the main API is called from the program.

Now, let's call the API hooking routine:

We need to call VirtualProtect() on both the API and the buffer to mark these regions of memory as PAGE_EXECUTE_READWRITE. We will be executing the code from the buffer as well.

VirtualProtect(buffer, 0x10, 0x40, &oldProtect);
VirtualProtect(api, 0x10, 0x40, &oldProtect);

Now comes the main code for hooking the API. I have explained it with comments:



Once we are done with it, we again mark these regions of memory as: PAGE_EXECUTE_READ.

VirtualProtect(api, 0x10, 0x20, &oldProtect)
VirtualProtect(buffer, 0x10, 0x20, &newProtect)

So, the buffer format is:

[first 5 bytes of the API][E9 - opcode for jump][function pointer - buffer - 0x5]

and the first 5 bytes of the API are calculated as:

E9 - jump opcode
Address = malicious subroutine address - function pointer - 0x5

As an example, if we are hooking the API, ws2_32.gethostbyname with the following details:

buffer = 00D90010
api = 71AB5355 (gethostbyname)
malicious subroutine: 00C8159B

This is how the first 3 instructions of the API look before hooking:

71AB5355 > 8BFF                 MOV EDI,EDI
71AB5357   55                      PUSH EBP
71AB5358   8BEC                  MOV EBP,ESP

Using the above format of the buffer, we know the buffer should look like this for hooking:

buffer = 8b ff 55 8b ec e9 45 53 d2 70

The opcodes in the above buffer correspond to:

00D90010   8BFF                  MOV EDI,EDI
00D90012   55                       PUSH EBP
00D90013   8BEC                 MOV EBP,ESP
00D90015  -E9 4053D270    JMP WS2_32.71AB535A

This jump instruction will redirect the execution to the 4th instruction of the API, ws2_32.gethostbyname.

Also, the first 5 bytes of the function pointer can be calculated using the above method as:

jump opcode: e9
address: 8F1CC241

API after hooking:

71AB5355 >-E9 41C21C8F      JMP 00C8159B    ; malicious subroutine
71AB535A   81EC 14020000        SUB ESP,214

malicious subroutine:

00C8159B   6A 00                    PUSH 0
00C8159D   FF7424 08            PUSH DWORD PTR SS:[ESP+8]
00C815A1   E8 23FDFFFF        CALL 00C812C9
00C815A6   59                         POP ECX
00C815A7   59                         POP ECX
00C815A8   50                         PUSH EAX
00C815A9   FF15 0030C900     CALL DWORD PTR DS:[C93000]
00C815AF   C2 0400               RETN 4

at address, 0xC93000 we have the address of the buffer.

So, the instruction, call dword ptr ds:[buffer] will redirect the execution to the buffer which has the opcodes for the first 3 instructions of the API and then redirects execution to the 4th instruction of the API.

Now, that we have understood this method of API hooking. Let us see how we can detect it.

In the case of Win32/Gepys virus family, it will add the full path of the malicious DLL to the Registry Entry: AppInit_DLL. This will allow the DLL to be loaded into the address space of any new process on the system (it should be linked with user32.dll).

Also, it performs the API hooking only when it is loaded in the address space of a Browser like firefox.exe, chrome.exe, iexplore.exe, opera.exe and so on.

So, to detect this method of API hooking, we will check the calls to VirtualProtect(). Since in API hooking we are writing our jump trampolines to the API, we will check specifically for calls to VirtualProtect() that mark the regions of memory as: PAGE_EXECUTE_READWRITE.

Also, we are interested in those VirtualProtect() calls which are invoked on the API addresses.

I wrote the following Pintool which can help automate this:



Below screenshot shows it detecting the API hooks in firefox.exe:


Virus delays execution using Window Messages
Friday, November 22, 2013 | Author: Deep Flash
Recently while analyzing a virus family, I found an interesting way to introduce delay before invoking the malicious code. It also helps in not making evident the location of the malicious code. This can be obfuscated further though.

After unpacking the malware, the first thing it does is to register a Window Class with the name, "Runtime Check" with the Window Procedure subroutine at address, 00402680. It then creates the Window. During the creation of the Window, the Window Procedure is invoked which handles the initial window messages like WM_CREATE.

After the Window is created, it retrieves the message from the Thread's queue using GetMessage() and dispatches it to the Window Procedure using DispatchMessage().

Inside the Window Procedure, it reads the code of the Window Message from the stack and stores it in the EAX register. It then checks whether the window message code is greater than 0xF. If it is equal to 0x113, then it sets up a Timer that elapses after 1 second. Since the last parameter to the SetTimer() function is NULL, the system will post a WM_TIMER message to the queue every time the timer elapses. Each time a WM_TIMER message is retrieved from the application thread's message queue using GetMessage(), it increments a counter. Once the counter is equal to 5, it calls the malicious subroutine. Since the timer is set to elapse after 1 second, so overall delay introduced is approximately, 5 seconds.

Below are the corresponding sections of code:


and here is the code rewritten in C:

if(wind_code > 0xF)
{
    if(wind_code == 0x113)
    {
        counter++;
        if(counter == 0x5)
        {
            call malicious_code;
        }
    }
}
else if(wind_code == 0xF)
{
    // code for handling the WM_PAINT message
}
else if(wind_code == 0x1)
{
    SetTimer(hWnd, 1, 0x3e8, 0)
}
Some notes about Zeus
Friday, November 15, 2013 | Author: Deep Flash
Zeus bot uses some techniques which make it difficult to debug. Few of these techniques are common and used by other malwares as well. I will mention the techniques which I found interesting and worth mentioning. It will help in analyzing malwares which use similar techniques:

1. Code Injection: Like most malwares today, they inject the malicious code into the process address space of a benign system process like explorer.exe, winlogon.exe, svchost.exe and others, Zeus does the same thing. It injects the malicious code into winlogon.exe

At first, it needs to find the PID (process id) of winlogon.exe. To do this, it uses following sequence:

CreateToolHelp32Snapshot() to get the snapshot of all the running processes in the system.
Then it walks through the list of the running processes using, Process32First() and Process32Next() till it finds winlogon.exe.
Once it finds, winlogon.exe, it gets the PID from the PROCESSENTRY32 structure.

This same technique is also used to find svchost.exe PID. It makes sure that the process is running under SYSTEM account by using the following APIs:

OpenProcessToken (with Token_Query access)
GetTokenInformation (Token_User)
LookupPrivilegeValue

If in case the svchost.exe process is not running under SYSTEM account, then it continues to enumerate the processes further till it satisfies this condition.

Now, it needs to open the process with the desired access (CREATE_THREAD|VM_OPERATION|VM_READ|VM_WRITE|QUERY_INFORMATION) using OpenProcess API.

It is important to open the process with this access since we will be injecting our code into it and also creating a remote thread in it.

Once the process has been opened, we receive a handle for it. Now, we proceed to inject the code in phases.

It allocates memory into the remote process using VirtualAllocEx().

It finds the size of the sections, .text, .data, .reloc and .data1 of the malicious executable embedded within itself,  in sequence and then uses WriteProcessMemory to write it into the process address space of winlogon.exe

Now it calls RtlCreateUserThread() to create the thread in remote process.

Most malwares resume execution in the remote process using CreateRemoteThread, ResumeThread and so on. This was one of the features where Zeus differs from the rest by using the not so commonly used API.

One of the key differences between RtlCreateUserThread and CreateRemoteThread is in the way they initialize the context structures (value of the registers, eax and eip). It has been documented in detail here:

http://waleedassar.blogspot.in/2012/06/createremotethread-vs.html

The stack parameters for the call to RtlCreateUserThread look like this:


Since we know the StartAddress of the remote thread (0x00A766F8) in winlogon.exe, we can attach our debugger to winlogon.exe and set a breakpoint at it to debug further.

2.  Remote Thread Execution: The entry point of the remote thread looks like this:


In the remote thread it has a callback function (0x0A766E9) which is invoked using the CreateTimerQueueTimer() function. We get the address of the callback function from the arguments of above API, so we set a breakpoint at it.


This will create a new thread with the start address, 0x0A764E4 which is one of the parameters passed to the callback function.

After creating the necessary files on the filesystem like sdra64.exe, user.ds, local.ds and so on, it proceeds to create another thread with the following parameters:

If we look at the parameter passed to the thread start function above, it is a structure that looks like this:

 
In this structure, we have the address of a subroutine, 0x00A76361 which is the main controller routine. We will discuss more about this routine later.

We also have the handle of the NamedPipe (\Device\NamedPipe\_AVIRA_2109), two events and a pointer to the string, "_AVIRA_2109"

Let us take a look at the thread function at 0xA7A1D2 now:


It will create a mutex with the name, _AVIRA_2109 and then connect to the NamedPipe. This is the server end of the named pipe. Data is read from the NamedPipe using ReadFile and written to it using WriteFile. This is used for inter process communication.

It reads 4 bytes from the NamedPipe (which is the code of the command) that is passed to the controller function mentioned above (0x00A76361).

Here is the call to the controller function:


 And the controller function:


The command code is passed in the ecx register which is checked in the controller function.

The use of Named Pipes is another feature in Zeus that is not used in many malwares. It makes the process of debugging its code more difficult.

Similar to NamedPipes, there is another way for interprocess communication using CreateMailSlot which can be used by malwares.