Write-up - RSSIL 2011 - RCE chimay_rouge

by @Jonathan Salwan - 2011-05-29

Classical reverse in Linux x86-64 bits. We need to found the good serial.

First glimpse

jonathan@pentest [RSSIL] $ file ./chimay_rouge 
chimay_rouge: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked 
(uses shared libs), for GNU/Linux 2.6.18, not stripped
jonathan@pentest [RSSIL] $ ./chimay_rouge 
serial : test
FAIL !
jonathan@pentest [RSSIL] $

Let's go, we open gdb and we begin to reverse the binary.

(gdb) disass main
Dump of assembler code for function main:
   [...]
   0x000000000040072f <+54>:    mov    $0x4008d5,%eax          {0x4008d5: "serial : "}
   0x0000000000400734 <+59>:    mov    %rax,%rdi
   0x0000000000400737 <+62>:    mov    $0x0,%eax
   0x000000000040073c <+67>:    callq  0x400530 <printf@plt>   <= on affiche "serial : "
   0x0000000000400741 <+72>:    mov    $0x4008df,%eax          {0x4008df: "%25s"}
   0x0000000000400746 <+77>:    lea    -0x20(%rbp),%rdx
   0x000000000040074a <+81>:    mov    %rdx,%rsi
   0x000000000040074d <+84>:    mov    %rax,%rdi
   0x0000000000400750 <+87>:    mov    $0x0,%eax
   0x0000000000400755 <+92>:    callq  0x400580 <__isoc99_scanf@plt> <= calls scanf() 
   0x000000000040075a <+97>:    lea    -0x20(%rbp),%rax         
   0x000000000040075e <+101>:   mov    %rax,%rdi
   0x0000000000400761 <+104>:   callq  0x400570 <strlen@plt> <= calls strlen on serial 
   0x0000000000400766 <+109>:   cmp    $0x18,%rax            <= compares the serial with 0x18
   0x000000000040076a <+113>:   je     0x400780 <main+135>   <= if equal, we jump on main+135
   0x000000000040076c <+115>:   mov    $0x4008e4,%edi           {0x4008e4: "FAIL !"}
   0x0000000000400771 <+120>:   callq  0x400540 <puts@plt>         
   0x0000000000400776 <+125>:   mov    $0x1,%edi                        
   0x000000000040077b <+130>:   callq  0x400550 <exit@plt>    <= exit(1)
   0x0000000000400780 <+135>:   lea    -0x20(%rbp),%rax
   [...]

Now, we know that the serial need to be 24 characters.

0x0000000000400780 <+135>:  lea    -0x20(%rbp),%rax
0x0000000000400784 <+139>:  mov    %rax,%rdi
0x0000000000400787 <+142>:  callq  0x400684 <chiffre>
0x000000000040078c <+147>:  lea    -0x40(%rbp),%rcx
0x0000000000400790 <+151>:  lea    -0x20(%rbp),%rax
0x0000000000400794 <+155>:  mov    $0x18,%edx
0x0000000000400799 <+160>:  mov    %rcx,%rsi
0x000000000040079c <+163>:  mov    %rax,%rdi
0x000000000040079f <+166>:  callq  0x400590 <memcmp@plt>
0x00000000004007a4 <+171>:  test   %eax,%eax

Then, we encode the serial and compares it with memcmp(). We found a interesting function called chiffre(), so we reverse it.

Below the function wich decrypt the serial.

0x00000000004006be <+58>:   jmp    0x4006f1 <chiffre+109>
0x00000000004006c0 <+60>:   mov    -0x4(%rbp),%eax
0x00000000004006c3 <+63>:   cltq   
0x00000000004006c5 <+65>:   add    -0x28(%rbp),%rax
0x00000000004006c9 <+69>:   mov    -0x4(%rbp),%edx
0x00000000004006cc <+72>:   movslq %edx,%rdx
0x00000000004006cf <+75>:   add    -0x28(%rbp),%rdx
0x00000000004006d3 <+79>:   movzbl (%rdx),%ecx
0x00000000004006d6 <+82>:   mov    -0x4(%rbp),%edx
0x00000000004006d9 <+85>:   lea    (%rcx,%rdx,1),%edx
0x00000000004006dc <+88>:   mov    %edx,%ecx
0x00000000004006de <+90>:   mov    -0x4(%rbp),%edx
0x00000000004006e1 <+93>:   movslq %edx,%rdx
0x00000000004006e4 <+96>:   movzbl -0x20(%rbp,%rdx,1),%edx
0x00000000004006e9 <+101>:  xor    %ecx,%edx
0x00000000004006eb <+103>:  mov    %dl,(%rax)
0x00000000004006ed <+105>:  addl   $0x1,-0x4(%rbp)
0x00000000004006f1 <+109>:  cmpl   $0x17,-0x4(%rbp)
0x00000000004006f5 <+113>:  jle    0x4006c0 <chiffre+60>

We put a breakpoint on "<+101>: xor %ecx,%edx" and see what's going on and recover the clef.

(gdb) b* 0x00000000004006e9
Breakpoint 2 at 0x4006e9
(gdb) r
Starting program: /home/jonathan/RSSIL/chimay_rouge 
serial : aaaaaaaaaaaaaaaaaaaaaaaa

Breakpoint 2, 0x00000000004006e9 in chiffre ()
(gdb) i r $edx $ecx
edx            0xf4 244 {key[0]}
ecx            0x61 97  {a}
(gdb) c
Continuing.

Breakpoint 2, 0x00000000004006e9 in chiffre ()
(gdb) i r $edx $ecx
edx            0x86 134 {key[1]}
ecx            0x62 98  {b}
(gdb) c
Continuing.

Breakpoint 2, 0x00000000004006e9 in chiffre ()
(gdb) i r $edx $ecx
edx            0x95 149 {key[2]}
ecx            0x63 99  {c}
(gdb)

%edx contains the key and %ecx our character. Below, the key which is used for uncrypt our string.

char key[] = "\xf4\x86\x95\x5d\x52\xb9\x97\x95\x0e\x6d\x67\x4d\x11\xcf\x7d\xdb\x51\x38\x00\x2c\x1d\x65\xa5\x4d";

Now, we need to know what's going on with memcmp() to know which is the good serial.

0x0000000000400799 <+160>:  mov    %rcx,%rsi
0x000000000040079c <+163>:  mov    %rax,%rdi
0x000000000040079f <+166>:  callq  0x400590 <memcmp@plt>

(gdb) b *0x000000000040079f
Breakpoint 3 at 0x40079f
(gdb) r
Starting program: /home/jonathan/RSSIL/chimay_rouge 
serial : aaaaaaaaaaaaaaaaaaaaaaaa

Breakpoint 3, 0x000000000040079f in main ()
(gdb) i r $rsi $rdi
rsi            0x7fffffffea90   140737488349840
rdi            0x7fffffffeab0   140737488349872
(gdb) x/s 0x7fffffffea90
0x7fffffffea90:  "\267\267\345\067$\200\355\024i\020\065\071n\243*Y>\275zjn\345\354="
(gdb) x/s 0x7fffffffeab0
0x7fffffffeab0:  "\225\344\366\071\067\337\360\375g\a\f!|\241\022\253 JsXh\023\322\065"
(gdb)

Simple xor with the string for know what is the good serial.

hex((0xf4 ^ 0xb7) - 0)
hex((0x86 ^ 0xb7) - 1)
hex((0x95 ^ 0xe5) - 2)
hex((0x5d ^ 0x37) - 3)
hex((0x52 ^ 0x24) - 4)
hex((0xb9 ^ 0x80) - 5)
hex((0x97 ^ 0xed) - 6)
hex((0x95 ^ 0x14) - 7)
hex((0x0e ^ 0x69) - 8)
hex((0x6d ^ 0x10) - 9)
hex((0x67 ^ 0x35) - 10)
hex((0x4d ^ 0x39) - 11)
hex((0x11 ^ 0x6e) - 12)
hex((0xcf ^ 0xa3) - 13)
hex((0x7d ^ 0x2a) - 14)
hex((0xdb ^ 0x59) - 15)
hex((0x51 ^ 0x3e) - 16)
hex((0x38 ^ 0xbd) - 17)
hex((0x00 ^ 0x7a) - 18)
hex((0x2c ^ 0x6a) - 19)
hex((0x1d ^ 0x6e) - 20)
hex((0x65 ^ 0xe5) - 21)
hex((0xa5 ^ 0xec) - 22)
hex((0x4d ^ 0x3d) - 23)

jonathan@pentest [RSSIL] $ echo -e "\x43\x30\x6e\x67\x72\x34\x74\x7a\x5f\x74\x48\x69\x73
\x5f\x49\x73\x5f\x74\x68\x33\x5f\x6b\x33\x59"
C0ngr4tz_tHis_Is_th3_k3Y
jonathan@pentest [RSSIL] $ echo -n "C0ngr4tz_tHis_Is_th3_k3Y" | ./chimay_rouge 
serial : Bravo vous pouvez valider

The key is C0ngr4tz_tHis_Is_th3_k3Y