The final Payload also wasn't uploaded to Virustotal, so the detection rates supposedly are very low.
Final Payload
Sample: netui.dll
Size: 37.376 Bytes
Timestamp: 09.06.2012 12:27:19
MD5: AA3E6AF90C144112A1AD0C19BDF873FF
We start by examing the Export functions of this .dll.
Init1
It sleeps for 10 seconds and waits for Main Thread to be finished (WaitForSingleObject()).
ServiceMain
This is the first time I see that IDA Pro 5.0 free correctly recognized the ServiceMain function with its structure!
At first the Service Control Handler is registered with help of RegisterServiceCtrlHandlerEx() function. The Service Handler checks for SERVICE_CONTROL_STOP, SERVICE_CONTROL_INTERROGATE or SERVICE_CONTROL_SHUTDOWN control codes and fills the elements of the SERVICE_STATUS structure with the appropriate values to call SetServiceStatus() function afterwards. Then a new Thread (Main Thread) is created and started by calling the CreateThread() function. There follows final calls to the SetServiceStatus() function.
DllMain
At first it builds the key for decrypting the strings, function names and library names which are later (also) used for dynamically resolving API addresses. Here is the full list of decrypted strings:
LoadLibraryA
GetProcAddress
SetCurrentDirectoryW
Sleep
KERNEL32.dll
RegisterServiceCtrlHandlerExW
SetServiceStatus
ADVAPI32.dll
PathRemoveFileSpecW
SHLWAPI.dll
_except_handler3
_local_unwind2
MSVCRT.dll
free
_initterm
malloc
_adjust_fdiv
netui.dll
Init1
ServiceMain
nvgdata.dat
nvsdata.dat
%s%S
SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer
IP
els.dll
rmdir /S /Q "%s"
systeminfo
Software\Microsoft\Internet Account Manager\Accounts\00000001
%.8d
%s%s
%s is %s\n
REMOVABLE
FIXED
REMOTE
CDROM
OTHER
sptr
qfa
mpk
/~%s/cgi-bin/%s.cgi?%s
Microsoft Enhanced Cryptographic Provider v1.0
POST
Domain...
Generic..
Server..
Share....
......
--%S
Init
UnInit
%s ID:%d Path:
COMSPEC
tmp.dat
/c %s > \"%s\"
pstorec.dll
PStoreCreateInstance
Name = %s
Internet Explorer
http
StringIndex
Data =
HKLM
HKCU
HKCC
HKCR
HKU
--%s--
Name: %s Type:
STRING Value:%s
DWORD Value:%.8x
BINARY Value:
brvc
MSIE 8.0
svchost.exe
RSA1
kernel32.dll
GetLocalTime
HeapDestroy
DeleteCriticalSection
WaitForSingleObject
InitializeCriticalSection
HeapCreate
SetErrorMode
HeapFree
HeapAlloc
lstrlenA
CloseHandle
WriteFile
SetFileTime
CreateFileW
GetLastError
DeleteFileW
lstrcatW
HeapReAlloc
ReadFile
GetFileSize
FindClose
FindNextFileW
HeapSize
CreateEventA
SetEvent
InternetOpenA
FileTimeToSystemTime
FindFirstFileW
PathIsDirectoryW
GetSystemTimeAsFileTime
GetFileTime
SetFilePointer
GetDriveTypeA
GetLogicalDriveStringsA
SetEndOfFile
Sleep
LeaveCriticalSection
EnterCriticalSection
ReleaseMutex
CreateThread
CreateMutexA
MultiByteToWideChar
WideCharToMultiByte
GetModuleHandleA
TerminateThread
WaitForMultipleObjects
GetKeyNameTextW
SystemTimeToFileTime
GetModuleFileNameExW
GetSystemDirectoryW
FreeLibrary
GetExitCodeThread
psapi.dll
CreateToolhelp32Snapshot
CreateProcessW
TerminateProcess
OpenProcess
lstrcmpW
lstrlenW
advapi32.dll
RegSetValueExW
RegQueryValueExW
RegOpenKeyExW
RegCloseKey
shlwapi.dll
RegEnumKeyExW
RegEnumValueW
RegQueryInfoKeyW
RegDeleteValueW
mpr.dll
WNetCloseEnum
WNetEnumResourceW
WNetOpenEnumW
msvcrt.dll
memset
memcpy
wininet.dll
InternetConnectA
StrToIntA
StrToIntW
StrStrIW
_snwprintf
wsock32.dll
gethostbyname
inet_ntoa
WSAStartup
WSACleanup
user32.dll
SetForegroundWindow
GetForegroundWindow
CallNextHookEx
StrStrA
GetKeyboardState
GetWindowTextW
UnhookWindowsHookEx
SetWindowsHookExA
DispatchMessageA
TranslateMessage
GetMessageA
Process32NextW
Process32FirstW
GetTempPathW
VirtualProtect
ToUnicodeEx
ole32.dll
CoInitialize
CoUninitialize
CoTaskMemFree
HttpSendRequestA
HttpSendRequestExA
InternetGetConnectedState
InternetCloseHandle
HttpOpenRequestA
InternetWriteFile
InternetQueryDataAvailable
_snprintf
TryEnterCriticalSection
GetCurrentThreadId
GetEnvironmentVariableW
GetWindowThreadProcessId
GetKeyboardLayout
AttachThreadInput
PostThreadMessageA
PathFindFileNameW
crypt32.dll
CryptStringToBinaryA
CryptBinaryToStringA
HttpEndRequestA
InternetReadFile
CryptReleaseContext
CryptDestroyKey
CryptEncrypt
CryptGetKeyParam
CryptExportKey
CryptGenKey
CryptImportKey
CryptAcquireContextA
GetModuleFileNameW
NetUI
{
}
Then some function addresses are resolved and stored into global variables. What's different to the other files is that the final Payload makes use of an Anti-Reversing technique by storing the vast majority of the function addresses in Heap memory. This way a reverser only sees the base pointer (eax/ecx in this case) and an offset into the Buffer that contains the addresses (see full list in Appendix), e.g.:
call dword ptr [eax+20h] -> CreateFile()
or
call dword ptr [ecx+0BCh] -> WNetEnumResourceW()
Then it checks if the final Payload (.dll) was loaded into the virtual address space of the current process (checks if "fwdReason" = "DLL_PROCESS_ATTACH [1]") and exits if not. Next it resolves a bunch of API addresses and exits if one function address can't be resolved without doing anything malicious. It then retrieves the module file name (GetModuleFileNameW()) and tests if it is "svchost.exe". If the final Payload wasn't installed as a Service (check Part 2 -> Registry "SharedTaskScheduler" or "Run" startup methods) the module name is either "rundll32.exe" or "Explorer.exe". Dlls which are present in the SharedTaskScheduler registry key are loaded by Explorer.exe at system startup. If the module name isn't svchost.exe, the malware knows that it had to create the Main Thread (CreateThread()), otherwise the Main Thread is created in the ServiceMain routine.
Main Thread
The Main Threads starts with the same anti (AV) emulation technqiue as we have seen before by using a set of MMX instructions. If the instructions aren't emulated the occuring exception is catched and the malware exits. There follows a function which resolves the majority of the Windows API function addresses for later use. If just one of these functions can't be resolved the malware also exits.
Figure 1: API function address resolving (if just one fails, the rest is skipped) |
Next the module file name is retrieved by calling GetModuleFileName() function and cut to the next directory by using PathRemoveFileSpec() function. This new path ("C:\Windows\System32" or "C:\Documents and Settings\<Username>\Local Settings\Application Data") is set as the current directory with help of SetCurrentDirectory() function. Then the process is set to handle specified types of serious errors, so the system does not display the critical-error-handler message box. This is done to prevent any suspicious error messages done accidently by the malware.
In the following function the temporary folder is retrieved to build the strings "C:\Documents and Settings\<Username>\Local Settings\Temp\nvgdata.dat" and "C:\Documents and Settings\<Username>\Local Settings\Temp\nvsdata.dat" (Note: The temporary path can differ, see Part 2). There follows once again the retrival of the "els.dll" file time, or if this fails the system time. Then it opens the "HKEY_LOCAL_MACHINE" registry root key that was created by the 3rd Dropper (see Part 2) to get the encrypted data (RegOpenKeyEx() + RegQueryValueEx()). If that fails it tries to get the encrypted data from the "HKEY_CURRENT_USER" root key that was also created by the 3rd Dropper for that reason.
Figure 2: Retrieving of the encrypted registry data stored by the 3rd Dropper (see Part 2) |
Next, the 9 strings from "IP" entry are decrypted in memory with the same function that was used for strings, functions names and library names at the beginning.
Then it checks if the last of the 9 strings is a "1" or "0" (see Part 2). If it is a "1" (as in our case), a new Thread with a Keylogger is created. As a keylogger, the "SetWindowsHookEx" method with type "WH_KEYBOARD_LL" is used (Google: "Keylogger SetWindowsHookEx"). First it checks if a key was pressed (WM_KEYDOWN, WM_SYSKEYDOWN) and then gets the window of the key message by using GetForegroundWindow() function.
Figure 4: Malware checks if a key was pressed |
Next it gets the process name of the window in which the key was pressed (GetWindowThreadProcessId(), OpenProcess() + GetModuleFileNameEx()) and stores in into a buffer with some additional characters to better distinguish from the rest("-", "[", "]"). Thereafter the window text/capture is retrieved and also stored into the buffer (GetWindowText()) again with some characters ("[" and "]"). There follows the translation of the virtual key pressed into the actual key character (GetKeyNameText(), GetKeyboardState(), GetKeyboardLayout() + ToUnicodeEx()). After translation the character is also appended to the data in the buffer. Special pressed keys (Control, Tab, ...) are stored between the characters "{" and "}". The stored information in the buffer has the following form:
--[ModuleFileName]--
[WindowText]
...keyloggedCharacters...{CTRL}{ALT}....\n\n
After the receiving of the pressed key, the function CallNextHookEx() is used to continue. This function is also called if the message hasn't the type "WH_KEYBOARD_LL" to pass the hook information to the next hook procedure, otherwise it would be lost and that would be suspicious.
That's all of the code of this final Payload I have analyzed. Below I give you some additional information I stumbled across during analysis, but doesn't had the time to sequence.
I hope you enjoyed this 3 Part series of dissecting a multi stage malware. The completion of the analysis of this final Payload is left to the reader. ;-)
Final random Parts
As I have said, here are some random information of the final Payload:
- The final Payload is multithreaded (8 CreateThread() function calls) and uses InitializeCriticalSection(), EnterCriticalSection(), TryEnterCriticalSection(), LeaveCriticalSection(), DeleteCriticalSection() functions for data access synchronization
- It makes use of the Microsoft CryptoAPI (CryptAcquireContext(), CryptImportKey(), CryptGenKey(), CryptExportKey(), CryptGetKeyParam(), CryptEncrypt(), ...) to encrypt data with the RSA public-key encryption and then store it on disk (CreatFile() + ReadFile())
- Just like the Downloader, it also uses the Common Gateway Interface to transfer encrypted data (the gathered information, ...) to a Server (200.74.244.118), this time with the URL ".../~bing/cgi-bin/..."
- By using the GetDriveType() and GetLogicalDriveStrings() functions it retrieves the drive types (CDROM, REMOTE, FIXED, ...) and its appropriate drive names
- ...
Appendix
Windows API function offsets:
Hex Function
0 InternetOpen
4 DeleteCriticalSection
8 WaitForSingleObject
C InitializeCriticalSection
10 lstrlen
14 CloseHandle
18 WriteFile
1C SetFileTime
20 CreateFile
24 GetLastError
28 DeleteFile
2C lstrcat
30 HeapReAlloc
34 ReadFile
38 GetFileSize
3C FindClose
40 FindNextFileW
44 HeapSize
48 GetLocalTime
4C FileTimeToSystemTime
50 FindFirstFileW
54 CreateEvent
58 GetSystemTimeAsFileTime
5C GetFileTime
60 SetFilePointer
64 SetEndOfFile
68 Sleep
6C LeaveCriticalSection
70 EnterCriticalSection
74 ReleaseMutex
78 CreateThread
7C CreateMutex
80 MultiByteToWideChar
84 WideCharToMultiByte
88 SetEvent
8C TerminateThread
90 FreeLibrary
94 lstrcmp
98 lstrlen
9C RegSetValueEx
A0 RegQueryValueEx
A4 RegOpenKeyEx
A8 RegCloseKey
AC RegEnumKeyExW
B0 RegEnumValueW
B4 RegQueryInfoKeyW
B8 WNetCloseEnum
BC WNetEnumResourceW
C0 WNetOpenEnumW
C4 CryptStringToBinary
C8 memset
CC memcpy
D0 InternetConnect
D4 HttpSendRequest
D8 HttpSendRequestEx
DC StrToIntA
E0 TryEnterCriticalSection
E4 StrStr
E8 StrStrI
EC _snprintf
F0 _snwprintf
F4 inet_ntoa
F8 gethostbyname
FC SetForegroundWindow
100 GetForegroundWindow
104 CallNextHookEx
108 ToUnicodeEx
10C GetKeyboardState
110 GetWindowText
114 OpenProcess
118 InternetGetConnectedState
11C InternetCloseHandle
120 HttpOpenRequest
124 InternetWriteFile
128 InternetQueryDataAvailable
12C HttpEndRequest
130 InternetReadFile
134 CryptReleaseContext
138 CryptDestroyKey
13C WaitForMultipleObjects
140 GetKeyNameText
144 GetModuleFileNameEx
148 GetTempPath
14C StrToIntW
150 GetCurrentThreadId
154 GetWindowThreadProcessId
158 GetKeyboardLayout
15C AttachThreadInput
160 PathFindFileName
164 CryptBinaryToString
168 CryptEncrypt
16C CryptGetKeyParam
170 CryptExportKey
174 CryptGenKey
178 CryptImportKey
17C CryptAcquireContext
0 Kommentare:
Post a Comment