RITSEC CTF 2019



A bit late for writeups, but still here are the solutions to the challenges I solved during the CTF. The CTF was from 15 Nov. 2019, 22:30 IST — Mon, 18 Nov. 2019, 10:30 IST. It was a decent CTF with quality challenges, from both beginner to advanced level.

Update: The scripts to solve and the flags are present in this repo.

I’ll do the writeups category-wise -


Crypto

 
pre-legend — 100 pts

9EEADi^⁸:E9F3]4@>⁴=2J32==^D@>6E9:?8\FD67F=\C:ED64

This is the provided cipher text. Since all of these are ASCII characters, we try a ROT of till say, 50.

On i=47, we get — https\x98\x8d\x8dgithub\x8ccom\x8dclayball\x8dsomething\x8buseful\x8britsec

There is a problem with the special characters, but we understand that is a GitHub repo, with the URL (after some testing) — https://github.com/clayball/something-useful-ritsec.

Although there is nothing flag related in the repo, but the discord group of the CTF said that the link itself is the flag.

Flag —RITSEC{https://github.com/clayball/something-useful-ritsec}

 
Shiny — 100 pts

We are given the following text, and an image .‡8]5);483‡5;

gold-bug.jfif
gold-bug.jfif

This did not hit me directly, so I had to do a bit of Googling. I found that this is a reference to a short story by Edgar Allan Poe, called The Gold Bug which involves a substitution cipher. I found an online tool for the same.

This gives us the flag —RITSEC{POEWASTHEGOAT}

 
random — 290 pts

After connecting to nc ctfchallenges.ritsec.club 8001 we find that we are presented with a series of numbers and we have to guess the next. The challenge title tells us that we have something to do with the random function in the C language, because of the hint,

Are you starting to ‘C’ a pattern?

We make a guess that whenever we request that host and port, the random function is initialized with a certain seed and we are given the first five random numbers generated from that seed. So, I wrote a simple C code to bruteforce all unix timestamps from 15th Nov 2019, 00:00 UTC to 17th Nov. 2019 00:00 UTC, and check for the seed. The code is shown below —

#include <stdio.h>
#include <stdlib.h>

int main() {
    int start = 1573776000;  // 15th Nov 2019, 00:00 UTC
    int end = 1573948800;  // // 17th Nov 2019, 00:00 UTC
    for(int i=start; i<end; i++) {
        srand(i);
        int a = rand();
        int b = rand();
        int c = rand();
        int d = rand();
        int e = rand();
        int f = rand();
        if(a==1068399227 && b==161933545 && c==741438783 && d==1951874661 && e==1076387813) {
            printf("Seed: %d\n", i);
            printf("Next: %d\n", f);
            break;
        }
    }
    return 0;
}

We provide the next number, and get the flag — RITSEC{404_RANDOMNESS_NOT_FOUND}


Misc

 
Crack me If You Can — 391 pts

In this challenge, after connecting to nc ctfchallenges.ritsec.club 8080, we find that we are presented with queries of hashes, and we have to break them in order to get the flag. They were NTLM and sha256 hashes. So, we used a combination of crackstation.net and John the Ripper to crack both of them.

We found the flag — RS{H@$HM31FY0UCAN}

 
Onion Layer Encoding — 100 pts

The challenge says that the text is encoded using either Base16 or Baser32 or Base64 in a sequence. So we write a simple python script to solve it.

import base64

flag = open("onionlayerencoding.txt","r").read()

while "RITSEC" not in str(flag):
    try:
        flag = base64.b16decode(flag)
    except:
        try:
            flag = base64.b32decode(flag)
        except:
            flag = base64.b64decode(flag)
            
print(flag)

The flag is — RITSEC{0n1On_L4y3R}

 
AlPhAbEtIcAl Challenge - 100pts

I couldn’t solve this during the CTF, but saw other writeups and found that it was actually pretty interesting. The cipher text that is provided is —

59:87:57:51:85:80{:40:50:56:08:82:58:81:08:18:85:57:87:48:85:88:40:50:56:59:15:56:11:18:85:59:51:}

We see that the ‘{‘ and ‘}’ are in place. So, this must represent the flag. The other numbers are assigned some alphabet starting from ‘A’. After this we see that we have the following — ABCDEF{GHIJKLMJNECBOEPGHIAQIRNEAD}.

On this we use an online substitution solver like quipquip.com and also the fact that ABCDEF corresponds to RITSEC, we get the flag as — RITSEC{YOUALPHABETIZEDYOURNUMBERS}


Web

 
misdirection — 100 pts

We are given a URL — http://ctfchallenges.ritsec.club:5000/ However, on clicking it we see that we are directed to another webpage http://ctfchallenges.ritsec.club:5000/n and the information that the webpage isn’t redirecting properly. So, I decided to see what is happening, for that I did a simple wget to the url.

Running wget
Running wget

We see that the page redirects to different pages and keeps doing that. We note that the last character is basically in the flag format when put together. We do that and get the flag — RS{4!way5_Ke3p-m0v1ng}

 
Buckets of fun — 100 pts

We are given the following URL — http://bucketsoffun-ctf.s3-website-us-east-1.amazonaws.com/

Taking a hint from the name of the challenge, we try the following URL in the browser —http://bucketsoffun-ctf.s3.amazonaws.com

The webpage
The webpage

We see a file youfoundme-asd897kjm.txt

Heading to http://bucketsoffun-ctf.s3.amazonaws.com/youfoundme-asd897kjm.txt we find the flag — RITSEC{LIST_HIDDEN_FILES}


Forensics

 
Take it to the Cleaners — 100 pts

We are given an image

The challenge
The challenge

Performing basic recon, we check the metadata for the image using exiftool.

exiftool output
exiftool output

In the user comment, we see a string which is probably base64 encoded.

Decoding it gives, EVGFRP{SBERAFVPF_SNVYF_JBAG_URYC_LBH_URER}

Looks rotated by an offset. We use http://theblob.org/rot.cgi to get rotations by different offsets. This is ROT13 and the flag is — RITSEC{FORENSICS_FAILS_WONT_HELP_YOU_HERE}

 
Long Gone — 100 pts

We are provided a chromebin. Extract it as it is a tar archive.

tar xzvf ./chromebin

We see there are a lot of folders, on inspecting the history we find it is an SQLite 3.X database. Loading it into DBBrowser, and inspecting the tables, shows an odd URL — us-central-1.ritsec.club/l/relaxfizzblur

Opening the url gives the flag — RITSEC{SP00KY_BR0WS3R_H1ST0RY}


Pwn

 
999 Bottles — 110 pts

We are given 999 ELF files, each having a password as a single character. Basically, 999 crackmes with a one character password. If we check the disassembly of main function of any one —

The disassembly for main
The disassembly for main

At 0x8048728 we see a comparison, where register edx (dl) stores our input character and eax (al) stores the value at address 0x804a039.

Also, in the disassembly, we have some character mappings to addresses —

Character mappings
Character mappings

So, one way to solve this challenge is to get the address to be compared and check the character at this address and automate it somehow.

During the CTF, however, I wrote a bruteforce script to try all characters for every ELF file.

from pwn import *
import string

FOLDER = './elfs/'
filenames = []
s = string.digits + string.letters + string.punctuation

for i in range(1,1000):
    filenames.append(str(i).zfill(3) + '.c.out')flag = ''
f = open('flag.txt', 'w')
for file in filenames:
    for inp in s:
        p = process(FOLDER+file)
        p.recv()
        p.sendline(inp)
        a = p.recvline()
        if 'OK!' in a:
            flag += inp
            p.close()
            print("FLAG: " + flag)
            f.write("FLAG: " + flag)
            f.write('\n')
            break
        else:
            p.close()
            
f.write("FLAG: " + flag)
print(flag)
f.close()

Finally, we have the following string in the output generated -

lr^wN${HnW<DtVjk.RITSEC{AuT057v}^W!xT

Note the string in the flag format, that is the flag — RITSEC{AuT057v}

A better way to solve it actually using the method described above. The following script can help do that -

import r2pipe  
import binascii  
import sys

for i in range(1, 1000):  
    print('elfs/{0:03}'.format(i))  
    b = r2pipe.open('elfs/{0:03}'.format(i) + '.c.out')

    disass = b.cmd('aaa; s main; pdd')  
    field = disass.split("eax = *(obj.")[1][0]  
    byte = disass.split(f'*(obj.{field}) = ')[-1][2:4]  
    print(binascii.unhexlify(byte).decode('ascii'), sep='')

This is all. Thanks for reading!

 

 

Follow me on Twitter, Github or connect on LinkedIn.