Floki Bot, described recently by Dr. Peter Stephenson from SC Magazine, is yet another bot based on the leaked Zeus code. However, the author came up with various custom modifications that makes it more interesting.
According to the advertisements announced on the black market, this bot is capable of making very stealthy injections, evading many mechanisms of detection. We decided to take a look at what are the tricks behind it. It turned out, that although the injection method that the dropper uses is not novel by itself, but it comes with few interesting twists, that are not so commonly used in malware.
The Floki Dropper
The Floki dropper looks simple and it has been found in wild without any outer protection layer. It has 3 resources with descriptive names – bot32, bot64, and key:
When we try to observe its activity, we can see it making an injection into explorer.
Indeed, when we attach the debugger to the newly created explorer process, we can see some alien code implanted – it is written on three additional memory areas with full permissions (RWE):
However, when we trace the API calls, we cannot find any reference to a function that will write the code into the explorer process. Fragment of the trace:
[...] 28a8;called module: C:Windowssystem32kernel32.dll:CreateProcessW 210f;called module: C:Windowssystem32kernel32.dll:IsWow64Process 1d94;called module: C:WindowsSYSTEM32ntdll.dll:ZwClose 210f;called module: C:Windowssystem32kernel32.dll:IsWow64Process 1d94;called module: C:WindowsSYSTEM32ntdll.dll:ZwClose 292c;called module: C:Windowssystem32kernel32.dll:DuplicateHandle 210f;called module: C:Windowssystem32kernel32.dll:IsWow64Process 1d94;called module: C:WindowsSYSTEM32ntdll.dll:ZwClose 2a1e;called module: C:Windowssystem32kernel32.dll:GetThreadContext 2a37;called module: C:Windowssystem32kernel32.dll:SetThreadContext 210f;called module: C:Windowssystem32kernel32.dll:IsWow64Process 2aa1;called module: C:Windowssystem32kernel32.dll:WaitForSingleObject 1818;called module: C:Windowssystem32kernel32.dll:IsBadReadPtr 182a;called module: C:WindowsSYSTEM32ntdll.dll:RtlFreeHeap 2aad;called module: C:Windowssystem32kernel32.dll:ExitProcess
We can see that a new process is created, and it’s context is being changed – that suggests manipulation – but where is the write? In order to find an answer to this question, we will take a deep dive inside the code.
At the beginning, the dropper dynamically loads some of the required imports:
The used approach depicts, that the author was trying not to leave any artifacts that could allow for easy detection of what modules and functions are going to be used. Instead of loading DLLs by their names, it picks them enumerating all the DLLs in the system32 directory:
For the sake of obfuscation, it doesn’t use string comparison. Instead, it calculates a checksum of each found name. The checksum is created by CRC32 from the name XORed with some hardcoded value, that is constant for a particular sample (in the described sample it is 0x58E5):
The resulting checksums are compared with the expected value, till the appropriate module is found and loaded. In similar way the export table of a particular module is enumerated and the required functions are being resolved.
After the initial imports load, exactly the same method is used to search NTDLL.DLL.
As we know, NTDLL.DLL provides an interface to execute native system calls. Every version of Windows may use a different number of a syscall in order to do the same thing. That’s why it is recommended to use them via wrappers, that we can find among functions exported by NTDLL. For example, this is how the implementation of the NtAllocateVirtualMemory may look on Windows 7:
Another variant, from Windows 8 looks a bit different:
The common part is, that the number of the syscall to be executed is moved into the EAX register.
The dropper loads NTDLL into the memory and extracts syscalls from selected functions:
0 : NtCreateSection 1 : NtMapViewOfSection 2 : ZwAllocateVirtualMemory 3 : ZwWriteVirtualMemory 4 : NtProtectVirtualMemory 5 : NtResumeThread 6 : ZwOpenProcess 7 : NtDuplicateObject 8 : NtUnmapViewOfSection
It checks a beginning of each function’s code by comparing it with 0xB8, that is a bytecode for moving a value into EAX:
If the check passed, the syscall value, that was moved into EAX, is extracted and stored in a buffer:
Then, when the dropper wants to call some of the functions, it uses those extracted values. The number of the syscall is fetched from the array where it was saved, and copied to EAX. Parameters of the function are pushed on the stack. The pointer to the parameters is loaded into EDX – and the syscall is triggered by with the help of an interrupt – INT 0x2E:
That’s how the functions NtCreateSection, NtMapViewOfSection and NtResumeThread are being called. Those were the missing elements of the API calls’ trace, so it explains a lot!
Example 1 – dropper makes a call that is the equivalent of calling the function NtCreateSection:
Example 2 – the dropper mapped a section by using a syscall – it is an equivalent of calling the function NtMapViewOfSection:
Once the memory is prepared, the shellcode is copied there:
After the preparations, those sections are mapped into the context of the explorer process, that has been created as suspended. Using SetThreadContext, it’s Entry Point is being redirected to the injected memory page. When the explorer process is being resumed, the new code executes and proceeds with unpacking the malicious core.
At this point of the injection, it’s malicious core is not yet revealed – it’s decryption process takes place inside the shellcode implanted in the explorer. This is also additional countermeasure that this dropper takes against detection tools.
Another trick that this bot uses, is a defense against inline hooking – a method utilized by various monitoring tools. All the mapped DLLs are compared with their raw versions, read from the disk by the dropper. If any anomaly is detected, the dropper overwrites the mapped DLL by the code copied from it’s raw version. As a results, the functions are getting “unhooked” and the monitoring programs are loosing the trace on the executed calls. Example from Cuckoo – the unhooking procedure was executed after calling NtGetThreadContext – as a result the sandbox lost control over executed calls:
The illustrated concept is not novel, however it was utilized in an interesting way. Many programs detect malicious activity by monitoring API calls, that are most often misused by malware. Also, applications used for automated analysis hooks API functions, in order to monitor where and how they are being used. The presented method allows to bypass them – at the same time being relatively easy to implement.
In this case, the author didn’t use the full potential of the technique, because he could have implement all the injection-related functions via direct syscalls – instead, he chose to use only some subset, related to writing into remote memory area. Some other syscalls has been loaded but not used – it may suggest that the product is still under development. Creation of the new process and changing it’s context still could be detected via API monitoring – and it was enough to rise alerts and make the dropper less stealthy than it was intended.
https://www.evilsocket.net/2014/02/11/on-windows-syscall-mechanism-and-syscall-numbers-extraction-methods/ – On Windows Syscall Mechanism and Syscall Numbers Extraction Methods