吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 5684|回复: 24
上一主题 下一主题
收起左侧

[CTF] Pwn格式化字符漏洞详细分析(第五空间2019决赛PWN5)

  [复制链接]
跳转到指定楼层
楼主
HNHuangJingYU 发表于 2021-11-12 21:20 回帖奖励
本帖最后由 HNHuangJingYU 于 2021-11-12 21:25 编辑

拿到题目(第五空间2019决赛PWN5)分析如图:(以下都是针对32位)

首先看了看栈溢出漏洞,read做了限制字符大小利用不了,但是看到了一个printf(buf)这就是一个明显的格式化字符漏洞,再结合题目分析一波,大概流程是随机生成一个数字存入到地址为dword_804C044的全局变量中,最后对输入的passwd字符进行比较,这里注意下atoi这个函数它只会提取正整数,除此之外都是返回0,因为dword变量是随机数,所以控制不了(之前见过一题也是随机数,但是它的随机种子在栈里面是可控的,然后用栈溢出,再引用ctypes库,加载libc.so.6然后就可以获得系统一样的随机数了),但是这题很明显就是通过printf(buf)这个漏洞去更改dword变量的值,所谓格式化漏洞。。。阿巴阿巴。。。。之前看格式化漏洞相关的wp大佬们都要讲一遍格式化字符漏洞知识,看基础还是自行看资料吧,比我这详细,,其实就几个核心点:

1. %2$s 以字符串格式输出参数二
2. %n ,如 printf("abcdefg%n"); ,%n前面写了7个字符,所以向ESP(栈顶指针)所指向的地址处所指向的地址处(ESP指向了栈顶,此处存储着一个地址)写入7。
3. %10$n ,与 %n 类似,不过是向[ESP + 10]处指向的内存处写入7。%n:将%n 之前 printf 已经打印的字符个数赋值给偏移处指针所指向的地址位置
这里的格式符是一定要理解清楚的,理解了这里做题就不难。最后payload如下:



玩点花样

当然就算当输入password时我们输入字符串使atpi函数返回0也能做,可以利用整型溢出的方法,将我们格式化字符的数值变为溢出状态并控制为0
在默认是最小值4的情况下它的栈情况:



这里可以看到它处于偏移为10的位置处(fmtarg这里显示10行、第9个参数估计是把第一和第二行识别为一行)但是手动数一下是第11行。

再变换一下如果要控制小于4的数是不是就看’%index$n’它处于payload的第几个。

假设变换后是这样

[Python] 纯文本查看 复制代码
payload =  b'%10$n' + p32(bss_addr)


理解下代码,这样确实让%n为0了,但是写入的参数是格式化字符,然后printf执行会报找栈对齐错误,再者毕竟也没有’%10$n’这个地址把。此时栈如图:



之前是不是取偏移为10的参数就取到了自己,加上一个栈对齐错误,‘%10$n’这里是不是占了5个字节,5字节加上后面的p32()是不是就是9字节。。。栈对齐错误,那么给’%10$n’再加上3个字节,使它对齐栈,这时候加上了一个填充字节,那么我们取的地址应该就在偏移为12处的位置,那么改良变换后的代码:

[Python] 纯文本查看 复制代码
payload =  b'%12$n'+b’aaa’ + p32(bss_addr)


然后看看栈空间:

第十二位参数刚刚是符号地址,并且栈对齐了。这里就完成了对符号地址处赋值为0的操作



0-3之间就是依葫芦画瓢反之就是在’%index$n’前后进行增减就好了,保证栈对齐就行



当要写入比较大的数据时运行程序会报错,因为填充的栈数据过大会覆盖其他重要的地址导致栈奔溃。

这之前要需要了解如下格式符:

[Python] 纯文本查看 复制代码
%$hhn 表示写入的地址空间为 1字节
%$hn -> 2 字节
%$n -> 4 字节
%$ln -> 8 字节,在 32bit 和 64bit 环境下一样。有时,直接写 4 字节会导致程序崩溃或等候时间过长,可以通过%$hn 或%$hhn 来适时调整。
%$lln -> 16字节


嗯,来到题目中如何给上面的符号地址赋值0x00abcdef呢?

因为如果填充这么大的长度数据进栈显然是不可能的,但是数据是以最小单位byte单位存储的并以地址连接方式组成数据,比如0x080492bc里面存储的值是0xb4853881那么按照小端存储(一般都是小端,我知道的单片机就是大端模式,之前老师上课讲过。。)来说它是这样的



假设想让0x804c044这里的值为0x00abcdef,那么也就是说需要在对应位置赋予对应的值,所以payload的前部分就是这样

[Python] 纯文本查看 复制代码
payload =  p32(bss_addr) + p32(bss_addr+1) + p32(bss_addr + 2) + p32(bss_addr +3 )


那后部分就是对应参数位的值,嗯,那么先看看效果代码、运行效果如下:
[Python] 纯文本查看 复制代码
payload =  p32(bss_addr) + p32(bss_addr+1) + p32(bss_addr + 2) + p32(bss_addr +3 )
payload += b'%10$n' + b'%11$n' + b'%12$n' + b'%13$n'




嗯,感觉好像差不多,因为我们前面有4个p32的数据,刚好就是0x10大小,那么修改一下他的值为0xef,那么就是说在前面填充223个字节,更新代码查看结果:

[Python] 纯文本查看 复制代码
payload =  p32(bss_addr) + p32(bss_addr+1) + p32(bss_addr + 2) + p32(bss_addr +3 )
payload += b'%223c%10$n' + b'%11$n' + b'%12$n' + b'%13$n'




ok,再来第二个也就是0xcd,因为前面已经填充了0xef个长度了,所以只能继续扩大然后用hhn取最后一个字节得到0xcd

[Python] 纯文本查看 复制代码
payload =  p32(bss_addr) + p32(bss_addr+1) + p32(bss_addr + 2) + p32(bss_addr +3 )
payload += b'%223c%10$n' + b'%222c%11$hhn' + b'%12$n' + b'%13$n'




依照上面可以得出如下:

[Python] 纯文本查看 复制代码
payload =  p32(bss_addr) + p32(bss_addr+1) + p32(bss_addr + 2) + p32(bss_addr +3 )
payload += b'%223c%10$n' + b'%222c%11$hhn' + b'%222c%12$hhn' + b'%85c%13$hhn'




ok最后成功赋值0x00ABCDEF

免费评分

参与人数 8威望 +2 吾爱币 +108 热心值 +8 收起 理由
fengbolee + 2 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
Hmily + 2 + 100 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
itmacbook + 1 + 1 热心回复!
wildbloom + 1 + 1 热心回复!
努力加载中 + 1 + 1 热心回复!
lx12 + 1 + 1 我很赞同!
KylinYang + 1 + 1 谢谢@Thanks!
magical666 + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

推荐
rogxo 发表于 2021-11-12 23:14
牛,先收藏一波
推荐
sandon 发表于 2021-11-13 07:58
4#
suiyuewudi 发表于 2021-11-12 21:38
5#
 楼主| HNHuangJingYU 发表于 2021-11-12 21:47 |楼主

适合有点pwn基础的看。。
6#
nnn1134 发表于 2021-11-13 09:33
值得学习
7#
海天绯红 发表于 2021-11-13 10:08
哈哈,正好需要!
8#
zwtstc 发表于 2021-11-13 10:11
学习了,感谢分享
9#
GeekPwn 发表于 2021-11-13 12:04
感谢,有用
10#
snake88 发表于 2021-11-13 13:07

看不懂,真的看不懂。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-12-22 11:39

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表