type
status
date
slug
summary
tags
category
icon
password
来之BRICS+ CTF Quals 2024这个比赛的有一道堆题,算是我到目前为止见过的最复杂的题目了,并且使用的libc版本为2.39,也是我见过的最高的版本,其中有很多的地方与我之前遇到过的版本不同,后面慢慢讲。
 
 

泄露堆地址

 
先申请两个proxy,使程序中有2个0x20和2个0x90的chunk,
 
然后在申请两个chains,并使这两个都指向第一个proxy1
 
连续申请7个proxy,在将这7个free掉,使0x20和0x90的tcachebins被填满
 
在将之前的第一个proxy1 free掉,使前两个0x20和0x90的chunk分别进入fastbins和unsortedbin,
notion image
 
连续申请7个proxy,这里在程序中会先出tcachebin上的free chunk,从而使得bin中只剩下fastbin和unsortedbin这两个chunk
 
之后来到关键的一步,此时我们在申请一个chains。程序会先给我一个0x20的chunk(这个chunk就是我们之前的proxy1的0x20chunk),我们要向其中填入一个proxy中的0x20的chunk。于是我们将proxy2填入其中,使得这个chains3中放的是proxy2的0x20的chunk。
 
此时我们在打印chains1的内容,程序便会寻找这个chains1中的记录的0x20chunk,然后吧这个chunk的数据段第一位记录的chunk内容打印出来,连同那个记录的0x20chunk的第二个数据段的位置的内容一同打印出来。
此时chains1中的记录的0x20chunk,为之前的proxy1的0x20chunk,但是这个被我们释放重新利用了,就是上面那个被填入proxy2的0x20chunk的chunk。
于是此时程序会寻找chains1中的记录的0x20chunk(就是proxy2的0x20chunk),把这个chunk里的内容打印出来,而这个chunk里记录着proxy2的0x90chunk的数据段地址,于是我们就能得到proxy2的0x90chunk的数据段地址,从而得到heap的基地址。
notion image
在打印的chains1的过程就是顺着有数字的线条的过程。
 
 

泄露libc地址

把之前用来填充tcachebin的7个chunk,都free,使其将tcachebin填满
notion image
 
 
之后free掉chains3,这样会free直接掉chains3指向的proxiy1中的0x20的chunk,这个chunk指向的proxiy2的两个chunk。这3个chunk都会被free掉,分别进入fastbins和unsortedbin。
notion image
 
 
之后申请7个chunk,把tcachebin中的chunk申请出来。
notion image
 
 
之后我们向程序申请两次chains,并且向这两次的chains中都填入proxy2(虽然此时的proxy2的两个chunk都是free,但是在proxy2这个地址中依然有这个chunk的地址)
于是在程序中变会出现proxy1的0x20chunk里存放着proxy2的0x20的chunk的数据段地址,同时proxy2的0x20chunk里也存放着proxy2的0x20的chunk的数据段地址(自己放自己)
notion image
 
 
在将chains2给free掉,这样会使chains2指向的那个0x20的chunk,这个chunk中存放的proxy1的0x20的chunk,proxy1的0x20的chunk中存放的proxy2的0x20的chunk,这2个chunk都free,进入fastbin中
notion image
 
 
然后在连续两次申请chains,并其中填入proxy2。
于是在之前的0x20的chunk和proxy1的0x20的chunk都被用来存放proxy2的0x20的chunk的数据段
notion image
 
此时的堆的大致结构如下
notion image
notion image
notion image
 
 
此时的程序中还有3个chunk是free chunk,我们现在申请一个proxy3,并向申请的这个proxy3中写入一个地址,这个地址可以任意写,并且这去地址的内容就是我们后面要读出来的数据内容,于是我们可以写入heap_unsortedbin=heap_base+0x2c0 就是上面的unsotedbin的fd中有libc的地址。
程序会把原本输入proxy2的两地址给我们当做这个proxy3的chunk使用,我们向proxy3的0x90的chunk中填入了proxy1的0x90的chunk的数据段
notion image
 
 
之后连续两次申请proxy,proxy4和proxy5。proxy4的0x20的chunk中存放着proxy1的0x90的chunk的数据段(把这个chunk从bin中拿出来使用)。
其他的3个chunk都是新申请的。
notion image
 
 
然后把之前用来填tcachebin中7个chunk释放。
notion image
 
 
把proxy4给free掉,于是会把之前先最开始申请的0x20chunk,和这个0x20的chunk中放的proxy1的0x90的chunk的数据段,这两个都free掉,进入fastbin和unsotedbin。
notion image
 
于是此时形成如此的情况
notion image
 
此时我们将chains5打印出来,变回进行下面有顺序的线条寻找,并最终把libc的地址打印出来
notion image
 
notion image
 
 
exp
 
 
 
再探C语言一道有趣的栈题
Loading...