首页
社区
课程
招聘
[原创]2019CTF晋级赛Q1第九题CandCpp 分析
发表于: 2019-3-22 22:13 7151

[原创]2019CTF晋级赛Q1第九题CandCpp 分析

2019-3-22 22:13
7151

先看看保护机制

然后拖进IDA分析下:

输入名字到一个全局变量,然后接下来是菜单:

里面有指示对应的功能!
下边还有个sub_400e10的函数,有点奇怪:

联想强网杯的一道题,这个应该是用来泄露的。因为条件不满足,正常条件怎么也不会触发。


输入lenth,然后这个公式变形

然后调用传入的函数指针的函数(分配作用)),传入这个函数的参数也是刚才变形之后的结果。
然后来看看分配的函数的功能:

申请以24字节为单位的块,然后每个24字节的块清零后两个8字节。
相当于,分配内存初始化 ,有点构造函数的味道,但构造函数不分配内存。
然后返回分配的内存指针,然后记录在ptr数组中。
然后就是读入数据:

也是以24字节为单位只往后16字节读入数据。


输入索引然后,查看ptr对应索引是否有值,然后以索引为参数调用函数指针传入的函数,sub_400ce0:

free对应内存,然后填0,没有UAF


和malloc的功能差不多,最主要的区别在于调用传入的函数,这个函数功能不一样:

判断一下传入a1,然后以24*a1+8为参数new对应大小的内存,也就是多了8字节,然后在new的内存开始处8字节存入size(以24为单位),以它往后都是以24字节为单位,第一个8字节存一个函数地址,然后后面两个清0。
其实就是多的8字节用来存size(以24为单位)。


和free功能一样,然后区别在于调用的传入的函数。

先从这篇内存中取出第一个8字节中存的size,然后计算出分配的这块内存的结束地址。
这个函数是关键,如果看伪码看不出,所以我调试下给大家看
用Python计算了当输入是16的时候申请的是2*24+8大小的块:

所以我申请输入16:

然后断下来后,看申请的内存:

深红圈住的是size:2
看执行情况

rdx里边存的就是ptr数组中存的地址,看看寄存器:

存的是0x614C28
mov rax,[rdx-8]
其实就是访问size了,执行下:

然后:

其实就是rdx+48,指向当前分配的内存的结束。

经过调试可以相信应该看得很清楚了吧!

然后就是从分配的内存的最后往上0x18个字节,就是跳过最后一个24字节,然后取里边的内容,其实取到了那个函数地址,然后访问里边的内容,与目标进行比较。

然后看里边的内容是不是和之前填的那个函数地址的内容一样,其实就是这里默认比较的东西。

如果不一样就会传入对应的内存地址v2(也就是当前的存有函数地址的内存地址)作为参数,调用它,关键就在这里,如果我们该掉它?或者错误的引导程序让他觉得别的地方填的内容就是它要比较的,如果不匹配然后就执行。
其实这里有个二重指针解引用
试想,我们把程序取出函数地址的地方指向一个存有我们想要执行的函数的内存,当发生这个二重指针解引用的时候不就取到了我们想要执行的函数了么?然后开始执行。这个程序没有Pie,全局段完全可以使用,所以你懂得!
并且这里还有个循环:

可造成多次检查和执行,可以构造出rop的效果。
如果和原来一样就delete掉原来的内存,然后填0.


输入索引,然后检查数组,然后执行传入的函数:
伪码有问题,直接看汇编吧:

其实就是printf("%s",ptr[idx]+8+24*i)
用来打印每个24字节块的后16个字节.

自此程序的功能都弄清楚了!

前面说了,delete功能会首先获得内存块的size,然后跳到根据size计算出来的这个块的地方,然后获取指针,检查那个填入块的函数指针,然后根据它是不是默认的那个来决定是否执行
而malloc功能的块比new功能的块少8个字节,当malloc功能的块拿去delete的时候,就会将对应的chunk的size段当做那个size,然后去取,就会造成错误。
调试检验下:
malloc一个24的块,输入1的时候那个公式算出来是1,这里我就不截图了,然后拿去delete,断下来:

看下分配的chunk:

然后进入流程:

rdx指向的分配的那个开始,然后取rdx-8的内容:

然后取到了size字段的0x21,然后经过那样去计算之后,会发生越界:

看看我们之前分配的内存:

已经越界到很下面去了。


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 3
支持
分享
最新回复 (4)
雪    币: 18
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
2
大师傅,你能告诉我你的main地址为啥设在0x4009ce而不是在0x4009a0,我设在0x4009a0crash掉了
2019-3-30 15:52
0
雪    币: 18
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
3
还有我的onegadget有点问题
你知道怎么回事吗
2019-3-30 15:56
0
雪    币: 4811
活跃值: (886)
能力值: ( LV13,RANK:319 )
在线值:
发帖
回帖
粉丝
4
endingc 大师傅,你能告诉我你的main地址为啥设在0x4009ce而不是在0x4009a0,我设在0x4009a0crash掉了
我之所以设置在0x4009ce是因为我当前攻击的时候只需要它输入,所以我直接设置在0x4009ce,理论上设置在Main函数的开头也是可以的但是这里可能有什么其他影响吧才会导致crus。

至于one_gadget,,这个你需要装一个小程序,我不知道你怎么装的,我装的时候那个使用ruby写的,装完ruby然后再一条命令就解决了,没有出现过你的整合各个错误,建议重装下哈
2019-3-30 20:56
0
雪    币: 4811
活跃值: (886)
能力值: ( LV13,RANK:319 )
在线值:
发帖
回帖
粉丝
5
endingc 还有我的onegadget有点问题你知道怎么回事吗
我知道为啥你的One_gadget 报那个错是为啥了。因为one_gadget更新了,现在是1.70版本,需要那个东西的支持,所以得安装那个东西,我刚刚遇到了
2019-4-4 21:26
0
游客
登录 | 注册 方可回帖
返回
//