I participated in this years Metasploit’s community ctf with Snadoteam we finished all but 2 of the challenges finishing fifth overall.

One of the most interesting challenges was definitely 10 of Diamonds being the “hardest” RE challenge in the ctf.

We found the 10_of_diamonds.exe in the home directory of the administrator on the windows box. Running file on it reveals that it is a MS-DOS executable, no surprise there.

Therefore i moved it over to my reverse engineering vm, Windows Defender sadly didn’t enjoy the new file on the filesystem and promptly deleted it. Because of this I decided to upload it to virustotal to see if it recognized the “malware”.

As we can see most of the hits are based on heuristics so the program is probably just doing some funky memory stuff. Quite curious I opened it in Radare

Huh

As we can see there is definitively something funky going on. A lot of functions are of the same length and there is one huge function at offset 0x00401337. The flag format for this ctf where png images so I made a educated guess that function did something related to the image and that the image was embedded into the executable somehow

Based on that i ran binwalk without any success on the file.

Since the only function called before the “main” function is the function.00491b63 I decided to take a look at it.

:S 

As we can see this pops the function address of from the stack after pushing it (call) and inserts that into eax then it ads another constant to that.

This overflows eax leaving us with a function that returns 0x491b63 any god fearing compiler would never have done some thing like this therefore I decided to move the file back into my vm and check if DIE recognized any type of packer/linker

DIE only recognized that there was some kind of linker which is something I already suspected. Based on this I decided to take a look at entry0 which is the entry point of the binary

            ;-- eip:
/ (fcn) entry0 462
| entry0 ();
| ; var int local_38h @ ebp-0x38
| ; var int local_34h @ ebp-0x34
| ; var int argc @ ebp-0x30
| ; var int local_2ch @ ebp-0x2c
| ; var int local_28h @ ebp-0x28
| ; var int local_24h @ ebp-0x24
| ; var unsigned int local_20h @ ebp-0x20
| ; var int local_1ch @ ebp-0x1c
| ; var int local_18h @ ebp-0x18
| ; var unsigned int local_14h @ ebp-0x14
| ; var int local_10h @ ebp-0x10
| ; var int local_ch @ ebp-0xc
| ; var int local_8h @ ebp-0x8
| ; var int local_4h @ ebp-0x4
| 0x00491995 55 push ebp
| 0x00491996 89e5 mov ebp, esp
| 0x00491998 83ec3c sub esp, 0x3c ; '<'
| 0x0049199b 56 push esi
| 0x0049199c e8c2010000 call fcn.00491b63
| 0x004919a1 89c6 mov esi, eax
| 0x004919a3 8d86867d0600 lea eax, [esi + 0x67d86]
| 0x004919a9 8945f4 mov dword [local_ch], eax
| 0x004919ac c745f8000000. mov dword [local_8h], 0
| 0x004919b3 8d8e877d0600 lea ecx, [esi + 0x67d87]
| 0x004919b9 894dfc mov dword [local_4h], ecx
| 0x004919bc c745f09563ca. mov dword [local_10h], 0xca6395
| 0x004919c3 8b55f0 mov edx, dword [local_10h]
| 0x004919c6 85d2 test edx, edx
| ,=< 0x004919c8 0f8407000000 je 0x4919d5
| | 0x004919ce c745f0198420. mov dword [local_10h], 0x3208419
| | ; CODE XREF from entry0 (0x4919c8)
| `-> 0x004919d5 8d45f4 lea eax, [local_ch]
| 0x004919d8 50 push eax
| 0x004919d9 e880fdffff call fcn.0049175e
| 0x004919de 83c404 add esp, 4
| 0x004919e1 8945ec mov dword [local_14h], eax
| 0x004919e4 837dec00 cmp dword [local_14h], 0
| ,=< 0x004919e8 0f841d000000 je 0x491a0b
| | 0x004919ee e870010000 call fcn.00491b63
| | 0x004919f3 89c6 mov esi, eax
| | 0x004919f5 8d86887d0600 lea eax, [esi + 0x67d88]
| | 0x004919fb 50 push eax ; int argc
| | 0x004919fc e8d2010000 call main ; int main(int argc, char **argv, char** envp)
| | 0x00491a01 b801000000 mov eax, 1
| ,==< 0x00491a06 e953010000 jmp 0x491b5e
| || ; CODE XREF from entry0 (0x4919e8)
| |`-> 0x00491a0b c745e8fffa04. mov dword [local_18h], 0x4faff
| | 0x00491a12 c745e40f59c1. mov dword [local_1ch], 0x3c1590f
| | 0x00491a19 8b45e4 mov eax, dword [local_1ch]
| | 0x00491a1c 8945e0 mov dword [local_20h], eax
| | 0x00491a1f 817de0bd5390. cmp dword [local_20h], 0x19053bd
| |,=< 0x00491a26 0f8405000000 je 0x491a31
| ,===< 0x00491a2c e90c000000 jmp 0x491a3d
| ||| ; CODE XREF from entry0 (0x491a26)
| ||`-> 0x00491a31 c745e4760177. mov dword [local_1ch], 0x770176
| ||,=< 0x00491a38 e900000000 jmp 0x491a3d
| ||| ; CODE XREFS from entry0 (0x491a2c, 0x491a38)
| `-`-> 0x00491a3d 6a04 push 4 ; 4
| | 0x00491a3f 6800100000 push 0x1000
| | 0x00491a44 ff75e8 push dword [local_18h]
| | 0x00491a47 6a00 push 0
| | 0x00491a49 e89b010000 call fcn.00491be9
| | 0x00491a4e 8945dc mov dword [local_24h], eax
| | 0x00491a51 c745d894b53b. mov dword [local_28h], 0x13bb594
| | 0x00491a58 ff75e8 push dword [local_18h]
| | 0x00491a5b 6a00 push 0
| | 0x00491a5d ff75dc push dword [local_24h]
| | 0x00491a60 e858010000 call fcn.00491bbd
| | 0x00491a65 83c40c add esp, 0xc
| | 0x00491a68 ff75dc push dword [local_24h]
| | 0x00491a6b e8c7f8f6ff call fcn.00401337
| | 0x00491a70 83c404 add esp, 4
| | 0x00491a73 e8eb000000 call fcn.00491b63
| | 0x00491a78 89c6 mov esi, eax
| | 0x00491a7a 8d86a97d0600 lea eax, [esi + 0x67da9]
| | 0x00491a80 50 push eax
| | 0x00491a81 ff75fc push dword [local_4h]
| | 0x00491a84 e813010000 call fcn.00491b9c
| | 0x00491a89 83c408 add esp, 8
| | 0x00491a8c 83f800 cmp eax, 0
| |,=< 0x00491a8f 0f8422000000 je 0x491ab7
| || 0x00491a95 8d86ca7d0600 lea eax, [esi + 0x67dca]
| || 0x00491a9b 50 push eax ; int argc
| || 0x00491a9c e832010000 call main ; int main(int argc, char **argv, char** envp)
| || 0x00491aa1 8d86f97d0600 lea eax, [esi + 0x67df9]
| || 0x00491aa7 50 push eax ; int argc
| || 0x00491aa8 e826010000 call main ; int main(int argc, char **argv, char** envp)
| || 0x00491aad b8ffffffff mov eax, 0xffffffff ; -1
| ,===< 0x00491ab2 e9a7000000 jmp 0x491b5e
| ||| ; CODE XREF from entry0 (0x491a8f)
| ||`-> 0x00491ab7 6a04 push 4 ; 4
| || 0x00491ab9 6800100000 push 0x1000
| || 0x00491abe ff75e8 push dword [local_18h]
| || 0x00491ac1 6a00 push 0
| || 0x00491ac3 e821010000 call fcn.00491be9
| || 0x00491ac8 8945d4 mov dword [local_2ch], eax
| || 0x00491acb ff75e8 push dword [local_18h]
| || 0x00491ace 6a00 push 0
| || 0x00491ad0 ff75d4 push dword [local_2ch]
| || 0x00491ad3 e8e5000000 call fcn.00491bbd
| || 0x00491ad8 83c40c add esp, 0xc
| || 0x00491adb 68fffa0400 push 0x4faff
| || 0x00491ae0 ff75d4 push dword [local_2ch]
| || 0x00491ae3 ff75dc push dword [local_24h]
| || 0x00491ae6 ff75fc push dword [local_4h]
| || 0x00491ae9 e8dbf7f6ff call fcn.004012c9
| || 0x00491aee 83c410 add esp, 0x10
| || 0x00491af1 e86d000000 call fcn.00491b63
| || 0x00491af6 89c6 mov esi, eax
| || 0x00491af8 8d861a7e0600 lea eax, [esi + 0x67e1a]
| || 0x00491afe 8945d0 mov dword [argc], eax
| || 0x00491b01 ff75d0 push dword [argc] ; int argc
| || 0x00491b04 e8ca000000 call main ; int main(int argc, char **argv, char** envp)
| || 0x00491b09 6a00 push 0
| || 0x00491b0b 6880000000 push 0x80 ; 128
| || 0x00491b10 6a02 push 2 ; 2
| || 0x00491b12 6a00 push 0
| || 0x00491b14 6a00 push 0
| || 0x00491b16 6800000040 push 0x40000000
| || 0x00491b1b 8d863b7e0600 lea eax, [esi + 0x67e3b]
| || 0x00491b21 50 push eax
| || 0x00491b22 e8d8000000 call fcn.00491bff
| || 0x00491b27 8945c8 mov dword [local_38h], eax
| || 0x00491b2a 6a00 push 0
| || 0x00491b2c 8d45cc lea eax, [local_34h]
| || 0x00491b2f 50 push eax
| || 0x00491b30 68fffa0400 push 0x4faff
| || 0x00491b35 ff75d4 push dword [local_2ch]
| || 0x00491b38 ff75c8 push dword [local_38h]
| || 0x00491b3b e8d5000000 call fcn.00491c15
| || 0x00491b40 e883000000 call fcn.00491bc8
| || 0x00491b45 ff75c8 push dword [local_38h]
| || 0x00491b48 e8bd000000 call fcn.00491c0a
| || 0x00491b4d 8d86447e0600 lea eax, [esi + 0x67e44]
| || 0x00491b53 50 push eax ; int argc
| || 0x00491b54 e87a000000 call main ; int main(int argc, char **argv, char** envp)
| || 0x00491b59 b800000000 mov eax, 0
| || ; CODE XREFS from entry0 (0x491a06, 0x491ab2)
| ``--> 0x00491b5e 5e pop esi
| 0x00491b5f 89ec mov esp, ebp
| 0x00491b61 5d pop ebp
\ 0x00491b62 c3 ret

main is being called multiple times which isn’t exactly normal I therefore decided that radare wasn’t the best tool for the job and opened it up in ida

signed int start()
{
  signed int v0; // esi
  signed int v1; // esi
  signed int result; // eax
  signed int v3; // esi
  signed int v4; // eax
  signed int v5; // esi
  int v6; // ST24_4
  char v7; // [esp+Ch] [ebp-34h]
  int v8; // [esp+10h] [ebp-30h]
  int v9; // [esp+14h] [ebp-2Ch]
  int v10; // [esp+18h] [ebp-28h]
  int v11; // [esp+1Ch] [ebp-24h]
  int v12; // [esp+20h] [ebp-20h]
  int v13; // [esp+24h] [ebp-1Ch]
  int v14; // [esp+28h] [ebp-18h]
  int v15; // [esp+2Ch] [ebp-14h]
  int v16; // [esp+30h] [ebp-10h]
  int v17; // [esp+34h] [ebp-Ch]
  int v18; // [esp+38h] [ebp-8h]
  int v19; // [esp+3Ch] [ebp-4h]

  v0 = sub_491B63();
  v17 = v0 + 425350;
  v18 = 0;
  v19 = v0 + 425351;
  v16 = 52462617;
  v15 = sub_49175E(&v17);
  if ( v15 )
  {
    v1 = sub_491B63();
    sub_491BD3(v1 + 425352);
    result = 1;
  }
  else
  {
    v14 = 326399;
    v13 = 63002895;
    v12 = 63002895;
    v11 = sub_491BE9(0, 326399, 4096, 4);
    v10 = 20690324;
    sub_491BBD(v11, 0, 326399);
    sub_401337(v11);
    v3 = sub_491B63();
    if ( sub_491B9C(v19, v3 + 425385) )
    {
      sub_491BD3(v3 + 425418);
      sub_491BD3(v3 + 425465);
      result = -1;
    }
    else
    {
      v9 = sub_491BE9(0, v14, 4096, 4);
      sub_491BBD(v9, 0, v14);
      sub_4012C9(v19, v11, v9, 326399);
      v4 = sub_491B63();
      v5 = v4;
      v8 = v4 + 425498;
      sub_491BD3(v4 + 425498);
      v6 = sub_491BFF(v5 + 425531, 0x40000000, 0, 0, 2, 128, 0);
      sub_491C15(v6, v9, 326399, &v7, 0);
      sub_491BC8();
      sub_491C0A(v6);
      sub_491BD3(v5 + 425540);
      result = 0;
    }
  }
  return result;
}

as we can se the deassembled code doesn’t make much sense which is expected as ida isn’t able to recognize exactly what is being called. Fortunately it knows what is getting imported

2

Does those offsets seem familiar ? Based on this I decided to try to rename all of the function calls programatically, this ended up not working as I wanted to so I decided to go for a manual dynamic  approach.

I also decided to rename the function which returned the constant to ret_[constant] and to rename the big function to gold so that i could keep track of them. After that I sorted the functions based on function size adding a break point at the jmp of each of the tiny functions

Then I ignored ida’s warning and ran the program

At each breakpoint I executed the jmp with the execute each instruction so that i jmped into the function being “called”

After viewing the function name i pressed the return to the calling function and renamed the function call above eip to something similar to the function name

After steeping trough another breakpoint this message was displayed

this happens in the following function called by start

signed int __cdecl sub_48175E(int a1)
{
  signed int v1; // eax
  signed int result; // eax
  int v3; // ST3C_4
  int v4; // [esp+24h] [ebp-14h]
  int v5; // [esp+28h] [ebp-10h]
  int v6; // [esp+2Ch] [ebp-Ch]
  int v7; // [esp+30h] [ebp-8h]
  int v8; // [esp+34h] [ebp-4h]

  v8 = 28856048;
  v7 = 28856048;
  v1 = ret_4791139();
  v6 = createFile(v1 + 425108, 2147483648, 0, 0, 3, 128, 0);
  if ( v6 == -1 )
  {
    v4 = 86806304;
    v5 = 5364207;
    ret_4791139();
    MessageBox();
    result = -1;
  }
  else
  {
    v5 = 21823640;
    v3 = ret_4791139() + 425161;
    sub_481BC8();
    sub_481BC8();
    if ( sub_481644(v6, &v4) == -1 )
    {
      sub_481B7B();
      ret_4791139();
      MessageBox();
      sub_481BD3();
      sub_481C0A(v6);
      sub_481BC8();
      sub_481BC8();
      result = -1;
    }
    else if ( sub_481311(a1, v4) == -1 )
    {
      ret_4791139();
      MessageBox();
      sub_481C0A(v6);
      result = -1;
    }
    else
    {
      ret_4791139();
      sub_481BD3();
      sub_481C0A(v6);
      sub_481BD3();
      result = 0;
    }
  }
  return result;
}

after creating a 10_of_diamonds.key file in the same dir as the program it spat out another message

luckily this brought me trough more of my breakpoints allowing me to rename more of the functions.

Based on this functions behavior and it’s position in start, which is basically the main of this program, I decided to rename it to fileini I then sat a breakpoint right before a conditional jump based on the return value of the function.

Since this function returns 0 only in case of an error while parsing the .key file I knew that the green branch was the one i was intrested in. I therefore forced IDA to follow the green path by right klicking on the first instruction in the greenpath and forcefully setting EIP to that instruction.

After this i returned execution to the program again, it covered some more small functions which I then renamed. Sadly nothing else seemed to happen and the program exited normally. After taking a look at start function again i noticed that there was a conditional jump based on a string compare and a filecreate in case the strings where equal I therefore decided to force the execution to take the green branch as I did before.

I also decided to inspect the local variable which was used in the strcmp and the constant, the local variable was just garbage so nothing of interest, but the constant was 73d3a702db472629f27b06ac8f056476. I kept this in the back of my head. Continuing execution in the way written above

This sadly made the program perform a divide by zero

 

This divide by zero happened in a function that took the local variable as an argument

Based on this i guessed that the local variable was somehow a seed for what was apparently a decoding function. Because of this I decided to break at the push before the strcmp and set it’s value to that of eax which contained the constant string

this made the program take the right branch after the strcmp and after some micro seconds the program exited. I looked excitedly after any new files and lo and behold in the program’s directory there is a new png called flag.png

I want to thank Rapid7 for hosting this ctf, as I poped my first shell on the first metasploitable box I feel a particular connection to ctf’s hosted by them.

I also want to thank snadoteam for allowing me to participate with them