diff --git a/includes/memhub.vp b/includes/memhub.vp index 46c8ece..f64d733 100644 --- a/includes/memhub.vp +++ b/includes/memhub.vp @@ -729,13 +729,18 @@ class MemBuddy(MemManager): if self.detection != 0: # [DET] 返回指针比实际用户区靠后 2 字节,回收时向前偏移 2 p_eff = t.CVoid(t.CUInt64T(ptr) - 2, t.CPtr) - # 从记录表移除该条(置 size=0):块复用后旧后标记位置 - # 会被新数据覆盖,若不移除会导致 _det_probe 误报 + # 从记录表取本条真实 size,free 后把用户区填 0xCD(UAF 写入 + # 检测:free 后块被写穿 → 探测时 0xCD 被破坏 → 报警);记录 + # 保留并置 free 标志(探测时对仍 free 的块验证 0xCD 完整)。 if self._det_records is not None: ri: t.CSizeT = 0 while ri < self._det_count: - if self._det_records[ri * 2] == t.CUInt64T(ptr): - self._det_records[ri * 2 + 1] = 0 + rp: t.CUInt64T = self._det_records[ri * 2] + rs: t.CUInt64T = self._det_records[ri * 2 + 1] + if rp == t.CUInt64T(ptr) and (rs & (t.CUInt64T(1) << 63)) == 0: + if rs > 0: + string.memset(ptr, MEMBUDDY_FILL_PATTERN, rs) + self._det_records[ri * 2 + 1] = rs | (t.CUInt64T(1) << 63) break ri += 1 if self._is_valid_ptr(p_eff) != 0: @@ -821,13 +826,33 @@ class MemBuddy(MemManager): def _det_probe(self): if self._det_records is None: return + free_flag: t.CUInt64T = t.CUInt64T(1) << 63 + cd_word: t.CUInt64T = (t.CUInt64T(0xCDCDCDCD) << 32) | t.CUInt64T(0xCDCDCDCD) i: t.CSizeT = 0 while i < self._det_count: p: t.CUInt64T = self._det_records[i * 2] s: t.CUInt64T = self._det_records[i * 2 + 1] + if (s & free_flag) != 0: + # free 记录:块头仍为 0(未被重新 alloc)则验证用户区 0xCD + # 完整——被写穿 = use-after-free 写入(free 后块被某代码覆盖) + real_s: t.CUInt64T = s & (free_flag - 1) + if real_s > 0: + blk_h: t.CUInt64T = p - 2 - MEMBUDDY_HEADER_SIZE + hdr_v: t.CUInt64T = t.CUInt64T(c.Deref(t.CUInt64T(blk_h, t.CPtr))) + if (hdr_v & 1) == 0: + w0: t.CUInt64T = t.CUInt64T(c.Deref(t.CUInt64T(p, t.CPtr))) + w1: t.CUInt64T = w0 + if real_s >= 8: + w1 = t.CUInt64T(c.Deref(t.CUInt64T(p + real_s - 8, t.CPtr))) + if w0 != cd_word or w1 != cd_word: + stdio.printf("[DET] UAF 写入: ptr=%llu size=%llu(free 后块被写,首=0x%llX 末=0x%llX)\n", + p, real_s, w0, w1) + stdlib.exit(1) + i += 1 + continue if s == 0: i += 1 - continue # 该条已被 free(记录移除) + continue # 无 size 记录(理论不发生,防御) m16: t.CUInt16T | t.CPtr = (t.CUInt16T | t.CPtr)(t.CVoid(p + s, t.CPtr)) mv: t.CUInt16T = m16[0] if mv != t.CUInt16T(MEMBUDDY_DET_MARKER):