OFPPT CTF 2022 writeup
This is a writeup for OFPPT-CTF 2022. The 0006 article.
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.
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.
I found "flag.txt" in line 76, and I needed to input "HELLO" to read flag. It is not simple like just input "HELLO".
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.
In retrospect, I think that you can get FLAG without "+" sign.
Pascal
Opened with Ghidra.
You can see the process function does something using the number from 16 to 20 in the main function.
The display_number function returns a number from 16 to 20.
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.
Decompile
Opened with Ghidra for the first step.
This program is similar to the Pascal. You can see that the ivar3 variable is compared with the input number in line 37.
In the function1, it calculates the greatest common divisor of local_20 variable and local_28 variable.
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.
Trickster
I was surprised that the game could be working with Python. This program is using library called pygame.
This game begin with the image like this.
You need to avoid the Grim Reaper.
If you bump into it, you will failed.
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.
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.