0xd13a

A rookie in a world of pwns

Alex CTF 2017 Writeup: C++ is awesome

RE2: C++ is awesome

100

They say C++ is complex, prove them wrong!

re2

The application re2 requires correct flag to be passed on command line:

1
2
$ ./re2 
Usage: ./re2 flag

Let’s open the executable in Radare2 and take a look. The main routine seems to be doing all the work so let’s analyze it:

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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
$ r2 re2
[0x00400a60]> aa
[x] Analyze all flags starting with sym. and entry0 (aa)
[0x00400a60]> pdf @ main
/ (fcn) main 301
|   main ();
|           ; var int local_70h @ rbp-0x70
|           ; var int local_64h @ rbp-0x64
|           ; var int local_60h @ rbp-0x60
|           ; var int local_50h @ rbp-0x50
|           ; var int local_21h @ rbp-0x21
|           ; var int local_20h @ rbp-0x20
|           ; var int local_14h @ rbp-0x14
|           ; DATA XREF from 0x00400a7d (entry0)
|           0x00400b89      55             push rbp
|           0x00400b8a      4889e5         mov rbp, rsp
|           0x00400b8d      53             push rbx
|           0x00400b8e      4883ec68       sub rsp, 0x68               ; 'h'
|           0x00400b92      897d9c         mov dword [rbp - local_64h], edi
|           0x00400b95      48897590       mov qword [rbp - local_70h], rsi
|           0x00400b99      837d9c02       cmp dword [rbp - local_64h], 2 ; [0x2:4]=0x102464c
|       ,=< 0x00400b9d      7438           je 0x400bd7
|       |   0x00400b9f      488b4590       mov rax, qword [rbp - local_70h]
|       |   0x00400ba3      488b18         mov rbx, qword [rax]
|       |   0x00400ba6      be090f4000     mov esi, str.Usage:         ; "Usage: " @ 0x400f09
|       |   0x00400bab      bf40216000     mov edi, obj.std::cout      ; " (GNU) 6.1.1 20160721 (Red Hat 6.1.1-4)" @ 0x602140
|       |   0x00400bb0      e81bfeffff     call sym.std::operator___std::char_traits_char__
|       |   0x00400bb5      4889de         mov rsi, rbx
|       |   0x00400bb8      4889c7         mov rdi, rax
|       |   0x00400bbb      e810feffff     call sym.std::operator___std::char_traits_char__
|       |   0x00400bc0      be110f4000     mov esi, str.flag_n         ; " flag." @ 0x400f11
|       |   0x00400bc5      4889c7         mov rdi, rax
|       |   0x00400bc8      e803feffff     call sym.std::operator___std::char_traits_char__
|       |   0x00400bcd      bf00000000     mov edi, 0
|       |   0x00400bd2      e8b9fdffff     call sym.imp.exit           ; sym.std::allocator_char_::allocator-0x90
|       `-> 0x00400bd7      488d45df       lea rax, qword [rbp - local_21h]
|           0x00400bdb      4889c7         mov rdi, rax
|           0x00400bde      e83dfeffff     call sym.std::allocator_char_::allocator
|           0x00400be3      488b4590       mov rax, qword [rbp - local_70h]
|           0x00400be7      4883c008       add rax, 8
|           0x00400beb      488b08         mov rcx, qword [rax]
|           0x00400bee      488d55df       lea rdx, qword [rbp - local_21h]
|           0x00400bf2      488d45b0       lea rax, qword [rbp - local_50h]
|           0x00400bf6      4889ce         mov rsi, rcx
|           0x00400bf9      4889c7         mov rdi, rax
|           0x00400bfc      e80ffeffff     call sym.std::__cxx11::basic_string_char_std::char_traits_char__std::allocator_char__::basic_string
|           0x00400c01      488d45df       lea rax, qword [rbp - local_21h]
|           0x00400c05      4889c7         mov rdi, rax
|           0x00400c08      e8f3fdffff     call sym.std::allocator_char_::_allocator
|           0x00400c0d      c745ec000000.  mov dword [rbp - local_14h], 0
|           0x00400c14      488d45b0       lea rax, qword [rbp - local_50h]
|           0x00400c18      4889c7         mov rdi, rax
|           0x00400c1b      e830feffff     call sym.std::__cxx11::basic_string_char_std::char_traits_char__std::allocator_char__::begin
|           0x00400c20      488945a0       mov qword [rbp - local_60h], rax
|           ; JMP XREF from 0x00400c93 (main)
|       .-> 0x00400c24      488d45b0       lea rax, qword [rbp - local_50h]
|       |   0x00400c28      4889c7         mov rdi, rax
|       |   0x00400c2b      e8c0fdffff     call sym.std::__cxx11::basic_string_char_std::char_traits_char__std::allocator_char__::end
|       |   0x00400c30      488945e0       mov qword [rbp - local_20h], rax
|       |   0x00400c34      488d55e0       lea rdx, qword [rbp - local_20h]
|       |   0x00400c38      488d45a0       lea rax, qword [rbp - local_60h]
|       |   0x00400c3c      4889d6         mov rsi, rdx
|       |   0x00400c3f      4889c7         mov rdi, rax
|       |   0x00400c42      e8f6000000     call fcn.00400d3d
|       |   0x00400c47      84c0           test al, al
|      ,==< 0x00400c49      744a           je 0x400c95
|      ||   0x00400c4b      488d45a0       lea rax, qword [rbp - local_60h]
|      ||   0x00400c4f      4889c7         mov rdi, rax
|      ||   0x00400c52      e843010000     call fcn.00400d9a
|      ||   0x00400c57      0fb610         movzx edx, byte [rax]
|      ||   0x00400c5a      488b0d3f1420.  mov rcx, qword [0x006020a0] ; [0x6020a0:8]=0x400e58 str.L3t_ME_T3ll_Y0u_S0m3th1ng_1mp0rtant_A__FL4G__W0nt_b3_3X4ctly_th4t_345y_t0_c4ptur3_H0wev3r_1T_w1ll_b3_C00l_1F_Y0u_g0t_1t ; "X.@"
|      ||   0x00400c61      8b45ec         mov eax, dword [rbp - local_14h]
|      ||   0x00400c64      4898           cdqe
|      ||   0x00400c66      8b0485c02060.  mov eax, dword [rax*4 + 0x6020c0] ; [0x6020c0:4]=36 ; "$"
|      ||   0x00400c6d      4898           cdqe
|      ||   0x00400c6f      4801c8         add rax, rcx                ; '&'
|      ||   0x00400c72      0fb600         movzx eax, byte [rax]
|      ||   0x00400c75      38c2           cmp dl, al
|      ||   0x00400c77      0f95c0         setne al
|      ||   0x00400c7a      84c0           test al, al
|     ,===< 0x00400c7c      7405           je 0x400c83
|     |||   0x00400c7e      e8d3feffff     call fcn.00400b56
|     `---> 0x00400c83      8345ec01       add dword [rbp - local_14h], 1
|      ||   0x00400c87      488d45a0       lea rax, qword [rbp - local_60h]
|      ||   0x00400c8b      4889c7         mov rdi, rax
|      ||   0x00400c8e      e8e7000000     call fcn.00400d7a
|      |`=< 0x00400c93      eb8f           jmp 0x400c24
|      `--> 0x00400c95      e8d9feffff     call fcn.00400b73
|           0x00400c9a      bb00000000     mov ebx, 0
|           0x00400c9f      488d45b0       lea rax, qword [rbp - local_50h]
|           0x00400ca3      4889c7         mov rdi, rax
|           0x00400ca6      e835fdffff     call sym.std::__cxx11::basic_string_char_std::char_traits_char__std::allocator_char__::_basic_string
|           0x00400cab      89d8           mov eax, ebx
\       ,=< 0x00400cad      eb34           jmp loc.00400ce3
|- loc.00400ce3 7
|   loc.00400ce3 ();
|           ; JMP XREF from 0x00400cad (main)
|           0x00400ce3      4883c468       add rsp, 0x68               ; 'h'
|           0x00400ce7      5b             pop rbx
|           0x00400ce8      5d             pop rbp
\           0x00400ce9      c3             ret

Application processes the command line parameter in a loop. For each character it goes to a lookup table (0x6020c0) and uses the value from it as an index into the long embedded string at 0x006020a0:

1
L3t_ME_T3ll_Y0u_S0m3th1ng_1mp0rtant_A_{FL4G}_W0nt_b3_3X4ctly_th4t_345y_t0_c4ptur3_H0wev3r_1T_w1ll_b3_C00l_1F_Y0u_g0t_1t

If the character in the parameter matches the character in the embedded string (compared at 0x00400c75) it continues. When the whole flag is matched, it is output.

To reverse the flag we can simply extract the embedded string and the lookup table from the binary, and repeat the lookup logic:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from pwn import *

data = open('re2', 'rb').read()

str_data = data[0xe58:0xecf]
offset_data = data[0x20c0:0x213c]

offsets = unpack_many(offset_data, 32)

flag = ''
for x in offsets:
    flag += str_data[x]

print flag

The flag is ALEXCTF{W3_L0v3_C_W1th_CL45535}.