OFPPT CTF 2022 writeup

This is a writeup for OFPPT-CTF 2022. The 0006 article.

f:id:Berrys:20220327004549p:plain

This was for beginner, but I couldn't solve all of them. I found something new knowledge in rev and web challenges.


Unicode

A file with the header shown in the image below was given.

f:id:Berrys:20220327011702p:plain

I found a string "JFIF", so I tried to fix the header in jpg format. It didn't work. This was only problem I couldn't solve in rev challenge.


Esoteric

I opened it with Ghidra.

f:id:Berrys:20220327015855p:plain
f:id:Berrys:20220327015905p:plain

I found "flag.txt" in line 76, and I needed to input "HELLO" to read flag. It is not simple like just input "HELLO".

f:id:Berrys:20220327012647p:plain

In line 73, "HELLO" was compared to the STR variable. The STR variable was empty when input "HELLO", therefore it is failed. In line 40, to put a string into STR variable, we need to use sa pointer used in line 31 and 32. So, we needed to input some symbols first shown in the image below to get FLAG.

f:id:Berrys:20220327015841p:plain

In retrospect, I think that you can get FLAG without "+" sign.


Pascal

Opened with Ghidra.

f:id:Berrys:20220327022814p:plain

You can see the process function does something using the number from 16 to 20 in the main function.

f:id:Berrys:20220327022824p:plain

The display_number function returns a number from 16 to 20.

f:id:Berrys:20220327022833p:plain

In the process function, you can see that the number of the argument is compared with the input number. You can get the FLAG if all the input is correct. You need to do same thing as the C function and the f function for the input value.
I used the pwntools. It was awesome.
from pwn import *

elf = ELF("./pascal", checksec=False)

host = '143.198.224.219'
port = 25030


def func2(num):
    tmp = 1
    for j in range(num):
        tmp *= num - j
    return tmp

def func1(num, i):
   return int(func2(num) / (func2(i) * func2(num - i)))


r = remote(host, port)

# receice a random number
now = r.recvline()
a = now.decode('utf-8')

for i in range(int(a) + 1):
    r.sendline(str(func1(int(a), i)).encode())

r.interactive()
FInally, you can get the FLAG.

f:id:Berrys:20220327022354p:plain

Decompile

Opened with Ghidra for the first step.

f:id:Berrys:20220327024910p:plain

This program is similar to the Pascal. You can see that the ivar3 variable is compared with the input number in line 37.

f:id:Berrys:20220327025037p:plain

In the function1, it calculates the greatest common divisor of local_20 variable and local_28 variable.

f:id:Berrys:20220327025047p:plain

In the function2, it calculates the factorial of the ivar3 variable plus 3.
The solution is below.
import math
from pwn import *

elf = ELF("./decompile", checksec=False)

host = '143.198.224.219'
port = 21530


def func1(num1, num2):
    return math.gcd(num1, num2)

def func2(num):
    if (num == 0):
        return 1
    else:
        return func2(num-1) * num


r = remote(host, port)

while (True):
    # receive two numbers
    now = r.recvline()
    if (b"fun() took" in now):
        break
    a, b = map(str, now.decode('utf-8').split())

    # send number which does func1 and func2
    num = func2(func1(int(a), int(b))+3)
    r.sendline(str(num).encode())


print(now.decode('utf-8'))
r.interactive()
You can get the FLAG.

f:id:Berrys:20220327025304p:plain

Trickster

I was surprised that the game could be working with Python. This program is using library called pygame.

f:id:Berrys:20220327033703p:plain

This game begin with the image like this.

f:id:Berrys:20220327033824p:plain

You need to avoid the Grim Reaper.

f:id:Berrys:20220327033836p:plain

If you bump into it, you will failed.

f:id:Berrys:20220327033847p:plain

For me, I fixed the program not to bump into the Grim Reaper. The FLAG will be shown over 100 dodge.


php

Index.php was given.

f:id:Berrys:20220327031820p:plain

I thought that I needed to calculate for a number would result in the same hash value (=Collision). However, I found there are two equal signs and three equal signs in the php comparison operator. In the case of two equal signs, a hash value begin with "0e" is computed as a power of zero. So, it will be true if the hash value of input number begin with "0e".
Now, You can find the correct input with the program below.
import string
import hashlib

strings = string.ascii_uppercase + string.ascii_lowercase + string.digits

def check(h):
    if (h[:2] != "0e"):
        return 0
    for i in range(2, len(h)):
        if (h[i] not in string.digits):
            return 0
    return 1

def make_magic(moji, cnt):
    h = hashlib.sha1(moji.encode()).hexdigest()
    if (check(h)):
        print(moji)
    
    if (cnt == 9):
        return
    
    for j in strings:
        moji += j
        make_magic(moji, cnt+1)
        moji = moji[:-1]


moji = ""
for i in strings:
    moji += i
    make_magic(moji, 0)
    moji = ""
I input a string "AAAAABzIOf" and got the FLAG.

f:id:Berrys:20220327031806p:plain