Reverse Engineering


In these days I had the opportunity to retrieve some information from an Iphone backup, in the specific case I was interested in WhatsApp’s messages. Nothing hard per se, it’s all inside some database files and with a tool like SQLite Database Browser you can easily access all the needed information but the annoying thing is represented by the interpretation of the result of your queries.
I didn’t have an immediate deadline for the analysis so I decided to code a little extractor for WhatsApp. Here are some screenshots:

- all the available chats on the top and the selected chat below:
Gui

- it can display images, movies and audio. A click will open the associated Windows program able to show/play the media:
Image
Movie
Audio

- it shows deleted messages:
Deleted

- events:
Events

- and messages that are not sent due to an internal error:
Not sent

- I can get the onwer’s info:
Owner

- and the contacts info too:
Contacts

The program has been tested on this configuration:
Os: Win7/XP
iOS: 6.1.3
WhatsApp: 2.8.7
It’s just a personal project but if you want you can try it. Download WABI from here

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 enjoy browsing crackmes.de, and I used to try a crackme from time to time. It’s not my intention to write a tutorial for this crackme, but after reading a comment from andrewl.us I decided to spend some words for this tutorial.
andrewl.us’s comment is pretty simple: “two solutions accepted, and neither uses a deobfuscator that emits a cleaner crackme”. That’s the point, nowadays only few people spend some time writing a detailed/original/complete solution, most of them prefer to say “I did it”… that’s sad and it’s not the spirit of crackmes.de!

Intro
The protection routine created by the author is really simple, but the obfuscation method applied makes our reversing session hard. Look here and you’ll understand how the code works:

406E2A jmp short loc_406E2D
...
406E2D nop
406E2E jmp loc_405B10
...
405B10 nop
405B11 nop
405B12 and al, 0FFh
405B14 jmp loc_4053CC
...

A lot of jumps and a lot of junk code. The real challenge is to identify the valid instructions of the crackme because most of them are only useless junk code. So, to get the valid instruction you can:
1. step all the crackme code using a debugger trying to identify valid and not valid instruction
2. deobfuscate the crackme in some way

Point #1 represents the easy way because you will surely find out the valid instructions checking the code instruction by instruction. In this case it’s a good approach because the crackme is only 35kb… Will you apply this method on a huge obfuscated file? That’s why I opt for point #2!

Due to the nature of the protected code I think it’s not possible to write a static program able to deobfuscate an exe protected with this method, but if you imagine the exe like a set of procedures combined all together you can produce something which is pretty near to the original untouched program.
To solve this crackme I’ll write an idc script able to extract valid instructions from a single procedure. Having this in mind you can then put everything all together obtaining a working deobfuscated crackme.

The deobfuscator
The idea is pretty simple: starting from a specific address the script traces through the necessary instructions trying to identify (and eventually remove) junk code. The script will show all the valid instructions inside the output area.
First of all I have to create the skeleton of the script.

static main()
{
   do {
      check_current_instruction;
      if (!junk_instruction)
         print_valid_instruction;
      get_address_next_instruction;
   }
   while (valid_address_instruction);
}

The script checks every single instruction trying to understand if it’s valid or junk. I’ll show you later how to check it, now take a look at the snippet used to print a valid instruction:

static print_valid_instruction(address)
{
   auto instrLen;
   auto op1, op2;

   Jump(address);
   MakeUnkn(address, 0);
   instrLen = MakeCode(address);
   Message("\n%X: %s", address, GetMnem(address));
   op1 = GetOpnd(address, 0);
   if (op1 != 0x00)
      Message(" %s", op1);
   op2 = GetOpnd(address, 1);
   if (op2 != 0x00)
      Message(", %s", op2);
   return instrLen;
}

The function receives the address of the current valid instruction printing it inside the output area.
I have used Jump, MakeUnkn and MakeCode because the code produced by IDA has a lot of undefined lines: with an undefined instruction is not always possible to get the right menmonic text associated to a specific opcode.
So, when you have the decoded instruction you can print it with the necessary operands. The function returns the length of the current instruction, used to get the address of the next one to check.

Nothing hard, let’s see how to identify the junk code. The idea is to isolate all the unnecessary instructions. First of all, to have a general idea of the crackme’s code take a look at this blocks:

.jmp:00405B10 90 nop
.jmp:00405B11 90 nop
.jmp:00405B12 24 FF and al, 0FFh <-- al remains the same
.jmp:00405B14 E9 B3 F8 FF FF jmp loc_4053CC
...
.jmp:00408969 40 inc eax <--
.jmp:0040896A 48 dec eax <-- eax remains the same
.jmp:0040896B 90 nop
.jmp:0040896C 90 nop
.jmp:0040896D E9 14 D4 FF FF jmp near ptr unk_405D86
...
.jmp:00405CC3 90 nop
.jmp:00405CC4 80 EB 00 sub bl, 0 <-- bl remains the same
.jmp:00405CC7 E9 34 0E 00 00 jmp near ptr unk_406B00
...
.jmp:00407163 50 push eax
.jmp:00407164 04 66 add al, 66h <-- add inside push/pop it's nonsense...
.jmp:00407166 58 pop eax
.jmp:00407167 E9 0C EB FF FF jmp near ptr unk_405C78

If you execute the snippets above you’ll find out that the state of the involved register remains the same, no changes are applied.
So, what can we put inside the junk code set? All the “jmp” instructions, “nop2, “and” with 0xFF and so on… If you look at the code I think you’ll surely find out what to mark as junk in a short time.
Just to understand it, here is a part of the script used to avoid some specific instructions:

   opcode = Byte(currAddress); // Get the byte at the current address
   ...
   else if ((opcode == 0x24) && (Byte(currAddress+1) == 0xFF)) // Avoid "and op1, 0xFF" instruction
      currAddress = currAddress + 2; // Move to the next instruction
   ...
   else if ((opcode == 0x60) && (Byte(currAddress+2) == 0x61)) // Avoid instructions from pushad to popad
      currAddress = currAddress + 3;
   ...
   else if (opcode == 0x90) // Avoid nop instruction
      currAddress = currAddress + 1;
   ...
   if (opcode == 0xE9) // Avoid jump instruction
      currAddress = (currAddress + Dword(currAddress+1) + 5) & 0x00000000FFFFFFFF;

Instead of printing the instruction I simply avoid it moving the attention to the next one. You don’t need to use MakeCode or something else because the script works directly on the bytes code.
Ok, is it really all? Hmm, there is something more to add. You have to pay particular attention to a point: how can you manage a conditional jump?
The question deserves a reply because sooner or later the crackme will have a check and you’ll have to face a conditional jump. I decided to let you choose the path to follow! What does it mean?
I remove all the conditional jumps except the one which is after a compare instruction. I need to remember that a compare has been executed:

   else if (opcode == 0x3B) { // Compare found, take it in mind!
      cmp = 1;
      currAddress = currAddress + print_valid_instruction(currAddress);
   }

The variable “cmp” is used to take in mind that a compare instruction has been executed. cmp variable is originally initialized to -1. Here is how I handle a conditional jump instruction:

   else if ((opcode == 0x74) || (opcode == 0x75)){
   // Check to see if a cmp instruction has been executed
   if (cmp == 1) {
      Jump(currAddress);
      jump = AskYN(0, "Want to jump?"); // Box with a question
      if (jump == 0) // No jump
         currAddress = currAddress + 2;
      else // Jump
         currAddress = (currAddress + Byte(currAddress+1) + 2) & 0x00000000FFFFFFFF;
      cmp = -1; // Restore the original value
   }
   else
      currAddress = (currAddress + Byte(currAddress+1) + 2) & 0x00000000FFFFFFFF;
}

That’s what I meant when I said “I decided to let you choose the path to follow”. Pressing Yes or No inside the appeared box you can decide the flow of the crackme code, it’s just like a live trace.
I decided to not print the conditional jump but if you think it will help you put it inside the set of valid instructions.

That’s how my deobfuscator works (get it from here). I don’t need anything else because with the output produced by the script I can study the entire protection routine via dead list without having to debug the program.
For those who wants to study the deobfuscated crackme using a debugger it’s possible to produce a clean crackme too. Instead of printing the result in the output area you could move the valid instructions somewhere inside the file. There are a lot of free bytes to use inside the exe; just choose a starting point and with some minor adjustments, as I suggested before combining all the deobfuscated procedures, you can have a working clean crackme version.

The protection routine
The algorithm used by the crackme is really simple, but it requires a brute-force approach…

4092BA: mov cx, 54h
408B0D: shl ecx, 10h
405507: mov cx, 5854h
405680: push ecx <-- push "TXT
4085F4: mov cx, 2E59h
407CC1: shl ecx, 10h
405B4C: mov cx, 454Bh
4087F4: push ecx <-- push "KEY."
406705: mov edx, esp <-- edx -> "KEY.TXT"
40881F: mov cx, 40h
407FAF: shl ecx, 10h
408603: mov cx, 812Fh
405435: push ecx <-- push 0x40812F: first instruction to execute after CreateFileA
4078B7: xor eax, eax
408EDE: push eax
407E92: mov al, 50h
408810: push eax <-- Flags & attributes: 0x50: FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE
4070EB: mov al, 3
4052CF: push eax <-- OPEN_EXISTING
405B5C: mov al, 0
408441: push eax
406E3B: push eax
40868B: mov al, 50h
40610A: shl eax, 18h
408AF1: push eax <-- Desired access: 0x50000000: GENERIC_WRITE | GENERIC_ALL
4080CC: push edx <-- Filename: "KEY.TXT"
4092CE: call CreateFileA
4092D3: ret

From the readme file we already know that the protection routine is based on a keyfile, now we know the name of the file to produce: KEY.TXT
At the beginning of the tutorial I told you that it’s not possible to write a fully working static deobfuscator, and now you can understand why: look at the push at 405435. The address on the stack (0x40812F) is the point where the precedure will return after ret instruction at 4092D3. How can you identify the address as a possible return value? Well, maybe possible, but hard…

Ok, back to our protection routine: after executing CreateFileA function, the code pass from instruction 40812F:

4077E5: xor edx, edx
4068B9: dec edx
407FDC: cmp edx, eax <-- check
4092D9: call ExitProcess <-- here if check fails

The snippet above contains a first check which is done on the keyfile handle. If the file doesn’t exist the crackme ends. As you’ll see there are some more checks performed by the crackme, all of them end with a call to ExitProcess without a single error message.
To pass this check create the file and put some bytes inside. As you can guess the next piece of code will be used to read the content of the keyfile:

407FDC: cmp edx, eax
406372: xor edx, edx
406C87: push edx <-- push 0
40909F: push edx <-- push 0
405DD3: push edx <-- push 0
405D95: mov ebp, esp
406FFC: push edx <-- push 0
405B01: mov esi, esp
407426: push eax <-- push file handle
407235: mov cx, 40h
406263: shl ecx, 10h
406F38: mov cx, 5ADDh
40759B: push ecx <-- push 0x405ADD: first instruction to execute after ReadFile
40778A: push edx
4089C3: push esi <-- bytes read
407181: push 18h
4070DC: push ebp <-- buffer that receives the data
408E56: push eax <-- file handle
4092C8: call ReadFile
4092CD: retn

An obvious conseguence of CreateFile: ReadFile. It’s time to see how it will use the keyfile’s bytes.

405426: mov esp, ebp <-- ESP points to the contents of the keyfile
40764F: mov cx, 0F45Ah
40782F: shl ecx, 10h
405DA4: mov cx, 675Dh
4066E6: mov esi, ecx <-- ESI = 0xF45A675D
407B95: mov cx, 4DDAh
40892D: shl ecx, 10h
407CDF: mov cx, 0FA31h
406B4C: mov edi, ecx <-- EDI = 0x4DDAFA31
406083: pop eax <-- EAX = first 4 bytes of the file (Key_1)
405999: pop ecx <-- ECX = second 4 bytes of the file (Key_2)
405A04: push ecx
405EC3: push eax
407B59: xor eax, esi <--
4075AA: xor ecx, edi <-- operations based on Key_1 and Key_2
4067C8: add eax, ecx <--
406F47: mov cx, 0BAE3h
406F83: shl ecx, 10h
406BB4: mov cx, 0DC73h <-- ECX = 0xBAE3DC73
405544: cmp eax, ecx <-- first check

This first check is based on the first eight bytes of the keyfile. The scheme is:

(Key_1 ^ 0xF45A675D) + (Key_2 ^ 0x4DDAFA31) = 0xBAE3DC73

Nothing hard per se but without other informations if you want to solve this equation you are forced to write a brute force algorithm over key_1 and key_2. Really expansive in terms of time…

408DCE: mov cx, 0AADDh
40846E: shl ecx, 10h
406E48: mov cx, 357Dh
408324: mov esi, ecx <-- ESI = 0xAADD357D
408DEC: mov cx, 44FAh
405FED: shl ecx, 10h
405B2E: mov cx, 0FC3Ch
4059A9: mov edi, ecx <-- EDI = 0x44FAFC3C
4069F3: pop eax <-- EAX = Key_1
4074BB: pop ecx <-- ECX = Key_2
4085A9: push ecx
40919F: push eax
4051FC: xor eax, esi <--
408EB0: xor ecx, edi <-- operations based on Key_1 and Key_2
409143: add eax, ecx <--
407901: mov cx, 0F23Fh
40893C: shl ecx, 10h
406335: mov cx, 2C88h <-- ECX = 0xF23F2C88
406B87: cmp eax, ecx <-- second check

Another check over the keyfile’s content. As you can see it’s pretty similar to the previous one:

(Key_1 ^ 0xAADD357D) + (Key_2 ^ 0x44FAFC3C) = 0xF23F2C88

2 equations and 2 variables, we can reduce the time of the brute-agorithm because you can test all possible values of key_1 only (key_2 is obtained as a conseguence).

407E66: pop esi <-- ESI = Key_1
407FCD: pop edi <-- EDI = Key_2
407228: pop ebx <-- EBX = third 4 bytes of the file (Key_3)
408144: mov cx, 2164h
406AF1: shl ecx, 10h
406A4C: mov cx, 3172h <-- ECX = 0x21643172
40602A: cmp ecx, ebx <-- third check

4 more bytes join the party. This time no math or logic operations but a simple compare byte to byte: Key_3 must be “r1d!”. We know part of the keyfile, but this information doesn’t reduce our brute-time…

408C84: mov cx, 6F04h
406290: shl ecx, 10h
4091E8: mov cx, 530Ah <-- ECX = 0x6F04530A
406F65: xor ecx, edi <-- Key_2 ^ 0x6F04530A
406F57: push ecx
407514: mov cx, 0F0Fh
405408: shl ecx, 10h
40597B: mov cx, 101Bh <-- ECX = 0x0F0F101B
40819E: xor ecx, esi <-- Key_1 ^ 0x0F0F101B
406BD3: push ecx
408D0B: mov eax, esp
40638F: xor ebp, ebp
405284: push ebp
407AD2: push ebp <-- Caption: NULL
408EBF: push eax <-- Text:
406E95: push ebp <-- 0
4092D4: call MessageBoxA <-- CONGRATULATION BOX
4092D9: call ExitProcess

The final part of the crackme, it shows a congratulation message box. The text of the box is obtained using the correct value for Key_1 and Key_2.

To sum-up: there are 3 checks to pass, the first two are based on Key_1 and key_2 while the last check is over key_3 only. Key_3 values is fixed and I have to find the first two dwords (represented by Key_1 and Key_2) using a brute. The solution is not unique, you can provide some different keyfiles but I think the Valid solution is the one wich reveal the right text inside the message box. For me the valid text is “Success” that is obtained with keyfile = “Hello wor1d!” but who knows… :)

Final notes
It’s indeed an easy crackme, but it represents a good starting sample for those who have never played with an obfuscated target.

I use to browse crackmes.de from time to time when I want a reversing challenge to play with. I have to admit that there are much more interesting crackmes in the past, but today (digging deeper) I’ve found an unusual one; it’s not hard but the idea is really nice! The name of the crackme is “What Is This???”

crackmesde8

No exe file this time, the downloaded archive contains a readme file and the above image, nothing else. You can’t interact with an image so you can only load it into your preferred hex editor hoping to understand what’s going on.

It’s pretty easy to understand that something has been added at the end of the file (jpeg file ends with FF D9 bytes sequence):end_file

As you can see, the author appended some bytes at the end of the image. Now, I have to understand what’s behind these unknown bytes and Google will help me. I decided to start with “**TI83F*” which is the only reasonable string to search for. At the end I reach a page at http://merthsoft.com/linkguide/ti83+/fformat.html which enlighten the path to the solution of the crackme: the string “**TI83F” represents a tag used to define a program for a Texas Instruments calculator.

With the file format under your eyes it’s pretty easy to understand each byte:

- 2A 2A 54 49 38 33 46 2A:  8 bytes signature: it’s always “**TI83F*”

- 1A 0A 00: 3-byte, further signature: these three bytes always contain {1Ah, 0Ah, 00h}
- 00..00: 2Ah bytes, comment: it’s either zero-terminated or padded on the right with space characters
- 56 00: 2 bytes, length, in bytes, of the data section of the file
- 0D 00 45 … 2A 3F D4: n bytes, data section: consists of a number of variable entries
- 90 16: 2 bytes, file checksum: lower 16 bits of the sum of all bytes in the data section

Now, the data section:

- 0D 00: 2 bytes, always has a value of 0Bh or 0Dh
- 45 00: 2 bytes, length, in bytes, of the variable data
- 05: 1 byte, variable type ID byte (0×05 = Programs)
- 41 00 00 .. 00: 8 bytes, variable name padded with NULL characters
- 00: 1 byte, version: usually set to 00
- 00: 1 byte, flag: set to 80h if variable is archived, 00h else
- 45 00: 2 bytes, length, in bytes, of the variable data
- 43 00 DC .. 2A 3F D4: n bytes, variable data

Nothing interesting right now, just some definitions. The algo is all inside the variable data, each byte of that block represents a piece of the algo. I won’t explain every single byte definition because I think you can understand it by yourself simply using the table at http://merthsoft.com/linkguide/ti82/tokens.html

To sum-up, the variable data starting with “43 00 DC” bytes sequence can be decoded into this program:

Input A
A->B
0->C
While C<100
A+10*tan(A)->A
C+1->C
End
If A=19911.236
Then
Disp “OK”
Else
Disp “NO”
End

The algo is a TI-83 program, it’s pretty basic and the language is intuitive but if you need help take a look at chapter 16 of TI-83 Guidebook available online. Now that you know what’s going on you only have to solve it, good luck :)

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

This is more like a twitter post than a blog post… Anyway, for all those who haven’t tried yet I suggest to take a look at the Cyber challenge by the General Intelligence and Security Service of the Netherlands: https://www.aivd.nl/organisatie/eenheden/nationaal-bureau/nieuws/aivd-cyber-challenge/

I had fun decrypting the ENCrypted file. I would like to blog something about the crackme but I think I can’t give out spoilers…

Good luck and enjoy this cyber-challenge! :)

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!

Can I blog an incomplete solution or an incomplete analysis? Why not! That’s the spirit of this blog entry!

More than one year ago I started a project with Kayaker, we decided to write a tool able to show hidden callbacks. If I remember correctly the idea was born while we were putting our hands on a rootkit. In the same days I bet there were many reversers around thinking the same thing because the same tool was developed by others. As you can imagine our tool never see the light, but not because there are similar tools available online; mostly because we are two old lazy reversers!

I bet you are thinking: why the hell are you writing this stupid intro? Well, the tools I mentioned before were bugged and some months ago I discovered the same thing, they are still bugged (I don’t know if they have solved their problems right now…). Strange that no one else noticed it yet.
Anyway, we won’t complete the tool, but with this blog post I would like to tell you some notes about our investigations. At the beginning I wanted to write a detailed and complete article about the subject, but I don’t know when I’ll be able to end this project so I decided to spread out some of my notes.

It’s a sort of two minds work so credit goes to Kayaker too!

The idea is to try to retrieve hidden callbacks that has been installed via CmRegisterCallback, PsSetCreateProcessNotifyRoutine, PsSetCreateThreadNotifyRoutine and PsSetLoadImageNotifyRoutine. After that it would be good to deregister one or more of them.



Where to start?
First of all you have to understand what’s behind functions like CmRegisterCallback, and others. Then, you’ll have something to work on. I’ll start with CmRegisterCallback (from XP SP2), the function is used to register a RegistryCallback routine, and I think the XP version is the most simple one to fully undestand the principles behind the function. There are some differencies between XP and 7 versions, but I think you’ll be able to fully understand 7 structure too! Here is the disassembled function (without useless parts of course):

487E6B  push   'bcMC'                          ; Pool Tag: "CMcb"
487E70  xor    ebx, ebx
487E72  push   38h                             ; NumberOfBytes: 0x38
487E74  inc    ebx
487E75  push   ebx                             ; PoolType: PAGEDPOOL
487E76  call   ExAllocatePoolWithTag           ; ExAllocatePoolWithTag(x,x,x): allocates pool memory
487E7B  mov    esi, eax                        ; eax is the pointer to the allocated pool memory, PCM_CALLBACK_CONTEXT_BLOCK
487E7D  xor    edi, edi
487E7F  cmp    esi, edi                        ; Is PCM_CALLBACK_CONTEXT_BLOCK a NULL pointer?
487E81  jz     cmRegisterCallback_fails        ; yes: function fails...
487E87  push   esi
487E88  push   [ebp+Function]                  ; PEX_CALLBACK_FUNCTION, pointer to callback function
487E8B  call   _ExAllocateCallBack             ; allocates and fill EX_CALLBACK_ROUTINE_BLOCK structure (more on this later...)
487E90  cmp    eax, edi                        ; ExAllocateCallback success or not?
487E92  mov    [ebp+PEX_CALLBACK_ROUTINE_BLOCK], eax ; store the pointer to the allocated pool memory
487E95  jnz    short _ExAllocateCallBack_success
   ...                                         ; fill CM_CALLBACK_CONTEXT_BLOCK fields
487EDC  mov    ebx, offset CmpCallBackVector
487EE1  mov    [ebp+i], edi                    ; i = 0
487EE4 try_next_slot:
487EE4  push   edi                             ; OldBlock: NULL
487EE5  push   [ebp+PEX_CALLBACK_ROUTINE_BLOCK] ; NewBlock with information to add
487EE8  push   ebx                             ; CmpCallbackVector[i]
487EE9  call   _ExCompareExchangeCallBack   ; try to *insert* the new callback inside CmpCallBack vector
487EEE  test   al, al                       ;check the result...
487EF0  jnz    short free_slot_has_been_found    ; jump if the vector has an empty space for the new entry
487EF2  add    [ebp+i], 4                      ; i++, increase the counter
487EF6  add    ebx, 4                          ; shift to the next item of the vector to check
487EF9  cmp    [ebp+i], 190h                   ; is the end of the vector? 
487F00  jb     short try_next_slot             ; no: try another one. yes: no free slot!
   ...    
487F11 cmRegisterCallback_fails:
487F11  mov    eax, STATUS_INSUFFICIENT_RESOURCES
487F16 end_CmRegisterCallback:
   ...
487F1A  retn   0Ch
   ... 
487F1D free_slot_has_been_found:
487F1D  mov    eax, 1
487F22  mov    ecx, offset _CmpCallBackCount   ; CmpCallBackCount: number of not NULL item inside the vector
487F27  xadd   [ecx], eax                      ; there's a new callback, it increases the number of item inside the vector
487F2A  xor    eax, eax
487F2C  jmp    short end_CmRegisterCallback




As you can see the idea behind the function is really simple!
Basically, it tries to add a new entry inside a vector named CmpCallBackVector, and when the entry is correctly inserted the registration process will end with a success.
How do I know is it using a vector? The add instruction at 0x487EF6 represents a clear clue, and the cmp at 0x487EF9 reveals the fixed length of the vector (the vector has 100 items (0×190/4…)). Now that I have this information I’m going to try to explain the entire procedure in detail. The algorithm could be divided into 5 big blocks:

1: try to allocate 0×38 bytes for a structure named CM_CALLBACK_CONTEXT_BLOCK
2: try to allocate 0x0C bytes for a structure named EX_CALLBACK_ROUTINE_BLOCK
3: fill CM_CALLBACK_CONTEXT_BLOCK fields
4: look for an empty slot, insert a sort of PEX_CALLBACK_ROUTINE_BLOCK in it and update CmpCallBackCount
5: notify success or error and exit

Point #1 is pretty simple to understand, it’s only a call to ExAllocatePoolWithTag.

To understand point #2 you have to see what’s going on behind ExAllocateCallBack procedure. Let’s start taking a look at it:

52AB35  push   'brbC'                              ; Pool Tag: Cbrb
52AB3A  push   0Ch                                 ; NumberOfBytes: 0x0C
52AB3C  push   1                                   ; PoolType: PAGED_POOL
52AB3E  call   ExAllocatePoolWithTag               ; alloc a EX_CALLBACK_ROUTINE_BLOCK structure
52AB43  test   eax, eax                            ; ExAllocatePoolWithTag success or not?
52AB45  jz     short _ExAllocateCallBack_fails
52AB47  mov    ecx, [ebp+_pex_callback_function]   ; pointer to callback function (PEX_CALLBACK_FUNCTION)
52AB4A  and    dword ptr [eax], 0                  ; 1° field: 0
52AB4D  mov    [eax+4], ecx                        ; 2° field: _pex_callback_function
52AB50  mov    ecx, [ebp+_pool_allocated_memory]   ; PCM_CALLBACK_CONTEXT_BLOCK
52AB53  mov    [eax+8], ecx                        ; 3° field: _pcm_callback_context_block
52AB56 _ExAllocateCallBack_fails:
   ...




The procedure is used to allocate and fill a special structure:

typedef struct _EX_CALLBACK_ROUTINE_BLOCK
{
EX_RUNDOWN_REF RundownProtect;
PEX_CALLBACK_FUNCTION Function;
PCM_CALLBACK_CONTEXT_BLOCK Context;
} EX_CALLBACK_ROUTINE_BLOCK, *PEX_CALLBACK_ROUTINE_BLOCK;

As you can see from the lines above the first field has been setted to 0 while the other fields are filled with two pointers: the function to register and the context containing info about the callback.

While point #3 is just a series of mov instructions used to fill CM_CALLBACK_ROUTINE_BLOCK structure, point #4 gives some usefull information to us: CmpCallBackVector has 100 elements and this part of code is used to scan the entire vector until an empty element is found. A failure leads us to a non-registration of the callback. What happens when there’s a empty slot inside the vector? The new entry will be added inside the vector. Most of the job is done by the function named ExCompareExchangeCallBack, here is the core of the function:

52AB81  mov    eax, [ebp+CmpCallbackVector]    ; vector at the current position
52AB84  mov    ebx, [eax]                      ; ebx is a PEX_CALLBACK_ROUTINE_BLOCK, the item could be NULL or not
52AB86  mov    eax, ebx
52AB88  xor    eax, [ebp+OldBlock]             ; OldBlock is NULL for a registration process
52AB8B  mov    [ebp+current_pex_callback_routine_block], ebx
52AB8E  cmp    eax, 7                          ; check used to see if the current item is NULL or not
52AB91  ja     short loc_52ABB5                ; jump if not NULL
52AB93  test   esi, esi                        ; is NewBlock NULL?
52AB95  jz     short loc_52ABA1                ; jump if it's NULL
52AB97  mov    eax, esi                        ; esi, NewBlock pointer (changed...)
52AB99  or     eax, 7                          ; PAY ATTENTION HERE: or 7 !?!
52AB9C  mov    [ebp+NewBlock], eax             ; change NewBlock pointer: NewBlock = NewBlock OR 7
52AB9F  jmp    short loc_52ABA5
   ...
52ABA5 mov    eax, [ebp+var_4]               ; here if CmpCallbackVector's item is null
52ABA8  mov    ecx, [ebp+CmpCallbackVector]    ; current empty slot
52ABAB  mov    edx, [ebp+NewBlock]             ; new pointer to insert
52ABAE  cmpxchg [ecx], edx                     ; insert the new pointer inside the empty slot!
52ABB1 cmp    eax, ebx
52ABB3 jnz    short loc_52AB81
52ABB5 and    ebx, not 7                     ; PAY ATTENTION HERE!
52ABB8 cmp    ebx, [ebp+OldBlock]            ; here if CmpCallbackVector's item is not null
52ABBB jnz    short loc_52AC19
52ABBD test   ebx, ebx
52ABBF jz     short loc_52AC15




The routine contains some more things inside, but we can stop here with the analysis because we have everything we need. If the pointer to the NewBlock to insert is not NULL and there’s an available empty slot the pointer is inserted inside the vector; after that CmpCallBackCount value will be updated (remember the snippet at the beginning of this blog entry?).

The last part of the algorithm (point #5) is a simple return with a success or insuccess value:

52AC15 mov    al, 1                          ; 1 means success, new item has been added to CmpCallbackVector
52AC17 jmp    short loc_52AC29
52AC19 test   esi, esi                      ; esi -> NewBlock 
52AC1B jz     short loc_52AC27
52AC1D push   8                       
52AC1F pop    edx
52AC20 mov    ecx, esi
52AC22 call   ExReleaseRundownProtectionEx   ; if esi is not null something went wrong...
52AC27 xor    al, al                         ; 0 means insuccess, new item has not been added to CmpCallbackVector




Ok, I think we have a general idea about the vector; each entry contains a *sort* of pointer to a EX_CALLBACK_ROUTINE_BLOCK, and to reveal all of them you only have to scan the entire vector!

To sum up, I have 3 possible scenes:
1. CmpCallbackVector’s item is empty:
the new block will be inserted inside the vector. The added value is not the one passed to ExCompareExchangeCallBack, but it’s the value modified by a “OR 7″ logic operation.
2. CmpCallbackVector’s item is full:
it simply returns STATUS_INSUCCESS and it will try with the next item of the vector
3. Someone is working on the CmpCallbackVector’s item:
the registration process reveals an interesting behaviour, just to be sure to be the only one accessing the resource the system uses a lock mechanism. The OR and AND operations are the core of that mechanism (0x52AB99 and 0x52ABB5, commented using “PAY ATTENTION HERE!”). If the current item of the vector is not NULL the compare instruction at 0x52AB8E fails and the code flow continues from 0x52ABB5. At this point the real address of the item is extracted (stored_value AND NOT 7) and compared with NULL; it’s obviously not NULL and as you can see around 0x52AC22 the resource is released because someone else is working on it. Now you should understand why the hell the system uses to OR by 7 the value to add inside the vector.

With all this kind of information I can finally write a routine able to read all the stored callbacks:

cells = 0x64;                    // cells inside CmpCallbackVector
nMod = *(DWORD*)_sysmodBuffer;   //	_sysmodBuffer filled by "ZwQuerySystemInformation(SystemModuleInformation..."
for(i=0;i<cells;i++)
{
   // take current item from CmpCallbackVector (look at the "& ~7" operation)
   pCBRB = (PEX_CALLBACK_ROUTINE_BLOCK)((*(DWORD*)(_CmpCallbackVectorAddress + 4*i )) & ~7);
   if (pCBRB != 0)
   {
      sysmodTmp = (PSYSTEM_MODULE_INFORMATION)((DWORD)_sysmodBuffer + 4);
      j = 0;
      while (jFunction) Base + (DWORD)sysmodTmp->Size) &&
			((DWORD)pCBRB->Function) > ((DWORD)sysmodTmp->Base))
         {
            // Callback has been found
            DbgPrint("Result: %LX: %s\r\n", pCBRB->Function, sysmodTmp->ImageName);
            break;
	 }
	 // get the next module
	 sysmodTmp = (PSYSTEM_MODULE_INFORMATION)((DWORD)sysmodTmp + sizeof(SYSTEM_MODULE_INFORMATION));
	 j = j + 1;
    }
}




It’s important to scan all the cells inside the vector! One of the tool available on the web fails to retrieve callbacks stored after an empty element of the vector.

Well, the only thing to reveal about the code above is CmpCallbackVectorAddress, the address of CmpCallBackVector. How can I locate the exact address of CmpCallBackVector? Imho, that’s the hardest part of the entire process!



How to find CmpCallbackVector address
To develop a tool for a specific OS is pretty easy because the vector’s address is hardcoded; it would be nice to discover an OS independent technique.
I think the most used approach is a byte-search based on a specific sequence of bytes; it’s a nice idea but I don’t want to list every OS version known to man inside my source code. We (I and kayaker) spent a lot of time over this point, we both wanted to develop something that is not totally related to a specific OS version; something that doesn’t require a series of “if OS == xxx” statements inside the code. It’s quite impossible to write a non OS dependent code but I believe it’s possible to remove some OS checks from the code.

We finally came up with two ideas, a practical and a theoretical idea. I hate theory and mine is the practical solution of course. I think both ideas are valid and just to be sure to find the right vector’s address we decided to combine them inside a hypothetical tool, four eyes are always better than two!



The practical approach
My idea is really simple, since of the vector’s address is hardcoded you’ll surely have it in two different parts of the code:

PAGE:005392D0   BB 20 05 48 00   mov    ebx, offset _CmpCallBackVector
.data:00480520                   _CmpCallBackVector db    0




The address is inside two sections, PAGE and data. An *xref-search* is the core of the idea! It’s pretty stupid indeed, but from what I’ve seen so far it works!
The pseudo code of my xref search is explained here, basically it scans the entire PAGE section trying to locate the right address:

callbackAddress = CmUnregisterCallback address in memory
pagePointer = pointer_to_PAGE_section
while (pagePointer < pointer_to_PAGE_section + size_of_PAGE_section)   
{
   value = get dword pointed by pagePointer
   if (value is inside DATA section)
      if ((pagePointer > callbackAddress) && (pagePointer < callbackAddress + range))   
      {
         CmpCallbackVector = value
	 exit!
      }
   pagePointer++      
}




As you can imagine a simple xref-search is unable to find out the right value, you need one more check. That’s why I added the line:

if ((pagePointer > callbackAddress) && (pagePointer < callbackAddress + range))   




where callbackAddress is the address of CmUnregisterCallback. What does it mean? Well, ‘pagePointer’ should be inside the first “range” bytes of CmUnregisterCallback function. If both “if” statements are satisfied I’m pretty sure about the vector’s address value.

There are still 2 points to clarify:
- what's range variable?
- why CmUnregisterCallback?

range is just a numerical value and you'll only have to decide a value to assign to it. Under XP the first bytes of the CmUnregisterCallback function are:

PAGE:005392C3 8B FF           mov    edi, edi
PAGE:005392C5 55              push   ebp
PAGE:005392C6 8B EC           mov    ebp, esp
PAGE:005392C8 51              push   ecx
PAGE:005392C9 83 65 FC 00     and    [ebp+var_4], 0
PAGE:005392CD 53              push   ebx
PAGE:005392CE 56              push   esi
PAGE:005392CF 57              push   edi
PAGE:005392D0 BB 20 05 48 00  mov    ebx, offset _CmpCallBackVector




In this specific case 16 could be a possible value… What about the other OSs? Well, as I said before I think it's hard to write a universal piece of code, but as far as I have seen it's possible to adjust the "range" to cover some more OSs. I don't have Vista and 7 running on my system and I'm working on the dead list only, but I think 148 could be a nice value to set and it should cover all the OSs. If you are still reading and you have Vista or 7, can you confirm that?
One more thing about the search pattern: I use CmUnregisterCallback because (inspecting all the OSs) CmRegisterCallback doesn't always store the CmpCallbackVector value inside the main routine, but it hides it under some calls. i.e. look at CmRegisterCallback from 7:

PAGE:0065712A mov  edi, edi
PAGE:0065712C push ebp
PAGE:0065712D mov  ebp, esp
PAGE:0065712F push [ebp+Cookie]
PAGE:00657132 mov  eax, offset stru_4FFDF0
PAGE:00657137 push 1
PAGE:00657139 push [ebp+Context]
PAGE:0065713C push [ebp+Function]
PAGE:0065713F call sub_657153                 ; It's everything inside this call!!!
PAGE:00657144 pop  ebp
PAGE:00657145 retn 0Ch




It’s much more complex to attack a procedure with sub-routines, don't you think? That's why I did opt for CmUnregisterCallback.



What about the PsSet* functions?
At the beginning of this blog post I mentioned some more functions, it's time to spend some words for them too.

The functions are:
PsSetCreateProcessNotifyRoutine
PsSetCreateThreadNotifyRoutine
PsSetLoadImageNotifyRoutine

There are some similarities between CmRegisterCallback and the new three functions: they all register something, they all use a vector to store the information, and they all use the same function! YES, to register a function they use the same scheme:

1. get the address of a specific vector
2. try to insert the new item inside the vector calling ExCompareExchangeCallBack

Just to clarify everything look at this snippet, taken from PsSetCreateThreadNotifyRoutine:

4ED7C4  mov    esi, offset _threadVector   ; the vector
4ED7C9  push   0
4ED7CB  push   ebx
4ED7CC  push   esi
4ED7CD  call   _ExCompareExchangeCallBack   ; the function
4ED7D2  test   al, al
4ED7D4  jnz    short loc_4ED7F3
4ED7D6  add    edi, 4
4ED7D9  add    esi, 4
4ED7DC  cmp    edi, 20h   ; the check over the number of items inside the vector
4ED7DF  jb     short loc_4ED7C9




The only different thing is the length of the vector:
_callbackVector: 0×64 slots
_processVector: 0×8 slots
_threadVector: 0×8 slots
_imageVector: 0×8 slots

Well, you can use all the info I gave you about CmRegisterCallback for these three functions too! I think you'll be able to retrieve all the hidden callbacks, and -just in case- unregister a callback. There are so many ways from the dirty one (put NULL inside the vector's slot) to the right one (calling the right unregister function)… you only have to decide!

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&#8221;
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…

While I was trying the code by Joachim Bauch I noticed a strange behaviour loading user32.dll. The test program I’m using to do some tests crashes with an eccess violation error on a portion of memory virtually loaded at runtime.

For those who has not read the article I present a quick sum up of the technique, focusing on the necessary steps only:
1. allocate the necessary bytes required to store all the bytes of the dll
2. copy the original dll bytes inside the new allocated memory buffer
3. perform base relocation adjusting the necessary references
4. call DllEntryPoint directly from the new allocated buffer
5. when you don’t need the dll anymore it frees the allocated buffer

The error occours when the buffer is completely deallocated. The technique seems to be right but the question arises: why the hell someone needs to access an address inside a deallocated memory?

The problem is not strictly related with Joachim’s code itself, it’s an error caused by the use of user32.dll! At the moment I haven’t tried all the system dll, but if you understand the problem I’m pretty sure you’ll be able to solve it with another dll involved.

I have all the source code in front of me but when the problem is not totally related with it I prefer to use a debugger approach.

When the exception occours your debugger breaks here:

7C91E464 MOV EAX,DWORD PTR FS:[18] ; TEB
7C91E46A MOV EAX,DWORD PTR DS:[EAX+30] ; PEB
7C91E46D MOV EAX,DWORD PTR DS:[EAX+2C] ; PEB.KernelCallbackTable
7C91E470 CALL DWORD PTR DS:[EAX+EDX*4] ; call dword ptr [0xB72A10], access violation occours here!

The address (0xB72A10) is inside the allocated buffer, it’s obviously an entry of a vector. EAX represents the starting address of the vector and EDX is an index, each dword is an element of the vector. Starting address is 0xB72970, I only have to understand what’s behind that address.

Load user32.dll inside IDA and look at the vector, the xref will bring you inside DllEntryPoint:

7E39B3F6 mov eax, large fs:18h ; TEB
7E39B3FC mov eax, [eax+30h] ; PEB
7E39B3FF mov eax, [eax+18h] ; PEB.ProcessHeap
7E39B402 mov hHeap, eax
7E39B407 mov eax, large fs:18h
7E39B40D mov eax, [eax+30h]
7E39B410 mov dword ptr [eax+2Ch], offset off_7E392970 ; PEB.KernelCallbackTable

Can you see where the problem is? No!?! Ok, take a look at the same code that has been copied inside the allocated buffer (base relocation performed!):

00B7B3F6 MOV EAX,DWORD PTR FS:[18]
00B7B3FC MOV EAX,DWORD PTR DS:[EAX+30]
00B7B3FF MOV EAX,DWORD PTR DS:[EAX+18]
00B7B402 MOV DWORD PTR DS:[BD1224],EAX
00B7B407 MOV EAX,DWORD PTR FS:[18]
00B7B40D MOV EAX,DWORD PTR DS:[EAX+30]
00B7B410 MOV DWORD PTR DS:[EAX+2C],0B72970 <-- look here!!!

At the beginning of user32.dll there’s a particular initialization, it involves the heap and the KernelCallbackTable address. Both values are changed according to the new image base address but they will not be changed back to the old values.
If you don’t want an access violation inside your program you’ll have to restore the old values, nothing else…

The conclusion is simple, the code is perfectly right but it may be prone to this kind of weird conceptual bug… pay attention when you load a system dll!

Next Page »

Follow

Get every new post delivered to your Inbox.