Analysis W32.Virut

of 25 /25
Analysis of W32/Virut.ce Author: Liviu Serban

Embed Size (px)

Transcript of Analysis W32.Virut

Page 1: Analysis W32.Virut

Analysis of W32/Virut.ce

Author: Liviu Serban

Page 2: Analysis W32.Virut

Avira GmbH Page 1 of 25

Analysis of W32/Virut.ce

W32/Virut.ce is one of the most widespread pieces of malware which can be found on infected computers. The virus is infecting executable files using latest techniques which make detecting and treating those files particularly difficult. On the current threat landscape we see more server-side polymorphism malware, infecting executable files is not that than a few years ago. During the last years emulation technics have become better which makes detection of polymorph malware much easier. The authors of the virus weren’t put off by the difficulties they faced in trying to infected executable files. But W32/Virut.ce is not only infecting executable files, the virus also includes a backdoor using the IRC protocol. This allows attackers to download and run further malware from the internet which can as example steal information. The server to which the malware connects is a pre-defined IRC server, the channel is called “virtu”. The technics used inside Virut reflects latest methods used to write malware using anti-emulation technics, anti-debugging tools and calling of multiple fake API functions. In our Virus Lab we made a deeper analysis of this file and created this document to share our information. Let’s start with the analysis of the virus: The malware creates a section object and copies the virus code into the mapped view of the created section. After this is done, the section is mapped into the active process. Beside that it hooks some API functions from ntdll.dll, the functions are the following:

NtOpenFile NtCreateFile NtCreateProcess NtCreateProcessExe

Every time someone creates a process or opens an executable file that file will be infected by the virus. The method of infection is quite straightforward. It copies the virus code at the end of the last section which is “.rsrc” or “.reloc” and employs several methods to gain control depending on the file that is currently infecting:

1) Modify the entry point to the address of the virus code 2) Patches a random kernel32.dll call which points to the virus code 3) Copies a small decryptor to the end of the “.text” section and modifies the entry point to point to

the decryption code. This decryptor will decrypt the virus code and gives control to the decrypted virus code in the last section.

4) Similar to point 3 with the difference that a random kernel32.dll call is patched inside the file which calls the code at the end of the “.text” section

The virus itself is using, as written above anti-debugging and anti-emulation techniques like:

Running on the exception handler rdtsc calls Two polymorphic layers of encryption

Page 3: Analysis W32.Virut

Avira GmbH Page 2 of 25

Analysis of W32/Virut.ce

Let’s start analyzing the virus using a debugger:

As you can see in the code snipped, the virus is located in the “.rsrc” section the PE File. As general rule, whenever you see code within “.rsrc”, “.reloc”, “.rdata” or inside the “.data” section you could be quite sure that it might be some malicious code. The first what this virus does it to call a function (renamed to “main_virut” in the code snipped). This function sets up a shell handler on the stack “push dword fs:0” and then “move fs:0,esp” after that it tries to call the GetProcAddress function but if you look at the GetProcAddress parameters pushed on the stack you would find something rather strange, ebx is the hModule which is zero and the lpProcName has a

Page 4: Analysis W32.Virut

Avira GmbH Page 3 of 25

Analysis of W32/Virut.ce

strange value. The MSDN documentation tells us that lpProcName is a long pointer to the function or variable name or the functions ordinal value. On some versions of NT this is doomed to throw an exception, on others GetProcAddress will return NULL. If it throws an exception the last exception handles will be executed and is pushed on the stack by the virus itself. This means the rest of the virus code will be executed on the exception handler. Explanation of the anti-emulation trick: A few notes about exception handling in Win32 systems and some notes about how C/C++ linker and Microsoft Windows Win32 API using the shell handlers. In order to explain this, we need a short example: DWORD do_something (void * pointer)


DWORD val = 0;



val = *(DWORD*)pointer;

return val;




printf( "Caught the exception in main()\n" );


return 0;


Looking at this function if the pointer is NULL of course will crash and the filter exception routine (_except) will get executed. So in a nutshell the execution will stop at val = *(DWORD*)pointer and the execution will resume in the printf inside the _except function.

So now let’s see how the C linker translates this into raw code. You have probably seen these instructions before:

Push dword fs:0 mov fs:0, esp

This is exactly the exception handler (try / _except statement). The FS register holds the address of the TEB and FS:[0] is the list head of the exception handlers. The exception handlers are in fact a linked list stored on the stack.

The structure looks like:






So what is pushed on the stack is a pointer to a function (the handler) and the link to the next exception_registration structure and the brand new exception_registration is now the list head. If you are scrolling back to the virus code you would see:

Page 5: Analysis W32.Virut

Avira GmbH Page 4 of 25

Analysis of W32/Virut.ce

call main_virut call 0xwhatever

when call main_virut is executed, the address of the next instruction is pushed on the stack and the execution continues at main_virut function which, as we know now sets up the exception handler. FS:0 (exception registration linked list) is ESP’s value and ESP itself points to the previous FS:0 and the next item on the stack is the return address that we were talking about. So that’s a new exception_registration structure. If GetProcAddress fails the execution is passed to the exception handler which is the rest of the virus code. Now looking at the exception handler it points at the first byte after GetProcAddress call. This call is the virus decrypter code, the virus has two layers of decryption. First it gets a key in EDX. The size is in ESI and the base is in EDI. It then starts to decrypt the virus using a simple XOR operation and adds certain values to the key at each step. After the decryption operation completed it jumps at the decrypted virus code using jump EDI.

Page 6: Analysis W32.Virut

Avira GmbH Page 5 of 25

Analysis of W32/Virut.ce

Explanation of the anti-virtualization trick:

After we can look at the decrypted virus code we see two interesting rdtsc calls. The simple rdtsc calls are used as anti-virtualization/anti debugging trick: First rdtsc reads the time stamp counter into EDX:EAX. After the first call the virus saves the EAX value into ECX and calls the rdtsc function again. The the virus substracts the new EAX (from the last rdtsc call from ECX which was the first rdtsc call). If the value is less than 0x40 it continues otherwise it will jump to exit. Why does the virus do that? Well, on a real computer the time between those two rdtsc calls should be in general less than 50 but on a debugger or a virut machine the value is generally higher than that. So on a virtual machine it will exit and the virus wouldn’t start.

After that it goes and calls the second decryption function. EAX points to virut_body, dl holds the decryption key and now we are able to go to the decrypted virus body to see the payload.

Page 7: Analysis W32.Virut

Avira GmbH Page 6 of 25

Analysis of W32/Virut.ce

We see the following interesting instruction in the code snipped: cmp dword ptr [ebx+4eh], “This” If you look before the two calls to rdtsc, you can see were EBX points to: mov ebx, [esp+4] Inside the esp+4 we can see a address within kernel32.dll. In order to understand you need to know the layout of the stack when int main() gets called via CreateProcess API. If you create a process using CreateProcess via the API or double click an executable file, CreateProcess gets called and besides doing a lot initialization it also creates a thread (the startup thread for the new process) and the startup function of this thread is a tiny stub located in kernel32.dll called BaseProcessStartup, this stub looks like:

Page 8: Analysis W32.Virut

Avira GmbH Page 7 of 25

Analysis of W32/Virut.ce

VOID WINAPI BaseProcessStartup (PPROCESS_START_ROUTINE lpStartAddress)


UINT uExitCode = 0;

DPRINT("BaseProcessStartup(..) - setting up exception frame.\n");







/* Call the Start Routine */

uExitCode = (lpStartAddress)();




uExitCode = GetExceptionCode();




The first thread in the process was created and its startup address is this stub which calls the entry point of the executable file. Now we know that after this instruction mov ebx,[esp+4], ebx points to something inside kernel32.dll. Since we have this information and since viruses don’t have imported functions the usual way to get to those APIs is get to the base address of the kernel32.dll and from there use the layout of PE files in order to get to the export directory of the DLL. From there the virus can get the exported functions which are needed, this is what the virus does in the last code snipped. In general there are four ways viruses can get the desired APIs:

1) Get the address of GetProcAddress which can be used to get the needed API 2) Scan the whole IMAGE_EXPORT_DIRECTORY of kernel32.dll and get the needed APIs 3) Use a CRC32 on the API names or the API address 4) Use the direct addresses of those APIs since kernel32.dll and ntdll.dll are located at known addresses in all

process (This doesn’t work on Microsoft Windows Vista because Vista uses randomization of the base address of these DLLs. It won’t relocate the DLLs at the same addresses every time).

Virut makes use of the first method which is obviously the most straightforward of all. The following APIs are requested by Virut from kernel32.dll using GetProcAddress:

Page 9: Analysis W32.Virut

Avira GmbH Page 8 of 25

Analysis of W32/Virut.ce

After obtaining the desired APIs from kernel32.dll, the virus goes to ntdll.dll to get some other APIs. After obtaining the ntdll.dll APIs it stores the SSDT index of the following APIs:

NtCreateFile NtOpenFile NtCreateProcess NtCreateProcessEx

Page 10: Analysis W32.Virut

Avira GmbH Page 9 of 25

Analysis of W32/Virut.ce

The mentioned APIs will be hooked by the virus. Hooking NtCreateProcess will end up that every started process will be infected. This is another method than using the classic FindFirstFile/FindNextFile functions. After the infection of the file, it will use the saved index to do an in2E or systenter into ring 0 to actually let the OS doing the real work of creating a process or file. It then creates a section object with the following name \BaseNamedObjects\VtSect maps the section into memory and copies the virus code into that mapped view of the section. The section is backed by the paging file and by any ordinary file. It will use this mapped view of the section to pen it in other processes, so that the virus code will end up in several processes. The following code is responsible for this action:

Page 11: Analysis W32.Virut

Avira GmbH Page 10 of 25

Analysis of W32/Virut.ce

After the section object has been created and it has been mapped into memory and the virus code has been copied into it, now the virus will use some useful APIs to find the winlogon address space. The set of APIs which are used are CreateToolHelp32Snapshot similar APIs. As you can see ESI is 0, it calls Process32First which is obviously the System Idle Process. Not that much to do with the system process since we are in User Mode. Then it calls Process32Next until ESI is > 4. We will open a process explorer to see why, the first process is the System Idle Process, the second is the System Process, the third is smss.exe and the fourth process is crss.exe. After all these iterations we will get to the winlogon.exe process. Looking at the stack in the right side of the picture you will see an smss.exe string on the stack. This comes due to the fact that Process32Next has two parameters, a handle to the snapshot obtained by calling CreateToolHelp32Snapshot and a PROCESSENTRY32 pointer that contains some info about the current process.

Page 12: Analysis W32.Virut

Avira GmbH Page 11 of 25

Analysis of W32/Virut.ce

Page 13: Analysis W32.Virut

Avira GmbH Page 12 of 25

Analysis of W32/Virut.ce

We open the process and then we go to the mapped section (Virut section that we have created earlier) into winlogon virtual address space, we hook NtCreateFile, NtOpenFile, NtCreateProcess and NtCreateProcessEx and then we create a remote thread inside winlogon.exe. This method allows to stay resident in memory as winlgon is not an ordinary user mode process and winlogon won’t close until shutdown the system. Hooking of the APIs in ntdll.dll will enable the virus to infected any exe file that is used as an argument for CreateProcess or CreateFile APIs. The following code snipped shows the map section in winlogon.exe and writes the inline jumps in the specified API functions:

Page 14: Analysis W32.Virut

Avira GmbH Page 13 of 25

Analysis of W32/Virut.ce

The next code snipped shows the inline_jump routine:

Now we know that NtCreateFile, NtOpenFile, NtCreateProcess and NtCreateProcessEx are hooked, we start debugging winlogon.exe and analyze the code over there to see how Virut infects files via the hooked API calls. The next code snipped shows the infected code in one of the active processes virtual address space:

Now going at virus_inline_jump we will see the code, that is used to infect the file give as argument to NtCreatefileSystem service:

Page 15: Analysis W32.Virut

Avira GmbH Page 14 of 25

Analysis of W32/Virut.ce

Now we try to understand what the virus is doing for this we’ll first have a look to the MSDN and look for the NtCreateFile System Service declaration:






IN ACCESS_MASK DesiredAccess,




IN ULONG FileAttributes,

IN ULONG ShareAccess,

IN ULONG CreateDisposition,

IN ULONG CreateOptions,


IN ULONG EaLength );

We can see that the virus is doing a push instruction which pushes all registers. The size on the stack for all register is 0x24 and we have the return address from NtCreateFile and the arguments for NtCreateFile itself. The instruction mov eax,[esp+30h] will get to the object attributes pointer within the stack. Using mov edx,[eax+8] will get the address of the file name that was passed as argument to the CreateFile API. Together with this file name we can check if it is a executable file and if yes, the file will get infected. The virus code is looking if the file is a EXE file and not a DLL file.

Page 16: Analysis W32.Virut

Avira GmbH Page 15 of 25

Analysis of W32/Virut.ce

The infection algorithm is pretty simple the only difficult is with the EPO (Entry Point Obscuring). The virus copies itself to the last section .rsrc or .reloc with its polymorphic decrypter and then it tries to find a way to gain control. One method is to copy a tiny stub to the last portion of the .text section and modify the entry point to point to that tiny stub and from there the virus will get to its decryption code in the last section. If it cannot copy the stub to the end of the .text section the virus will try to find a kernel32.dll call to hook it to point to the virus code within the last section. There are two methods to handle import calls depending on the used compiler: Using Borland C++ and using the GetModuleHandle API function, the code which is generated by the Borland compiler would look like: call somewhere_inside_text_section

→ opcode is 0xE9xxxxxxxx somewhere_inside_text_section:

jmp dword ptr [address_of_GetModuleHandle_in_import_table]

For the Microsoft C++ compiler the same would look like:

call dword ptr [address_of_GetModuleHandle_in_import_table]

→ opcode is 0xFF15xxxxxxxx

The reason why Borland and Microsoft have chosen different approaches is beyond the scope of this article. Coming back to our virus analysis what Virut tries to do is to find 0xE9xxxxxxxx or a 0xFF15xxxx opcode to patch to point to the virus code. That makes the detection and disinfection even harder since what it basically does is to patch a random kernel32.dll call and finding that patched call to repair it makes the disinfection process tricky.

The following sniped shows the used code:

Page 17: Analysis W32.Virut

Avira GmbH Page 16 of 25

Analysis of W32/Virut.ce

Page 18: Analysis W32.Virut

Avira GmbH Page 17 of 25

Analysis of W32/Virut.ce

In the last snipped it gets the .text section IMAGE_SECTION_HEADER and subtracts SizeOfRawData from VirtualSize. If this value is lower than the virus stub than just copy that stub at the Entry Point (of course saving the Entry Point before giving control to the original file).

Page 19: Analysis W32.Virut

Avira GmbH Page 18 of 25

Analysis of W32/Virut.ce

There are basically four methods Virut employs to infect a file:

1) Modify the Entry Point (no Entry Point Obscuring)

2) Get a random kernel32.dll call and patch it to point to the virus code within the last section

Page 20: Analysis W32.Virut

Avira GmbH Page 19 of 25

Analysis of W32/Virut.ce

3) Copy a small stub to the end of the .text section and modify the entry point to that code which will decrypt the virus and the will pass control to the decrypted virus code within the last section

4) Get a random kernel32.dll call and patch it to point to the code stub at the end of the .text section

Page 21: Analysis W32.Virut

Avira GmbH Page 20 of 25

Analysis of W32/Virut.ce

IRC and Download File W32/Virut functionality

As we have written above, Virut is not only infecting PE Files, it also offers a IRC Backdoor and Download File functions. First it loads the required API functions used to establish connections to a IRC server and to download files.

The following APIs the call will return:

Page 22: Analysis W32.Virut

Avira GmbH Page 21 of 25

Analysis of W32/Virut.ce

After this first step it then tries to establish a connection to a IRC server. First a socked is created and after the socked is created the connection will be done via HTTP:

In the next code snipped you can see all the addresses, the nickname and the parameters needed for the IRC connection.

If the connection to the IRC server is successful it tries to send IRC parameters in order to inform the server:

Page 23: Analysis W32.Virut

Avira GmbH Page 22 of 25

Analysis of W32/Virut.ce

After this it waits to receive data from the IRC server. This is basically a HTTP link that Virut will use to download some files and run the downloaded files on the local machine.

Now the information has been sent back by the server and Virut has been woken up. What it needs to do is to parse the information from the server. This work is done in parse_irc function which basically checks to see if a HTTP link has been sent.

The code looks like:

Page 24: Analysis W32.Virut

Avira GmbH Page 23 of 25

Analysis of W32/Virut.ce

After this it goes to create an internet connection and use that link to download the file from the receive URL and create a thread that will write the file on the disc and create a process using the file as an argument:

Page 25: Analysis W32.Virut

Avira GmbH Page 24 of 25

Analysis of W32/Virut.ce

Last but not least, we found the following strings inside the malware: