From aldeid
Jump to navigation Jump to search
You are here:
User-mode Rootkits



  1. If a rootkit has infected the machine, it has the ability to intercept user code calls.
  2. The control is then transferred to the rootkit that modifies the function
  3. and performs a system call to
  4. request the information from the kernel.
  5. The kernel returns the information to the library function.
  6. The library function returns the information to the rootkit
  7. which in turn re-modifies the library function. The rootkit has the ability to update the information returned from the library function

Infection steps

DLL injection


This step consists in injecting a malicious code (e.g. a DLL) into a running process. Here are some techniques to do it:

The above techniques both use LoadLibrary at some point in time, which makes the injected DLL visible in the modules list. There is a new technique:


Hooks and Hook chain

A hook is a mechanism by which an application can intercept events, such as messages, mouse actions, and keystrokes.
Hook Chain
The system supports many different types of hooks; each type provides access to a different aspect of its message-handling mechanism.
The system maintains a separate hook chain for each type of hook.
A hook chain is a list of pointers to special, application-defined callback functions called hook procedures.


This hooking mechanism can be used by attackers to inject a DLL into a remote process. Below is an extract from the reversed code of BWLoader, a DLL injector used to crack StarCraft.


Load DLL into attacking process space:

mov     eax, [ebp+lpLibFileName]
push    eax             ; lpLibFileName
call    ds:LoadLibraryA

Get address of filter function:

push    offset ProcName ; "CBTProc"
mov     eax, [ebp+hmod]
push    eax             ; hModule
call    ds:GetProcAddress

Get ID of target thread (GetWindowThreadProcessId) and installs the filter function (SetWindowsHookExA):

push    0               ; lpdwProcessId
mov     eax, [ebp+hWnd]
push    eax             ; hWnd
call    ds:GetWindowThreadProcessId
cmp     esi, esp
call    sub_41ACA3
mov     esi, esp
push    eax             ; dwThreadId
mov     ecx, [ebp+hmod]
push    ecx             ; hmod
mov     edx, [ebp+lpfn]
push    edx             ; lpfn
push    5               ; idHook
call    ds:SetWindowsHookExA


  • This only works for GUI applications.
  • On Vista, UIPI prevents SetWindowsHookEx to higher integrity level.



Below is an extract of the kInject code, depicting the CreateRemoteThread injection technique.

kInject allows to inject arbitrary DLL into another process.


Open the remote process:

push    eax             ; dwProcessId
push    1               ; bInheritHandle
push    1F0FFFh         ; dwDesiredAccess
call    OpenProcess

Allocate memory in the remote process:

mov     eax, [ebp+nSize]
push    eax             ; dwSize
push    0               ; lpAddress
mov     eax, [ebp+hProcess]
push    eax             ; hProcess
call    VirtualAllocEx

The name of the DLL to inject is written to the victim process by calling WriteProcessMemory:

push    0               ; lpNumberOfBytesWritten
mov     eax, [ebp+nSize]
push    eax             ; nSize
mov     eax, [ebp+lpBuffer]
push    eax             ; lpBuffer
mov     eax, [ebp+lpParameter]
push    eax             ; lpBaseAddress
mov     eax, [ebp+hProcess]
push    eax             ; hProcess
call    WriteProcessMemory

Find address of kernel32.dll (GetModuleHandleA) and address of LoadLibraryA (GetProcAddress)

push    offset aLoadlibrarya ; "LoadLibraryA"
add     esp, 0FFFFFFF4h
push    offset ModuleName ; "kernel32.dll"
call    GetModuleHandleA
add     esp, 0Ch
mov     eax, eax
push    eax             ; hModule
call    GetProcAddress

Create remote thread to run LoadLibraryA:

push    0               ; lpThreadId
push    0               ; dwCreationFlags
mov     eax, [ebp+lpParameter]
push    eax             ; lpParameter
mov     eax, [ebp+lpStartAddress]
push    eax             ; lpStartAddress
push    0               ; dwStackSize
push    0               ; lpThreadAttributes
mov     eax, [ebp+hProcess]
push    eax             ; hProcess
call    CreateRemoteThread


  • Only works on NT/XP based systems
  • On Vista, can't get correct permissions for CreateRemoteThread on protected processes.

Manual Mapping / Reflective DLL Injection

  • The above mentioned techniques (SetWindowsHookEx and CreateRemoteThread) both use LoadLibrary at some point in time, which makes the injected DLL visible in the modules list.
  • There is a technique called Manual Mapping or Reflective DLL Injection, which fixes this issue.
  • In use in the Metasploit framework
  • It makes it much more difficult to detect injected DLL. One approach to detecting DLLs loaded with Reflective DLL Injection is to examine virtual memory ranges (described by virtual address descriptors, VADs) for suspicious characteristics.

API Hooking

Below is an extract from the reversed code corresponding to vanquish.dll (see the Vanquish rootkit). It depicts the API Hooking process.

Find address of victim function:

.text:01AE12D2                 mov     eax, [ebp+lpProcName]
.text:01AE12D5                 push    eax                       ; lpProcName
.text:01AE12D6                 mov     ecx, [ebp+hModule]
.text:01AE12D9                 push    ecx                       ; hModule
.text:01AE12DA                 call    ds:GetProcAddress

Set memory permissions:

.text:01AE2011                 mov     [ebp+flNewProtect], 40h
.text:01AE2018                 mov     eax, [ebp+flNewProtect]
.text:01AE201B                 mov     [ebp+flOldProtect], eax
.text:01AE201E                 lea     ecx, [ebp+flOldProtect]
.text:01AE2021                 push    ecx                       ; lpflOldProtect
.text:01AE2022                 mov     edx, [ebp+flNewProtect]
.text:01AE2025                 push    edx                       ; flNewProtect
.text:01AE2026                 push    5                         ; dwSize
.text:01AE2028                 mov     eax, [ebp+lpBaseAddress]
.text:01AE202B                 push    eax                       ; lpAddress
.text:01AE202C                 call    ds:VirtualProtect

Copy Bytes from Victim Function,

.text:01AE206F                 push    5
.text:01AE2071                 mov     eax, [ebp+lpBaseAddress]
.text:01AE2074                 push    eax
.text:01AE2075                 mov     ecx, [ebp+arg_8]
.text:01AE2078                 push    ecx
.text:01AE2079                 call    sub_1AE1DFE               ; this does the copy

Compute Instruction

.text:01AE2087                 mov     [ebp+var_8], edx
.text:01AE208A                 mov     eax, [ebp+arg_C]
.text:01AE208D                 mov     byte ptr [eax], 0E9h
.text:01AE2090                 mov     ecx, [ebp+var_8]
.text:01AE2093                 and     ecx, 0FFh

Write Instruction

.text:01AE20E6                 push    5
.text:01AE20E8                 mov     ecx, [ebp+arg_C]
.text:01AE20EB                 push    ecx
.text:01AE20EC                 mov     edx, [ebp+lpBaseAddress]
.text:01AE20EF                 push    edx
.text:01AE20F0                 call    sub_1AE1DFE               ; this overwrites bytes

Reset Permissions:

.text:01AE211D                 lea     ecx, [ebp+flNewProtect]
.text:01AE2120                 push    ecx                       ; lpflOldProtect
.text:01AE2121                 mov     edx, [ebp+flOldProtect]
.text:01AE2124                 push    edx                       ; flNewProtect
.text:01AE2125                 push    5                         ; dwSize
.text:01AE2127                 mov     eax, [ebp+lpBaseAddress]
.text:01AE212A                 push    eax                       ; lpAddress
.text:01AE212B                 call    ds:VirtualProtect


blog comments powered by Disqus

Pages in this Category