Reversing as an Art

Notes on RCE fun.

9447 CTF - Rolling Writeup

1
2
3
4
5
6
7
8
9
Category: Reversing Points: 100 Description:

Rolling your own stuff is pretty good :)

The flag format is 9447{$STR}, where $STR is the one accepted by the binary.

Note: This challenge is the only challenge to break the 9447{string} flag format. 
If $STR is the solution and the one accepted by the binary, 
please submit the flag as 9447{$STR} by manually adding the 9447{}.

What’s up guys?!

Today I’ll share the solution of the rolling challenge from the 9447 CTF where I took part as one of the members of CleveCode Rising Team. The challenge is a pretty simple reversing task with hidden password which is the flag. During the CTF I was unable to solve it due to technical problems on my linux box – for some reason the file was always crashing at some point. So, this is a post CTF solution.

As I’ve witnessed several times lately, CTF contests catch me in situations where not all the tools are present and what I get in most is just remote shell. In light of this, I decided to solve the task with the help of radare and gdb only. More to that, I wanted to play with the framework for some time know, so this is a good chance to learn.

First Run

Before digging in, let’s just run the file. Interestingly, there is some “obfuscation” even from the start. With the help of translation the messages could be “de-obfuscated”, the used language is Welsh.

./rolling
Fynd i mewn i cyfrinair -> Enter a password
./rolling foo
Nac oes. Ceisiwch eto.  -> No. Try again.

Radare to the rescue

We start by understanding what this rolling is about:

radare2 ./rolling
[0x004004f0]> ia
[Imports]
ordinal=001 plt=0x000004a0 bind=GLOBAL type=FUNC name=puts
ordinal=002 plt=0x000004b0 bind=GLOBAL type=FUNC name=mmap
ordinal=003 plt=0x000004c0 bind=GLOBAL type=FUNC name=__libc_start_main
ordinal=004 plt=0x000004d0 bind=UNKNOWN type=NOTYPE name=__gmon_start__
ordinal=005 plt=0x000004e0 bind=GLOBAL type=FUNC name=memcpy

5 imports
file    ./rolling
type        EXEC (Executable file)
pic         false
has_va      true
root        elf
class       ELF64
lang        c
arch        x86
bits        64
machine     AMD x86-64 architecture
os          linux
subsys      linux
endian      little
strip       true
static      false
linenum     false
lsyms       false
relocs      false
rpath       NONE

So this is an ELF64 binary with striped symbols – x64 bit linux box is needed to execute it. Before moving on, I suggest to go over Linux AMD64 ABI to get yourself more familiar with the calling convention. Let’s continue, by letting radare to fully analyze the file (aa). There are other various option available for the analysis, just use a? to check them out.

[0x004004f0]> aa

We need to get to the main function as this is where the fun begins. Let’s list all available functions:

[0x004004f0]> afl
0x004004f0 89    4  fcn.004004f0
0x00400549 64    4  fcn.00400549
0x00400589 35    3  fcn.00400589
0x00400520 41    4  fcn.00400520
0x004005ac 187   6  fcn.004005ac
0x00400550 57    4  fcn.00400550
0x004005fe 105   5  fcn.00400650
0x00400667 96    1  fcn.00400667
0x004004b0 6     1  sym.imp.mmap
0x004004b6 16    1  fcn.004004b6
0x0040049c 10    1  fcn.0040049c
0x004004a6 16    1  fcn.004004a6
0x004004c6 16    1  fcn.004004c6
0x004004d6 16    1  fcn.004004d6
0x004004e6 99    4  fcn.004004e6
0x004004e0 6     1  sym.imp.memcpy
0x004006c7 125   4  fcn.004006c7
0x004005dd 138   3  fcn.004005dd
0x00400744 106   5  main
0x004004a0 6     1  sym.imp.puts
0x004007ae 139   3  fcn.004007ae
0x00400839 9     1  fcn.00400839
0x00400842 11    1  fcn.00400842
0x0040084d 116   3  fcn.0040084d
0x004006c3 4     1  fcn.004006c3
0x004004c0 6     1  sym.imp.__libc_start_main

Jump to the main and list it:

[0x004004f0]> s main
[0x00400744]> pdf

It will be also useful to add some meaningful names to the functions. So the one which is called @ 0x0040076C eventually returns an address in RAX register which will be executed @ 0x0040077F. This behavior is leading to a new name DecryptShellcode. Address renaming can be done with afn. We continue with the under the hood listing of DecryptShellcode (don’t forget to explore other options with a?):

[0x00400744]> afn DecrypteShellcode fcn.004006c7
[0x00400744]> pdf @ DecrypteShellcode

So, what we have here is the following:

  • The first byte of the parameter to the executable is supplied as a parameter to the DecrypteShellcode
  • The DecrypteShellcode parameter should be between 0x39 and 0x2f to follow to 0x4006E8 otherwise to 0x400715
    • Pay attention that the third parameter to DecryptBuffer functions is hardcoded to 2 @ 0x400715
  • The parameter to the executable will decide which buffer will be decrypted and executed

We will explore the first execution path as it seems the most probable one, being dependent on the supplied parameter. Again, here too, key functions was renamed:

[0x00400744]> afn GetEncryptedBuffer fcn.00400667
[0x00400744]> afn DecryptBuffer fcn.004005dd

and add some comments for clearance:

[0x00400744]> C?
...
| CC[-] [comment-text]    add/remove comment. Use CC! to edit with $EDITOR
...
[0x00400744]> CC "Encrypted Buffer"@  0x004006ed
[0x00400744]> CC "Buffer Size" @ 0x004006e8

Let’s see what we have in GetEncryptedBuffer:

[0x00400744]> pdf @ GetEncryptedBuffer

The GetEncryptedBuffer will

  • map part of the executable file (rolling) into the memory starting from the beginning of the file
  • copy static buffer to the mapped memory
  • return encrypted buffer to the callee

Continue now to the DecryptBuffer:

[0x00400744]> pdf @ DecryptBuffer

I will not describe the implemented algorithm there as it does not really matter. The only thing that is important there is the information which should reveal the first byte of the key:

DecryptBuffer listing
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
/ (fcn) DecryptBuffer 138
|          0x004005dd    55           push rbp
|          0x004005de    4889e5       mov rbp, rsp
|          0x004005e1    48897de8     mov [rbp-0x18], rdi           ; encrypted buffer
|          0x004005e5    8975e4       mov [rbp-0x1c], esi           ; encrypted buffer size
|          0x004005e8    8955e0       mov [rbp-0x20], edx           ; amount of decryption passes
|          0x004005eb    c745f800000. mov dword [rbp-0x8], 0x0
|          0x004005f2    c745f800000. mov dword [rbp-0x8], 0x0
|          ; CODE (CALL) XREF from 0x0040065a (fcn.004005ac)
|      ,=< 0x004005f9    eb5f         jmp loc.0040065a
|      |   0x004005fb    8b45e4       mov eax, [rbp-0x1c]
|- fcn.00400650 105
|      |   0x004005fe    83e801       sub eax, 0x1
|      |   0x00400601    8945fc       mov [rbp-0x4], eax
|     ,==< 0x00400604    eb4a         jmp 0x400650 ; (fcn.004005ac)
|    .---> 0x00400606    8b45fc       mov eax, [rbp-0x4]
|    |||   0x00400609    4898         cdqe
|    |||   0x0040060b    488d1485000. lea rdx, [rax*4]
|    |||   0x00400613    488b45e8     mov rax, [rbp-0x18]
|    |||   0x00400617    4801d0       add rax, rdx
|    |||   0x0040061a    8b55fc       mov edx, [rbp-0x4]
|    |||   0x0040061d    4863d2       movsxd rdx, edx
|    |||   0x00400620    488d0c95000. lea rcx, [rdx*4]
|    |||   0x00400628    488b55e8     mov rdx, [rbp-0x18]
|    |||   0x0040062c    4801ca       add rdx, rcx
|    |||   0x0040062f    8b0a         mov ecx, [rdx]
|    |||   0x00400631    8b55fc       mov edx, [rbp-0x4]
|    |||   0x00400634    4863d2       movsxd rdx, edx
|    |||   0x00400637    48c1e202     shl rdx, 0x2
|    |||   0x0040063b    488d72fc     lea rsi, [rdx-0x4]
|    |||   0x0040063f    488b55e8     mov rdx, [rbp-0x18]
|    |||   0x00400643    4801f2       add rdx, rsi
|    |||   0x00400646    8b12         mov edx, [rdx]
|    |||   0x00400648    31ca         xor edx, ecx
|    |||   0x0040064a    8910         mov [rax], edx
|    |||   0x0040064c    836dfc01     sub dword [rbp-0x4], 0x1
|    ||    ; CODE (CALL) XREF from 0x00400604 (fcn.004005ac)
|    |`--> 0x00400650    837dfc00     cmp dword [rbp-0x4], 0x0
|    `===< 0x00400654    7fb0         jg 0x400606
|      |   0x00400656    8345f801     add dword [rbp-0x8], 0x1
|      |   ; CODE (CALL) XREF from 0x004005f9 (fcn.004005ac)
|- loc.0040065a 105
|      `-> 0x0040065a    8b45e0       mov eax, [rbp-0x20]           ; amount of decryption passes
|          0x0040065d    83e801       sub eax, 0x1
|          0x00400660    3b45f8       cmp eax, [rbp-0x8]            ; [rbp-0x8] is 0
|          0x00400663    7f96         jg 0x4005fb
|          0x00400665    5d           pop rbp
\          0x00400666    c3           ret

Finding the first byte of the key:

  • DecrypteShellcode @ 0x004006D4, the fist byte of the key must obey 0x2f < first_key_byte < 0x39
  • DecrypteShellcode @ 0x004006FF, the first byte is subtracted by 0x37 and passed to DecryptBuffer as “amount of decryption passes”
  • DecryptBuffer @ 0x0040065A, the (“amount of decryption passes” – 1) must be greater then 0.

So, following the above, we can conclude that the first byte of the key must be ‘9’ (0x39).

Shellcode

This portion of the task is done for now. We need to actually get the decrypted code, because it will reveal the rest of the key. To get the code, let’s jump to short session with GDB. We will break on 0x0040077F (execution of the shellcode) and dump the code for further analysis.

gdb$ dump binary memory shell.bin $rax $rax+0x87c

Opening it again in radare, doing some analysis (the shellcode is really simple) will grant the final key:

Shellcode
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/ (fcn) fcn.00000000 542
|           0x00000000    55           push rbp
|           ; DATA XREF from 0x00000210 (fcn.00000000)
|           0x00000001    4889e5       mov rbp, rsp
|           0x00000004    48897df8     mov [rbp-0x8], rdi
|           0x00000008    488b45f8     mov rax, [rbp-0x8]
|           0x0000000c    0fb600       movzx eax, byte [rax]
|           0x0000000f    3c39         cmp al, 0x39                     ; 9
|       ,=< 0x00000011    0f8500020000 jne 0x217
|       |   0x00000017    488b45f8     mov rax, [rbp-0x8]
|       |   0x0000001b    4883c001     add rax, 0x1
|       |   0x0000001f    0fb600       movzx eax, byte [rax]
|       |   0x00000022    3c34         cmp al, 0x34                     ; 4
|      ,==< 0x00000024    0f85ed010000 jne 0x217
|      ||   0x0000002a    488b45f8     mov rax, [rbp-0x8]
|      ||   0x0000002e    4883c002     add rax, 0x2
|      ||   0x00000032    0fb600       movzx eax, byte [rax]
|      ||   0x00000035    3c34         cmp al, 0x34                     ; 4
|     ,===< 0x00000037    0f85da010000 jne 0x217
|     |||   0x0000003d    488b45f8     mov rax, [rbp-0x8]
|     |||   0x00000041    4883c003     add rax, 0x3
|     |||   0x00000045    0fb600       movzx eax, byte [rax]
|     |||   0x00000048    3c37         cmp al, 0x37                     ; 7
|    ,====< 0x0000004a    0f85c7010000 jne 0x217
|    ||||   0x00000050    488b45f8     mov rax, [rbp-0x8]
|    ||||   0x00000054    4883c004     add rax, 0x4
|    ||||   0x00000058    0fb600       movzx eax, byte [rax]
|    ||||   0x0000005b    0fbed0       movsx edx, al
|    ||||   0x0000005e    488b45f8     mov rax, [rbp-0x8]
|    ||||   0x00000062    0fb600       movzx eax, byte [rax]
|    ||||   0x00000065    0fbec0       movsx eax, al
|    ||||   0x00000068    83c039       add eax, 0x39
|    ||||   0x0000006b    39c2         cmp edx, eax                     ; r
|   ,=====< 0x0000006d    0f85a4010000 jne 0x217
|   |||||   0x00000073    488b45f8     mov rax, [rbp-0x8]
|   |||||   0x00000077    4883c005     add rax, 0x5
|   |||||   0x0000007b    0fb600       movzx eax, byte [rax]
|   |||||   0x0000007e    0fbec0       movsx eax, al
|   |||||   0x00000081    488b55f8     mov rdx, [rbp-0x8]
|   |||||   0x00000085    4883c201     add rdx, 0x1
|   |||||   0x00000089    0fb612       movzx edx, byte [rdx]
|   |||||   0x0000008c    0fbed2       movsx edx, dl
|   |||||   0x0000008f    83c23b       add edx, 0x3b
|   |||||   0x00000092    39d0         cmp eax, edx                     ; o
|  ,======< 0x00000094    0f857d010000 jne 0x217
|  ||||||   0x0000009a    488b45f8     mov rax, [rbp-0x8]
|  ||||||   0x0000009e    4883c006     add rax, 0x6
|  ||||||   0x000000a2    0fb600       movzx eax, byte [rax]
|  ||||||   0x000000a5    0fbec0       movsx eax, al
|  ||||||   0x000000a8    488b55f8     mov rdx, [rbp-0x8]
|  ||||||   0x000000ac    4883c202     add rdx, 0x2
|  ||||||   0x000000b0    0fb612       movzx edx, byte [rdx]
|  ||||||   0x000000b3    0fbed2       movsx edx, dl
|  ||||||   0x000000b6    83c238       add edx, 0x38
|  ||||||   0x000000b9    39d0         cmp eax, edx                     ; l
| ,=======< 0x000000bb    0f8556010000 jne 0x217
| |||||||   0x000000c1    488b45f8     mov rax, [rbp-0x8]
| |||||||   0x000000c5    4883c007     add rax, 0x7
| |||||||   0x000000c9    0fb600       movzx eax, byte [rax]
| |||||||   0x000000cc    0fbec0       movsx eax, al
| |||||||   0x000000cf    488b55f8     mov rdx, [rbp-0x8]
| |||||||   0x000000d3    4883c203     add rdx, 0x3
| |||||||   0x000000d7    0fb612       movzx edx, byte [rdx]
| |||||||   0x000000da    0fbed2       movsx edx, dl
| |||||||   0x000000dd    83c235       add edx, 0x35
| |||||||   0x000000e0    39d0         cmp eax, edx                     ;l
| ========< 0x000000e2    0f852f010000 jne 0x217
| |||||||   0x000000e8    488b45f8     mov rax, [rbp-0x8]
| |||||||   0x000000ec    4883c008     add rax, 0x8
| |||||||   0x000000f0    0fb600       movzx eax, byte [rax]
| |||||||   0x000000f3    0fbec0       movsx eax, al
| |||||||   0x000000f6    488b55f8     mov rdx, [rbp-0x8]
| |||||||   0x000000fa    4883c204     add rdx, 0x4
| |||||||   0x000000fe    0fb612       movzx edx, byte [rdx]
| |||||||   0x00000101    0fbed2       movsx edx, dl
| |||||||   0x00000104    83ea09       sub edx, 0x9
| |||||||   0x00000107    39d0         cmp eax, edx                     ; i
| ========< 0x00000109    0f8508010000 jne 0x217
| |||||||   0x0000010f    488b45f8     mov rax, [rbp-0x8]
| |||||||   0x00000113    4883c009     add rax, 0x9
| |||||||   0x00000117    0fb600       movzx eax, byte [rax]
| |||||||   0x0000011a    0fbec0       movsx eax, al
| |||||||   0x0000011d    488b55f8     mov rdx, [rbp-0x8]
| |||||||   0x00000121    4883c205     add rdx, 0x5
| |||||||   0x00000125    0fb612       movzx edx, byte [rdx]
| |||||||   0x00000128    0fbed2       movsx edx, dl
| |||||||   0x0000012b    83ea01       sub edx, 0x1
| |||||||   0x0000012e    39d0         cmp eax, edx                     ; n
| ========< 0x00000130    0f85e1000000 jne 0x217
| |||||||   0x00000136    488b45f8     mov rax, [rbp-0x8]
| |||||||   0x0000013a    4883c00a     add rax, 0xa
| |||||||   0x0000013e    0fb600       movzx eax, byte [rax]
| |||||||   0x00000141    0fbec0       movsx eax, al
| |||||||   0x00000144    488b55f8     mov rdx, [rbp-0x8]
| |||||||   0x00000148    4883c206     add rdx, 0x6
| |||||||   0x0000014c    0fb612       movzx edx, byte [rdx]
| |||||||   0x0000014f    0fbed2       movsx edx, dl
| |||||||   0x00000152    83ea05       sub edx, 0x5
| |||||||   0x00000155    39d0         cmp eax, edx                     ; g
| ========< 0x00000157    0f85ba000000 jne 0x217
| |||||||   0x0000015d    488b45f8     mov rax, [rbp-0x8]
| |||||||   0x00000161    4883c00b     add rax, 0xb
| |||||||   0x00000165    0fb600       movzx eax, byte [rax]
| |||||||   0x00000168    0fbec0       movsx eax, al
| |||||||   0x0000016b    488b55f8     mov rdx, [rbp-0x8]
| |||||||   0x0000016f    4883c207     add rdx, 0x7
| |||||||   0x00000173    0fb612       movzx edx, byte [rdx]
| |||||||   0x00000176    0fbed2       movsx edx, dl
| |||||||   0x00000179    83ea03       sub edx, 0x3
| |||||||   0x0000017c    39d0         cmp eax, edx                     ; i
| ========< 0x0000017e    0f8593000000 jne 0x217
| |||||||   0x00000184    488b45f8     mov rax, [rbp-0x8]
| |||||||   0x00000188    4883c00c     add rax, 0xc
| |||||||   0x0000018c    0fb600       movzx eax, byte [rax]
| |||||||   0x0000018f    0fbec0       movsx eax, al
| |||||||   0x00000192    488b55f8     mov rdx, [rbp-0x8]
| |||||||   0x00000196    4883c208     add rdx, 0x8
| |||||||   0x0000019a    0fb612       movzx edx, byte [rdx]
| |||||||   0x0000019d    0fbed2       movsx edx, dl
| |||||||   0x000001a0    83c20a       add edx, 0xa
| |||||||   0x000001a3    39d0         cmp eax, edx                     ; s
| ========< 0x000001a5    7570         jne 0x217
| |||||||   0x000001a7    488b45f8     mov rax, [rbp-0x8]
| |||||||   0x000001ab    4883c00d     add rax, 0xd
| |||||||   0x000001af    0fb600       movzx eax, byte [rax]
| |||||||   0x000001b2    0fbec0       movsx eax, al
| |||||||   0x000001b5    488b55f8     mov rdx, [rbp-0x8]
| |||||||   0x000001b9    4883c209     add rdx, 0x9
| |||||||   0x000001bd    0fb612       movzx edx, byte [rdx]
| |||||||   0x000001c0    0fbed2       movsx edx, dl
| |||||||   0x000001c3    83ea08       sub edx, 0x8
| |||||||   0x000001c6    39d0         cmp eax, edx                     ; f
| ========< 0x000001c8    754d         jne 0x217
| |||||||   0x000001ca    488b45f8     mov rax, [rbp-0x8]
| |||||||   0x000001ce    4883c00e     add rax, 0xe
| |||||||   0x000001d2    0fb600       movzx eax, byte [rax]
| |||||||   0x000001d5    0fbec0       movsx eax, al
| |||||||   0x000001d8    488b55f8     mov rdx, [rbp-0x8]
| |||||||   0x000001dc    4883c20a     add rdx, 0xa
| |||||||   0x000001e0    0fb612       movzx edx, byte [rdx]
| |||||||   0x000001e3    0fbed2       movsx edx, dl
| |||||||   0x000001e6    83c20e       add edx, 0xe
| |||||||   0x000001e9    39d0         cmp eax, edx                     ; u
| ========< 0x000001eb    752a         jne 0x217
| |||||||   0x000001ed    488b45f8     mov rax, [rbp-0x8]
| |||||||   0x000001f1    4883c00f     add rax, 0xf
| |||||||   0x000001f5    0fb600       movzx eax, byte [rax]
| |||||||   0x000001f8    0fbec0       movsx eax, al
| |||||||   0x000001fb    488b55f8     mov rdx, [rbp-0x8]
| |||||||   0x000001ff    4883c20b     add rdx, 0xb
| |||||||   0x00000203    0fb612       movzx edx, byte [rdx]
| |||||||   0x00000206    0fbed2       movsx edx, dl
| |||||||   0x00000209    83c205       add edx, 0x5
| |||||||   0x0000020c    39d0         cmp eax, edx                     ; n
| ========< 0x0000020e    7507         jne 0x217
| |||||||   0x00000210    b801000000   mov eax, 0x1 ;  0x00000001
| |||||||   0x00000215    eb05         jmp loc.0000021c
| ```````-> 0x00000217    b800000000   mov eax, 0x0
|           ; CODE (CALL) XREF from 0x00000215 (fcn.00000000)
|- loc.0000021c 2
|           0x0000021c    5d           pop rbp
\           0x0000021d    c3           ret

The key/flag is:

9447rollingisfun

./rolling 9447rollingisfun
Llongyfarchiadau -> Congratulations

Comments