Posts CDDC [Secret Code]
Post
Cancel

CDDC [Secret Code]

This challenge was very weird. Since it was a binary we could download and we were suppose to extract the flag from it, I decided to do use GDB to retrieve the flag.

Running

On the initial run, the output looks like this

1
2
3
4
5
6
7
jason@kali:~/cddc$ ./SecretCode 
         __                                     _           
 / / _   ) )     _   ) o  _ o _)_ _       _    / ` _   _ _  
(_/ ) ) /_/ (_( )_) (  ( (_ ( (_ (_) (_( (    (_. (_) ) )_) 
               (                         _)            (    

[S][E][C][R][E][T] [C][O][D][E]:

Decompilation

The disassembly of the main function seems to compare a local variable with a hardcoded value and calls another function.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
undefined4 main(void)

{
  undefined4 uVar1;
  int in_GS_OFFSET;
  int local_18;
  int local_14;
  undefined *local_10;
  
  local_10 = &stack0x00000004;
  local_14 = *(int *)(in_GS_OFFSET + 0x14);
  local_18 = 0;
  puts("         __                                     _           ");
  puts(" / / _   ) )     _   ) o  _ o _)_ _       _    / ` _   _ _  ");
  puts("(_/ ) ) /_/ (_( )_) (  ( (_ ( (_ (_) (_( (    (_. (_) ) )_) ");
  puts("               (                         _)            (    \n");
  printf("[S][E][C][R][E][T] [C][O][D][E]: ");
  __isoc99_scanf(&DAT_000109b2,&local_18);
  if (local_18 == -0xff23502) {
    check(0xf00dcafe);
  }
  else {
    check(local_18);
  }
  uVar1 = 0;
  if (local_14 != *(int *)(in_GS_OFFSET + 0x14)) {
    uVar1 = __stack_chk_fail_local();
  }
  return uVar1;
}

I ran the binary with gdb and disassemble main.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
(gdb) disas main
Dump of assembler code for function main:
    0x565556f6 <+0>:     lea    0x4(%esp),%ecx
    0x565556fa <+4>:     and    $0xfffffff0,%esp
    0x565556fd <+7>:     pushl  -0x4(%ecx)
    0x56555700 <+10>:    push   %ebp
    0x56555701 <+11>:    mov    %esp,%ebp
    0x56555703 <+13>:    push   %ebx
    0x56555704 <+14>:    push   %ecx
    0x56555705 <+15>:    sub    $0x10,%esp
    0x56555708 <+18>:    call   0x56555500 <__x86.get_pc_thunk.bx>
    0x5655570d <+23>:    add    $0x18bf,%ebx
    0x56555713 <+29>:    mov    %gs:0x14,%eax
    0x56555719 <+35>:    mov    %eax,-0xc(%ebp)
    0x5655571c <+38>:    xor    %eax,%eax
    0x5655571e <+40>:    movl   $0x0,-0x10(%ebp)
    0x56555725 <+47>:    sub    $0xc,%esp
    0x56555728 <+50>:    lea    -0x173c(%ebx),%eax
    0x5655572e <+56>:    push   %eax
    0x5655572f <+57>:    call   0x56555480 <puts@plt>
    0x56555734 <+62>:    add    $0x10,%esp
    0x56555737 <+65>:    sub    $0xc,%esp
    0x5655573a <+68>:    lea    -0x16fc(%ebx),%eax
    0x56555740 <+74>:    push   %eax
    0x56555741 <+75>:    call   0x56555480 <puts@plt>
    0x56555746 <+80>:    add    $0x10,%esp
    0x56555749 <+83>:    sub    $0xc,%esp
    0x5655574c <+86>:    lea    -0x16bc(%ebx),%eax
    0x56555752 <+92>:    push   %eax
    0x56555753 <+93>:    call   0x56555480 <puts@plt>
    0x56555758 <+98>:    add    $0x10,%esp
    0x5655575b <+101>:   sub    $0xc,%esp
    0x5655575e <+104>:   lea    -0x167c(%ebx),%eax
    0x56555764 <+110>:   push   %eax
    0x56555765 <+111>:   call   0x56555480 <puts@plt>
    0x5655576a <+116>:   add    $0x10,%esp
    0x5655576d <+119>:   sub    $0xc,%esp
    0x56555770 <+122>:   lea    -0x163c(%ebx),%eax
    0x56555776 <+128>:   push   %eax
    0x56555777 <+129>:   call   0x56555460 <printf@plt>
    0x5655577c <+134>:   add    $0x10,%esp
    0x5655577f <+137>:   sub    $0x8,%esp
    0x56555782 <+140>:   lea    -0x10(%ebp),%eax
    0x56555785 <+143>:   push   %eax
    0x56555786 <+144>:   lea    -0x161a(%ebx),%eax
    0x5655578c <+150>:   push   %eax
    0x5655578d <+151>:   call   0x565554a0 <__isoc99_scanf@plt>
    0x56555792 <+156>:   add    $0x10,%esp
    0x56555795 <+159>:   mov    -0x10(%ebp),%eax
    0x56555798 <+162>:   cmp    $0xf00dcafe,%eax
    0x5655579d <+167>:   jne    0x565557b0 <main+186>
--Type <RET> for more, q to quit, c to continue without paging--c
    0x5655579f <+169>:   mov    -0x10(%ebp),%eax
    0x565557a2 <+172>:   sub    $0xc,%esp
    0x565557a5 <+175>:   push   %eax
    0x565557a6 <+176>:   call   0x565555fd <check>
    0x565557ab <+181>:   add    $0x10,%esp
    0x565557ae <+184>:   jmp    0x565557bf <main+201>
    0x565557b0 <+186>:   mov    -0x10(%ebp),%eax
    0x565557b3 <+189>:   sub    $0xc,%esp
    0x565557b6 <+192>:   push   %eax
    0x565557b7 <+193>:   call   0x565555fd <check>
    0x565557bc <+198>:   add    $0x10,%esp
    0x565557bf <+201>:   mov    $0x0,%eax
    0x565557c4 <+206>:   mov    -0xc(%ebp),%edx
    0x565557c7 <+209>:   xor    %gs:0x14,%edx
    0x565557ce <+216>:   je     0x565557d5 <main+223>
    0x565557d0 <+218>:   call   0x56555860 <__stack_chk_fail_local>
    0x565557d5 <+223>:   lea    -0x8(%ebp),%esp
    0x565557d8 <+226>:   pop    %ecx
    0x565557d9 <+227>:   pop    %ebx
    0x565557da <+228>:   pop    %ebp
    0x565557db <+229>:   lea    -0x4(%ecx),%esp
    0x565557de <+232>:   ret    
End of assembler dump.

Exploit

I set a breakpoint at address 0x56555798 as it is the comparison. Next, I continued the process and entered a random string as input. When it hit the break point, I ran “set $eax=0xf00dcafe” and disassemble check.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
(gdb) disas check
Dump of assembler code for function check:
   0x565555fd <+0>:     push   %ebp
   0x565555fe <+1>:     mov    %esp,%ebp
   0x56555600 <+3>:     push   %edi
   0x56555601 <+4>:     push   %esi
   0x56555602 <+5>:     push   %ebx
   0x56555603 <+6>:     sub    $0x4c,%esp
   0x56555606 <+9>:     call   0x565557df <__x86.get_pc_thunk.ax>
   0x5655560b <+14>:    add    $0x19c1,%eax
   0x56555610 <+19>:    mov    %eax,-0x54(%ebp)
   0x56555613 <+22>:    mov    %gs:0x14,%eax
   0x56555619 <+28>:    mov    %eax,-0x1c(%ebp)
   0x5655561c <+31>:    xor    %eax,%eax
   0x5655561e <+33>:    movb   $0x0,-0x3d(%ebp)
   0x56555622 <+37>:    movl   $0x43444443,-0x33(%ebp)
   0x56555629 <+44>:    movl   $0x457b3032,-0x2f(%ebp)
   0x56555630 <+51>:    movl   $0x567a7135,-0x2b(%ebp)
   0x56555637 <+58>:    movl   $0x7a347036,-0x27(%ebp)
   0x5655563e <+65>:    movl   $0x6b653b5a,-0x23(%ebp)
   0x56555645 <+72>:    movw   $0x7d73,-0x1f(%ebp)
   0x5655564b <+78>:    movb   $0x0,-0x1d(%ebp)
   0x5655564f <+82>:    movl   $0xdeadbeef,-0x3c(%ebp)
   0x56555656 <+89>:    movl   $0xbabeface,-0x38(%ebp)
   0x5655565d <+96>:    mov    -0x3c(%ebp),%ecx
   0x56555660 <+99>:    sub    -0x38(%ebp),%ecx
   0x56555663 <+102>:   mov    %ecx,%esi
   0x56555665 <+104>:   mov    $0x0,%edi
   0x5655566a <+109>:   mov    0x8(%ebp),%ecx
   0x5655566d <+112>:   mov    $0x0,%ebx
   0x56555672 <+117>:   add    $0x33e0f923,%ecx
   0x56555678 <+123>:   adc    $0xffffffff,%ebx
   0x5655567b <+126>:   mov    %esi,%eax
   0x5655567d <+128>:   xor    %ecx,%eax
   0x5655567f <+130>:   mov    %eax,-0x50(%ebp)
   0x56555682 <+133>:   mov    %edi,%eax
   0x56555684 <+135>:   xor    %ebx,%eax
   0x56555686 <+137>:   mov    %eax,-0x4c(%ebp)
   0x56555689 <+140>:   mov    -0x50(%ebp),%ebx
   0x5655568c <+143>:   mov    -0x4c(%ebp),%esi
   0x5655568f <+146>:   mov    %ebx,%eax
   0x56555691 <+148>:   or     %esi,%eax
   0x56555693 <+150>:   test   %eax,%eax
   0x56555695 <+152>:   jne    0x565556dc <check+223>
   0x56555697 <+154>:   movb   $0x0,-0x3d(%ebp)
   0x5655569b <+158>:   jmp    0x565556c4 <check+199>
   0x5655569d <+160>:   movzbl -0x3d(%ebp),%eax
   0x565556a1 <+164>:   add    $0x7,%eax
   0x565556a4 <+167>:   movzbl -0x33(%ebp,%eax,1),%ecx
   0x565556a9 <+172>:   movzbl -0x3d(%ebp),%edx
   0x565556ad <+176>:   movzbl -0x3d(%ebp),%eax
--Type <RET> for more, q to quit, c to continue without paging--
   0x565556b1 <+180>:   add    $0x7,%eax
   0x565556b4 <+183>:   xor    %ecx,%edx
   0x565556b6 <+185>:   mov    %dl,-0x33(%ebp,%eax,1)
   0x565556ba <+189>:   movzbl -0x3d(%ebp),%eax
   0x565556be <+193>:   add    $0x1,%eax
   0x565556c1 <+196>:   mov    %al,-0x3d(%ebp)
   0x565556c4 <+199>:   cmpb   $0xd,-0x3d(%ebp)
   0x565556c8 <+203>:   jbe    0x5655569d <check+160>
   0x565556ca <+205>:   sub    $0xc,%esp
   0x565556cd <+208>:   lea    -0x33(%ebp),%eax
   0x565556d0 <+211>:   push   %eax
   0x565556d1 <+212>:   mov    -0x54(%ebp),%ebx
   0x565556d4 <+215>:   call   0x56555480 <puts@plt>
   0x565556d9 <+220>:   add    $0x10,%esp
   0x565556dc <+223>:   nop
   0x565556dd <+224>:   mov    -0x1c(%ebp),%eax
   0x565556e0 <+227>:   xor    %gs:0x14,%eax
   0x565556e7 <+234>:   je     0x565556ee <check+241>
   0x565556e9 <+236>:   call   0x56555860 <__stack_chk_fail_local>
   0x565556ee <+241>:   lea    -0xc(%ebp),%esp
   0x565556f1 <+244>:   pop    %ebx
   0x565556f2 <+245>:   pop    %esi
   0x565556f3 <+246>:   pop    %edi
   0x565556f4 <+247>:   pop    %ebp
   0x565556f5 <+248>:   ret    
End of assembler dump.

This function seems to check the input to the function and does some xor magic to obtain the flag. I will set a breakpoint after the first test instruction at 0x56555695 and continue the process. Next, I will hit the second breakpoint at check() and jump to the instruction after the jne instruction to skip the check.

1
2
3
4
(gdb) jump *0x56555697
Continuing at 0x56555697.
CDDC20{E4syR3v3rS1ng~}
[Inferior 1 (process 2135) exited normally]

More info

Ask me on Discord @Coldspot#7033

This post is licensed under CC BY 4.0 by the author.