C’est la rentrée
Académie de l’investigation - C’est la rentrée was an easy challenge and the first part of a series of forensic challenges (50 pts for this first part).
Bienvenue à l’académie de l’investigation numérique ! Votre mission, valider un maximum d’étapes de cette série afin de démontrer votre dextérité en analyse mémoire GNU/Linux. Première étape : retrouvez le HOSTNAME, le nom de l’utilisateur authentifié lors du dump et la version de Linux sur lequel le dump a été fait. Format du flag : FCSC{hostname:user:x.x.x-x-amdxx}
We have to find the hostname, authenticated user and kernel version of a given memory dump.
C’est la rentrée: Exploit
Volatility doesn’t have any Linux profile by default, and we don’t know the kernel version of this memory dump (That’s the point of the challenge).
So, we gonna have to use the best CTF tool: strings
!
First of all, let’s search for the hostname:
magnussen@funcMyLife:~/cestlarentree$ strings dmp.mem | grep hostname:
%sset-hostname: hostname set via dbus failed, fallback to "sethostname"
%sset-hostname: couldn't set the system hostname to '%s': (%d) %s
%sset-hostname: you should use hostnamed when systemd hardening is in effect!
%sget-hostname: "%s" (last on set)
%sget-hostname: "%s" (from dbus)
%sget-hostname: couldn't get the system hostname: (%d) %s
%sget-hostname: system hostname too long: "%s"
%sget-hostname: "%s"
MESSAGE=<info> [1585265017.0294] hostname: hostname changed from (none) to "challenge.fcsc"
MESSAGE=<info> [1585265017.0294] hostname: hostname: using hostnamed
27 00:23:37 NetworkManager[636]: <info> [1585265017.0294] hostname: hostname changed from (none) to "challenge.fcsc"
-[27 00:23:37 NetworkManager[636]: <info> [1585265017.0294] hostname: hostname: using hostnamed1'
Good, now let’s check for the user, we know the hostname, so it’ll be pretty simple to find the authenticated user, let’s search for a prompt:
magnussen@funcMyLife:~/cestlarentree$ strings dmp.mem | grep @challenge
Lesage@challenge: ~/Documents 129x37
Lesage@challenge: ~/Documents/temp
Lesage@challenge: ~/Documents/temp 129x37
Lesage@challenge: ~/Documents/temp
)}root@challenge:~#
Lesage@challenge: ~e
Lesage@challenge: ~e
Lesage@challenge: ~e
Two out of three! Let’s get that kernel version! Let’s check for boot images:
magnussen@funcMyLife:~/cestlarentree$ strings dmp.mem | grep BOOT
BOOT_IMAGE=/boot/vmlinuz-5.4.0-4-amd64 root=UUID=536c82dd-f1c5-43ce-b65d-c94e5c4a5031 ro quiet
TIMESTAMP_BOOTTIME=905.989541
TIMESTAMP_BOOTTIME=905.989548
TIMESTAMP_BOOTTIME=905.989555
TIMESTAMP_BOOTTIME=10505.644058
TIMESTAMP_BOOTTIME=10505.644124
BOOTUP_THEMEI
BOOTUP_THEMEq
NOTICE BOOTSTRAP PROGRESS=100 TAG=done SUMMARY="Done"
Nice! We have everything, just have to format the flag and submit it!
FCSC{challenge.fcsc:Lesage:5.4.0-4-amd64}
This was an easy challenge to get started in the forensic category. It allows us to find the kernel version in order to create a volatility profile that we’ll be useful for the other challenges.
Porte Dérobée
Académie de l’investigation - Porte Dérobée was an easy challenge and the second part of a series of forensic challenges (50 pts for this second part).
Un poste distant est connecté au poste en cours d’analyse via une porte dérobée avec la capacité d’exécuter des commandes. Quel est le numéro de port à l’écoute de cette connexion ? Quelle est l’adresse IP distante connectée au moment du dump ? Quel est l’horodatage de la création du processus en UTC de cette porte dérobée ? Format du flag : FCSC{port:IP:YYYY-MM-DD HH:MM:SS}
There’s a backdoor on the computer we’re analyzing, we have to find the listening port, the source ip of this backdoor and when this process was created.
Porte Dérobée: Exploit
I’ve created a volatility profile in order to analyze this memory dump (The profile is based on a Debian 9.2.1 with 5.4.0-4-amd64 kernel).
If you want to see the steps to create a Linux volatility profile, you can read Onosh’s write-up
Let’s enumerate the established connection at the time of the memory dump with volatility:
magnussen@funcMyLife:~/portederobee$ python /home/magnussen/tools/volatility/vol.py -f dmp.mem --profile LinuxDebianx64 linux_netstat | grep ESTABLISHED
Volatility Foundation Volatility Framework 2.6.1
TCP 10.42.42.131 :36970 116.203.52.118 : 443 ESTABLISHED tor/706
TCP 10.42.42.131 :37252 163.172.182.147 : 443 ESTABLISHED tor/706
TCP fd:6663:7363:1000:c10b:6374:25f:dc37:36280 fd:6663:7363:1000:55cf:b9c6:f41d:cc24:58014 ESTABLISHED ncat/1515
TCP 10.42.42.131 :47106 216.58.206.226 : 443 ESTABLISHED chromium/119187
TCP 10.42.42.131 :55224 151.101.121.140 : 443 ESTABLISHED chromium/119187
TCP 10.42.42.131 :55226 151.101.121.140 : 443 ESTABLISHED chromium/119187
TCP 10.42.42.131 :53190 104.124.192.89 : 443 ESTABLISHED chromium/119187
TCP 10.42.42.131 :45652 35.190.72.21 : 443 ESTABLISHED chromium/119187
TCP 10.42.42.131 :47102 216.58.206.226 : 443 ESTABLISHED chromium/119187
TCP 10.42.42.131 :47104 216.58.206.226 : 443 ESTABLISHED chromium/119187
TCP 10.42.42.131 :38186 216.58.213.142 : 443 ESTABLISHED chromium/119187
TCP 10.42.42.131 :47100 216.58.206.226 : 443 ESTABLISHED chromium/119187
TCP 10.42.42.131 :50612 104.93.255.199 : 443 ESTABLISHED chromium/119187
TCP 10.42.42.131 :58772 185.199.111.154 : 443 ESTABLISHED chromium/119187
TCP 10.42.42.131 :38184 216.58.213.142 : 443 ESTABLISHED chromium/119187
TCP 10.42.42.131 :57000 10.42.42.134 : 22 ESTABLISHED ssh/119468
TCP fd:6663:7363:1000:c10b:6374:25f:dc37:36280 fd:6663:7363:1000:55cf:b9c6:f41d:cc24:58014 ESTABLISHED sh/119511
TCP 127.0.0.1 :38498 127.0.0.1 :34243 ESTABLISHED cli/119514
TCP 127.0.0.1 :34243 127.0.0.1 :38498 ESTABLISHED cli/119514
TCP 10.42.42.131 :51858 10.42.42.128 : 445 ESTABLISHED smbclient/119577
Ok so we see that a connection from fd:6663:7363:1000:55cf:b9c6:f41d:cc24 was established on the port 36280 and that the process is netcat, this process is frequently used by reverse shell.
We know the attacker address and the port the backdoor uses, we just have to find when the process started, let’s use its PID to do so.
magnussen@funcMyLife:~/portederobee$ python /home/magnussen/tools/volatility/vol.py -f dmp.mem --profile LinuxDebianx64 linux_pslist -p 1515
Volatility Foundation Volatility Framework 2.6.1
Offset Name Pid PPid Uid Gid DTB Start Time
------------------ -------------------- --------------- --------------- --------------- ------ ------------------ ----------
0xffff9d72c014be00 ncat 1515 1513 1001 1001 0x000000003e3d0000 2020-03-26 23:24:20 UTC+0000
Nice, we have our flag!
FCSC{36280:fd:6663:7363:1000:55cf:b9c6:f41d:cc24:2020-03-26 23:24:20}
This was an easy challenge, the hardest part was to create the volatility profile to analyze the memory dump.
Administration
Académie de l’investigation - Administration was an easy challenge and the fourth part of a series of Forensic challenges (50 pts for this fourth part).
Ce poste administre un serveur distant avec le protocole SSH à l’aide d’une authentification par clé (clé protégée par mot de passe). La clé publique a été utilisée pour chiffrer le message ci-joint (flag.txt.enc). Retrouvez et reconstituez la clé en mémoire qui permettra de déchiffrer ce message. Le fichier de dump à analyser est identique au challenge C’est la rentrée.
We have a file that was signed with the public ssh key and we have to read the content of this file.
Administration: Exploit
The file was encrypted with the public RSA key (signed), we have to find the private key to decrypt it.
Let’s use rsakeyfind
to find the private key:
magnussen@funcMyLife:~/administration$ rsakeyfind dmp.mem
FOUND PRIVATE KEY AT c64ac50
version =
00
modulus =
00 d7 1e 77 82 8c 92 31 e7 69 02 a2 d5 5c 78 de
a2 0c 8f fe 28 59 31 df 40 9c 60 61 06 b9 2f 62
40 80 76 cb 67 4a b5 59 56 69 17 07 fa f9 4c bd
6c 37 7a 46 7d 70 a7 67 22 b3 4d 7a 94 c3 ba 4b
7c 4b a9 32 7c b7 38 95 45 64 a4 05 a8 9f 12 7c
4e c6 c8 2d 40 06 30 f4 60 a6 91 bb 9b ca 04 79
11 13 75 f0 ae d3 51 89 c5 74 b9 aa 3f b6 83 e4
78 6b cd f9 5c 4c 85 ea 52 3b 51 93 fc 14 6b 33
5d 30 70 fa 50 1b 1b 38 81 13 8d f7 a5 0c c0 8e
f9 63 52 18 4e a9 f9 f8 5c 5d cd 7a 0d d4 8e 7b
ee 91 7b ad 7d b4 92 d5 ab 16 3b 0a 8a ce 8e de
47 1a 17 01 86 7b ab 99 f1 4b 0c 3a 0d 82 47 c1
91 8c bb 2e 22 9e 49 63 6e 02 c1 c9 3a 9b a5 22
1b 07 95 d6 10 02 50 fd fd d1 9b be ab c2 c0 74
d7 ec 00 fb 11 71 cb 7a dc 81 79 9f 86 68 46 63
82 4d b7 f1 e6 16 6f 42 63 f4 94 a0 ca 33 cc 75
13
publicExponent =
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 01
privateExponent =
62 b5 60 31 4f 3f 66 16 c1 60 ac 47 2a ff 6b 69
00 4a b2 5c e1 50 b9 18 74 a8 e4 dc a8 ec cd 30
bb c1 c6 e3 c6 ac 20 2a 3e 5e 8b 12 e6 82 08 09
38 0b ab 7c b3 cc 9c ce 97 67 dd ef 95 40 4e 92
e2 44 e9 1d c1 14 fd a9 b1 dc 71 9c 46 21 bd 58
88 6e 22 15 56 c1 ef e0 c9 8d e5 80 3e da 7e 93
0f 52 f6 f5 c1 91 90 9e 42 49 4f 8d 9c ba 38 83
e9 33 c2 50 4f ec c2 f0 a8 b7 6e 28 25 56 6b 62
67 fe 08 f1 56 e5 6f 0e 99 f1 e5 95 7b ef eb 0a
2c 92 97 57 23 33 36 07 dd fb ae f1 b1 d8 33 b7
96 71 42 36 c5 a4 a9 19 4b 1b 52 4c 50 69 91 f0
0e fa 80 37 4b b5 d0 2f b7 44 0d d4 f8 39 8d ab
71 67 59 05 88 3d eb 48 48 33 88 4e fe f8 27 1b
d6 55 60 5e 48 b7 6d 9a a8 37 f9 7a de 1b cd 5d
1a 30 d4 e9 9e 5b 3c 15 f8 9c 1f da d1 86 48 55
ce 83 ee 8e 51 c7 de 32 12 47 7d 46 b8 35 df 41
prime1 =
00
prime2 =
00
exponent1 =
00
exponent2 =
00
coefficient =
00
FOUND PRIVATE KEY AT 1084c490
version =
00
modulus =
00 d7 1e 77 82 8c 92 31 e7 69 02 a2 d5 5c 78 de
a2 0c 8f fe 28 59 31 df 40 9c 60 61 06 b9 2f 62
40 80 76 cb 67 4a b5 59 56 69 17 07 fa f9 4c bd
6c 37 7a 46 7d 70 a7 67 22 b3 4d 7a 94 c3 ba 4b
7c 4b a9 32 7c b7 38 95 45 64 a4 05 a8 9f 12 7c
4e c6 c8 2d 40 06 30 f4 60 a6 91 bb 9b ca 04 79
11 13 75 f0 ae d3 51 89 c5 74 b9 aa 3f b6 83 e4
78 6b cd f9 5c 4c 85 ea 52 3b 51 93 fc 14 6b 33
5d 30 70 fa 50 1b 1b 38 81 13 8d f7 a5 0c c0 8e
f9 63 52 18 4e a9 f9 f8 5c 5d cd 7a 0d d4 8e 7b
ee 91 7b ad 7d b4 92 d5 ab 16 3b 0a 8a ce 8e de
47 1a 17 01 86 7b ab 99 f1 4b 0c 3a 0d 82 47 c1
91 8c bb 2e 22 9e 49 63 6e 02 c1 c9 3a 9b a5 22
1b 07 95 d6 10 02 50 fd fd d1 9b be ab c2 c0 74
d7 ec 00 fb 11 71 cb 7a dc 81 79 9f 86 68 46 63
82 4d b7 f1 e6 16 6f 42 63 f4 94 a0 ca 33 cc 75
13
publicExponent =
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 01
privateExponent =
62 b5 60 31 4f 3f 66 16 c1 60 ac 47 2a ff 6b 69
00 4a b2 5c e1 50 b9 18 74 a8 e4 dc a8 ec cd 30
bb c1 c6 e3 c6 ac 20 2a 3e 5e 8b 12 e6 82 08 09
38 0b ab 7c b3 cc 9c ce 97 67 dd ef 95 40 4e 92
e2 44 e9 1d c1 14 fd a9 b1 dc 71 9c 46 21 bd 58
88 6e 22 15 56 c1 ef e0 c9 8d e5 80 3e da 7e 93
0f 52 f6 f5 c1 91 90 9e 42 49 4f 8d 9c ba 38 83
e9 33 c2 50 4f ec c2 f0 a8 b7 6e 28 25 56 6b 62
67 fe 08 f1 56 e5 6f 0e 99 f1 e5 95 7b ef eb 0a
2c 92 97 57 23 33 36 07 dd fb ae f1 b1 d8 33 b7
96 71 42 36 c5 a4 a9 19 4b 1b 52 4c 50 69 91 f0
0e fa 80 37 4b b5 d0 2f b7 44 0d d4 f8 39 8d ab
71 67 59 05 88 3d eb 48 48 33 88 4e fe f8 27 1b
d6 55 60 5e 48 b7 6d 9a a8 37 f9 7a de 1b cd 5d
1a 30 d4 e9 9e 5b 3c 15 f8 9c 1f da d1 86 48 55
ce 83 ee 8e 51 c7 de 32 12 47 7d 46 b8 35 df 41
prime1 =
00
prime2 =
00
exponent1 =
00
exponent2 =
00
coefficient =
00
Ok, we just have to recreate the key pair and dump the private key, here’s the python script:
#!/usr/bin/python3
from Crypto.PublicKey import RSA
n = 27156259324364494546819374388173785636458745291644993656824052031192832665358626503824931967165063745738985155119632190909321739257721575254417781138851315918480436949082522936024649499965168635833472768161976247672142217286254570819498806298839620160775476215759967149684677314805111395364593027482965588868928996365215081601336731466193713741949208719563914532447046849652165136410573886954569273298157849675625380629094578684611548488935568178937156287424712755109581855128863319366210889843193945634323967939306175015830804489787158898856492500262280275347410451775447871929463819519225112797600024987362493494547
e = 65537
d = 12460793603648154172634576294324764356921851601543376249263971385355308664001474224072254667082530432608492326239491878557534268321073641012723370224568362486847791322959696503229217995375933460744071182449104318476534793448468002100858570014170698345588600649409245649408999743821342293382425828500964969230457875702866061208039614953232618242245516551805487351387027773141972856162319523928419780405972969066802476877491166892646959172911316485769848621265023891332664138536799344975526764381672350159251366511979950064130731366992390823381013182186815338822199229913107286819591289270388870750262162515570617343809
private_key = RSA.construct((n, e, d))
with open('private.pem', "wb") as target:
target.write(private_key.exportKey())
We have the private key, let’s use openssl
to decrypt the flag.txt.enc file.
magnussen@funcMyLife:~/administration$ openssl rsautl -decrypt -inkey private.pem -in flag.txt.enc -out flag.txt
magnussen@funcMyLife:~/administration$ cat flag.txt
FCSC{ac5cad66114d4866a4b55e43cb8896cc4947855241b5af8d2f8a123c36083d98}
Yeah! We have our flag!
This was an easy challenge, the hardest part was to find the good tool to extract the key.
Premiers artéfacts
Académie de l’investigation - Premiers artéfacts was a medium challenge and the fifth part of a series of Forensic challenges (200 pts for this first part).
Pour avancer dans l’analyse, vous devez retrouver : Le nom de processus ayant le PID 1254. La commande exacte qui a été exécutée le 2020-03-26 23:29:19 UTC. Le nombre d’IP-DST unique en communications TCP établies (état ESTABLISHED) lors du dump. Format du flag : FCSC{nom_du_processus:une_commande:n}
We have to find the process with the PID 1254, the command executed at 2020-03-26 23:29:19 UTC and the number of established connection.
Premiers artéfacts: Exploit
Let’s use our volatility profile to retrieve the name of the process with the PID 1254:
magnussen@funcMyLife:~/premierartefact$ python /home/magnussen/tools/volatility/vol.py -f dmp.mem --profile LinuxDebianx64 linux_psxview |grep 1254
Volatility Foundation Volatility Framework 2.6.1
INFO : volatility.debug : SLUB is currently unsupported.
0x000000003fdccd80 pool-xfconfd 1254 False True False False False False
For the command executed at 2020-03-26 23:29:19 UTC, we’ll use linux_bash
:
magnussen@funcMyLife:~/premierartefact$ python /home/magnussen/tools/volatility/vol.py -f dmp.mem --profile LinuxDebianx64 linux_bash
Volatility Foundation Volatility Framework 2.6.1
Pid Name Command Time Command
-------- -------------------- ------------------------------ -------
1523 bash 2020-03-26 23:24:18 UTC+0000 rm .bash_history
1523 bash 2020-03-26 23:24:18 UTC+0000 exit
1523 bash 2020-03-26 23:24:18 UTC+0000 vim /home/Lesage/.bash_history
1523 bash 2020-03-26 23:24:27 UTC+0000 ss -laupt
1523 bash 2020-03-26 23:26:06 UTC+0000 rkhunter -c
1523 bash 2020-03-26 23:29:19 UTC+0000 nmap -sS -sV 10.42.42.0/24
1523 bash 2020-03-26 23:31:31 UTC+0000 ?+??U
1523 bash 2020-03-26 23:31:31 UTC+0000 ip -c addr
1523 bash 2020-03-26 23:38:00 UTC+0000 swapoff -a
1523 bash 2020-03-26 23:38:05 UTC+0000 swapon -a
1523 bash 2020-03-26 23:40:18 UTC+0000 ls
1523 bash 2020-03-26 23:40:23 UTC+0000 cat LiME.txt
1523 bash 2020-03-26 23:40:33 UTC+0000 cd LiME/src/
1523 bash 2020-03-26 23:40:54 UTC+0000
1523 bash 2020-03-26 23:40:54 UTC+0000 insmod lime-5.4.0-4-amd64.ko "path=/dmp.mem format=lime timeout=0"
So the command is nmap -sS -sV 10.42.42.0/24
.
We just have to find the ESTABLISHED connection, let’s use linux_netstat
.
magnussen@funcMyLife:~/premierartefact$ python /home/magnussen/tools/volatility/vol.py -f dmp.mem --profile LinuxDebianx64 linux_netstat | grep ESTABLISHED | awk '{print $4}' | sort | uniq | wc -l
Volatility Foundation Volatility Framework 2.6.1
13
So the flag is: FCSC{pool-xfconfd:nmap -sS -sV 10.42.42.0/24:13}
Nice challenge, as for the previous ones, the hardest part was to create the volatility profile.
Thanks to the FCSC team, this was an awesome CTF, I’ve learned a lot and had a lot of fun. Congratulation for the organization, see you next year!