Challenge Description
1
2
3
4
This is a beginners Reversing Challenge. It is build with the optimization level set to 0 so that the assembler is more readable.
If you are new to reversing, please remember that to solve Reversing challenges you probably need to know some C/C++, Assembler and also some experience with gdb (the gnu debugger).
And maybe Ghidra. So this challenge is a great place to start Reversing, but unfortunately it's only 10 points because it's easier than other reversing challenges.
It probably requires more skills than solving a 10 point Forensics problem like RubberDuck. If you solve the challenge you can use the flag to decrypt the sources and see how the challenge is created.
SOLUTION
Analysed using GDB + pwngdb
- Load The Binary in GDB
1
$ gdb ./Ramada
2 . Start the Program with any String with any length
1
pwndbg> start AAAAAAAAAA
3 . Disassemble at current position, which in this case will be 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
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
pwndbg> disassemble
Dump of assembler code for function main:
0x0000555555555100 <+0>: endbr64
0x0000555555555104 <+4>: push r13
0x0000555555555106 <+6>: push r12
0x0000555555555108 <+8>: push rbp
0x0000555555555109 <+9>: mov rbp,rsi
0x000055555555510c <+12>: push rbx
0x000055555555510d <+13>: mov ebx,edi
0x000055555555510f <+15>: lea rdi,[rip+0xef2] # 0x555555556008
0x0000555555555116 <+22>: sub rsp,0x48
0x000055555555511a <+26>: call 0x5555555550b0 <puts@plt>
0x000055555555511f <+31>: call 0x5555555550c0 <getpid@plt>
0x0000555555555124 <+36>: mov r13d,eax
0x0000555555555127 <+39>: call 0x5555555550f0 <getppid@plt>
0x000055555555512c <+44>: mov ecx,r13d
0x000055555555512f <+47>: mov edx,r13d
0x0000555555555132 <+50>: mov edi,0x1
0x0000555555555137 <+55>: mov r12d,eax
0x000055555555513a <+58>: lea rsi,[rip+0xfc2] # 0x555555556103
0x0000555555555141 <+65>: xor eax,eax
0x0000555555555143 <+67>: call 0x5555555550e0 <__printf_chk@plt>
0x0000555555555148 <+72>: xor eax,eax
0x000055555555514a <+74>: mov ecx,r12d
0x000055555555514d <+77>: mov edx,r12d
0x0000555555555150 <+80>: lea rsi,[rip+0xfc0] # 0x555555556117
0x0000555555555157 <+87>: mov edi,0x1
0x000055555555515c <+92>: call 0x5555555550e0 <__printf_chk@plt>
0x0000555555555161 <+97>: cmp ebx,0x1
0x0000555555555164 <+100>: je 0x555555555249 <main+329>
0x000055555555516a <+106>: mov rbp,QWORD PTR [rbp+0x8]
0x000055555555516e <+110>: mov ecx,0x9
0x0000555555555173 <+115>: lea rsi,[rip+0xfb1] # 0x55555555612b
0x000055555555517a <+122>: mov rdi,rbp
=> 0x000055555555517d <+125>: repz cmps BYTE PTR ds:[rsi],BYTE PTR es:[rdi]
0x000055555555517f <+127>: seta r12b
0x0000555555555183 <+131>: sbb r12b,0x0
0x0000555555555187 <+135>: movsx r12d,r12b
0x000055555555518b <+139>: test r12d,r12d
0x000055555555518e <+142>: jne 0x55555555525d <main+349>
0x0000555555555194 <+148>: mov rdi,rbp
0x0000555555555197 <+151>: call 0x5555555550d0 <strlen@plt>
0x000055555555519c <+156>: cmp BYTE PTR [rbp+rax*1-0x1],0x7d
0x00005555555551a1 <+161>: jne 0x55555555521f <main+287>
0x00005555555551a3 <+163>: cmp rax,0x1f
0x00005555555551a7 <+167>: jne 0x55555555520b <main+267>
0x00005555555551a9 <+169>: call 0x5555555553c0 <_Z8InitDatav>
0x00005555555551ae <+174>: mov r13,rsp
0x00005555555551b1 <+177>: mov eax,r12d
0x00005555555551b4 <+180>: mov ecx,0x10
0x00005555555551b9 <+185>: mov rdi,r13
0x00005555555551bc <+188>: lea rsi,[rbp+0x9]
0x00005555555551c0 <+192>: mov edx,0x15
0x00005555555551c5 <+197>: rep stos DWORD PTR es:[rdi],eax
0x00005555555551c7 <+199>: mov rdi,r13
0x00005555555551ca <+202>: call 0x5555555550a0 <strncpy@plt>
0x00005555555551cf <+207>: mov edi,0x1
0x00005555555551d4 <+212>: xor eax,eax
0x00005555555551d6 <+214>: mov rdx,r13
0x00005555555551d9 <+217>: lea rsi,[rip+0xf55] # 0x555555556135
0x00005555555551e0 <+224>: call 0x5555555550e0 <__printf_chk@plt>
0x00005555555551e5 <+229>: mov rdi,r13
0x00005555555551e8 <+232>: call 0x555555555370 <_Z9CheckFlagPKc>
0x00005555555551ed <+237>: test eax,eax
0x00005555555551ef <+239>: je 0x555555555233 <main+307>
0x00005555555551f1 <+241>: lea rdi,[rip+0xf53] # 0x55555555614b
0x00005555555551f8 <+248>: call 0x5555555550b0 <puts@plt>
0x00005555555551fd <+253>: add rsp,0x48
0x0000555555555201 <+257>: mov eax,r12d
0x0000555555555204 <+260>: pop rbx
0x0000555555555205 <+261>: pop rbp
0x0000555555555206 <+262>: pop r12
0x0000555555555208 <+264>: pop r13
0x000055555555520a <+266>: ret
0x000055555555520b <+267>: lea rdi,[rip+0xea6] # 0x5555555560b8
0x0000555555555212 <+274>: mov r12d,0x4
0x0000555555555218 <+280>: call 0x5555555550b0 <puts@plt>
0x000055555555521d <+285>: jmp 0x5555555551fd <main+253>
0x000055555555521f <+287>: lea rdi,[rip+0xe6a] # 0x555555556090
0x0000555555555226 <+294>: mov r12d,0x3
0x000055555555522c <+300>: call 0x5555555550b0 <puts@plt>
0x0000555555555231 <+305>: jmp 0x5555555551fd <main+253>
0x0000555555555233 <+307>: mov rdx,rbp
0x0000555555555236 <+310>: lea rsi,[rip+0xea3] # 0x5555555560e0
0x000055555555523d <+317>: mov edi,0x1
0x0000555555555242 <+322>: call 0x5555555550e0 <__printf_chk@plt>
0x0000555555555247 <+327>: jmp 0x5555555551f1 <main+241>
0x0000555555555249 <+329>: lea rdi,[rip+0xdf0] # 0x555555556040
0x00005555555551fd <+253>: add rsp,0x48
0x0000555555555201 <+257>: mov eax,r12d
0x0000555555555204 <+260>: pop rbx
0x0000555555555205 <+261>: pop rbp
0x0000555555555206 <+262>: pop r12
0x0000555555555208 <+264>: pop r13
0x000055555555520a <+266>: ret
0x000055555555520b <+267>: lea rdi,[rip+0xea6] # 0x5555555560b8
0x0000555555555212 <+274>: mov r12d,0x4
0x0000555555555218 <+280>: call 0x5555555550b0 <puts@plt>
0x000055555555521d <+285>: jmp 0x5555555551fd <main+253>
0x000055555555521f <+287>: lea rdi,[rip+0xe6a] # 0x555555556090
0x0000555555555226 <+294>: mov r12d,0x3
0x000055555555522c <+300>: call 0x5555555550b0 <puts@plt>
0x0000555555555231 <+305>: jmp 0x5555555551fd <main+253>
0x0000555555555233 <+307>: mov rdx,rbp
0x0000555555555236 <+310>: lea rsi,[rip+0xea3] # 0x5555555560e0
0x000055555555523d <+317>: mov edi,0x1
0x0000555555555242 <+322>: call 0x5555555550e0 <__printf_chk@plt>
0x0000555555555247 <+327>: jmp 0x5555555551f1 <main+241>
0x0000555555555249 <+329>: lea rdi,[rip+0xdf0] # 0x555555556040
0x0000555555555250 <+336>: mov r12d,0x1
0x0000555555555256 <+342>: call 0x5555555550b0 <puts@plt>
0x000055555555525b <+347>: jmp 0x5555555551fd <main+253>
0x000055555555525d <+349>: lea rdi,[rip+0xdfc] # 0x555555556060
0x0000555555555264 <+356>: mov r12d,0x2
0x000055555555526a <+362>: call 0x5555555550b0 <puts@plt>
0x000055555555526f <+367>: jmp 0x5555555551fd <main+253>
End of assembler dump.
4 . Passing the start BUFFER STRING check
In main
function we can see that in address 0x000055555555517d
CTFlearn{
is stored in rsi
register
for comparison with rdi
Thus the ultimate FLAG Length will be 32
1
2
*RDI 0x7fffffffe22d ◂— 'AAAAAAAAAAAAAA'
*RSI 0x55555555612b ◂— 'CTFlearn{'
1
=> 0x000055555555517d <+125>: repz cmps BYTE PTR ds:[rsi],BYTE PTR es:[rdi]
- Character by Character check for
CTFlearn{
and supplied BUFFER STRING
wherercx
define the length of the string until which to check
or we can say is the index of the string compare andrcx
is
substracted by 1.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
► 0x55555555517d <main+125> repe cmpsb byte ptr [rsi], byte ptr [rdi]
↓
0x55555555517d <main+125> repe cmpsb byte ptr [rsi], byte ptr [rdi]
↓
0x55555555517d <main+125> repe cmpsb byte ptr [rsi], byte ptr [rdi]
↓
0x55555555517d <main+125> repe cmpsb byte ptr [rsi], byte ptr [rdi]
↓
0x55555555517d <main+125> repe cmpsb byte ptr [rsi], byte ptr [rdi]
↓
0x55555555517d <main+125> repe cmpsb byte ptr [rsi], byte ptr [rdi]
↓
0x55555555517d <main+125> repe cmpsb byte ptr [rsi], byte ptr [rdi]
↓
0x55555555517d <main+125> repe cmpsb byte ptr [rsi], byte ptr [rdi]
↓
0x55555555517d <main+125> repe cmpsb byte ptr [rsi], byte ptr [rdi]
↓
0x55555555517d <main+125> repe cmpsb byte ptr [rsi], byte ptr [rdi]
0x55555555517f <main+127> seta r12b
The String should start with CTFlearn{
to pass the starting BUFFER check.
Start the analysis again with the BUFFER STRING CTFlearn{AAAAAAAAA
1
pwndbg> start CTFlearn{AAAAAAAAA
5 . Passing End character check for BUFFER Input STRING
In Address 0x55555555519c
the last Character
of the supplied BUFFER STRING is compared with 0x7d
or }
Thus the BUFFER STRING must end with }
to to pass the BUFFER STRING check.
1
► 0x55555555519c <main+156> cmp byte ptr [rbp + rax - 1], 0x7d
Start the debugging again with the BUFFER STRING CTFlearn{AAAAAAAAA}
1
pwndbg> start CTFlearn{AAAAAAAAA}
6 . Passing the BUFFER STRING Length Check
In address 0x5555555551a3
we can see that
0x1f
is compared with rax
value which in this case is 0x13
or rax=19 which is the length of our supplied BUFFER STRING
as 0x1f
or 31
is compared with the supplied BUFFER STRING length
we can say that the FLAG length is 31
1
► 0x5555555551a3 <main+163> cmp rax, 0x1f
- Thus supplying a BUFFER STRING with above discussed format can pass the length check
which in this case can be taken asCTFlearn{AAAAAAAAAAAAAAAAAAAAA}
Start the debugging again with the BUFFER STRING CTFlearn{AAAAAAAAAAAAAAAAAAAAA}
1
pwndbg> start CTFlearn{AAAAAAAAAAAAAAAAAAAAA}
7 . Getting the Hex Values to compare
Now it is better to be analysed with Ghidra
On analyzing with Ghidra we can see that there is a function named as CheckFlag
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/* CheckFlag(char const*) */
undefined8 CheckFlag(char *param_1)
{
long lVar1;
int iVar2;
lVar1 = 0;
do {
iVar2 = (int)param_1[lVar1];
if (*(int *)(data + lVar1 * 4) != iVar2 * iVar2 * iVar2) {
puts("No flag for you!");
return 4;
}
lVar1 = lVar1 + 1;
} while (lVar1 != 0x15);
return 0;
}
Here data
is getting data from initData
function
In initData
we have the Pre FLAG Data that is used for comparison
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
/* WARNING: Unknown calling convention yet parameter storage is locked */
/* InitData() */
void InitData(void)
{
data._0_4_ = 0x13693;
data._4_4_ = 0x6b2c0;
data._8_4_ = 0x11a9f9;
data._12_4_ = 0x157000;
data._16_4_ = 0x1cb91;
data._20_4_ = 0x1bb528;
data._24_4_ = 0x1bb528;
data._28_4_ = 0xded21;
data._32_4_ = 0x144f38;
data._36_4_ = 0xfb89d;
data._40_4_ = 0x169b48;
data._44_4_ = 0xd151f;
data._48_4_ = 0x8b98b;
data._52_4_ = 0x17d140;
data._56_4_ = 0xded21;
data._60_4_ = 0x1338c0;
data._64_4_ = 0x1338c0;
data._68_4_ = 0x11a9f9;
data._72_4_ = 0x1b000;
data._76_4_ = 0x144f38;
data._80_4_ = 0x1734eb;
return;
}
The FLAG Can simply be constructed from this data with a simple Python Program
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
print('FLAG : CTFlearn{', end='')
initData = [
0x13693, 0x6b2c0, 0x11a9f9,
0x157000, 0x1cb91, 0x1bb528,
0x1bb528, 0xded21, 0x144f38,
0xfb89d, 0x169b48, 0xd151f,
0x8b98b, 0x17d140, 0xded21,
0x1338c0, 0x1338c0, 0x11a9f9,
0x1b000, 0x144f38, 0x1734eb
]
for i in initData:
print(chr(round(i**(1/3))), end='')
print('}')
FLAG : CTFlearn{+Lip1zzaner_Stalli0ns}
This is how, I solved this challenge.
Thankyou, for reading my writeup :)
Hope, I would see you in my next writeup.
Support Me if you want to.