0x00 分析方法
1)基本信息收集
对于一个进程的分析,首先可以通过ps,lsof等命令了解程序的一些基本信息。这个阶段可以搜集进程开放了哪些端口,使用了哪些句柄,程序的运行状态。
2)获取程序组成二进制文件
下一阶段可以思考程序由哪些程序文件组成,通过ps命令可以找到程序的启动文件路径,通过进程的maps文件,可以查看进程加载了哪些so文件。 这一步可以得到程序的所有二进制代码,作为IDA与gdb的分析输入。
3)数据作为切入点,数据流跟踪
进程信息的搜集与程序代码分析都比较零散,无法很好的将各个部分连接起来。得到了二进制代码,逆向之后,也常常感觉到难以下手,缺少一个切入点。 此时数据流可以作为一条贯穿始终的线索,同时也可以作为对代码研究的切入点。
例如,当我们执行一个web登录请求时,首先可以用tcpdump抓取数据,分析apache与客户端之间的数据交互。 然后可以用strace监听apache与mysql, 分析这个数据流到达的过程中,apache与mysql利用哪些系统调用读写数据,用什么方式与其他进程进行通信。
使用gdb下断点,断下数据查看调用栈,分析处理数据的函数,即可在IDA中精确定位到相关逻辑处理的代码。这样即可通过一个可视化的操作作为切入点,对其每个阶段的数据流进行跟踪,最终精确定位到这个操作的逻辑处理代码,分析这个业务的逻辑。
分析思路如上图所示。
0x01 进程信息
1)ps 命令收集进程运行信息
ps 可以找到进程的PID,状态,启用用户,进程启动命令等重要信息。
常用参数:
-A 显示所有进程(等价于-e)(utility)
-a 显示一个终端的所有进程,除了会话引线
-N 忽略选择。
-d 显示所有进程,但省略所有的会话引线(utility)
-x 显示没有控制终端的进程,同时显示各个命令的具体路径。dx不可合用。(utility)
-p pid 进程使用cpu的时间
-u uid or username 选择有效的用户id或者是用户名
-g gid or groupname 显示组的所有进程。
U username 显示该用户下的所有进程,且显示各个命令的详细路径。如:ps U zhang;(utility)
-f 全部列出,通常和其他选项联用。如:ps -fa or ps -fx and so on.
-l 长格式(有F,wchan,C 等字段)
-j 作业格式
-o 用户自定义格式。
v 以虚拟存储器格式显示
s 以信号格式显示
-m 显示所有的线程
-H 显示进程的层次(和其它的命令合用,如:ps -Ha)(utility)
e 命令之后显示环境(如:ps -d e; ps -a e)(utility)
h 不显示第一行
常用参数组合 afx,aux,alx
2)netstat 查看端口开放信息
Netstat 命令用于显示各种网络相关信息,如网络连接,路由表,接口状态等等。
常见参数:
-a (all)显示所有选项,默认不显示LISTEN相关
-t (tcp)仅显示tcp相关选项
-u (udp)仅显示udp相关选项
-n 拒绝显示别名,能显示数字的全部转化成数字。
-l 仅列出有在 Listen (监听) 的服務状态
-p 显示建立相关链接的程序名
-r 显示路由信息,路由表
-e 显示扩展信息,例如uid等
-s 按各个协议进行统计
-c 每隔一个固定时间,执行该netstat命令。
参考资料:http://www.cnblogs.com/ggjucheng/archive/2012/01/08/2316661.html
3)lsof查看句柄信息
lsof(list open files)是一个列出当前系统打开文件的工具。在linux环境下,任何事物都以文件的形式存在,通过文件不仅仅可以访问常规数据,还可以访问网络连接和硬件。
常见参数
-a 列出打开文件存在的进程
-c<进程名> 列出指定进程所打开的文件
-g 列出GID号进程详情
-d<文件号> 列出占用该文件号的进程
+d<目录> 列出目录下被打开的文件
+D<目录> 递归列出目录下被打开的文件
-n<目录> 列出使用NFS的文件
-i<条件> 列出符合条件的进程。(4、6、协议、:端口、 @ip )
-p<进程号> 列出指定进程号所打开的文件
-u 列出UID号进程详情
-h 显示帮助信息
-v 显示版本信息
参考资料:http://www.cnblogs.com/peida/archive/2013/02/26/2932972.html
4)cat /proc/{PID}/maps
每个进程的模块加载信息都会存到PID对应的maps文件中。通过这条命令可以打印进程的模块加载信息及加载到内存中的地址。
0x02 数据交互
在整个分析过程中,数据流贯穿始终的线索。 数据本身才是核心的资产,同时数据也是验证一些猜想的最好证据。 如想要验证某个连接是否我的网络操作的连接,如果抓包该连接中出现了我提交的数据就可以证明这个连接与我的操作相关了。如gdb调试中在内存中打印出输入的数据,就能确定走到了相关的函数调用点。
进程与外界的数据交互,可能是与文件的交互,与其他进程的交互,或者与其他主机建立网络连接交互。在linux中这些都可以关联到句柄上,可以使用lsof查看。 但是有些交互发生在瞬间,很快就关闭了,没有合适的时机进行查看。 此时可以用strace 对进程进行监听,同时strace也可以通过一些系统调用分析程序的执行过程。
1)Strace 使用
常用参数:
-c 统计每一系统调用的所执行的时间,次数和出错的次数等.
-d 输出strace关于标准错误的调试信息.
-f 跟踪由fork调用所产生的子进程.
-ff 如果提供-o filename,则所有进程的跟踪结果输出到相应的filename.pid中,pid是各进程的进程号.
-F 尝试跟踪vfork调用.在-f时,vfork不被跟踪.
-h 输出简要的帮助信息.
-i 输出系统调用的入口指针.
-q 禁止输出关于脱离的消息.
-r 打印出相对时间关于,,每一个系统调用.
-t 在输出中的每一行前加上时间信息.
-tt 在输出中的每一行前加上时间信息,微秒级.
-ttt 微秒级输出,以秒了表示时间.
-T 显示每一调用所耗的时间.
-v 输出所有的系统调用.一些调用关于环境变量,状态,输入输出等调用由于使用频繁,默认不输出.
-V 输出strace的版本信息.
-x 以十六进制形式输出非标准字符串
-xx 所有字符串以十六进制形式输出.
参考资料:http://www.cnblogs.com/ggjucheng/archive/2012/01/08/2316692.html
用的比较顺手的组合strace –p 9126 –s 1024 –ff –o log
该命令会跟踪子进程和线程,并按线程将结果保存到不同的文件中。
使用strace最终apache得到的一些结果
该结果显示了一个网络连接建立,发送,接收,再到关闭的一个系统调用过程,能够帮助我们分析程序是如何执行的。
2)tcpdump使用
Tcpdump 是linux下常用的抓包工具,但是命令行下可视化分析不太方便。 推荐用-o选项将数据保存成pcapng格式的文件,再用wireshark或科来之类的软件对数据进行分析。
0x03 程序行为
通过对进程信息的收集,我们能得到相关的启动程序与模块so文件,这时就能够丢到IDA中进行逆向分析了。 IDA的使用推荐阅读《IDA Pro权威指南》。再用gdb进行动态调试能够很好的帮助理解程序的运行过程,对数据的处理过程。在条件符合的情况下用gdbserver结合IDA的远程调试,或者使用BinNavi,能够更方便的分析程序流程。