Skip to content

Commit 2e9f857

Browse files
committed
Added quackme
1 parent 53e3dcd commit 2e9f857

File tree

3 files changed

+188
-2
lines changed

3 files changed

+188
-2
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ This CTF was done with [@pauxy](https://github.com/pauxy) and [@StopDuckRoll](ht
8181
- [assembly-0](Reversing/assembly-0) - 150
8282
- [assembly-1](Reversing/assembly-1) - 200
8383
- [be-quick-or-be-dead-1](Reversing/be-quick-or-be-dead-1) - 200
84-
- [quackme](Reversing/quackme) (Unsolved) - 200
84+
- [quackme](Reversing/quackme) - 200
8585
- [assembly-2](Reversing/assembly-2) (Unsolved) - 250
8686
- be-quick-or-be-dead-2 (Unsolved) - 275
8787
- Radix's Terminal (Unsolved) - 400

Reversing/quackme/README.md

Lines changed: 177 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,183 @@ Reversing
1111
>Objdump or something similar is probably a good place to start.
1212
1313
## Solution
14+
Upon listing all the functions, there are multiple written functions. We can analyse and print the function `do_magic()`
1415

16+
```asm
17+
[0x08048642]> pdf
18+
/ (fcn) sym.do_magic 211
19+
| sym.do_magic ();
20+
| ; var int local_1dh @ ebp-0x1d
21+
| ; var int local_1ch @ ebp-0x1c
22+
| ; var int local_18h @ ebp-0x18
23+
| ; var int local_14h @ ebp-0x14
24+
| ; var int local_10h @ ebp-0x10
25+
| ; var int local_ch @ ebp-0xc
26+
| ; CALL XREF from sym.main (0x804874a)
27+
| 0x08048642 55 push ebp
28+
| 0x08048643 89e5 mov ebp, esp
29+
| 0x08048645 83ec28 sub esp, 0x28 ; '('
30+
| 0x08048648 e88effffff call sym.read_input
31+
| 0x0804864d 8945ec mov dword [local_14h], eax
32+
| 0x08048650 83ec0c sub esp, 0xc
33+
| 0x08048653 ff75ec push dword [local_14h]
34+
| 0x08048656 e835feffff call sym.imp.strlen ; size_t strlen(const char *s)
35+
| 0x0804865b 83c410 add esp, 0x10
36+
| 0x0804865e 8945f0 mov dword [local_10h], eax
37+
| 0x08048661 8b45f0 mov eax, dword [local_10h]
38+
| 0x08048664 83c001 add eax, 1
39+
| 0x08048667 83ec0c sub esp, 0xc
40+
| 0x0804866a 50 push eax
41+
| 0x0804866b e8f0fdffff call sym.imp.malloc ; void *malloc(size_t size)
42+
| 0x08048670 83c410 add esp, 0x10
43+
| 0x08048673 8945f4 mov dword [local_ch], eax
44+
| 0x08048676 837df400 cmp dword [local_ch], 0
45+
| ,=< 0x0804867a 751a jne 0x8048696
46+
| | 0x0804867c 83ec0c sub esp, 0xc
47+
| | 0x0804867f 6884880408 push str.malloc___returned_NULL._Out_of_Memory ; 0x8048884 ; "malloc() returned NULL. Out of Memory\n"
48+
| | 0x08048684 e8e7fdffff call sym.imp.puts ; int puts(const char *s)
49+
| | 0x08048689 83c410 add esp, 0x10
50+
| | 0x0804868c 83ec0c sub esp, 0xc
51+
| | 0x0804868f 6aff push 0xffffffffffffffff
52+
| | 0x08048691 e8eafdffff call sym.imp.exit ; void exit(int status)
53+
| | ; CODE XREF from sym.do_magic (0x804867a)
54+
| `-> 0x08048696 8b45f0 mov eax, dword [local_10h]
55+
| 0x08048699 83c001 add eax, 1
56+
| 0x0804869c 83ec04 sub esp, 4
57+
| 0x0804869f 50 push eax
58+
| 0x080486a0 6a00 push 0
59+
| 0x080486a2 ff75f4 push dword [local_ch]
60+
| 0x080486a5 e816feffff call sym.imp.memset ; void *memset(void *s, int c, size_t n)
61+
| 0x080486aa 83c410 add esp, 0x10
62+
| 0x080486ad c745e4000000. mov dword [local_1ch], 0
63+
| 0x080486b4 c745e8000000. mov dword [local_18h], 0
64+
| ,=< 0x080486bb eb4e jmp 0x804870b
65+
| | ; CODE XREF from sym.do_magic (0x8048711)
66+
| .--> 0x080486bd 8b45e8 mov eax, dword [local_18h]
67+
| :| 0x080486c0 0558880408 add eax, obj.sekrutBuffer
68+
| :| 0x080486c5 0fb608 movzx ecx, byte [eax]
69+
| :| 0x080486c8 8b55e8 mov edx, dword [local_18h]
70+
| :| 0x080486cb 8b45ec mov eax, dword [local_14h]
71+
| :| 0x080486ce 01d0 add eax, edx
72+
| :| 0x080486d0 0fb600 movzx eax, byte [eax]
73+
| :| 0x080486d3 31c8 xor eax, ecx
74+
| :| 0x080486d5 8845e3 mov byte [local_1dh], al
75+
| :| 0x080486d8 8b1538a00408 mov edx, dword obj.greetingMessage ; [0x804a038:4]=0x80487f0 str.You_have_now_entered_the_Duck_Web__and_you_re_in_for_a_honkin__good_time.__Can_you_figure_out_my_trick
76+
| :| 0x080486de 8b45e8 mov eax, dword [local_18h]
77+
| :| 0x080486e1 01d0 add eax, edx
78+
| :| 0x080486e3 0fb600 movzx eax, byte [eax]
79+
| :| 0x080486e6 3a45e3 cmp al, byte [local_1dh]
80+
| ,===< 0x080486e9 7504 jne 0x80486ef
81+
| |:| 0x080486eb 8345e401 add dword [local_1ch], 1
82+
| |:| ; CODE XREF from sym.do_magic (0x80486e9)
83+
| `---> 0x080486ef 837de419 cmp dword [local_1ch], 0x19 ; [0x19:4]=-1 ; 25
84+
| ,===< 0x080486f3 7512 jne 0x8048707
85+
| |:| 0x080486f5 83ec0c sub esp, 0xc
86+
| |:| 0x080486f8 68ab880408 push str.You_are_winner ; 0x80488ab ; "You are winner!"
87+
| |:| 0x080486fd e86efdffff call sym.imp.puts ; int puts(const char *s)
88+
| |:| 0x08048702 83c410 add esp, 0x10
89+
| ,====< 0x08048705 eb0c jmp 0x8048713
90+
| ||:| ; CODE XREF from sym.do_magic (0x80486f3)
91+
| |`---> 0x08048707 8345e801 add dword [local_18h], 1
92+
| | :| ; CODE XREF from sym.do_magic (0x80486bb)
93+
| | :`-> 0x0804870b 8b45e8 mov eax, dword [local_18h]
94+
| | : 0x0804870e 3b45f0 cmp eax, dword [local_10h]
95+
| | `==< 0x08048711 7caa jl 0x80486bd
96+
| `----> 0x08048713 c9 leave
97+
\ 0x08048714 c3 ret
98+
```
99+
100+
Let's take a look what is necessary to get to `puts("You are winner!");` address. We see that we need to pass this test where _ebp + 0x1c_ must be equals to _0x19_.
101+
102+
103+
```asm
104+
0x080486ef 837de419 cmp dword [local_1ch], 0x19 ; [0x19:4]=-1 ; 25
105+
...
106+
0x080486f8 68ab880408 push str.You_are_winner ; 0x80488ab ; "You are winner!"
107+
0x080486fd e86efdffff call sym.imp.puts ; int puts(const char *s)
108+
```
109+
110+
Looking around the assembly, we can see that there is an instruction that adds _1_ to _ebp + 0x1c_.
111+
112+
```asm
113+
0x080486eb 8345e401 add dword [local_1ch], 1
114+
```
115+
116+
We also notice that there is a loop at the bottom of the assembly.
117+
118+
```asm
119+
; CODE XREF from sym.do_magic (0x80486f3)
120+
0x08048707 8345e801 add dword [local_18h], 1
121+
; CODE XREF from sym.do_magic (0x80486bb)
122+
0x0804870b 8b45e8 mov eax, dword [local_18h]
123+
0x0804870e 3b45f0 cmp eax, dword [local_10h]
124+
0x08048711 7caa jl 0x80486bd
125+
```
126+
127+
Debugging the program, we can see that the number of loops it does corresponds to the number of characters inputted.
128+
129+
We also see that there's an XOR function, where _eax_ is the characters you put in and _ecx_ are the characters provided by the binary.
130+
131+
```asm
132+
0x080486d3 31c8 xor eax, ecx
133+
```
134+
135+
Putting everything together, it is trying to loop through every character in the input, xor it with the characters in the binary make sure it equates to the initial message. The initial message is: _You have now entered the Duck Web, and you're in for a honkin' good time._
136+
137+
Writing some pseudo code, it will look something like this
138+
139+
```
140+
count = 0
141+
for (i = 0; i < length_of_user_input; i++) {
142+
data = user_input[i] xor binary_data[i]
143+
if (data == initial_message[i]) {
144+
count += 1
145+
}
146+
if (count == 25) {
147+
print "You are winner!"
148+
}
149+
}
150+
```
151+
152+
Let's leak the values of the binary string. We see that the string is located in here
153+
154+
```asm
155+
0x080486c0 0558880408 add eax, obj.sekrutBuffer
156+
```
157+
Get the value from the address
158+
159+
```asm
160+
[0x08048642]> px @ obj.sekrutBuffer
161+
- offset - 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF
162+
0x08048858 2906 164f 2b35 301e 511b 5b14 4b08 5d2b )..O+50.Q.[.K.]+
163+
0x08048868 5014 5d00 1917 5952 5d00 4e6f 206c 696e P.]...YR].No lin
164+
```
165+
166+
We only need the first 25 bytes. We can then use a Python program to XOR the data ourselves and get the flag.
167+
168+
```python
169+
initialMsg = "You have now entered the Duck Web, and you're in for a honkin' good time."
170+
xorData = '2906164f2b35301e511b5b144b085d2b50145d00191759525d'.decode('hex')
171+
172+
flag = ''
173+
for i in range(len(xorData)):
174+
flag += chr(ord(xorData[i]) ^ ord(initialMsg[i]))
175+
176+
print flag
177+
```
178+
179+
And we get the flag! Just to confirm, we can pass the flag into the binary
180+
181+
```
182+
$ ./main
183+
You have now entered the Duck Web, and you're in for a honkin' good time.
184+
Can you figure out my trick?
185+
picoCTF{qu4ckm3_5f8d9c17}
186+
You are winner!
187+
That's all folks.
188+
```
189+
190+
And there we go. This took me 1 whole day to solve. I hate reversing.
15191

16192
### Flag
17-
``
193+
`picoCTF{qu4ckm3_5f8d9c17}`

Reversing/quackme/solution/solve.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/usr/bin/python
2+
3+
initialMsg = "You have now entered the Duck Web, and you're in for a honkin' good time."
4+
xorData = '2906164f2b35301e511b5b144b085d2b50145d00191759525d'.decode('hex')
5+
6+
flag = ''
7+
for i in range(len(xorData)):
8+
flag += chr(ord(xorData[i]) ^ ord(initialMsg[i]))
9+
10+
print flag

0 commit comments

Comments
 (0)