en
6/6/2022
SECCON Beginners CTF 2022 Writeup
Tags:
ctf

This year I had a chance to participate in SECCON Beginners 2022 CTF (after a bit of hiatus from cybersecurity).

This time, I finally decided to do a writeup. This will be my first writeup so I’m sorry for any mistakes.

I’ll explain the challenges in order which I solved them. Which are:
crypto: CoughingFox
reversing: Quiz
misc: phisher
misc: hitchhike4b
web: textex

CoughingFox

For this challenge we are given the following source code:

from random import shuffle

flag = b"ctf4b{XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}"

cipher = []

for i in range(len(flag)):
    f = flag[i]
    c = (f + i)**2 + i
    cipher.append(c)

shuffle(cipher)
print("".join(map(chr, cipher)))

And the following output:

cipher = [12147, 20481, 7073, 10408, 26615, 19066, 19363, 10852, 11705, 17445, 3028, 10640, 10623, 13243, 5789, 17436, 12348, 10818, 15891, 2818, 13690, 11671, 6410, 16649, 15905, 22240, 7096, 9801, 6090, 9624, 16660, 18531, 22533, 24381, 14909, 17705, 16389, 21346, 19626, 29977, 23452, 14895, 17452, 17733, 22235, 24687, 15649, 21941, 11472]

If we look at this part of the source code, we would know how the cipher text was constructed

for i in range(len(flag)):
    f = flag[i]
    c = (f + i)**2 + i
    cipher.append(c)

shuffle(cipher)

The cipher was constructed by taking the byte value of each character of the flag, add it by the index, power it by 2, then add the index to it again. Finally, the cipher array is shuffled.

We can identify each entry by subtracting each entry with the corresponding index, and square root it. But since the array is shuffled, we can loop the array 49 times (the length of the flag), subtract the number with the inner iterator (j), then subtract it again to get the original number in each loop. idx array saves the index of each character that was discovered. And text array saves the character in byte representation. The flag variable is here for reference.

import math

idx = []
text = []
flag = b"ctf4b{XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}"

for i in range(len(flag)):
    for j in range(len(flag)):
        if((math.sqrt(cipher[i]-j)-j).is_integer()):
            idx.append(j)
            text.append(math.floor(math.sqrt(cipher[i]-j))-j)

Finally, since the saved index was the order that was discovered, we need to rearrage them to be the correct order.

ans = []

for i in range(len(flag)):
    for j in range(len(flag)):
        if i == idx[j]:
            ans.append(text[j])

print("".join(map(chr, ans)))

flag:

ctf4b{Hey,Fox?YouCanNotTearThatHouseDown,CanYou?}

Quiz

In this challenge we are given a binary with the flag inside.

A simple call of strings reveals the flag

$ strings quiz | grep ctf
ctf4b{w0w_d1d_y0u_ca7ch_7h3_fl4g_1n_0n3_sh07?}

phisher

In this challenge, the program will convert the text we input into an image, then use OCR to read it as text again.

The goal here is to fool the program using similar characters while technically not inputting any of the actual characters.

By using a Homoglyph Attack Generator like this one I’ve been able to come up with the payload: ωωω․ехаⅿрIе․сοⅿ

phisher in command line

hitchhike4b

When we execute the program, we are dropped into the python’s interative help tool and are given the source code with flag hidden.

# Source Code

import os
os.environ["PAGER"] = "cat" # No hitchhike(SECCON 2021)

if __name__ == "__main__":
    flag1 = "********************FLAG_PART_1********************"
    help() # I need somebody ...

if __name__ != "__main__":
    flag2 = "********************FLAG_PART_2********************"
    help() # Not just anybody ...

From the source code, we know that the pager has been changed to the cat command and that flag1 variable will be set when the scope is __main__.

If we type __main__ into the help tool, we can see the data and important information of the running program.

help> __main__
Help on module __main__:

NAME
    __main__

DATA
    __annotations__ = {}
    flag1 = 'ctf4b{53cc0n_15_1n_m'

FILE
    /home/ctf/hitchhike4b/app_35f13ca33b0cc8c9e7d723b78627d39aceeac1fc.py

We get half the flag here, as well as the file name. If we use the program name (file name without extension) to get the program’s help information, we get dropped into another help prompt (this seems to be due to another help() getting executed, though I’m not sure). If you exit from that prompt, the contents of flag2 can be seen.

help> q

You are now leaving help and returning to the Python interpreter.
If you want to ask for help on a particular object directly from the
interpreter, you can type "help(object)".  Executing "help('string')"
has the same effect as typing a particular string at the help> prompt.
Help on module app_35f13ca33b0cc8c9e7d723b78627d39aceeac1fc:

NAME
    app_35f13ca33b0cc8c9e7d723b78627d39aceeac1fc

DATA
    flag2 = 'y_34r5_4nd_1n_my_3y35}'

FILE
    /home/ctf/hitchhike4b/app_35f13ca33b0cc8c9e7d723b78627d39aceeac1fc.py


help>

flag:

ctf4b{53cc0n_15_1n_my_34r5_4nd_1n_my_3y35}

textex

This one will probably be easier if you know some LaTeX. However, I don’t, so there were a lot of trial-and-error going on.

To put it simply, in this challenge, we are given access to a LaTeX to pdf converter site. We are also given the source code without the flag.

We can see that the flag file is next to the server program app.py

$ tree app
app
├── Dockerfile
├── app.py
├── flag
├── requirements.txt
├── templates
│   └── index.html
├── tex_box
│   ├── error
│   │   ├── error.pdf
│   │   ├── error.tex
│   │   └── ramen.jpg
│   └── error.pdf
└── uwsgi.ini

3 directories, 10 files

If we examine app.py we can find that the word flag is blocked

[...]
try:
        # No flag !!!!
        if "flag" in tex_code.lower():
            tex_code = ""
[...]

However we can get around that by defining part of the word, then combining it

\def \fla {fla}
\def \g {g}
\def \f {\fla\g}

In LaTeX we can import text by using the \input{} command, however, since the flag contains characters {, }, and _, it will get parsed as LaTeX syntax and throw errors. To circumvent that we can detokenize the text.

\documentclass{article}

\begin{document}

\newread\file
\openin\file=\f
\read\file to\fileline
\detokenize\expandafter{\fileline}
\closein\file

\end{document}

The result is detokenized flag.

textex pdf

Since we know the flag format, we can reconstruct the flag from what we see.

flag:

ctf4b{15_73x_pr0n0unc3d_ch0u?}
Made with by Naborisk