首页
社区
课程
招聘
[原创]fstrm-capture 控制帧构造流程分析
发表于: 15小时前 83

[原创]fstrm-capture 控制帧构造流程分析

15小时前
83

作为一个资历尚浅的pwn手,我大概算是第一次独立逆向这种真实环境下的程序,本帖仅当记录一下逆向和调试过程,若有纰漏,还请多多指出。


程序名称:fstrm_capture

debian系下安装命令:apt install fstrm-bins,默认在/usr/bin目录下,是安装fstrm-bin的三个命令行工具之一

程序用途:监听一个套接字,接收Frame Streams协议格式的数据流,然后保存至文件中。


复制后ldd检查一下运行情况:

可以看到依赖一个libfstrm.so.0库,以及一个libevent-2.1.so.7库

file检查,确定符号表已经被剥离。

尝试先用strace确定使用了哪些系统调用,以便快速找到主要逻辑:

可以发现最上面的openat调用,更之前是mprotect和brk,以及一些初始化,这里注意到openat的字符串是尾缀为.fstrm的文件名,不难猜测这是程序正在打开文件

而最下面,程序卡在了epoll_wait处,想必是一个死循环

直接启动gdbserver和gdb,并且在open上下断点,同时查看bt,可以找到是谁调用了open

调用者的地址是0x5555 5555 9eaf,我们通过cat /proc/7502/maps和readelf快速锁定此函数的VA

用0x5555 5555 7000减掉代码段所在的LOAD相对于虚拟内存运行基址的VA 0x3000,得到映射在虚拟内存中的起始位置,用0x5555 5555 9eaf减去这跟起始位置的值,等于0x5eaf,也就是调用open的代码出现在这个相对VA上

这里我的办法稍微麻烦了一些,其实可以用IDA直接追踪一下open的调用,直接找到目标函数

打开IDA,目标函数是sub_5d10,IDA显示的VA也是0x5d10,简单分析后情况如下:

将sub_5010重命名为handle_it,并继续对它进行分析:、其中fstrm_control_init,fstrm_control_set_type等几个函数是libfstrm.so的库函数,这里也把对它们的分析结果贴出来:

对于fstrm_control_set_type函数,它并没有标出自己的参数情况,所以它的参数是用gdb看的:

rdi寄存器和rsi寄存器负责保存前两个参数,所以参数分别是0x5555 5555 3550和0x2


总地来说,这一大堆逻辑,其实都是创建了这样一个内存链式结构:

修复的结构体的命名不太严谨,不过应该不影响阅读:


这里解释一下:

这是一个实现动态数组分配的机制

一块内存的类型是struct_35,该内存由fstrm_control_init在堆上分配;struct_35->ptr指向一个struct_33类型的内存,这段内存同样由fstrm_control_init分配,the_array_start_ptr代表一个结构体数组的头部指针,malloc_pos_ptr是游标,room_has_been_used表示当前结构体数组的元素数量,the_whole_room是当前最大可储存的元素数

该数组的每一个元素,都是struct_34类型,前八字节表示字符串长度,后八字节存储一个指针,指向字符串大小


它应该是为大型软件设计的,而fstrm_capture应用它仅仅是存一个普通字符串,也就是-t参数


fstrm_control_encode是一个编码函数,大概的过程是大小端序的转换,我只做了一半分析,有需求可自行查看


size[0].m128i_u64[1]属于某union(大小为16字节)的后半部分,前半部分就是size本身,这里应该也是编译器优化问题

程序最后调用fwrite,将size[0].m128i_u64[1]所存储的内容按size x 1写入文件之中


这里是最后的结果:



本来想抓个包再检验一下,但其实跟hexdump看的东西区别不大,只是经过编码后的情况,如果不深入编码逻辑的话,应该没必要细究


对我而言,难点主要来自没接触过frame stream协议,以及对动态数组的原理不熟悉

到此告一段落。


下面是附件,包含原装的libfstrm库和fstrm_capture,以及我分析得到的i64文件




[内核课程]《Windows内核攻防实战》!从零到实战,融合AI与Windows内核攻防全技术栈,打造具备自动化能力的内核开发高手。

上传的附件:
收藏
免费 0
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回