DEV Community

VaiTon for Ulisse

Posted on • Originally published at ctf.ulis.se

padlock

Challenge description

Mindblown by ioccc? How can someone write programs like this... Anyway, try open this padlock :)

Author: bronson113

First analysis

The source code is a C program that prints itself.
It's a quine, a program that prints its own source code.

If we compile the program and run it, we are welcomed by a

zsh: segmentation fault  ./quine
Enter fullscreen mode Exit fullscreen mode

Maybe it needs some arguments? Let's try with ./quine 1:

//X
...
Enter fullscreen mode Exit fullscreen mode

I won't repeat the program source code here, but keep in mind that when I put ... it means that the source code of the program is repeated.

Let's try with a bigger number, like ./quine 1000:

//XXXX
...
Enter fullscreen mode Exit fullscreen mode

So the program does print a variable number of Xs somewhat depending on the argument.
Let's try with ./quine abcd:

//XXXX
...
Enter fullscreen mode Exit fullscreen mode

The output is the same, so the number of Xs depends only on the length of the argument.

With the help of a little python, we can find that sometimes, instead of an X, the program prints an O.
For example, with ./quine b:

// O
Enter fullscreen mode Exit fullscreen mode

The first idea was to bruteforce the flag, but as the number of Xs and Os could be > 10, it could take a long time.
So I decided to try to find a pattern in the output.

Finding the pattern

I wrote a python script that prints the output of the program for strings of N chars made of the same char, for every char.

$ ./quine aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
//XXXXXXXXXXXXXXXXXXOXXXXXXXXXXX
...
Enter fullscreen mode Exit fullscreen mode
$ ./quine bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
//OXXXXXXXXXXXXXXXXXXOXXXXXXXXXX
...
Enter fullscreen mode Exit fullscreen mode

The pattern starts to emerge. We get an O when the char is the same as the flag char on that position. We get an X when the char is different from the flag char on that position.

Finding the flag

Now that we know the pattern, we can find the flag. We just need to bruteforce every letter and keep the one in the positions where we get an O.

import subprocess
import string

CHAR_N = 70
flag = [""] * CHAR_N

for ch in string.printable:
    proc = subprocess.Popen(
        ["./quine", ch * CHAR_N], stdin=subprocess.PIPE, stdout=subprocess.PIPE
    )
    (stdout, stderr) = proc.communicate()

    line = stdout.decode().split("\n")[0][2:]
    print(line)

    for i, x in enumerate(line):
        if x == "O":
            flag[i] = ch

flag = "".join(flag)
print(flag)
Enter fullscreen mode Exit fullscreen mode

and we get the flag:
bctf{qu1n3_1s_4ll_ab0ut_r3p371t10n_4nD_m4n1pul4710n_OwO_OuO_UwU}

Top comments (0)