By Austin Jackson from Cyborg Security

Last weekend, Cyborg Security hosted our first Capture the Flag (CTF) event. The CTF was oriented for people interested in threat hunting, cyber defense, blue team, network traffic analysis, malware analysis, and forensics. There were challenges for beginners and more experienced players alike. Congratulations to the teams copo.banget and deadPix3l for a 1st place tie with a high score of 560 points! The solutions for all of the CTF challenges are below. We really enjoyed putting on this CTF event and we look forward to hosting more blue team oriented CTF events in the future.


Challenge text: I think a spider may have crept into the Cyborg Security logo, could you help me get him out?

The Cyborg Security logo in PNG format was given:

Image for post
Image for post

By using binwalk an additional PNG is found to be hiding in the logo file:

$ binwalk --dd='.*' Cyborg_Logo.pngDECIMAL       HEXADECIMAL     DESCRIPTION
0 0x0 PNG image, 500 x 424, 8-bit/color RGBA, non-interlaced
41 0x29 Zlib compressed data, best compression
145201 0x23731 PNG image, 620 x 442, 8-bit/color RGB, non-interlaced
145329 0x237B1 Zlib compressed data, compressed
$ cd _Cyborg_Logo.png.extracted/ && file *
0: PNG image data, 500 x 424, 8-bit/color RGBA, non-interlaced
29: empty
29-0: zlib compressed data
237B1: empty
237B1-0: zlib compressed data
23731: PNG image data, 620 x 442, 8-bit/color RGB, non-interlaced

The hidden PNG is Lucas the Spider, not so intimidating after all…

Image for post
Image for post

By checking the Exif data of the picture, an interesting comment is found which can then be base64 decoded to discover the flag.

$ exiftool 23731 | grep -i comment
Comment : Q3lib3JnQ1RGe2x1YzRzXzFzXzRfbjFjM19zcDFkM3JfdGgwfQo=
$ echo "Q3lib3JnQ1RGe2x1YzRzXzFzXzRfbjFjM19zcDFkM3JfdGgwfQo=" | base64 -d

The flag is: CyborgCTF{luc4s1s4n1c3sp1d3r_th0}


Challenge text: This partial Linux disk image is hiding a flag, can you find it?

A partial Linux ext4 file system image is given. It can be mounted and found to only contain the /run directory.

$ file i_dont_run_fast.img 
i_dont_run_fast.img: Linux rev 1.0 ext4 filesystem data, UUID=8c732098-890a-4939-868d-85f380b893c4 (extents) (64bit) (large files) (huge files)
$ sudo mount i_dont_run_fast.img /mnt/
$ ls /mnt/

Searching recursively for the flag format discovers a file containing the flag within a systemd path.

sudo grep -r "CyborgCTF" /mnt/run/

The flag is: CyborgCTF{n3wf1l3syst3mwh0d1s}


Challenge text: I think my EXE is corrupted, maybe there’s still something useful inside?

You can use a variety of tools to find interesting static strings in this corrupted binary such as strings, FLOSS, or a hex editor. By inspecting the strings it can be determined that this binary is a Rust compiled executable for Windows that is at least missing a file header.

There are two interesting stings that appear to be base64 encoded:

$ strings corrupttt.exe | grep -E '[A-Za-z0-9+/]{4}*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)'

When appended and base64 decoded, the flag is discovered:

$ echo "Q3lib3JnQ1RGezFfaDR0M18xdF93aDNuX215X2IxbnpfZzN0X2MwcnJ1cHQzZH0=" | base64 -d

The flag is: CyborgCTF{1h4t31twh3nmyb1nzg3t_c0rrupt3d}


Challenge text: My Neuralink went down, now all I got is this crummy old Nextel. What was the password to unlock it again?

The given file call_me_on_my_neuralink is a Linux ELF:

$ file call_me_on_my_neuralink
call_me_on_my_neuralink: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/,
BuildID[sha1]=633e63ae6e6a7021d175a461e867954c450d9f25, for GNU/Linux 3.2.0, not strippe

When executed, a password is wanted:

Image for post
Image for post

By opening the binary in a disassembler such as IDA we can see that the program control flow to “ACCESS GRANTED” versus “ACCESS DENIED” is dependent on the output of the ring_ring function:

Image for post
Image for post

Here’s a decompilation of the ring_ring function:

Image for post
Image for post

An array of data is pushed onto the stack and then that data is compared to the user input. The comparison happens in reverse order and the stored data is XOR’d by 99 (0x63 in hex) before compared. By taking the stored data and reversing these operations the flag is discovered.

>>> data = [30, 15, 80, 23, 27, 80, 13, 60, 26, 14, 60, 13, 83, 60, 80, 14, 60, 15, 15, 87, 0, 60, 83, 23, 60, 7, 80, 16, 22, 60, 80, 11, 16, 24, 37, 55, 32, 4, 17, 12, 1, 26, 32]
>>> ''.join([chr(i ^ 0x63) for i in data[::-1]])

The flag is: CyborgCTF{sh3us3dt0c4llm30nmy_n3xt3l}


Challenge text: Some evil Schwansomware encrypted my favorite picture! Help me get it back? One of our forensic analysts looked at the malware and told us this number might important: 1585613911

A Linux ELF and an encrypted file are given:

$ file Schwansomware*
Schwansomware: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/,
BuildID[sha1]=c1a01dc366cc2c0060524c7a948c8571ee1fc4ca, for GNU/Linux 3.2.0, not stripped
Schwansomware.enc: data

By decompiling the main function using IDA the logic of the program can be understood:

Image for post
Image for post

The encrypted file was originally Schwansomware.jpg and was encrypted using an array of random data that was seeded using a known epoch time (1585613911). This array of random data is the same length as the original file and was byte by byte XOR’d with the bytes of the original file.

In order to recover this encrypted file we can write some C code to re-create the “random” stream of data with the same seed.

#include <stdio.h>
#include <stdlib.h>
int main()
$ du -b Schwansomware.enc
657099 Schwansomware.enc
unsigned char *stream = malloc(657099);
for (int i = 0; i < 657099; i++) {
stream[i] = rand();
printf("%d ", stream[i]);
return 0;
$ gcc gen_srand_array.c
$ ./a.out > Schwansomware_array.txt

Now we can reverse the XOR operation on our encrypted file to recover the JPG. This can be done in a variety of ways, in Python for example:

with open('Schwansomware.enc', 'rb') as f:
encrypted_bytes = [i for i in]
with open('Schwansomware_array.txt', 'r') as f:
srand_bytes = list(map(int,
outf = []
for a, b in zip(encrypted_bytes, srand_bytes):
outf.append(a ^ b)
with open('Schwansomware.jpg', 'wb') as f:

With the picture now recovered, the flag can be seen:

Image for post
Image for post

The flag is: CyborgCTF{n0pr0bl3m0b4by}


Challenge text: N/A

A PCAP file is given which contains many HTTP requests. Almost all of the HTTP requests are POST requests.

Image for post
Image for post

Using the hint from the challenge title we can search specifically for HTTP GET requests by doing http.request.method=="GET".

Image for post
Image for post

Only one HTTP GET request is present, by following the TCP stream we discover a base64 encoded string. By decoding the string a flag is discovered.

echo "Q3lib3JnQ1RGe2QwX3kwdV9nM3RfMXRfbjB3fQo=" | base64 -d

The flag is: CyborgCTF{d0y0ug3t1tn0w}


Challenge text: N/A

A PCAP file is given which contains many DNS requests.

Image for post
Image for post

Using a tshark and some bashfu we can combine all of these domains together, strip of the TLD, and then base64 decode to discover the flag.

$ tshark -r dns_on_a_roll.pcapng -T fields -e -2R "dns.flags.response eq 0" | cut -d'.' -f1 | tr -d '\n' | base64 -d
We're no strangers to love
You know the rules and so do I
A full commitment's what I'm thinking of
You wouldn't get this from any other guy
I just wanna tell you how I'm feeling
Gotta make you understand
Never gonna give you up
Never gonna let you down
Never gonna run around and desert you
Never gonna make you cry
Never gonna say CyborgCTF{th3_0l3_dns_r1ckr0ll}
Never gonna tell a lie and hurt you

The flag is: CyborgCTF{th30l3dns_r1ckr0ll}


Challenge text: We’ve intercepted a communication stream between a rogue cyborg and an unknown accomplice. Can you figure out what they are talking about?

A PCAP file is given which contains one plain-jane TCP stream and two Websocket TCP streams. The Websocket data is encrypted.

Image for post
Image for post

By following the first TCP stream a password is discovered super-secret-passcode.

Image for post
Image for post

By looking at the Websocket communication the encrypted payloads are seen within the “Line-based text data” field of the packets:

Image for post
Image for post

All of these encrypted fields can be extracted using tshark:

$ tshark -r we4thertenko.pcapng -Y websocket -T fields -e text > websocket_dump.txt

The 4 in We4thertenko was a hint to use RC4 decryption. Using a RC4 Python implementation from GitHub, the websocket dump created above, and some Pythonfu we can decrypt the encrypted conversation to discover the flag.

$ python -i
>>> rc4_decrypt = decrypt
>>> websocket_dump = open('websocket_dump.txt').read().splitlines()
>>> websocket_data = [i.split(',')[1].strip(' [truncated]') for i in websocket_dump if ',' in i]
>>> websocket_data
'F37DF253A20549EB7A4F7202943D7EC73172481510B6E6D26DAB5E45AACB1E81C49046201014E2F602547F9345BCED861304F31611', ... ]
>>> websocket_data_decrypt = [rc4_decrypt('super-secret-passcode', i) for i in websocket_data]
>>> websocket_data_decrypt
['{"sysid": "ODRjNWE2MWQyZjlm\\n", "message": "SGVsbG8sIHRoaXMgaXMgTXIuIFg=\\n"}', '{"message": "SGVsbG8gTXIuIFgsIHRoaXMgaXMgTXIuIFk=\\n"}', ... ]
>>> import base64, json
>>> for i in websocket_data_decrypt:
... try:
... base64.b64decode(json.loads(i)['message'])
... except: pass
b'Hello, this is Mr. X'
b'Hello Mr. X, this is Mr. Y'
b'Hello Mr. X, this is Mr. Y'
b'Please Code in'
b'Please Code in'
b'Code Weathertenko'
b'Thank you, code confirmed'
b'Thank you, code confirmed'
b'Please proceed with your message'
b'Please proceed with your message'
b'Stand by for passcode'
b'Stand by for passcode'
b'Thank you commander'
b'Hail hydra, this chatroom will no self-destruct'
b'Hail hydra, this chatroom will no self-destruct'

The flag is: CyborgCTF{w3bs0ck3tm1ss1l3s4r34g0}


Challenge text: The malware used in a cyberattack against the Ukrainian power grid in 2016 has a wiper component that is always named what?

The malware used in the cyberattack against the Ukrainian power grid in 2016 is called Industroyer (also known as CRASHOVERRIDE). A fantastic report on Industroyer was done by Anton Cherepanov of ESET. In the report on page 5 and 13 you can find information about the data wiper component, “The Data wiper component is always named haslo.dat.”

The flag is: CyborgCTF{haslo.dat}


Challenge text: What is the last name of the person who created a credential harvesting tool used last year to kick a few hornets nests?

The hint here is to search for hornets nest and credential harvesting using a search engine. If you search “hornets nest credential harvesting” on Google the first link is “Untangling Legion Loader’s Hornet Nest of Malware” by Shaul Vilkomir-Preisman from Deep Instinct. In the report one piece of the malware downloads and reflectively loads an credential harvesting tool called SharpWeb which is open-source on GitHub. The authors name can easily be found via the GitHub repository, Dwight Hohnstein.

The flag is: CyborgCTF{Hohnstein}


Challenge text: If the Snatch Ransomware was a Marvel character what would their name be?

Many reports can be found on the Snatch Ransomware, such as the report from the Carbon Black Threat Analysis Unit (TAU). In the report you’ll find that the ransomware names its windows service and registry key that it uses for persistence as SuperBackupMan.

The flag is: CyborgCTF{SuperBackupMan}


Challenge text: An APT group implicated in the hacking of the Democratic National Committee (DNC) re-emerged in late 2019, their new third-stage backdoor executable is named what?

One of the APT groups implicated in the hacking of the DNC was Cozy Bear (also known as APT29). In late 2019 ESET released a great report on the re-emergence of APT29, OPERATION GHOST The Dukes aren’t back — they never left. In the report on page 24 there are details about FatDuke the third stage backdoor executable which is named Canocpc.exe.

The flag is: CyborgCTF{Canocpc.exe}


Challenge text: Who’s ya sauce?

By viewing the HTML source code of the CTF main page there’s a comment with the flag…

$ curl -s | grep CyborgCTF
<!-- CyborgCTF{w3lc0m3_t0_th3_b33p_b00p} -->

The flag is: CyborgCTF{w3lc0m3t0th3b33pb00p}

Cyborg Security is a pioneer in cybernetic threat hunting, delivering an advanced, actionable threat hunting platform.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store