A Hesperbot Core Analysis
Like most malware families, Hesperbot may originate in a spam email. Once executed, it will attempt to download its malicious modules through command-and-control (C&C) servers and monitor the activities of the infected computer. These “monitoring activities” may range from logging of keystrokes, recording of the screen, web browser hijacking and many more.As I reverse engineer this trojan, I decided to divide it into three layers for easy understanding. These three layers are The Packer, The Injector and The Core.
Three Layers of Hesperbot:
The Packer
The packer makes use of the Thread Information Block (TIB) to retrieve NTDLL.DLL base address. The base address in turn is used in getting the virtual address of the APIs it needs by feeding it to its own hashing algorithm.This Trojan uses the following hashes of APIs to operate:
For NTDLL.DLL:
- 0x952A9E4: ZwAllocateVirtualMemory
- 0xCFF13015: LdrProcessRelocationBlock
It uses ZwAllocateVirtualMemory in order to allot memory space to decrypt 24176hex of data starting from 0x00404438 virtual address where it transfers execution to decrypted data in memory.
Again it traverses TIB, but this time to get the base address of KERNEL32.DLL.
It then checks for the following hashes and saves them for later use.
For KERNEL32.DLL:
- 0x3A35705F: VirtualFree
- 0x697A6AFE: VirtualAlloc
- 0xA9DE6F5A: VirtualProtect
- 0xC8AC8026: LoadLibraryA
- 0x1FC0EAEE: GetProcAddress
It allocates another memory space using kernel32.VirtualAlloc and decrypts part of its data (the dropper module). As you can see in the figure below, the encrypted data is on the left and the decrypted data consists of MZ-PE header on the right.
This data is then overwritten to the memory space of the original process in conjunction with the usage of kernel32.VirtualProtect to avoid access violation errors in the committed pages of the original process.
All the necessary APIs are then gathered and stored in its Import Address Table (IAT) using kernel32.LoadLibraryA and kernel32.GetProcAddress.
Code execution is then transferred subsequently to the injector module at 0x0044744F.
The Injector
The Trojan hashes and stores various system information which can be used to identify the infected computer once it connects to a C&C server.- computer name
- HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\InstallDate
- system version (like service pack number)
- processor architecture (x86, AMD64, IA64)
- HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\MachineGuid
- HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\DigitalProductId
<randommutex>.mutex
<randomsemaphore>.semaphore
A system infected with Hesperbot Trojan can be easily distinguished because of this.
It then creates two folders (Sun and a randomly generated directory) in which it store an encrypted copy of itself as <random>.bkp and <random>.dat. The folder location varies from operating systems:
For WinXP:
- %ALLUSERSPROFILE%\Application Data\Sun\<random>.bkp
- %ALLUSERSPROFILE%\Application Data\<RandomDirName>\<random>.dat
For Win7 and above:
- %ALLUSERSPROFILE%\Sun\<random>.bkp
- %ALLUSERSPROFILE%\ RandomDirName>\<random>.dat
It will then generate a platform-specific loader code, by checking the OS architechture by using GetNativeSystemInfo.
Hesperbot has three ways to inject its core module to explorer.exe and these all depends whether cmdguard.sys or klif.sys exists in the system. Three scenarios are listed below
- SCENERIO 1: %systemroot%\system32\drivers\cmdguard.sys exists (Comodo Firewall Guard driver)
- copy procedure to high memory and transfer execution
- spawn suspended process of explorer.exe using kernel32.CreateProcessW
- craft bytes in stack that will jump to malware code in memory
- modify explorer.exe entry-point and insert the crafted bytes from stack using kernel32.VirtualProtectEx and kernel32.WriteProcessMemory
- resume suspended process using ntdll.ZwResumeThread
- SCENARIO 2: %systemroot%\system32\drivers\klif.sys exists (Kaspersky Antivirus system driver)
- copy core procedure to memory
- spawn suspended process of attrib.exe using kernel32.CreateProcessW
- craft bytes in stack that will jump to malware code in memory
- modify attrib.exe entry-point and insert the crafted bytes from stack using kernel32.VirtualProtectEx and kernel32.WriteProcessMemory
- resume process of attrib.exe using ntdll.ZwResumeThread
- injected code in attrib.exe uses kernel32.CreateRemoteThread in order to create a new thread that will inject the core module to explorer.exe
- SCENARIO 3: cmdguard.sys and klif.sys do not exist
- copy core procedure to memory
- spawn suspended process of attrib.exe using kernel32.CreateProcessW
- craft bytes in stack that will jump to malware code in memory
- modify attrib.exe entry-point and insert the crafted bytes from stack using kernel32.VirtualProtectEx and kernel32.WriteProcessMemory
- resume process of attrib.exe using ntdll.ZwResumeThread
- injected code in attrib.exe that spawns explorer.exe in suspended state
- making use of windows messaging vulnerability to trigger shellcode execution into explorer.exe address space. (This is commonly known as PowerLoader injection http://www.malwaretech.com/2013/08/powerloader-injection-something-truly.html)
- the shellcode uses CreateThread and VirtualAlloc to pass execution the core module
For debugging purposes, these are the steps on how I got to trace the shell code:
1. First of all, know which shell code will be executed. For this sample of Hesperbot, the start of its shell code is at 0x0044A77C – E8 29 00 00 00
2. Replace the first byte 0xE8 to 0xCC (int 3). Save this modified copy.
3. In Ollydbg, goto Options->Just-in-time-debugging and click “Make OllyDbg just-in-time debugger” then exit Ollydbg.
4. Now execute your modified copy of the malware and it should crash windows explorer.
5. Hit the “Debug” button and Ollydbg should pop up, just replace back the modified byte from 0xCC to 0xE8 and start tracing that shell code!
These are the hashes of APIs that are used by Hesperbot Trojan in order to protect itself from easy detection by AV vendors.
- 0xB02814b6 = kernel32.ExpandEnvironmentStringsW
- 0x002CFE2B = kernel32.CreateFileW
- 0xB376CE13 = kernel32.lstrlenW
- 0xA24F346A = kernel32.CreateProcessW
- 0x107B9483 = kernel32.WriteProcessMemory
- 0x1A471325 = kernel32.VirtualProtectEx
- 0xFDEB2A69 = kernel32.IsProcessorFeaturePresent
- 0x8D70B719 = kernel32.IsWow64Process
- 0x4B892318 = kernel32.CreateRemoteThread
- 0x26662FCC = kernel32.CreateThread
- 0xDF894B12 = kernel32.VirtualAlloc
- 0x3708EE6B = ntdll.ZwCreateSection
- 0xC477C525 = ntdll.ZwMapViewofSection
- 0x2015436B = ntdll.ZwResumeThread
- 0xB85C56EA = ntdll.ZwTerminateProcess
- 0x3F66C5FF = ntdll.ZwGetContextThread
- 0xD1E48C8B = ntdll.ZwSetContextThread
- 0x4C7D8945 = ntdll.ZwDelayExecution
- 0x7B005F26 = ntdll._allmul
- 0x0BD5C7BD = ntdll.ZwQueryInformationProcess
- 0x87CE75D8 = ntdll.ZwClose
- 0xE3086B33 = ntdll.ZwOpenProcess
- 0x35013E23 = ntdll.ZwTerminateThread
- 0xA2E76D4C= ntdll.ZwOpenThread
- 0x6DD66096 = ntdll.ZwQueryInformationThread
- 0x8EAE85FE = ntdll.ZwReadVirtualMemory
- 0xAAD44E29 = ntdll.ZwOpenSection
- 0xB7EF35F4 = ntdll.RtlCreateUserThread
- 0x9CD6615A = user32.FindWindowA
- 0x4A4627DC = user32.GetWindowThreadProcessId
- 0x3CC18006 = user32.SendMessageW
- 0x8252D56B = user32.SetWindowLongW
- 0x1FFBFCD8 = user32.GetClassName
- 0x52BD91BC = user32.SystemParametersInfoW
- 0xD563318F = user32.RegisterClassExW
- 0x835DB020 = user32.CreateWindowExW
- 0x8252D56B = user32.GetMessageW
- 0x8252D56B = user32.TranslateMessage
- 0x2776DB53 = user32.DispatchMessageW
The Hesperbot Core
Execution is then passed to the core module after injecting it to explorer.exe. Like always, it must gather first all the necessary APIs it needs by using kernel32.LoadLibrary and kernel32.GetProcAdress method.It will then set its priority level to THREAD_PRIORITY_ABOVE_NORMAL to give more priority to itself than most active threads in explorer.exe.
It will also attempt to set explorer.exe’s integrity level to LOWINTEGRITYLEVEL_FULLACCESS, so that new processes (like other downloaded malicious modules) with higher integrity than explorer.exe can have read/write access to it.
Integrity levels are a new kernel security feature introduced in Windows Vista. You can read more about it in https://en.wikipedia.org/wiki/Mandatory_Integrity_Control.
The core then creates a mutex for itself with the format Global\inst_<randomstring> and Global\<randomstring>.
It then verifies which running process it is injected to. It does this by hashing its current process filename using its own hashing algorithm and comparing to a table of hashes found in its body. So far, these are the hashes of processes which I recovered from its table through trial and error. Understand that recovering these process names is near impossible because of how the hashing algorithm was designed by the malware author.
- 0x11955DB8: explorer.exe
- 0XAAF840B5: csrss.exe
- 0X1FC97071: svchost.exe
- 0x537B492F: iexplore.exe
- 0x76379A9A: firefoxe.exe
- 0XCA846265: chrome.exe
- 0X6FB8169E: opera.exe
- 0X9544710B: browser.exe
- 0X78AB2C5C: webkit2webprocess.exe
- 0X2771AA06: maxthon.exe
- 0XB64FEEED: sleipnir.exe
- 0XE80C41EC: deepnet.exe
- 0X30B15DB3: seamonkey.exe
- 0X532A495F: k-meleon.exe
As you can see, most of these hashes are process names of known web browsers. This gives us a hint that it will try to monitor web activity at some point.
The core module is the one responsible for creating a copy of the trojan in %windir%\<randomFolder>\<randomFileName>.exe. This executable is also referenced by a REGRUN entry at HKEY_LOCAL_MACHINE\ SOFTWARE\Microsoft\Windows\CurrentVersion\Run “randomValueName” to ensure auto execution on windows startup.
It will check for a valid internet connection by querying websites like:
- http://wikipedia.org
- http://facebook.com
- http://google.com
- http://microsoft.com
It then attempts to connect to its control server using https service and port 443. Its control server can be any of the following:
- whoischeck.biz
- 192.31.186.116
- 188.241.112.29
- 5.63.152.44
- 96.43.141.186
- 94.126.178.29
If the default control server (which is whoischeck.biz) did not respond to the request, it continues to check for other control servers listed above using Domain Generator Algorithm (DGA) in which a random domain name is used in order to evade general antivirus detections.
It will then send the following information after a successful connection handshake is established:
- Computername that will serve as the ID of the infected machine e.g. "WINXP-6F60CDCD2A3429D85B855BF7"
- Bot name “tr-botnet”
- Network adapter information like adapter name, ip address, gateway, dhcp server, etc.
- Installed smart cards by using SCardEstablishContext, SCardListReadersW and SCardConnectW
This Trojan supposedly downloads other malicious modules from its control server like keylogger, screen recorder, Virtual Network Computing (VNC), network traffic interceptor, etc. However; as of this writing, its control servers seems to be taken down already and are not responding.
Conclusion
Reverse engineering hesperbot core is quite fascinating. It demonstrates numerous tricks up its sleeves to elude easy detection by most antivirus vendors like hashing of process names and needed APIs; encrypting and decrypting part of its codes in memory; and generating random domain names when connecting to its command-and-control server.It also demonstrates three techniques to process injection. These are via (1)CreateProcess-ResumeThread, (2) CreateRemoteThread, (3) and by exploiting window messaging vulnerability using FindWindow-“shell_traywnd” – SetWindowLong trick.
Christopher D. Del Fierro