这个样本为一个远控木马,其中有一些比较有意思的地方,比如在解密时使用“Mother360”作为密钥,创建事件时,以“Cao360”作为事件名。
前言
该样本为一个远控木马,和大灰狼非常类似,应该是大灰狼家族的木马。最近两年从疫情开始,有一些黑客又陆续重新开始使用几年前流行的Gh0st、大灰狼、Farfli等远控木马开始钓鱼,因为这些远控的源码曾被公开,所以变种很多。
总的来说,这个样本有一些比较有意思的地方,比如在解密时使用“Mother360”作为密钥,创建部分事件时,以“Cao360”作为事件名,这背后是什么意思?各位师傅们有什么看法?下面开始对这个样本进行逆向分析,我这里重点是分析它的启动过程。
基本分析
使用PEiD查看,发现未加壳:
既然没有加壳,那么我们就可以直接通过IDA Pro来查看导入表,如果有加壳,需要先脱壳。通过IDA Pro我们发现导入函数不多,其中需要特别关注的是导入了LoadLibraryA和GetProcAddress,后面我们会详细介绍:
另一个需要关注点是它以序号的方式导入了一些网络操作相关的函数,比如WS2_32中的recv、gethostname等API函数,这些函数表示该样本会有一些socket等网络连接:
然后我们就可以使用Process Monitor进行监控,以便于查看它所进行的网络连接,如果可能的话,会直接看到他的C2服务器,这里使用Process Monitor监控后发现的确会有网络连接行为,如下图所示:
为了搞清楚该样本是怎么运行的,我们需要更进一步的详细分析,尤其是启动过程,对于网络操作,由于通过Process Monitor已经获取到了他的C2服务器,这里就不再进行详细分析了,可以直接通过wireshark等工具进行抓包分析。
详细分析
整体流程
该样本的启动过程可以分为如下四部分,接下来我们逐个进行分析。
动态加载函数
前面提到了该样本所使用的导入函数很少,导入函数中有Loadlibrary和GetProcessAddress,一般情况当我们看到这里就需要特别关注一下。LoadlLibrary的功能是用来获取模块的句柄,如果模块未加载,则将模块加载入进程,函数原型如下:
HMODULE LoadLibraryA(
[in] LPCSTR lpLibFileName
);
参数lpFileName 是可执行程序的路径,返回加载后模块的句柄。
GetProcessAddress是用来从指定的动态链接库 (DLL) 中检索导出函数或变量的地址。其函数原型如下:
FARPROC GetProcAddress(
[in] HMODULE hModule,
[in] LPCSTR lpProcName
);
其中,参数hModule包含函数或变量的 DLL 模块的句柄。通过调用LoadLibrary、 LoadLibraryEx、LoadPackagedLibrary或 GetModuleHandle函数可以返回此句柄。参数 lpProcName表示函数或变量名,或函数的序号。如果该参数为序号,则必须在低位字中;高位字必须为零。
通过上述两个函数的组合,便可以实现动态加载和调用指定的函数,比如,我们想要动态加载MessageBox函数,由于MessageBox函数位于user32.dll中,所以我们可以通过如下方式进行加载:
1.调用LoadLibraryA,将参数lpLibFileName设置为user32.dll;
2.调用GetProcAddress,参数hModule为第一步LoadLibraryA的返回值,参数lpProcName设置为MessageBox;
通过上述两个步骤,就可以获取到MessageBox函数的地址,之后便可以进行调用。
回到我们要分析的样本,该样本首先便利用动态加载的方式,加载了kernel32.dll、user32.dll等多个常用的动态链接库,该样本首先通过字符串拼接,然后将拼接后的字符串作为参数lpLibFileName传递给LoadLibraryA,以实现动态加载kernel32.dll的过程:
与此类似,在样本中有多处地方也通过字符串拼接的方式,比如在调用GetProcAddress获取函数地址时,将拼接后的字符串作为参数。这样可以在一定程度上躲避杀毒软件都查杀,增加恶意代码分析人员的分析难度。
解密配置信息
样本实现动态加载后,便可以调用任意Windows API函数。该样本将嵌入自身的数据进行了两次解密,第一次解密是将416208处的内容入栈,大小为472字节,调用解密函数,第二次解密是将416068处的内容入栈,大小为410个字节,调用解密函数。
进入40AA12处的函数内,我们可以看到该函数使用“Mother360”作为解密函数的密钥:
如下是一个进行各种数学运算的函数:
紧接着是另外一个进行数学运算的函数:
一些师傅可能直接就能发现使用的是RC4加密算法,看不出来也没关系,我们可以直接使用ollydbg动态调试,获得解密后的内容即可,其中对416028处解密后,得到对应的第一段配置信息,其内容为:
对416068处内容解密后,得到对应的第二段配置信息,其内容为:
通过两次解密,我们可以看到这是样本将一些自身的配置信息比如分组信息、C2服务器IP等释放到内存中。
遍历查找进程
所谓遍历进程,就是把系统中当前运行的所有进程列举出来,挨个查看进程相关信息,比如很多恶意软件会通过这种方法查找当前主机是否运行着杀毒软件。举例来讲,可能某个恶意软件发现系统中运行着名为“360tray.exe”的程序,那么就可以认为当前主机运行着360安全卫士,如果有杀毒软件,可能会直接退出,如果不存在“360tray.exe”,也不存在“QQPCRTP.exe”,说明没有运行QQ电脑管家,如果把常见的杀毒软件都不存在,那么恶意软件就可以执行恶意操作了。在这里我们首先介绍一种非常常见的遍历进程的方法,该方法就是先通过调用CreateToolhelp32Snapshot来获取系统中的进程快照,或指定进程的快照,该函数的原型如下:
HANDLE CreateToolhelp32Snapshot(
[in] DWORD dwFlags,
[in] DWORD th32ProcessID
);
其中各个参数含义如下:
dwFlags:指定了获取系统进程快照的类型;
th32ProcessID:指向要获取进程快照的ID,获取系统内所有进程快照时是0;
如果函数调用成功返回快照句柄,否则返回INVALID_HANDLE_VALUE。在得到系统进程快照句柄之后,需要调用Process32First函数查找系统进程快照中的第一个进程。Process32First函数的原型如下:
BOOL Process32First(
[in] HANDLE hSnapshot,
[in, out] LPPROCESSENTRY32 lppe
);
其中各个参数含义如下:
hSnapshot是从先前调用CreateToolhelp32Snapshot函数返回的快照句柄 。
lppe 指向 PROCESSENTRY32结构的指针。它包含进程信息,例如可执行文件的名称、进程标识符和父进程的进程标识符。
该函数都返回值如下:
如果进程列表的第一个条目已复制到缓冲区,则返回TRUE ,否则返回FALSE。如果不存在进程或快照不包含进程信息, GetLastError函数将返回ERROR_NO_MORE_FILES错误值 。
在获得第一个进程后,便可以读取lppe结构体的内容来获得进程名。之后再通过调用Process32Next 函数来检索有关系统快照中记录的下一个进程的信息。该函数与Process32First用法类似。
回到我们要分析的样本,我们发现该样本会根据解密后的配置信息中某一个字段是否为1,当为1时会调用40AC6E处的函数,该函数会获取WinExec函数地址:
通过WinExec函数可以执行命令,这里我们需要特别留意一下看后续是否会调用WinExec函数,查看它会执行什么命令。
之后该样本会获取CreateToolhelp32Snapshot函数地址,而后再通过call指令调用该函数获取当前进程快照:
分析到这里,我们就知道该样本极有可能在遍历当前主机的所有进程,进而查找某一个特定的进程名。果不其然,该样本调用不断的循环从进程快照中遍历进程:
之后,发现该样本调用了字符串比较的函数:
来对比进程快照中是否包含rundll32.exe,当然,会一直不断的循环对比,直到找到rundll32.exe,或者将进程快照中所有的进程名对比一遍。那么如果找到了rundll32.exe,即lstrcmpiA返回值为0的时候,会怎么做呢?
一旦发现有rundll32.exe在运行,则调用WinExec函数:
顾名思义,该函数就是用来执行特定命令的,其原型为:
UINT WinExec(
[in] LPCSTR lpCmdLine,
[in] UINT uCmdShow
);
lpCmdLine是要执行的应用程序的命令行,uCmdShow是启动的显示选项,SW_HIDE表示隐藏启动。
而“taskkill /f /im rundll32.exe ”表示强制结束rundll32.exe进程。至于这里为什么会根据自身的配置信息结束掉rundll32.exe进程,我也没想明白,如果有知道的师傅欢迎留言交流!
与C2建立连接
远控木马最常用的通讯方式就是使用socket套接字,相信大家都很熟悉了,我这里就不过多介绍了,直接继续分析该样本。
之后我们会发现一个比较有意思的现象,就是该样本会创建一个事件,该事件名为“Cao360”:
之后就通过创建socket套接字:
使用之前解密出的C2地址,同时设置端口,之后调用connect连接远程C2:
通过上述步骤已经与C2建立了连接,就是我们常说的被控端上线了。接下来继续分析发现会创建一个线程:
这也是比较常规的方法,就是在线程中与远程C2进行交互,我们继续分析发现该样本开始获取主机的一些基本信息,比如系统版本:
甚至通过读取注册表项以查询该主机的CPU频率:
获取主机磁盘空间:
获取一系列基本信息之后,因为之前已经与C2服务器建立了socket套接字连接,那么我们就有理由推测该样本可能会将这些信息传递给C2服务器。果然,继续分析发现了该样本调用了send函数:
send函数的作用就是在已经连接的套接字上发送数据。其函数原型为:
int WSAAPI send(
[in] SOCKET s,
[in] const char *buf,
[in] intlen,
[in] intflags
);
我们主要关注前三个参数:
s 标识已连接套接字的描述符。
buf 指向包含要传输的数据的缓冲区的指针。
lenbuf参数指向缓冲区中数据的长度(以字节为单位) 。
之后还会通过recv接收数据:
recv函数与send函数类似,这里不再过多介绍。然后样本会调用VirtualAlloc来分配内存:
将接收的内容复制到新分配的内存空间中,然后根据接收的内容进行下一步的操作。由于这些内容同样也是经过了RC4加密,并且采用了压缩算法,分析起来比较麻烦,篇幅较大,这里就不再详细分析了,感兴趣的小伙伴们可以从网上找到相关的开源代码生成一个服务端,使用wireshark等抓取其中的流量,结合IDA和ollydbg一起逆向分析。
总结
至此,整个样本的启动过程分析的差不多了,感兴趣的可以对加密算法、通信协议、远控功能等进行分析。它所采用的加密算法是RC4加密算法,由于我对加密算法不太熟,所以就不在各位师傅面前班门弄斧了。它的通信过程也是比较有规律的,比如它的通信流量虽然是加密的,但是有固定的格式,而且开头前五个字节是固定的。该样本的远控功能还是比较多的,可以进行键盘记录、进程管理、远程CMD、服务管理等常见的功能。
个人水平有限,文章内如有错误欢迎指出。对恶意代码分析感兴趣的可以Email联系我:bWFsd2FyZS5leHBsb2l0QGZveG1haWwuY29t,或者有一些有意思的恶意软件也可以发给我,我们一起共同学习。
- 本文作者: xia0
- 本文来源: 奇安信攻防社区
- 原文链接: https://forum.butian.net/share/1110
- 版权声明: 除特别声明外,本文各项权利归原文作者和发表平台所有。转载请注明出处!