Clampi goes to unusual measures to bypass the local firewall on the compromised computer, such as the Windows Firewall. Usually, such firewalls allow only specific programs to communicate using specific ports and protocols. For instance, your browser would be allowed to use outbound TCP port 80.
As we’ve previously discussed, Clampi needs to communicate with a “Gate” gateway server in order to get its orders and send information. Any firewall would block the program if it tried to connect to the outside world. Bypassing this can be done in many ways, the most common one in the malware world being to add an entry in the Windows registry, added the program to the trusted file list.
The Clampi gang decided to inject their networking code into Internet Explorer, which is granted Web access by any standard firewall configuration out there. Fair enough—that’s another approach, but not a new one. Yet you’ve seen these guys don’t do things the way other malware authors usually do. They’ve decided to implement an API proxy and have only stubs of code injected and executed into the browser, but only when it’s needed. When Clampi needs to send information to the Gate, it will use the API proxy.
Let’s dive into the technical details now. Soon after Clampi is executed, it creates an Internet Explorer instance. Its window is hidden, the primary thread is suspended, and the program is started with a command line that looks like shellcode (named shellcode 0). Note that the shellcode/command line consists of a small decryptor stub, followed by an ASCII string. It’s a classic way to avoid NULL bytes (except for the terminating one), which would have the undesired side-effect of stopping the shellcode prematurely.
Clampi then injects a thread into Internet Explorer, pointing to GetCommandLineA. Upon execution of this thread, the shellcode address will be retrieved.
A second remote thread is then created, and executes shellcode 0.
IE Command line and Shellcode 0
The shellcode entry-point is located at address 0x14CAF0 above. Below is the disassembled routine:
Decryptor stub of Shellcode 0
Upon execution, shellcode 0 will decrypt the ASCII code located between 0x14CB12 and 0x14CC6D.
Shellcodes 1 and 2
The code above contains two shellcodes. The main one starts at 0x14CB12. Its goal is to create and initialize a shared memory map:
1. It first executes RDTSC as a random number generator; uses it to build a random eight-character-long ASCII string, stored inside the shellcode itself, between addresses 0x14CB19 and 0x14CB21 (the byte at 0x14CB21 is the terminating NULL). Initially, these bytes are filled with NOP instructions, though they never get executed.
2. It creates a named file map of size (15 + N) bytes, N being passed as a parameter to the thread executing the shellcode. The map’s name will be the one generated earlier.
3. It checks that the map was created successfully; if a map having this name already exists, another name is generated.
4. It creates a view of the file map in memory.
5. Finally, the map is initialized as described below:
Offset Size Data
0x0 9 Map name
0x9 4 Address of the view
0xD 4 Map handle
0x11 4 Address of shellcode 2
Here is an example of a map named “MOOINPNM” after it’s been initialized. The current view is at address 0x380000, which you also see at offset 9. The map handle is 0x58 and the address of the secondary shellcode is 0x14CB93, which is stored at offset 0x11.
Memory map header
The second shellcode starts at 0x14CB93. Its goal is to destroy a shared memory map. Since shellcode 2 is located inside shellcode 1, note that execution of shellcode 2 is carefully avoided during the execution of shellcode 1 by the call instruction located at 0x14CB8E.
These memory maps will be used to exchange information between Clampi and the Internet Explorer instance acting as the API proxy.
Before the API proxy can be used, a memory map is created and dynamically filled by yet more shellcode (shellcode 3) whose purpose will be to carry out the execution of an API. This shellcode is 0x1F-bytes long.
Thus, Clampi creates a remote thread in IE that will execute shellcode 1, with the parameter 0x1F. It fills the returned map with shellcode 3:
We’ll detail what shellcode 3 does later on. Before this, let’s see Clampi’s actions when it wants to use Internet Explorer as an API proxy.
1. It creates a remote thread that executes shellcode 1, which creates memory map 1. This map’s size varies depending on the number of parameters used by the API.
2. It fills memory map 1 with the API information (API address, parameters, etc.).
3. It eventually creates more memory maps if the API parameters are pointers to more data (strings for instance).
4. It creates a thread that calls shellcode 3, with memory map 1 as a parameter.
5. Shellcode 3 executes the API.
6. Clampi deletes the memory maps by creating threads executing shellcode 2.
The structure of a memory map containing the API description is as follows:
Offset Size Data
0x0 0x15 Memory map description, see above
0x15 4 API address (in)
0x19 4 API return code (out)
0x1D 4 API parameter count, cnt (in)
0x21 4*cnt API parameters (in)
What shellcode 3 does now appears obvious: It pushes the API parameters on the stack, calls the API, and then sets the API return value to its location in the memory map.
This diagram illustrates the different steps taken to have the API proxy execute a call to LoadLibrary:
We also created a tool to monitor Clampi’s API proxy. Below is a partial trace of the APIs executed by the proxy:
<...> API: WININET.dll!InternetConnectA (addr=771C30C3, 8 params) - CC0004 - 1A0015 ("188.8.131.52.......") - 50 - 0 - 0 - 3 - 0 - 0 API: kernel32.dll!GetModuleHandleA (addr=7C80B6A1, 1 params) - 220015 ("wininet.dll........") API: kernel32.dll!GetProcAddress (addr=7C80ADA0, 2 params) - 771B0000 ("MZ...............") - 230015 ("HttpOpenRequestA...") API: WININET.dll!HttpOpenRequestA (addr=771C36AD, 8 params) - CC0008 - 1A0015 ("POST...............") - 1B0015 ("/aJdup6JXYU4LNrIo..") - 0 - 0 - 0 - 80000000 (".aJdup6JXYU4LNrIo...") - 0 API: kernel32.dll!GetModuleHandleA (addr=7C80B6A1, 1 params) - 220015 ("wininet.dll........") API: kernel32.dll!GetProcAddress (addr=7C80ADA0, 2 params) - 771B0000 ("MZ...............") - 230015 ("HttpSendRequestA...") API: WININET.dll!HttpSendRequestA (addr=771C6249, 5 params) - CC000C - 1A0015 ("Content-Type: application/x-www-form-urlencoded...") - 2F - 1B0015 ("o=i&b=YsvVNRc/BlrMWO3sTqW/ZhDw7YfukYGn1oEbp9J/s...") - 15E <...>
As you can see, the proxy is indeed used for network communication with the Gate. By doing so, Clampi achieves enhanced stealth, bypasses simple desktop firewalls, and also makes the analysis of its code more difficult.