Home Writeups Contact

Dc1ph3r Discord CTF

This was a small CTF hosted on the dc1ph3r discord server and had a total of 3 simple but fun challenges. It turned out at the end that the winner receives a 2 month subscription to pentester lab, so a huge thanks to @MrT4ntr4 for that!

Challenge #1 - Game of Bases

ctf introduction and challenge description

In Game_of_Bases.txt there is:


My personal favourite tool for these types of challenges is CyberChef, it allows you to do all kinds of encoding/decoding and other forensics. cyberchef base32 to base64 For both of the encoded strings, I can tell which base encoding it (most likely) is based off of the character set, which is also shown in CyberChef. The order is base32 -> base64 Flag: FLAG{Y0u_kn0W_3nc0din6!_Pr377y_w3ll}

Challenge #2 - RSAyyy

challenge 2 This challenge was just a simple test of understanding for RSA. You are given Rsay.txt:

n: 379557705825593928168388035830440307401877224401739990998883
e: 65537
c: 244703312358921240309421014098878267031729391832640247437102

The steps to solve RSA when given these are:

Since n = p*q, we need to factor n. Luckily, n already exists in the super handy site factordbfactordb now with p and q, we can get φ(n) using the totient function: phin = (p-1) * (q-1)

We can calculate d as the inverse of e mod φ(n)

import gmpy
d = gmpy.invert(e, phin)

and decryption is given using c^d mod n. There is a nice function in python called pow() which does this well.
m = hex(pow(c, d, n))[2:] I use the [2:] to get rid of the 0x at the start. printing this returns the hex string 526b78425233744764554e724d573432583149315158304b

With the codecs module, we can create a couple simple functions so it doesn't get too messy.

import codecs
decode_hex = codecs.getdecoder("hex_codec")
decode_b64 = codecs.getdecoder("base64_codec") # We will use this in a second

Using hex_codec(m)[0] we receive: b'RkxBR3tGdUNrMW42X1I1QX0K' which is a base64 string. Now, with decode_b64(b64_string)[0].decode('utf-8') and printing out the result, we get the flag! Flag: FLAG{FuCk1n6_R5A}

import gmpy
import codecs

n = 379557705825593928168388035830440307401877224401739990998883
e = 65537
p = 564819669946735512444543556507
q = 671998030559713968361666935769
c = 244703312358921240309421014098878267031729391832640247437102
phin = (p-1) * (q-1)
d = gmpy.invert(e, phin)
# print(d*e % phin) = 1
m = hex(pow(c, d, n))[2:]

decode_hex = codecs.getdecoder("hex_codec")
decode_b64 = codecs.getdecoder("base64_codec")
b64_string = decode_hex(m)[0]

plaintext = decode_b64(b64_string)[0].decode('utf-8')

Challenge #3 - Dumb Admin

Created by Corb3nik

Unfortunately, the website for this challenge was shut down and the local files are unavailable, so I'm going to be doing this writeup pretty much from memory :P (I'll update it when/if I have access to the full challenge)

The challenge starts off on a web page, and from viewing the source you can see some weird esolang in place of js. On first look, you might think "Oh, it's brainfuck", but although they look similar it's actually the less well known JSfuck.

Here's some example JSfuck (not the code used in the challenge)


On "decoding" the script with this, we are led towards a page that has php which first checks if its "blacklisted" word is in a get parameter in the url, and if it is it will replace it with nothing. However, later in the script it will give you the flag if that blacklisted word remains in the url.

Similar to some LFI bypass that people may be familiar with, we can abuse the implementation by "sandwiching" parts of the blacklisted words between eachother.
For example, if the blacklisted word was hello this is what would happen:
links example
After doing this, we are presented with the flag! Flag: flag{1_Kn0w_fr0m_N0w_0n_u11_R35pect_PHP_and_j4v4scr1p7}

winner announced