2013-11-04
Abstract
ZAccess (a.k.a. ZeroAccess) is a complex botnet with many different variants and updates to the malware having been observed over several years. In June He Xu and colleagues found and analysed some variants which integrated a debugger engine. He takes a look at some of the features in those variants.
Copyright © 2013 Virus Bulletin
ZAccess (a.k.a. ZeroAccess) is a complex and infamous botnet. Since 2009, we have observed many different variants and significant updates. In June 2013, we found and analysed some variants which integrated a debugger engine. This article takes a look at some of the features in those variants.
The new variants come with a unified packer that can support both EXE and DLL file formats. The packer uses its original characteristics in the PE header to replace the embedded malware. In other words, the embedded file characteristics will be decided by the packer’s value.
The packer will overwrite the embedded sample’s PE checksum value. In most cases, the value is 0x313 or 0x200 – which might be the packer version.
When the malware has been unpacked, the packer hands control to the loader component.
The loader checks the PE header’s characteristics to determine whether it should be run as EXE or DLL (Figure 1). If the marker is set as DLL, the loader simply creates a new thread (which we will talk about later). If the marker is set as EXE, it will check the debugger status and run the file either as a debugger or as a debuggee (Figure 2).
In the first instance, the malware will load as a debugger. After that, it will create itself as a debuggee with the flags: DEBUG_PROCESS | CREATE_PRESERVE_CODE_AUTHZ_LEVEL. Next, the debugger instance will start a new thread to create and try to read the mailslot named ‘\device\mailslot\uewuyew<PID>’.
When all initialization tasks have been completed, the debugger process will loop to wait for further debugging events. The debugger supports the following debug event types:
EXCEPTION_DEBUG_EVENT CREATE_THREAD_DEBUG_EVENT CREATE_PROCESS_DEBUG_EVENT EXIT_THREAD_DEBUG_EVENT EXIT_PROCESS_DEBUG_EVENT LOAD_DLL_DEBUG_EVENT UNLOAD_DLL_DEBUG_EVENT OUTPUT_DEBUG_STRING_EVENT
There are some tricks in the loop routine:
The debugger will not wait for the debuggee. If there is no debug event, or there is no debug event in the local pending pool, the debugger will jump out of the loop and exit directly, which will cause the debuggee to terminate passively.
The debugger will examine the dwFirstChance value of every exception event. It will kill the debuggee if the value is zero. For this condition, WinDBG will always reset the value when the breakpoint is triggered. As a result, it is a very effective anti-debug method.
The debuggee code is very simple. It will try to load the system module untfs.dll, and get one API address by ordinal 2302h (Figure 3) – which does not exist in the system module (see Figure 4 and Figure 5). You would think, therefore, that this operation would fail.
However, that is not the case here: the debugger will not let the debuggee fail over this non-existent ordinal. So what does the debugger do?
The debugger replaces the newly loaded system module in the debug event processing routine.
First, the debugger will set the single step marker in the EFlags register when processing the DEBUG_EVENT ID 06, as shown in Figure 6.
When the debuggee runs, the debugger will receive the SINGLE_STEP event at the next DEBUG_EVENT with ID 01, and will trigger an exception (Figure 7).
The debugger will extract the final malicious DLL from a customized structure with the special signature AP32 (see Figure 8).
In fact, the structure is from aPLib source code and the detail is as below:
; offs size data ; --------------------------------- ; 0 dword tag (‘AP32’) ; 4 dword header_size (24 bytes) ; 8 dword packed_size ; 12 dword packed_crc ; 16 dword orig_size ; 20 dword orig_crc
At last, we can get the DLL without entry point code (see Figure 9), but including only one export function.
According to the export table, the function has the ordinal 2302 (see Figure 10), but without a name. This is exactly what the debuggee wants. The debuggee can then enter the real malicious DLL export function as shown in Figure 3.
The DLL code is similar to that seen in previous variants [1]. It also embeds an MS Cabinet file (see Figure 11).
Within the code, we can easily see the names of the different modules, such as s32, s64, n64, n32 and fp.exe. The malware connects to j.maxmind.com to test for an Internet connection. If the connection is successful, it will execute the main botnet routine as usual.
The use of the debugger/debuggee trick makes the malware much more difficult to analyse in dynamic mode, demonstrating that the ZAccess author is a pretty proficient programmer. The combination of debugger code and botnet features could cause much confusion in distinguishing malicious from clean code.
[1] Tan, N.; Yang, K. ZAccess detailed analysis. Virus Bulletin, August 2012, p.4. http://www.virusbtn.com/virusbulletin/archive/2012/08/vb201208-ZAccess.