本文首发于“合天智汇”公众号 作者: xiaoyuer
这次我们对很多木马和APT组织常见的一个手法进行正向开发和逆向分析,这个手法就是当发现当前系统中存在特定的杀毒软件和行为监控软件等安全软件时,退出自身进程不再执行自身的恶意模块。其实这个原理还是很简单的,就是进程遍历,然后与这些安全软件的进程进行对比。
进程遍历的常见方法是首先使用CreateToolhelp32Snapshot函数创建一个进程快照,这个快照是当前系统中所运行的所有进程,和使用Windows任务管理器查看进程的结果类似,区别在于Windows任务管理器是实时的,而创建进程快照是“拍照”那一刻所运行着的所有进程。之后使用Process32First和Process32Next对所有的进程进行遍历,将得到的进程名与安全软件的进程名进行对比,如果相等,则退出自身进程。对于windows10的任务管理器不再显示映像名称,可以使用cmd中的tasklist命令来查看当前运行的所有进程。
那我们怎么知道安全软件的进程名呢?这就要靠自己去收集了,比如360tray.exe和360sd.exe就是360安全卫士和360杀毒的进程名,我们以360杀毒为例,当我们发现当前机器上运行了360杀毒则直接退出。
正向开发之进程遍历查找360杀毒
1、CreateToolhelp32Snapshot函数
这个函数的参数有两个,第一个是dwFlags参数,这个参数用来指定快照中包含的系统内容,在这里我们要查看当前系统中所有的进程,所以dwFlags参数要指定为TH32CS_SNAPPROCESS,第二个参数为进程ID,这里我们应该指定为0,为什么会有这个参数呢?因为CreateToolhelp32Snapshot函数不仅仅可以用来查看当前系统中运行的进程,还可以查看某一个指定进程的所有堆(TH32CS_SNAPHEAPLIST)或者模块(TH32CS_SNAPMODULE),这个参数只有当查看某一个指定进程的所有堆或者模块时才有效。我们需要将其指定为0,表示查看当前系统中运行的进程,函数调用成功后返回值是快照的句柄(handle)。如果想了解更多内容可以查看MSDN文档。
2、Process32First函数
这个函数查找系统快照中第一个进程信息,有两个参数,第一个参数hSnapshot是CreateToolhelp32Snapshot返回的进程句柄,第二个参数LPPROCESSENTRY32是一个结构体指针,而这个结构体首先是需要我们来初始化,之后当Process32First调用成功后,就会将函数的返回值存储到这个结构体中,这一点和Python不太一样,需要注意。
3、Process32Next函数
这个函数查找系统快照中下一个进程信息,和Process32First参数一样,两者结合即可遍历系统快照中的进程。
4、编写代码
首先需要把必须的一些头文件包含进来,之后创建了一个listProcess函数来遍历进程,在listProcess函数里首先初始化LPPROCESSENTRY32结构体,其中需要注意的是在调用Process32First之前,我们需要先将结构体中的dwSize初始化,这个值表示结构体大小,可以通过sizeof(LPPROCESSENTRY32)获取。之后依次调用CreateToolhelp32Snapshot、Process32First、Process32Next,然后使用StrStr函数进行对比,系统快照中的进程名保存在LPPROCESSENTRY32结构体中的szExeFile这个成员变量里。理解这几个API函数和相互之间的调用关系,编写程序便水到渠成了。编译运行,在一台没有装360杀毒的主机上运行,最后执行完毕:
如果在一台装有360杀毒的主机上运行,当检测到有360se.exe之后便停止运行:
逆向分析之进程遍历查找360杀毒
ida停留在这个界面,我们双击查看listProcess函数的内容:
首先查看其调用了CrateToolhelp32Snapshot函数:
其中可以看到PROCESSENTRY32结构体在此系统版本和编译环境下的大小为128h,dwFlags的值为2,这是因为TH32CS_SNAPPROCESS是一个宏定义,它对应的常量为2:
得到CrateToolhelp32Snapshot返回值后为什么要将其与0FFFFFFFFh进行对比?查看其二进制:
32个1,我们通过查看宏的方式,看到这个值是-1。
为什么是32个1呢?我第一时间想到原来学习计算机组成原理的时候有一节课在讲补码,好像涉及到这个。经过查阅资料,发现确实是-1。负数是通过对其绝对值相同的正数先按位取反再加1得到的,即-1是通过对1按位取反之后再加1得到的,这样能保证两者相加结果为0(两者相加会溢出,正好为0)。把当年没认真学的知识弄清楚的感觉真棒!
之后,调用了Process32First函数,参数分别为一个指针和一个快照:
之后,获取其进程名然后使用StrStr查找是否包含360sd.exe:
重点查看这里:
其中,先将eax的值(即为PROCESSENTRY32结构体中的szExeFile成员变量,具体可查看PROCESSENTRY32结构体)存入esp+4,再将the process is %s
字符串存入esp中,这其实相当于是先push eax,再push字符串,然后调用printf进行输出。
之后再调用StrStr将进程名与360sd.exe进行对比。如果匹配上,则直接进入最左侧:
如果匹配不上,则进入右侧,调用Process32Next,再循环执行。当Process32Next返回值为FALSE即为零时,则会跳转到中间,此时所有的进程已经遍历完。
至此,整个程序逆向分析完毕。
总结
此次正向开发和逆向分析,主要是对windows中的进程遍历相关的API进行了熟悉和掌握,同时,将遍历到的每一个进程名与常见的安全软件进行匹配,之后再采取相应的措施。基于此,可以拓展开发更多的功能,比如匹配一些行为监控软件、Wireshark、虚拟机vmtools软件等等