# Deep Analysis of SmokeLoader **n1ght-w0lf.github.io/malware analysis/smokeloader/** ### Abdallah Elshinbary Malware Analysis & Reverse Engineering Adventures 13 minute read June 21, 2020 SmokeLoader is a well known bot that is been around since 2011. It’s mainly used to drop other malware families. SmokeLoader has been under development and is constantly changing with multiple novel features added throughout the years. ``` Sample SHA256: fc20b03299b8ae91e72e104ee4f18e40125b2b061f1509d1c5b3f9fac3104934 ``` ----- ## Stage 1 This stage starts off by allocating memory for `shellcode using` `LocalAlloc() (not VirtualAlloc), then it fills this` memory with the shellcode (86 KB). Next, it changes the protection of the allocated memory region to `PAGE_EXECUTE_READWRITE using` ``` VirtualProtect(), then it writes the shellcode and executes it. ## Shellcode ``` The shellcode starts by getting the addresses of `LoadLibraryA and` `GetProcAddress to resolve APIs dynamically, but` first let’s see how it does that. First it passes some hash values to a sub-routine that returns the address of the requested function. ----- After some digging, I found out that the algorithm for calculating the hashes is pretty simple. ``` int calc_hash(char* name) { int x, hash = 0; for(int i=0; i.tmp" then loads` it using `LdrLoadDll() and resolves its imports from it.` ## Custom Imports SmokeLoader stores a hash table of its imports, it uses the same `PEB traversal technique explained earlier to walk` through the DLLs’ export table and compare the hash of each API name with the stored hashes. The hashing function is an implementation of `djb2 hashing algorithms:` ``` int calc_hash(char *api_name) { int hash=0x1505; for(int i=0; i<=strlen(api_name); i++) // null byte included hash = ((hash << 5) + hash) + api_name[i]; return hash; } ``` Here is a list of imported functions and their corresponding hashes: Expand to see more ntdll.dll LdrLoadDll (0x64033f83) NtClose (0xfd507add) NtTerminateProcess (0xf779110f) RtlInitUnicodeString (0x60a350a9) RtlMoveMemory (0x845136e7) ----- RtlZeroMemory (0x8a3d4cb0) kernel32.dll CopyFileW (0x306cceb7) CreateEventW (0xfd4027f2) CreateFileMappingW (0x5b3f901c) CreateThread (0x60277e71) DeleteFileW (0xb7e96d0f) ExpandEnvironmentStringsW (0x057074bb) GetModuleFileNameA (0x8acccaed) GetModuleFileNameW (0x8acccdc3) GetModuleHandleA (0x9cbd2a58) GetSystemDirectoryA (0xaebc5060) GetTempFileNameW (0x9a376a33) GetTempPathW (0x7e28b9df) GetVolumeInformationA (0xf25ce6a4) LocalAlloc (0xeda647bb) LocalFree (0x742c61b2) MapViewOfFile (0x4db4c713) Sleep (0xd156a5be) WaitForSingleObject (0x8681d8fa) lstrcatW (0x2ab51a99) lstrcmpA (0x2abb9b4b) user32.dll EnumChildWindows (0x9a8897c9) EnumPropsA (0x8f0f57cf) GetForegroundWindow (0x5a6c9878) GetKeyboardLayoutList (0x04e9de30) GetShellWindow (0xd454e895) GetWindowThreadProcessId (0x576a5801) SendMessageA (0x41ecd315) SendNotifyMessageA (0xc6123bae) SetPropA (0x90bc10d3) wsprintfW (0x0bafd3f9) advapi32.dll GetTokenInformation (0x696464ac) OpenProcessToken (0x74f5e377) shell32.dll ShellExecuteExW (0xf8e40384) And here is the list of the imported functions from the copied ntdll (for anti-hooking): Expand to see more 4DD3.tmp NtAllocateVirtualMemory (0x5a0c2ccc) NtCreateSection (0xd5f23ad0) NtEnumerateKey (0xb6306996) NtFreeVirtualMemory (0x2a6fa509) NtMapViewOfSection (0x870246aa) NtOpenKey (0xc29efe42) NtOpenProcess (0x507bcb58) NtQueryInformationProcess (0xd6d488a2) NtQueryKey (0xa9475346) NtQuerySystemInformation (0xb83de8a8) NtUnmapViewOfSection (0x8352aa4d) NtWriteVirtualMemory (0x546899d2) RtlDecompressBuffer (0xdeb36606) ----- towlower (0xf7660ba8) wcsstr (0xbb629f0b) ## Anti VM SmokeLoader enumerates all the subkeys of these keys: System\CurrentControlSet\Enum\IDE System\CurrentControlSet\Enum\SCSI Then it transforms them into lowercase and searches for these strings in the enumerated keys names: qemu virtio vmware vbox xen If one of them is found, the binary exits. ## Process Injection [SmokeLoader uses PROPagate injection method to inject the next stage into](http://www.hexacorn.com/blog/2017/10/26/propagate-a-new-code-injection-trick/) `explorer.exe .` First it decompresses the next stage using `RtlDecompressBuffer() .` Then there is a call to `NtOpenProcess() to open` `explorer.exe for the injection.` ----- The injection process starts by creating two shared sections between the current process and explorer process (one section for the modified property and the other for the next stage’s code), then SmokeLoader maps the created sections to the current process and explorer process memory space (so any changes in the sections will be reflected in explorer process). Note that both sections have `"RWX" protection which might raise some red flags by security solutions.` We can see that explorer got a handle to these two sections (this is similar to classic code injection but with much more stealth). SmokeLoader then writes the next stage to one of the sections and the modified property (which will call the next stage’s code) to the other section. ----- Finally, it sets the modified property using `SetPropA() and sends a message to explorer window using` ``` SendNotifyMessageA(), this will result in the injected code being executed in the context of explorer.exe . ## Stage 3 ``` This is the final stage of SmokeLoader, it starts by doing some anti-analysis checks. ## Checking Running Processes This stage loops through the running process, it calculates each process name’s hash and compares it against some hardcoded hashes. Here is the algorithm for calculating the hash of a process name: ``` uint ROL(uint x, uint bits) { return x<>(32-bits); } int calc_hash(char *proc_name) { int hash = 0; for(int i=0; i