perf
简介
perf 是 Linux 系统性能分析工具集,全称是 Performance Event Counters
它基于 Linux 内核的 perf_events 子系统,能够提供硬件和软件层面的性能分析能力
我们这里会用到它的一些功能以获取一些硬件事件的信息,因此,你必须确保自己的虚拟机支持 PMU
功能
准备perf
事前准备
首先确定你的设备支持 PMU 功能,如果条件允许,实体机上使用 perf 会方便很多,如果你使用的是 wsl2 作为使用的虚拟机,请在设置中开启 性能计数器 ,并使用除 ubuntu 以外的系统,因为 wsl2 对内核的魔改会导致一些兼容性问题,我捣鼓了两天也没能完美解决,可以在 wsl2 上选择其他 Linux 进行尝试,或者换用 VMware ,在使用VMware时,请在硬件设置里,添加上虚拟化 CPU 性能计数器,并禁用所有HyperV相关的设置,并关闭虚拟化保护
包括(仅限VMware使用者,wsl2 不要改):
- Windows安全中心 -> 设备安全性 -> 内核隔离 -> 内存完整性/本地安全机构保护
- Windows功能 -> Hyper-V/Virtual Machine Platform/Windows虚拟机监控程序平台
perf安装
安装 perf 可以通过
|
|
相关设置
使用权限
等安装完成后并不能直接使用,你需要先查看
|
|
这个perf_event_paranoid设置了运行时权限相关的内容,建议修改成小于等于1的值
|
|
CPU核心与内存分配
此时可以尝试一下使用
|
|
检测perf是否能正常运行,如果你的 CPU 是有大小核区分的话,可能会出现内存分配问题,尝试查看你的 CPU 状态
|
|
这里可以看到你的 CPU 属于 atom 的核心,也就是常说的能效核 确定了 CPU 核心属于 atom 或 core 后,将进程绑定在非 atom 的核心上运行 可以通过 taskset 指令绑定核心
|
|
手动编译 perf (适用于wsl2用户)
如果你使用的是 wsl2 ,且以上设置后仍不可使用,可以尝试手动编译适合自己的 perf 首先准备编译需要用到的一些工具包
|
|
接下来确定内核版本
|
|
记录下完整的版本号 接下来 git clone 得到对应版本的 wsl2 内核源码,只需要 clone 该版本分支下的内容即可 可以前往WSL2-Linux-Kernel手动查看对应分支后再clone
将源码完全解压,并进入 perf 目录
|
|
此时可以开始编译
|
|
完成编译后将得到的 perf 复制到 /usr/local/bin 目录
|
|
此时再次重复之前的权限设置和核心内存设置即可
RMKS
如果以上设置都完成了,但你的perf只能使用软件事件或根本无法使用,这里包括使用 perf 输出指令数为0或 <not supported>,那么恭喜你该尝试其他的设备了,至少我这里虚拟机基本全军覆没,为了方便,最后还是上实体机了
简单使用说明
如果你需要 perf 的完整使用说明,可以前往perf学习
这里我们主要用到 stat
|
|
|
|
Side-Chanel-Attack
这里简单介绍使用 perf 指令计数的侧信道攻击,我选择搭配例题讲解 这里使用的是 SwampCTF2019 的题目 future_fun 作为例题,同时我也是在这个题上研究学习的该手法 题目可以从 SwampCTF-2019 寻找下载
简单原理
一个程序如果要判断两个字符串是否相同,最简单的方法就是直接从第一个字符开始,逐个进行比较,如果发现不同的字符,就会停下并返回结果,如果一个字符相同,就会继续比较下去,因此如果字符相同的个数更多,执行的指令数会与不同的情况更多,这样就可以逐个字符的确认完整的字符串,有点像拿铁丝翘一些比较原始的锁,将每个弹簧分别依次复位并成功开锁
例题
拿到 future_fun 的题目文件后,直接运行,可以提前知到flag格式为 flag{} ,事实上不知道flag格式也行,只是多跑两轮计数罢了
|
|
此时我们再使用 perf 进行测试
|
|
此时可以看到输出下面多出来了一行
|
|
这里的 8176046 就是结束时总共的指令数,如果这一位你的结果是0,那么请回到上一节排查问题
我们尝试将第一个字符改成f
|
|
可以发现指令数的确显著变大了,继续测试
|
|
结果的确如预想一样,当一个字符对应上后指令数会显著增大
所以我们可以尝试逐字符输入,每个字符处分别尝试所有的可打印字符,并统计指令数,将最大的一个提取出来,最后可以写出一份合适的exp,最后得到以下输出
|
|
exp
|
|
最后的垃圾话
这种打法还是太超模了,很大一部分简单的 re 题目就这一个exp都能差不多解决了,但是要是加上一些长度检验之类的防范措施,就得再手动修改下exp了
这篇文章还是受 guyinatuxedo 的启发,但是他的文章内容是错的,至少perf部分有问题,不要错把运行时间与指令数搞混淆
如果不使用 instructions:u 而去看运行时间,理论上也能出,但是受限于运行时环境的稳定性,可能需要多次计算取平均