Malware


Two months ago Halvar Flake announced a new malware challenge for female reversers only. I’m a man and I couldn’t submit a solution but I decided to give it a try, challenges are always funny. I shared this reversing session with Kayaker, so credit for this blog post goes to him too.

The solution posted by Marion Marschalek (congratulations!) is pretty nice and it explains almost everything in details. I’m not writing a blog post with the same information she gave, but I would like to add something about the way I used to automatically naming/resolving the imported functions.
The idea is to change instructions like:
.text:0040100B call dword ptr [ecx+220h]
into something like:
.text:0040100B call dword ptr [ecx+_API.malloc]

To perform this switch I have written an IDC script. There are two functions inside it, GetAPINames and ResolveAPINames. The first function is used to retrieve the name of all the hidden API while the other one will change the call instructions into a new readable version.
The script stores all the information inside a structure named _API which is filled with all the API names. The structure is necessary and I’ll use it for some minor manual fix too.

GetAPINames
There’s no trace of clear API names inside the disasm, everything is constructed at runtime inside call 402DB0, take a look at this piece of code (without unnecessary junk code lines):

00403E42 C6 44 24 24 43 mov [esp+179CCh+var_179A8], 'C'
...
00403E49 C6 44 24 25 72 mov [esp+179CCh+var_179A7], 'r'
...
00403EC1 C6 44 24 26 65 mov [esp+179CCh+var_179A6], 'e'
...
00403F14 C6 44 24 2F 61 mov [esp+179D4h+var_179A5], 'a'
00403F19 C6 44 24 30 74 mov [esp+179D4h+var_179A4], 't'
00403F1E C6 44 24 31 65 mov [esp+179D4h+var_179A3], 'e'
00403F23 C6 44 24 32 54 mov [esp+179D4h+var_179A2], 'T'
00403F28 C6 44 24 33 68 mov [esp+179D4h+var_179A1], 'h'
00403F2D C6 44 24 34 72 mov [esp+179D4h+var_179A0], 'r'
00403F32 C6 44 24 35 65 mov [esp+179D4h+var_1799F], 'e'
00403F37 C6 44 24 36 61 mov [esp+179D4h+var_1799E], 'a'
00403F3C C6 44 24 37 64 mov [esp+179D4h+var_1799D], 'd'
00403F41 C6 44 24 38 00 mov [esp+179D4h+var_1799C], 0

As you can see CreateThread string is obtained appending every single char. To create names the malware uses another similar way:

00406EC9 C6 84 24 BC 0F 00 00 47 mov [esp+179CCh+var_16A10], 'G'
00406ED1 C6 84 24 BD 0F 00 00 65 mov [esp+179CCh+var_16A0F], 'e'
...
00406F4C C6 84 24 BE 0F 00 00 74 mov [esp+179CCh+var_16A0E], 't'
...
00406FA5 C6 84 24 C7 0F 00 00 4D mov [esp+179D4h+var_16A0D], 'M'
00406FAD C6 84 24 C8 0F 00 00 6F mov [esp+179D4h+var_16A0C], 'o'
00406FB5 C6 84 24 C9 0F 00 00 64 mov [esp+179D4h+var_16A0B], 'd'
00406FBD C6 84 24 CA 0F 00 00 75 mov [esp+179D4h+var_16A0A], 'u'
00406FC5 C6 84 24 CB 0F 00 00 6C mov [esp+179D4h+var_16A09], 'l'
00406FCD C6 84 24 CC 0F 00 00 65 mov [esp+179D4h+var_16A08], 'e'
00406FD5 C6 84 24 CD 0F 00 00 46 mov [esp+179D4h+var_16A07], 'F'
00406FDD C6 84 24 CE 0F 00 00 69 mov [esp+179D4h+var_16A06], 'i'
00406FE5 C6 84 24 CF 0F 00 00 6C mov [esp+179D4h+var_16A05], 'l'
00406FED C6 84 24 D0 0F 00 00 65 mov [esp+179D4h+var_16A04], 'e'
00406FF5 C6 84 24 D1 0F 00 00 4E mov [esp+179D4h+var_16A03], 'N'
00406FFD C6 84 24 D2 0F 00 00 61 mov [esp+179D4h+var_16A02], 'a'
00407005 C6 84 24 D3 0F 00 00 6D mov [esp+179D4h+var_16A01], 'm'
0040700D C6 84 24 D4 0F 00 00 65 mov [esp+179D4h+var_16A00], 'e'
00407015 C6 84 24 D5 0F 00 00 45 mov [esp+179D4h+var_169FF], 'E'
0040701D C6 84 24 D6 0F 00 00 78 mov [esp+179D4h+var_169FE], 'x'
00407025 C6 84 24 D7 0F 00 00 41 mov [esp+179D4h+var_169FD], 'A'
0040702D C6 84 24 D8 0F 00 00 00 mov [esp+179D4h+var_169FC], 0

The way used to create GetModuleFileNameExA is pretty similar to the previous one but there’s a little difference, look at the opcodes. The mov instructions are similar but the ModR/M byte defines a distinct displacement.
Is it possible to recognize and isolate all the instructions used to create all those strings? Well, it’s not so hard because some bytes are fixed! The idea is to parse all the instructions inside 402DB0 trying to recognize those two special mov instructions:

if (Byte(currAddress) == 0xC6) {
  if (Byte(currAddress+1) == 0x44) {
    if (Byte(currAddress+2) == 0x24) {
      if (Byte(currAddress+4) != 0x00) {
        // Get current char and append it to partial name
        szChar = sprintf("%c", Byte(currAddress+4));
        szAPI = sprintf("%s", szAPI + szChar);
      } else {
        if ((strstr(szAPI, ".DLL") == -1) && (strstr(szAPI, ".dll") == -1))
        {
          // Add member to struct (no DLL name)
          AddStrucMember(id, szAPI, -1, FF_DATA, -1, 4);
        }
        szAPI = sprintf("%s", ""); // reset for next string
      }
    }
  }
}

The instructions are checked byte by byte and the strings are created char by char. szChar is the current char to append to the partial string szAPI.
There’s a little problem with this parser, it constructs DLL names too. I’m not interested in DLL names, so a check over the formatted string is necessary:

if ((strstr(szAPI, ".DLL") == -1) && (strstr(szAPI, ".dll") == -1))

Now that I’m sure I don’t have a DLL name I can insert it into the structure:

AddStrucMember(id, szAPI, -1, FF_DATA, -1, 4);

The use of the structure is fondamental for the script.
Now that you know how to parse the first type of mov instruction you can easily change some checks over the fixed bytes and you’ll retrieve names like GetModuleFileNameExA too:

if (Byte(currAddress) == 0xC6) {
  if (Byte(currAddress+1) == 0x84) {
    if (Byte(currAddress+2) == 0x24) {
      if (Byte(currAddress+5) == 0x00) {
        if (Byte(currAddress+6) == 0x00)     {
          if (Byte(currAddress+7) != 0x00) {
            ...

This part of the script works pretty fine but it has a little problem with few functions. To understand it here is an example with GetQueuedCompletionStatus:

00405C2A mov [esp+179CCh+var_179A8], 'G'
00405C31 mov [esp+179CCh+var_179A7], 'e'
00405CA9 mov [esp+179CCh+var_179A6], 't'
00405CF3 mov bl, 'Q'
00405CFE mov [esp+179D4h+var_179A5], bl
00405D02 mov [esp+179D4h+var_179A4], 'u'
00405D07 mov [esp+179D4h+var_179A3], 'e'
00405D0C mov [esp+179D4h+var_179A2], 'u'
00405D11 mov [esp+179D4h+var_179A1], 'e'
00405D16 mov [esp+179D4h+var_179A0], 'd'
00405D1B mov [esp+179D4h+var_1799F], 'C'
00405D20 mov [esp+179D4h+var_1799E], 'o'
00405D25 mov [esp+179D4h+var_1799D], 'm'
...

As you can see the letter ‘Q’ is obtained by a sequence of two instructions and my script is not able to catch it; it creates GetueuedCompletionStatus name. It has been proved that human brain is able to recognize word without few letters or with scrambled letters so I think I can pass over this minor problem!

ResolveAPINames
Ok, now that I have the API structure I need to use it for the resolution part. The function ResolveAPINames scans the entire disasmed code trying to fix the necessary calls. To identify the call you can use a simple strstr function, and to convert it you can use OpStroff (it converts operand to an offset in a structure):

if(strstr(GetDisasm(ea), "call dword ptr") != -1) {
  OpStroff(ea, 0, GetStrucIdByName("_API"));

The malware uses a nice addressing method and IDA is not able to parse the hidden API but the nature of the addressing method lets us to solve the problem with some lines of code only. Now you can understand why the structure is the core of the entire script.

Manual fix
The script is able to resolve 678 calls, but it fails to fix some special cases like this:

00414E36 lea esi, [eax+1FCh]
00414E3C call dword ptr [eax+_API.GetTickCount]
00414E42 push eax
00414E43 call dword ptr [esi]

GetTickCount has been resolved but the next call not. It’s obvious that esi points to the API at offset 0x1FC. You can solve it manually because the structure contains it. Right click over 0x1FC and select the line “[eax+_API.srand]“. Now you know how to manually fix special cases too.

I got some requests for this little tool so I decided to put it online for everyone.

As I told you in a recent blog post the program is still uncomplete because I want to add some more features and I don’t know if it has real bad bug(s) inside. So, your question might be “why are you putting it online?”. Just because I think that bug reports, constructive feedbacks, criticisms and comments represent a good way for making decent programs. Feel free to use my e-mail address for any kind of messages you want to send me.

DexInspector

DexInspector

Rewording a quote from a famous film I would say “The Malwares are everywhere, even now in this very room”, and that’s could be true if you have an Android based mobile phone because the number of this kind of malwares are increasing nowadays. It’s not so hard to study an Android malware; there are some nice tools available on the net, and in the foreseeable future I could add my simple DexInspector too.

Why do I need another .dex analyzer? Well, I decided to write this tool because I had some problems dealing with disassembled output produced by some existing tools. Some of them shows an output which is hard to follow because of its syntax that is strictly related to .dex opcodes; on the other hand other tools try to understand what’s behind the code, but it’s really hard with a static analysis and the result may produce ambiguous results. I always use more than one single tool in my reversing sessions, and I think DexInspector could be a valid help for .dex analysis.

Since I don’t like to fill this blog post with a series of anonymous screenshots without a single word, to introduce the tool I’m going to use a malware named “FakeLookout.A” guiding you through a possible reversing session.
You can find a nice description of the malware at http://blog.trustgo.com/fakelookout/ and I’ll explain you how to get this information:

This malware can receive and execute commands from remote server.
Server address: hxxp://[hidden]press.com/controls.php
Commands:
clearFileList
getDir
clearAlarm
getFile
getSize
getTexts

DexInspector

.dex has been fully loaded

This is the main dialog of DexInspector, exactly when a .dex file has been fully loaded.
The box with a series of “[INFO]” entries is used to display information, depending on the current task. In this case it tells us everything has been loaded correctly.  The treeview on the left contains a list of all the .java files declared in the malware project.  Each disassembled class will be showed inside the empty box. The toolbar contains some buttons (used to view necessary information about structures inside a .dex file), a control used to store all the methods inside the current disassembled class and  3 search text controls.

Map list dialog

From the map_list dialog you can have an idea of what the file is. It has a lot of methods, classes and strings (item: method_id_item, class_def_item and string_id_item), so the question is: if I want to understand what’s going on inside the malware, where is a good starting point? The name of the classes and the original files used by the programmer are valid candidates, but like a common reversing session I prefer to start the static analysis directly from strings window, even if there are too many strings.

Selected string with location info

Due to the .dex nature it’s easy to discard useless entries; i.e. you can avoid specific type strings (something like “IILI”), strings starting with ‘L’ or ‘[', etcetc.  Among all the strings I see a suspicious address: "http://thelongislandpress.com/controls.php", the server doesn't exist anymore so I think I don't need to obscure the address.
As you can see from the listview at the bottom of the dialog the string is located in a single file named "com.updateszxt.HttpFileUploader.zdi".
What kind of file is this? It's the disassembled file and the .zdi is the extension I use, you can find the file on your hard disk too.  Anyway, the name of the original file is HttpFileUploader.java:

Disassembled view: class, fields and constructor

The original file has inside the definition of the public class com.updateszxt.HttpFileUploader which extends java.lang.Object and contains some fields definitions (both static and instance). The http address is used inside the constructor of the class, here is constructor’s code:

Code of the constructor

The program analysis is done instruction-by-instruction involving debug information which are mostly useful when you have to understand the code. In this specific case the program uses debug information in different places, the first one is inside the declaration of the method: the parameters have specific names which are not randomly created.
It’s pretty simple to understand what’s going on. First thing: the method is used to check if a specific folder exists. If the folder, named “dataCache”, doesn’t exist it will be created inside Android external storage directory. Second thing: it initializes an url using the http address above. Nothing special indeed, but before going directly to the next part of the class I wanto to point your attention to an instruction:
  java.io.File folder = v1;
It’s not a line derived from one of the .dex opcodes but it comes from debug information and represents a local variable definition. Nothing special, but dealing with the original name could be handy.
Another addition is represented by the info inside the small box, it shows something depending on the selected instruction. i.e.:
selected instruction:   v2 = v2->append(v3);
info: java.lang.StringBuilder java.lang.StringBuilder->append(java.lang.String)
The meaning of the info is: the method append from java.lang.StringBuilder gets a java.lang.String parameter and returns a java.lang.StringBuilder type.

Ok, back to the code!

Interesting code starts here

Searching through the methods listed in the combo box I select the one named runIt, after a little glance you can understand what’s going on: the program estabilishes a connection with the remote server, it gets a command and execute it. The command is returned by getControls method and it’s one of the six I have mentioned at the beginning of this post (it’s also possible to have a path following the command).

Check for the right command to execute

Except few lines at the beginning of the method the codeflow of the program depends on the invoked command. As you can see from the snippet the command is compared with “clearFileList”, if it’s the one they want to invoke it will be executed otherwise the next command will be checked (“getDir”). This kind of check is done until the right command is not found.

Final words
Malware analysis ends here, there are a some nice methods to explore and I’ll let you discover the rest yourself because I think I have attached too many pictures for a simple program. It’s time to end up with this blog post, you should have an idea of what DexInspector does.
It’s not perfect, but I feel comfortable with it. It’s still under development because I have to test it again and again (bugs are like malwares, they are everywhere!) and I would like to add some more things.
If you think it might help your Android reversing sessions I’ll put it online available for everyone, on condition that you’ll report bugs, comments and criticisms to me, ok? Let me know and don’t expect too much, it’s only a disassembler!

Here’s a sample I got some days ago via Facebook (md5: 6853d7ce162adb707ddfa6529b82b4af). Only few antivirus are able to recognize it right now.

To obtain the exe you have to simply click on a link which is show inside a chat request from a friend of you (the infected friend). The message I got is:
“Foto :D http://apps.facebook.com/peoplephotos/photo.php?=id_number”
where “foto” is the italian translation of “photo”, and id_number is your Facebook id (I removed mine).

The link is not working anymore on Facebook but I think they have some more available links to use… anyway, the interesting part of the malware is the use of a technique called Dynamic forking. It’s an old technique used sometimes inside packers and stuff like that, but as far as I have seen (and according to some friends) it’s a rarity to see it inside a malware. There’s an article explaining everything about the method right here: http://www.security.org.sg/code/loadexe.html (it’s dated April 2004!).
Is it really so interesting? Yes indeed, mainly because it’s not so easy to catch and debug the second exe on the fly. Not to mention you can’t dump it in an easy way. Is it impossible to study the exe? Not really… there’s always a simple way to do such things.

The “dynamic forking” method is all inside a call starting at 0x4013A0 address:

...
4013CE push CREATE_SUSPENDED
...
4013D3 push edx ; CommandLine = "PATH OF THE MALWARE\facebook-pic000163927.exe"
...
4013DB call _CreateProcessA ; it runs itself
...
401414 push ecx
401415 push edx
401416 mov _GetThreadContext, eax
40141B call eax
...
401432 push 4 ; number of bytes to read
...
401440 mov _ReadProcessMemory, eax
401445 call eax ; read BaseAddress from CONTEXT structure, it's 0x400000
...
401459 push edx ; BaseAddress: 0x400000
40145A push ecx ; process handle
40145B mov _ZwUnmapViewOfSection, eax
401460 call eax ; unmap!

It follows the article step by step, the last call is the most important one because it’s used to unmap the entire view of the section that contains BaseAddress. After that, the next part of the procedure is used to fill part of the unmapped section:

401462 mov esi, [ebp+decompressedBuffer] ; take care of ESI value!!!
401465 mov edi, [esi+3Ch]
401468 mov edx, [edi+esi+54h] ; SizeOfHeaders
40146C add edi, esi ; edi -> "PE"
40146E mov [ebp+decompressedBuffer], edx
...
40148A mov _VirtualAllocEx, eax
...
40149A push ecx ; size: 0x2FC000
40149B mov ecx, [ebp+var_1C]
40149E push edx ; 0x400000
40149F push ecx ; hprocess
4014A0 call eax ; VirtualAllocEx
...
4014D2 push 0
4014D4 push edx ; 0x400: number of bytes to write
4014D5 mov edx, [ebp+var_1C]
4014D8 push esi ; decompressedBuffer
4014D9 push ecx ; 0x400000
4014DA push edx
4014DB mov _WriteProcessMemory, eax
4014E0 call eax ; replace the header of the *new* process
... ; replace the rest of the *new* process's code

It allocs the necessary space for the *new* process (0x2FC000 represent the SizeOfImage of the real malware), and it replaces the old process code with the new one which is taken from a buffer pointed by ESI (look at 0×401462). This buffer is really important, I’ll tell you later why. Now, the final part of the procedure:

40158D mov [ebp+var_280], eax ; change oep of the file from 0x4017D3 to 0x40C4FF
...
4015A4 push ecx
4015A5 push edx
4015A6 mov _SetThreadContext, eax
4015AB call eax ; SetThreadContext
...
4015BE mov _ResumeThread, eax
4015C3 call eax ; ResumeThread

Pretty simple, it changes the entry point and it runs the process from the new location.

At this point I’m not able to debug the new process with a debugger like Ollydbg, I’m not even able to dump the new process… and the question is: how can I solve the problem? The dynamic forking is a powerfull method but there’s a big flaw in it, you always know how to dump the real malware: in this case decompressedBuffer is the answer! The buffer contains all the new code, and you only have to understand where the hell it was stored:

401383 push ecx ; finaluncompressedsize
401384 push ebp ; compressedbuffersize
401385 push edx ; compressedbuffer
401386 push edi ; uncompressedbuffersize
401387 push esi ; uncompressed buffer
401388 push COMPRESSION_FORMAT_LZNT1
40138A mov RtlDecompressBuffer, eax
40138F call eax

The malware uses lznt1 compression algo to reveal the real code. When the decompression ends you only have to dump 0×11200 bytes starting from UncompressedBuffer address and voilà! Now you can easily check the real malware!

Well, something unusual is always better than the usual boring thing…

Today I’m going to tell you something about the last malware I checked (MD5 0C17E03F41289E47EEB5D0F3F1F48C9C).

The exe file imports few functions only, but the malware calls a lot of APIs. The author uses a special trick to call an API function, he creates a sort of bridge between the first instruction and the rest of the code of the function itself. The first instruction is executed directly from the stack, then a jmp instruction (the bridge) will lead you to the second instruction (and the rest of the code) of the function. I think I’ve already seen the trick somewhere but unfortunately I don’t remember where… maybe a specific packer or just something similar, I don’t know. If you have seen this trick before just drop me a comment, thx!

The malware is packed, but inside the unpacked file there’s something strange:

no_address

The exe is full of calls to NULL value. I’m pretty sure that it’s not an error occorred during the unpacking process; there’s something at the beginning of the exe able to fix the addresses. I started my analysis from the first lines of the unpacked file.

The Import Table is really small but spying inside the strings window I found a lot of common API strings. There’s a big list of functions, and they are divided into some groups; one group containing kernel32 functions, another one with user32 and so on. Working a little with some cross references I got the point I was looking for. It’s time to describe how the malware changes all the “call NULL” instructions.

First of all the malware gains access to kernel32 base address:

4013D5    mov  edi, large fs:30h  ; PEB
4013DC    mov  edi, [edi+0Ch]     ; PEB+0x00c   Ldr : Ptr32 _PEB_LDR_DATA
4013DF    mov  edi, [edi+0Ch]     ; +0x00c InLoadOrderModuleList : _LIST_ENTRY
4013E2    jmp  short loc_401404

4013E4 check_current_module:
4013E4    mov  eax, edi    ; eax points to current _LDR_MODULE structure
4013E6    add  eax, 2Ch
4013E9    push [ebp+arg_0]        ; unicode "kernel32.dll"
4013EC    push dword ptr [eax+4]  ; current module name inside InLoadOrderModuleList
4013EF    call Compare_UNICODE_Strings
4013F4    or   eax, eax
4013F6    jnz  short strings_are_not_equal
4013F8    mov  eax, edi           ; LDR_MODULE of the module I was looking for
4013FA    mov  eax, [eax+18h]     ; He gets the BaseAddress!!!
4013FD    pop  edi
4013FE    leave
4013FF    retn 4

401402 strings_are_not_equal:
401402    mov  edi, [edi]        ; jump to next module structure
401404 loc_401404:
401404    cmp  dword ptr [edi+18h], 0          ; Is BaseAddress 0?
401408    jnz  short check_current_module
40140A    xor  eax, eax
40140C    pop  edi
40140D    leave
40140E    retn 4

Quite common way, but quite uncommon inside a malware… at least from my not so experienced perspective. Anyway, once it has the right BaseAddress tha malware starts bridge-ing all the necessary functions.

main_routine

It’s everything inside this call. It takes four parameters, we can ignore the first one pushed into the stack. What about the others?
- eax represents the BaseAddress of a module, in this case ntdll
- 404040 points to a sequence of strings, in this case the first one is “RtlZeroMemory”
- 406000 represents an address inside the malware
The procedure is called each time the malware needs to bridge a group of functions, all of them belong to a specific module. In this specific case it works with ntdll’s functions. The list of the functions starts from 0×404040 address:

api_ntdll1

The routine contains a loop running until all the functions inside the current group are not all bridged. Here is how the first function is bridged (the sub routine starts at 0×401411):

1. It takes VirtualAlloc starting address via Kernel32′s ExportTable
2. It gets the number of bytes of the first instruction of VirtualAlloc. On my XP machine VirtualAlloc starts with a two byte length instruction “MOV EDI, EDI”
3. It subtracts 7 from ESP value. 7 is obtained adding 5 (a fixed value) to the number of bytes of VirtualAlloc first instruction (2+5=7)
4. It copies the first two bytes of VirtualAlloc’s code inside the word pointed by the new stack pointer value
5. If the length of the first instruction is one byte only the malware checks for a possible active breakpoint comparing the byte with 0xCC value; quite useless check at this point…
6. It sets the byte pointed by ESP+2 to 0xE9
7. It fills the final 4 of 7 bytes obtaining:

virtualalloc_bridge

You have the first instruction of VirtualAlloc at 0x12FDF5, then the jump instruction will lead you directly at the second instruction of VirtualAlloc. Now you understand why it decreases ESP value by 7, two bytes for the first instruction and 5 for the jump. Starting from 0x12FDFC you have the old untouched stack.
8. It gets the length of the first instruction of the function to bridge. In this specific case the name of the function is RtlZeroMemory and the length is 1
9. It adds 5 to the obtained value
10. It calls VirtualAlloc passing trought the stack. It calls 0x12FDF5, and it allocs 6 bytes. 6 is the value that comes from point #9 (5+1=6)
11. It copies the first instruction of RtlZeroMemory inside the allocated memory space
12. An anti breakpoint check occours this time because the first instruction is one byte only
13. It sets the second byte inside the allocated memory space to 0xE9 (again, a jmp instruction)
14. It fills the rest of the bytes:

rtlzeromemory_bridge

Here is the bridge! It’s like what happened to VirtualAlloc, the allocated memory space contains the first instruction of RtlZeroMemory and a jump to the rest of the code
15. It restores the original stack pointer value simply adding 7 to the current ESP value
16. It returns the starting address of the allocated memory space (in this case 0×320000)

To sum up, the routine bridges the function and returns a memory address. The address will be saved starting from 0×406000 which is another parameter passed to the routine. If you don’t remind all the parameters you can take a look some lines above.
So, starting from 0×406000 you’ll have a series of dwords, each one containing a pointer to a memory allocated space; these are the values used to replace all the NULL calls. Now I finally know why after the unpacking process I still had a series of “call NULL” instructions.

Is it really necessary to bridge everything?
Yes if the author wants to fool an automatic analysis. I don’t know if the trick works or not, but it’s the only reasonable thing I can think of.
On the other hand, he can’t stop a complete human analysis because once you know how it works it’s pretty easy to convert all the “call NULL” instructions into the right ones; a simple idc script will solve the puzzle.

It’s a nice piece of malware to analyse btw, it has some interesting routines inside!

I put my hands on a malware linked from one of the online malware repositories (md5: 57127815d6864a495151e49c7bf7d192). From a quick glance at it I had the impression it’s an interesting malware to play with. It’s recognizable by almost all the antivirus products out there, and to have an idea about what it does I read some technical descriptions from some random antivirus pages.
In this post I won’t describe what the malicious file does, but I’ll spend few words on a specific behaviour only: CVE-2006-5758. I didn’t check all the sites, but seems like no one is reporting information about the exploit used inside this malware. It tries to exploit a GDI Local Elevation of Privilege vulnerability, patched on April 2007 (MS07-017); yes, more than one year and a half old. From what I have seen there’s only one article on the web talking about this malicious file, it’s available at cyberinsecure web page.
The article doesn’t refer to a specific malware, and I don’t know if I have the same file, but the quick description reveals almost the same characteristics of the file I’m working on:
After remapping the memory, the malware will initialize a CPalette object. It will then search for the palette object in the shared kernel memory structure. Since the memory is now writable, it can be altered to include a pointer to a special function that will remove any existing SST hooks. Finally, a call to GetNearestPaletteIndex will indirectly cause the function to be executed. Afterwards, the palette object is restored leaving no trace of the attack.“.
I’ll use this comment to guide you through the post.

I wasn’t able to identify the packer used to protect the malware, it’s not such a problem indeed because the exe file is debug-able and it’s not hard to step through the code. You can try rebuilding the file, but in general I prefer to work on untouched files so my best choice it’s a simple dump. After that, in order to view all runtime retrieved functions I use my Ida plugin named Reveal Imports. In this way you can easily navigate through the disasmed file. Looking at the revealed imports I noticed some weird functions:

api

Quite unusual functions for a malware. The first thing to do is to check if they are used or not. These functions are called by the malware, and now I have to understand why. From my non professional experience with malwares in general, I know that most of the time the unusual code you see inside a malware comes from a source code available online. Google is a good friend, and a simple search reveals something interesting at milw0rm.
It’s the source code of the exploit that is used inside the malware (not the source of the malware!). I think it’s quite useful for newbies to disasm a routine having an eye on the source code, this malware represents a good exercize.

After remapping the memory…
The *exploit* routine starts at 40293E, and there’s an interesting loop at the beginning of the routine:

40296C search_right_handle:
40296C    cmp  [ebp+hFileMappingObject], 0FFFFh   ; hFileMappingObject is initially 0
402973    jnb  short loc_4029C1
402975    xor  eax, eax
402977    mov  [ebp+var_28], eax
40297A    push eax                             ; dwNumberOfBytesToMap
40297B    push eax                             ; dwFileOffsetLow
40297C    push eax                             ; dwFileOffsetHigh
40297D    push FILE_MAP_ALL_ACCESS             ; dwDesiredAccess
402982    push [ebp+hFileMappingObject]        ; hFileMappingObject
402985    call ds:MapViewOfFile
40298B    mov  [ebp+lpBaseAddress], eax
40298E    test eax, eax
402990    jz   short MapView_fails
402992    lea  ecx, [ebp+var_2C]
402995    push 0                          ; ResultLength
402997    push 10h                        ; SectionInformationLength
402999    push ecx                        ; SectionInformation
40299A    push 0                          ; SectionInformationClass
40299C    push [ebp+hFileMappingObject]   ; SectionHandle
40299F    call NtQuerySection             ; Retrieves information about the section object
4029A5    cmp  [ebp+var_28], SEC_COMMIT
4029AC    jz   short section_found
4029AE    push [ebp+lpBaseAddress]        ; lpBaseAddress
4029B1    call ds:UnmapViewOfFile         ; Wrong handle, unmap!
4029B7    xor  eax, eax
4029B9    mov  [ebp+lpBaseAddress], eax
4029BC
4029BC MapView_fails:
4029BC    inc  [ebp+hFileMappingObject]   ; Increments hFileMappingObject
4029BF    jmp  short search_right_handle

It repeatedly calls MapViewOfFile function using handle from 0 to 0xFFFF. If it finds the right handle it goes on with the rest of the code. As you can see from the snippet the malware restores the state of a wrong mapped view calling UnMapViewOfFile. That’s because it needs one and only one specific kind of section. It’s the first important step to complete.
On my XP machine the malware locates the right mapped view at 0xC30000, if you look at Ollydbg’s “Memory map” window you’ll see it only after MapViewOfFile was called; you should know why.

…the malware will initialize a CPalette object…

4029CC call RtlAllocateHeap_bridge   ; Allocates memory space
4029D1 test eax, eax
4029D3 jz   loc_402AA4
4029D9 mov  [ebp+var_14], eax
4029DC mov  word ptr [eax+2], 1    ; palNumEntries
4029E2 mov  word ptr [eax], 300h   ; palVersion     
4029E7 push eax                    ; Logical palette
4029E8 call CreatePalette          ; Creates a logical palette

Pretty easy to understand.

…It will then search for the palette object in the shared memory structure…
The mapped view is then used by the malware inside a new loop. The malware looks for a PGDI_TABLE_ENTRY through the new memory space:

402A04 search_object:
402A04    mov  eax, [ebp+lpBaseAddress]
402A07    add  eax, [ebp+var_24]
402A0A    cmp  [ebp+GDI_Structure], eax         ; Is it inside the mapped memory?
402A0D    jnb  short loc_402A37
402A0F    mov  eax, [ebp+GDI_Structure]
402A12    xor  ecx, ecx
402A14    mov  cx, [eax+4]
402A18    mov  edx, [ebp+Pid]                   ; pGdiEntry->ProcessID
402A1B    cmp  ecx, edx
402A1D    jnz  short try_next_structure
402A1F    xor  ecx, ecx
402A21    mov  cx, [eax+0Ah]                    ; pGdiEntry->nType
402A25    cmp  ecx, 8                           ; PAL_TYPE
402A28    jnz  short try_next_structure
402A2A    mov  eax, [eax]                       ; pGdiEntry->pKernelInfo
402A2C    mov  [ebp+original_KernelInfo], eax   ; Saves the original value
402A2F    jmp  short loc_402A37
402A31 try_next_structure:
402A31    add  [ebp+GDI_Structure], 10h         ; Moves on the next structure to check
402A35    jmp  short search_object

It saves the original value of KernleInfo field which contains a pointer to something stored at ring0. You can imagine why it’s saving that value.. it will replace the address with something else for sure.

…it can be altered to include a pointer to a special function…

402A3E call _RtlAllocateHeap_bridge
   ...
402A4E push [ebp+hO]
402A51 pop  dword ptr [eax]              ; Stores handle obtained calling CreatePalette
402A53 mov  dword ptr [eax+14h], 1
402A5A push [ebp+hook_hidden_function]   ; push 402AC0
402A5D pop  dword ptr [eax+3Ch]          ; Stores the real function to call
   ... 
402A6B mov  eax, [ebp+GDI_Structure]     ; Address of the original structure to replace
402A6E push [ebp+fake_structure]         ; Push the fake structure address                 
402A71 pop  dword ptr [eax]              ; To tamper!

It replaces the original data with something else. It’s more or less always the same trick, you exchange the old value with a new preferred one!

…Finally, a call to GetNearestPaletteIndex will indirectly cause the function to be executed…
The next call to GetNearestPaletteIndex will call what I have named hook_hidden_function, the hidden dangerous routine. To understand how the trick works you have to look inside win32k.sys, here’s part of GetNearestPaletteIndex:

00402A73 push 0
00402A75 push [ebp+hO]
00402A78 call GetNearestPaletteIndex
   ...
BF94B4AF mov  esi, [ebp+8]          ; esi -> fake structure created between 402A4E and 402A6E
   ...
BF94B4E0 call dword ptr [esi+3Ch]   ; esi+3C points to hook_hidden_function!!!

The malware will call the hidden function, you ignore it until you’ll realize that the machine is compromised. Nice trick indeed.

The malware seems to have some more interesting features, I hope to write something else about it in the next days.

In these days I wanted to fix my Reveal Imports plugin. I wrote it some months ago while I was checking a malware (click here for the full story); it’s bugged and it works on some malwares only.
The bad news is that I lost the source code… yes, it sometimes happens. It’s not the end of the world because if you were able to code a bugged program you should be able to write a new bugged one!

The idea of the new plugin is the same: it reveals imports of a dumped process loaded inside Ida.

plugin_reveal_imports

In general, for a non rebuilded dump you’ll have some problems guessing what kind of code will you face after “jmp 7C810DA6″ instruction. The plugin will come in handy when you need to analyze a dump without rebuilding the file using an external tool (i.e. Import Reconstructor).

To use the plugin is pretty easy, start saving it inside IDA plugin directory. Load the file in Ida, move the cursor inside the section containing the code you want to check and hit ALT+z to reveal hidden imports. If there’s something to reveal a window will appear showing the result.

It’s the first release and it’s far from being perfect. Anyway, if you like the plugin idea you can help me telling every kind of bug/problem/strange behaviour it has. This time I’ll try to fix/improve it.

Download

Here are the first lines of a malware I was looking at some days ago (MD5: DA4B7EF93C588AD799F1A1C5AFB6CFAD). The malware is packed, I think with an home made packer; 40107C is the entry point, the first line of the loader’s code. The code is filled with useless instructions, nothing hard but if you want to study the entire loader you have to pay attention on every single lines of code. This time I’m not interested in the loader itself, but I’ll focus my attention on a strange behaviour, something I have never noticed before. The malware crashes at 4010AC on XP sp3 machine but it works fine on XP with service pack 1 or 2.

40107C ADD ECX,DWORD PTR SS:[ESP]   ; useless
40107F MOV ESI,-70                  ; useless
401084 ADD EDI,EAX                  ; useless
401086 MOV ECX,2AFFC5C8             ; useless
40108B ROL ECX,1                    ; useless
40108E ROR EDX,15                   ; useless
401091 MOV EDI,ESP                  ; edi = 12FFC4
401093 MOV EDX,FE000001             ; edx = 0xFE000001
401098 ROL EDX,7                    ; edx = 0xFF
40109B SUB EAX,EBX                  ; useless
40109D AND EDI,EDX                  ; edi = 0x12FFC4 && 0xFF = 0xC4
40109F MOV EDX,25FE0                ; edx = 0x25FE0
4010A4 ROL EDX,3                    ; edx = 0x12FF00
4010A7 ADD EDX,EDI                  ; edx = 0x12FFC4
4010A9 SAL ECX,11                   ; useless
4010AC MOV EAX,DWORD PTR DS:[EDX]   ; eax = 0x77E5EB69

The comments are taken from a XP sp1 debugging session. At the end of the snippet eax points to ExitThread’s parameter, the one inside BaseProcessStart. There’s nothing interesting in these few lines of code, but it’s always better to open your eyes when there are hardcoded values around. I’m referring to value 0x12FF00 (hardcoded is not totally right but the sense is the same). It’s not obvious but this piece of code could not work on every single machine. Seems like the author was sure about the initial stack address value. I don’t know when the malware was written, but this piece of code crashes on XP machine with Service Pack 3. Maybe the malware was written before the final release of the latest service pack, I dont know. Here is the same code tested on a machine running XP sp3 :

401091 MOV EDI,ESP                  ; edi = 13FFC4
401093 MOV EDX,FE000001             ; edx = 0xFE000001
401098 ROL EDX,7                    ; edx = 0xFF
40109D AND EDI,EDX                  ; edi = 0x13FFC4 && 0xFF = 0xC4
40109F MOV EDX,25FE0                ; edx = 0x25FE0
4010A4 ROL EDX,3                    ; edx = 0x12FF00
4010A7 ADD EDX,EDI                  ; edx = 0x12FFC4
4010AC MOV EAX,DWORD PTR DS:[EDX]   ; CRASH!!!

The initial stack address is not the same, this time it’s 0x13FFC4. The malware was expecting to see 0x12FFC4, but the value it was looking for is stored inside 0x13FFC4 address.

Who decide which kind of value should be assigned to esp? 12FFC4 or 13FFC4?
My investigation started from kernel32.CreateProcessInternalW function. All the code refers to a XP sp3 machine, but sp1 code is almost equal.

7C819DE1  mov  eax, [ebp+MaximumStackSize]
7C819DE7  lea  ecx, [ebp+InitialTEB]
7C819DED  push ecx                          ; InitialTEB
7C819DEE  push eax                          ; MaximumStackSize
7C819DEF  push [ebp+StackSize]              ; StackSize
7C819DF5  push [ebp+hProcess]               ; hProcess
7C819DFB  call _BaseCreateStack@16          ; BaseCreateStack(x,x,x,x)
7C819E00  mov  [ebp+var_9EC], eax           ; eax = 0 means SUCCESS
7C819E06  cmp  eax, ebx                     ; ebx = 0
7C819E08  jl   _BaseSetLastNTError          ; Jump to error check
7C819E0E  push ebx                          ; NULL
7C819E0F  push [ebp+InitialSP]              ; Stack pointer
7C819E15  push [ebp+InitialPC]              ; Program counter
7C819E1B  push [ebp+Parameter]              ; Parameter
7C819E21  lea  eax, [ebp+Context]
7C819E27  push eax                          ; Context
7C819E28  call _BaseInitializeContext@20    ; BaseInitializeContext(x,x,x,x,x)

This is where the new process’s context will be initialized. This is only an initialization, you won’t see the final values (values at EP of the new process) of each register, but it’s enough to understand why the esp values are not equal.
There are two functions in the snippet above, BaseCreateStack is used to create a stack for the process to run. BaseInitializeContext, as suggested by the name, initializes the context structure using some values obtained by the previous function. Let’s start with the first one: BaseCreateStack.

Firstly, it checks two values: MaximumStackSize and StackSize. Both of them are loaded from the process to run using NtQuerySection. Among all the information of a PE header there are two fields named SizeOfStackReserve and SizeOfStackCommit that are taken and saved by the system as MaximumStackSize and StackSize. Msdn has a description of the fields:
SizeOfStackReserve: the number of bytes to reserve for the stack. Only the memory specified by the SizeOfStackCommit member is committed at load time; the rest is made available one page at a time until this reserve size is reached.
SizeOfStackCommit: the number of bytes to commit for the stack.

Ok, now the system is going to check if they are valid or not:

7C8102B5 mov  eax, large fs:18h               ; eax = TEB
7C8102BB mov  ecx, [eax+30h]                  ; ecx = PEB
...
7C8102D2 push dword ptr [ecx+8]               ;  PEB->ImageBaseAddress
...
7C8102DB call ds:__imp__RtlImageNtHeader@4    ; RtlImageNtHeader(x)
7C8102E1 test eax, eax
7C8102E3 jz   failure
7C8102E9 mov  ecx, [ebp+MaximumStackSize]
7C8102EC test ecx, ecx                      ; is MaximumStackSize zero?
7C8102EE mov  edx, [eax+IMAGE_NT_HEADERS.OptionalHeader.SizeOfStackCommit]
7C8102F1 jnz  short MaximumStackSize_not_zero
7C8102F3 mov  ecx, [eax+IMAGE_NT_HEADERS.OptionalHeader.SizeOfStackReserve]
7C8102F6 mov  [ebp+MaximumStackSize], ecx

If MaximumStackSize has a not zero value the flow goes on otherwise it’s necessary to set a value to this variable. Which is this value? It’s the one taken from the process’s PE header pointed by PEB->ImageBaseAddress.

Ok, now it’s time for a check over the other variable; the check is pretty similar to the previous one:

7C8102F9 MaximumStackSize_not_zero:
7C8102F9 mov  eax, [ebp+StackSize]
7C8102FC test eax, eax                ; Is StackSize zero?
7C8102FE push edi
7C8102FF mov  edi, 0FFF00000h
7C810304 jnz  StackSize_not_zero
7C81030A mov  eax, edx
...

If StackSize is zero the content of the variable is filled with the value taken some lines above at 7C8102EE: SizeOfStackCommit. It’s almost the same check I described for MaximumStackSize.
If the values are not zero, the system checks them again, just to be sure they are valid:

7C80AFC2 cmp  eax, ecx             ; compare between StackSize and MaximumStackSize
7C80AFC4 jb   loc_7C81030C
7C80AFCA lea  ecx, [eax+0FFFFFh]           ; 
7C80AFD0 and  ecx, edi                     ; fix MaximumStackSize
7C80AFD2 mov  [ebp+MaximumStackSize], ecx  ;
7C80AFD5 jmp  loc_7C81030C

StackSize must be minor than MaximumStackSize, if it doesn’t happen the system raise up MaximumStackSize. Now that the initial check is complete the function proceeds working on some alignment stuff, not so interesting per se. I can pass over this part reaching an interesting snippet:

7C81036F mov  ebx, ds:__imp__NtAllocateVirtualMemory@24 ; NtAllocateVirtualMemory(x,x,x,x,x,x)









...
7C81037A push PAGE_READWRITE                  ; Protect: PAGE_READ_WRITE
...
7C810380 push MEM_RESERVE                     ; AllocationType: MEM_RESERVE
7C810385 lea  eax, [ebp+MaximumStackSize]
7C810388 push eax                             ; RegionSize = MaximumStackSize
7C810389 push 0                               ; ZeroBits = 0
7C81038B lea  eax, [ebp+_BaseAddress]
7C81038E push eax                             ; BaseAddress = 0;
7C81038F push [ebp+hProcess]                  ; ProcessHandle
7C810392 mov  [ebp+MaximumStackSize], ecx
7C810395 call ebx                             ; NtAllocateVirtualMemory

The system reserves the right address space for the stack. It reserves MaximumStackSize bytes starting from an address chosen by the system; the address is the first available address inside the virtual space. The chosen address is stored inside BaseAddress and it’s used to update the content of InitialTeb->StackAllocationBase field:

7C81039F mov  edi, [ebp+InitialTEB]
7C8103A2 mov  ecx, [ebp+_BaseAddress]
7C8103A5 mov  eax, [ebp+MaximumStackSize]
7C8103A8 and  [edi+INITIAL_TEB.PreviousStackBase], 0
7C8103AB and  [edi+INITIAL_TEB.PreviousStackLimit], 0
7C8103AF mov  [edi+INITIAL_TEB.AllocateStackBase], ecx

The stack is created, there are 3 fields to set and for now the system updates the bottom of the stack only.

7C8103B2 add  ecx, eax                         
7C8103B4 mov  [edi+INITIAL_TEB.StackBase], ecx

InitialTeb->StackBase = BaseAddress + MaximumStackSize
The system sets up the stack area by giving the upper and lower bound. The initial stack value is StackBase and it will decrease everytime a push/call/.. occours.

The procedure goes on committing the initial area of the stack, and after that BaseInitializeContext fixes the righ values for the registers (including esp). No need to continue stepping the code, I have a lot information now, and I might come to a conclusion.

PE fields:
SizeOfStackReserve: 0×100000
SizeOfStackCommit: 0×1000

Under XP sp3:
AllocateStackBase = 0×40000
MaximumStackSize = 0×100000
StackBase = 0×140000

Under XP sp1/sp2:
AllocateStackBase = 0×30000
MaximumStackSize = 0×100000
StackBase = 0×130000

It’s impossible for sp_1/2 to have an esp value like 0x13FFC4 because the upper bound (StackBase) is 0×130000. StackBase was obtained by the operation “AllocateStackBase + MaximumStackSize” (AllocateStackBase is the same as BaseAddress value). MaximumStackSize was taken from the malware’s header, and AllocateStackBase was initialized from NtAllocateVirtualMemory call.
Seems like the solution to the puzzle comes from NtAllocateVirtualMemory. The function is called using zero as BaseAddress parameter; as I said before it means that the system decides to assign the first free virtual location which is obviously 0×40000 under sp_3 and 0×30000 under sp_1/2. From my sp_3 machine, trying to browse the memory I noticed a 0×1000 bytes allocated starting from 0×3000, there’s no trace about this memory area in old XP service packs… What did they change in XP sp3? Well, I’m ready for a vacation in Holland for now. I’ll try to reply when I’ll be back in two weeks. If the answer is obvious and/or you know why… feel free to comment your idea :)

Is it possible to solve the problem?
Well, it’s insane to fix a malware just to be sure to run it under an XP sp3 machine. Anyway it’s not hard to make it runnable, you can simply change SizeOfStackReserve and/or SizeOfStackCommit directly from the PE header. I tried changing SizeOfStackReserve from 0×100000 to 0xF0000 and I got a runnable file. I don’t know how safe is to change such parameters…

All the tests were done on my personal machines, I would like to know if your sp3 machine (or any other OS) has the same initial stack value.

Just a quick post today about an uncommon compression used in few malwares. Look at this snippet:

The malware uses two uncommon functions RtlGetCompressionWorkSpaceSize and RtlDecompressBuffer. The functions are documented on MSDN, but the pages start with “[This is preliminary documentation and subject to change.]“. Searching through the net I found an old article by Alex Ionescu dated 2003, the article is titled “Native API Compression and Introduction to NT Design” and it’s available at his page. At that time the functions were undocumented, but he did explain how they works; the funny thing is that after 5 years MSDN is not sure about the description of the two functions…

Anyway, the function are mostly used to decompress a file (which is hidden inside the original exe). It’s pretty easy to use these functions, and with few lines of code you can have your compression engine. It’s always hard to understand the content of an encrypted/compressed series of bytes, but not this time because it’s easy to recognize a compressed exe just looking at the bytes.

As you can see there are some recognizable keywords: MZ, Rich, text, data. It’s enough to understand we are probably in front of an exe file. I wouldn’t hide an exe using this kind of compression…

This is a sort of continuation of the previous post, the one about malware able to infect right-handed only.
It’s a Msn malware, one of the recent one (as far as I remember I got it from Malware Domain List). I think there’s often something interesting inside a malware, no matter what it does and this is a perfect example!

The malware is not really interesting per se, but it has something I’ve never noticed before. It’s not a cool and dangerous new technique, but a coding behaviour. Look at the graph overview:

The image represents the content of a malware procedure. Nothing strange per se, except the fact that it contains 657 instructions in it, too many for a simple malware. It’s a big routine and I was surprised at first because you can do a lot of things with so many instructions. I started analysing the code, nothing is passed to the routine and nothing is returned back to the original caller. I tought it should be an important part of the malware, but I was disappointed by the real content of the routine. After few seconds I realized what’s really going on: 657 lines of code for doing something that normally would require around 50 lines…
The function contains a block of 17 instructions repeated 38 times. When I’m facing things like that I always have a little discussion with my brain. The questions are:
- why do you need to repeat each block 38 times?
- can’t you just use a while statement?
- is this a sort of anti-disassembling trick?
- can you produce such a procedure setting up some specific compiler’s options?

The repeated block contains the instruction below:

00402175    push 9                       ; Length of the string to decrypt
00402177    push offset ntdll_dll        ; String to decrypt
0040217C    push offset aM4l0x123456789  ; key: "M4L0X123456789"
00402181    call sub_401050              ; decrypt "ntdll.dll"
00402186    add  esp, 0Ch
00402189    mov  edi, eax
0040218B    mov  edx, offset ntdll_dll
00402190    or   ecx, 0FFFFFFFFh
00402193    xor  eax, eax
00402195    repne scasb
00402197    not  ecx
00402199    sub  edi, ecx
0040219B    mov  esi, edi
0040219D    mov  eax, ecx
0040219F    mov  edi, edx     
004021A1    shr  ecx, 2
004021A4    rep movsd
004021A6    mov  ecx, eax
004021A8    and  ecx, 3
004021AB    rep movsb

It’s only a decryption routine, nothing more. The string is decrypted by the “call 401050″, the rest of the code simply moves the string in the right buffer.
Ok, let’s try answering the initial questions.

According to some PE scanners the exe file was produced by Microsoft Visual C++ 6.0 SPx.
It’s possible to code the big procedure just using a loop (while, for, do-while) containing the snippet above. I don’t think the author used one of these statements because as far as I know it’s not possible to tell the compiler to explode a cycle into a sequence of blocks. At this point I have to options:
- he wrote the same block for 38 times
- he defined a macro with the block’s instructions repeating the macro for 38 times
I won’t code something like that, but the macro option seems to be the most probable choice.
Is it an anti-disassembling trick? My answer is no because it’s really easy to read such a code. You don’t have to deal with variables used inside a for/while; to understand what’s going on you only have to compare three or four blocks.
I don’t have a valid answer to the doubt I had at first….

Trying to find out some more info I studied the rest of the code. I was quite surprised to see another funny diagram.

This time the image represents the content of the procedure used to retrieve the address of the API functions. Again, no while/for/do-while statement. The rectangle on the upper part of the image it’s a sequence of calls to GetProcAddress, and the code below it’s just a sequence of checks on the addresses obtained by GetProcAddress.
It’s a series of:

address = GetProcAddress(hDLL, "function_name");

followed by a series of:

if (!address) goto _error;

Apart the non-use of a loop there’s something more this time, something that I think reveals an unusual coding style; tha author checks errors at the end of the procedure. I always prefer to check return values as soon as I can, it’s not a rule but it’s something that help you to avoid oversight and potential errors… The procedure has a little bug/oversight at the end, the author forgot to close an opened handle. Just a coincidence?

Anyway, two procedures without a single loop. Seems like the author didn’t use any kind of loop for choice. In case you still have some doubts here’s another cool pictures for you:

The routine inside the picture contains the code used to check if the API(s) are patched or not. The check is done comparing the first byte with 0xE8 and 0xE9 (call and jump). If the functions are not patched the malware goes on, otherwise it ends. As you can see no loops are used.

In summary: it’s not jungle code, it’s not an anti-disasm code and it’s not a specific compiler setting. I think it’s only a personal choice, but I would really like to know why the author used this particular style.
Do you have any suggestions?

Beyond the coding style, the malware has some more strange things. As pointed out by *asaperlo*, the code contains a bugged RC4 implementation (Look at the comments of the previous blog post).
It also has a virtual machine check. The idea is pretty simple, the malware checks the nick of the current user. If the nick is “sandbox” or “vmware” you are under a virtual machine…
This malware spawns another one (it’s encrypted inside the file), it might be material for another post.

That’s a funny coded malware for sure!

Next Page »

Follow

Get every new post delivered to your Inbox.