Back

ABCCTF QUALIFIERS

Naijasecforce and partners organized a CTF as part of the 2021 Nigerian Cybersecurity Conference.

#ctf

NaijaSecForce organized a jeopardy style CTF as part of the 2021 Nigerian Cybersecurity Conference. The CTF's qualifying round had 20(+1 entry challenge) challenges in total and I had fun playing the game with the other members of M4x_he4dr00m — Nullcell, Kurrupt68, 5hyl0ck and Sh3n0kam3. The ctf starts with an email that contains a cryptic note.

Entry Challenge

All the formatted words refer to a type of encryption and an hint provided by the organizers mentioned forming the chain from bottom up so the encryption mentioned last is noted first and so on. Noref -> Feron-74, Mota -> Atom128, Alig -> Gila7, of course "Rome ... this tenth time" was referring to ROT10 and thanks to an hint supplied after a while, Lady was referring to Megan35. As anyone would imagine, this was arguably the most difficult part of the ctf due to the sheer amount of connections that could be made from the content. https://www.persona-shield.com/gila7c.htm helped with the decryptions.

NkZNY3NhRDNXVG9yc2FzZTZGeWxkcjVvNnUvNmR5eCtxbTA1UWI4aFdhV2lxNmFQQXZhWUFpNDQ= is base64 decoded to 6FMcsaD3WTorsase6Fyldr5o6u/6dyx+qm05Qb8hWaWiq6aPAvaYAi44 which is Feron-74 decoded to SJGtTj0NStWNSIu50yQbT6XgKlAxfo0S0IAZAqCC which is Atom128 decoded to 3A35wx3880ndvrP6XTcdfLwLtdzG which is Gila7 decoded to uWpgwVY/scj/x2sFvg/5 which is Rot10 decoded to kMfwmLO/isz/n2iVlw/5 which is Megan35 decoded to huvpbdc.dvf.oi

At this point in the challenge, 5hyl0ck had already figured out where the ctf is being hosted with a combination of wit and OSINT. The ctf Discord's server is named ctf.ng which is an online ctf hosting website and of course, they had abcctf posters up on their website. It only took a couple of guesses for the ctf website http://abc.ctf.ng to be known.

ctf.ng

Comparing http://abc.ctf.ng to huvpbdc.dvf.oi and its easy to tell it's a form of polyalphabetic substitution cipher(If it was a simple substitution cipher, both t's in "http" would result in the same encoded alphabets). Vignere is the most common polyalphabetic cipher, using https://www.dcode.fr/vigenere-cipher bruteforce option with the "knowing a plaintext word" option revealed the key as ABC which is unsuprisingly the last formatted word in the mail (or the first actually)

CRYPTO

Cicero

Cicero

uvwwnz is abcctf rotated by 20 characters. ROT20 the string gives abcctf!Cicero@knows@codes! which is edited to fit the ctf flag format.

abcctf{Cicero_knows_codes}

Sway me

Sway me

A png file with dancing stickmen is given. A simple google search is enough to reveal its the Dancing Men Cipher and it decodes to "whenmendance"

abcctf{when_men_dance}

Self-made

Self made

A reference to a password was enough to suspect a polyaplphabetic substitution cipher and true enough its a vigenere cipher with key "the password" and decodes to "abcctfAmericansknowFrance"

abcctf{Americans_know_France}

Comercio

Comercio

ABC will take you to the zoo and Comercio will give you the cash. Was given a txt file that contains z's and o's, the txt file is named onoff which in itself is a hint for the challenge. Switching 'z' with '0' and switching 'o' with '1' outputs binary which when converted to ascii gives "the reason for this is to test your ability because the flag is abcctf{BiNary_to_THe_bANk5}"

Way to go!

Way to Go

File containing base32 characters padded with non base32 characters. Removing non-base32 characters, base32 decoding and piping the output into a file gives a png.

Way to Go

abcctf{bA53_t0_cOdE}

Bonanza!!!

Bonanza

File name "baseflip.txt" is an hint to the challenge's content. Reverse, base64 decode and the reverse one more time. True to the challenge name, it was a point Bonanza XD

Bonanza

abcctf{flip_the_base}

REVERSING

Stringzzz!!!

Bonanza

Opening the executable in Ghidra and the decompiled main function mentions a Secure flag analyzer, checking the call to Secure_flag_analyzer in main reveals the flag

Bonanza

abcctf{n0t_al1_str1ngs_ar3_3qu4l}

Forensics

Flipper!!!

Flipper!!!

Docx are zip files, unzipping, cating(opening) and grepping(searching) through the files for the string "abcctf" reveals the flag.

Flipper!!!

abcctf{tA!Ls_n0T_heaD5}

Flippin

Flippin

Flippin.docx is a corrupted word document. Opening the file with microsoft word gives the user to fix the document. After fixing, the new docx is unzipped and its content is compared with the unzipped content of the corrupted docx.

Flippin

6162 6363 7466 7b68 3164 6445 4e5f 214e 5f77 3072 447d Converting the hex to ascii

abcctf{h1ddEN\_!N_w0rD}

Arranger

Arranger

30 images with column numbers, stitching them side by side according to their row number reveals the flag. A custom python script was used.

import os

from PIL import Image

with open('files.txt') as filehandler:
images = filehandler.readlines()

path = os.path.dirname(os.path.realpath(**file**))

actual = [Image.open(os.path.join(path, i.strip())) for i in images]

widths, heights = zip(\*(i.size for i in actual))

total_width = sum(widths)
max_height = max(heights)

print('total_width is: ', total_width)
print('max height is: ', max_height)

new_im = Image.new('RGB', (total_width, max_height))

x_offset = 0
for im in actual:
new_im.paste(im, (x_offset, 0))
x_offset += im.size[0]

P.S files.txt contains a numerically sorted list of the image files

Arranger

abcctf{5hR3d_m3_n0T}

Secret Service

Secret Service

3 wav files are given. Listening to them and its obvious they're keypad tones. Using a DTMF decoder unknown.wav - 9798999911610212383

phone.wav - 48117110681159566339

calls.wav - 0125

Combined - 9798999911610212383481171106811595663390125

Decimal Encoding - 97 98 99 99 116 102 123 83 48 117 110 68 115 95 66 33 90 125 which reveals the flag abcctf{S0unDs_B!Z}

WEB

And so it begins

And so it begins

Checking the page source of the web page shows that it's an angular js website, main.js was bound to contain information about the web page (It's a js framework afterall). Scanning through the file reveals a github repo link

And so it begins

Checking the commit history reveals the flag.

And so it begins

abcctf{DOWNL0AD3D_THE_G!T}

A step ahead (And so it begins B)

A step ahead

Searching through the main.js shows http://185.203.119.50:3000/api and "/api/login", attempting to login and intercepting the request with burpsuite would also reveal the same thing.

A step ahead

Analyzing the github user from the first web challenge reveals https://github.com/noxcoder/web1-be/ which shoows the directory structure: /login, /register, /flag2 and /flag3 so we registered a user using the login parameters noted from the attempted login request(email & password) using the api's register function at /api/register

$ curl -X POST http://185.203.119.50:3000/api/register -d "email=NullCell&password=InsanelySecurePassword_Password"
{"msg":"User created successfully"}

Logging in with the newly created user and the flag is revealed. abcctf{We_Forgot_To_Save_The_FlagXD}

End of a series (And so it begins C)

End of a series

Checking the source code for /api/flag3 in the web1-be repo found during the previous challenge shows that the GET request requires a cookie name currentUser to be set to web1-admin.

End of a series

Sending the get request with the specified cookie value to /api/flag3 reveals the flag

End of a series

abcctf{N0W_you_G0T_p3rm!ssion5}

Focus

Focus

From the hint, it can be deduced that the php preg_match function is being referred to. Opening the webpage in a browser reveals a simple page that receives user input and presumably executes it as a command.

Focus

However, commands seem to be blacklisted presumably with the preg_match function so we tried inputing different symbols to see which were allowed. Noticed that #&+{}": were not blacklisted so we tried "" as the command and got an error.

Focus

The error reveals 2 things, firstly that bypassing the filters would allow us execute os code via the system() command and secondly - through a bit of Google-fu - that the Illegal string offset error is displayed when a string is attempted to be used as an array - The backend code expects our input to be an array and trying using a string would return the error. It also lets us know the array key for our command has to be "cmd".

Focus

Every php array requires some sort of symbols so we had to use an array that only used characters from the whitelisted symbols #&+-{}": ,only JSON arrays fit the bill, JSON arrays utilitze ": which are all whitelisted characters. Trying {"cmd":"ls"} as our payload returns the list of the files in the web directory.

Focus

Trying to cat the content of index.php returns nothing, the preg_match filter is still at work. One way to bypass pregmatch is to use multiline inputs, because pregmatch only tries to match the first line. So we urlencoded a multiline json array to bypass the preg_match filter. Trying to cat the index.php file returned an error so we used the cat command's full path "/bin/cat index.php" instead of "cat index.php".

Focus

Focus

The /home/focus/prison path is why the cat command wouldn't work - when you try to execute a command on Linux it checks your path to know which folder to check for the executable you're trying to execute, trying to execute the cat command without using the full path would have the machine checking /home/focus/prison for an executable named cat - There was no executable named cat. The path revealed the presence a "focus" user so we decided to check out the home folder for the user - "/bin/ls /home/focus" is the urlencoded command.

Focus

There's a flag file and cating it gives us the flag.

Focus

abcctf{pr3g_m4k3s_m3_w4nt_m0r3!}

PWN

I love to smash

To start with some basic insight into the program using Ghidra.

I love to smash

From here we can see that there are no controls on the size of the buffer for storing the variable that prints name. We have a buffer overflow vulnerability. Usually this would be the end but we have to consider what more we can do.

Testng a buffer overflow of against the binary and calculating the offset shows that the EIP overflow happens at the 136th byte. Now that we have control of the Instruction Pointer we can continue.

I love to smash

I love to smash

Since we already know that the crash happens during a return from the say_hello function, we can set a breakpoint at the end of the say_hello function and see what happens to the registers and use that to get the EIP overflow offset.

I love to smash I love to smash

At this point we could control the EIP to execute our shellcode. However, we find that the binary has protections in place to prevent code from executing on the stack.

I love to smash

We’ve been given a libc.so file, so we know this is definitely a ROP challenge using ret2libc. Our aim now is to point EIP into the ‘system’ function in libc and somehow have something useful in stack to set things up in our favor. We know that the string ‘/bin/sh’ is also in libc, so we can setup ‘system(“/bin/sh”)’ quite easily.

We do not know where the system function is in libc and we also do not know where the string ‘/bin/sh’ is. In addition, even after acquiring the relative locations of ‘system()’ and ‘bin/sh’, we have to account for the changes in address layout each time the program is run.

First we need a function in the program that holds a reference pointer to a function of the same name in ‘libc’. Going through the machine code of the program we select malloc()

I love to smash

We will utilize the puts() function in the executable to print out the address of the malloc() function in libc and, having the location, re-run the program. We will need to use ROP to control the EIP.

I love to smash I love to smash I love to smash

With this, we’re able to utilize puts to leak the address of malloc() in libc(store that for future use) and then re-run the program with actual exploitation intent.

After leaking the address of malloc() in libc, we can then use the distances of system() and ‘/bin/sh’ to guide the program into running system(‘bin/sh’)

I love to smash I love to smash

A few minor changes in the source code allow us to use the exploit on a remote executable

I love to smash I love to smash abcctf{1_l0v3_t0_sm4sh}