这篇文章主要分析一个dll,该恶意软件与APT28有关。
先拖进IDA,f5反汇编后如下图,第一次见这么简单的dll
我们查看导出有DllEntryPoint和RunMod,因为我们的IDA静态无法分析dll,所以用rundll32.exe通过调用RunMod函数启动dll
因为这样的动态调试还不会,所以先搁置一下,先用静态查看一下RunMod函数做了什么(Update already)
IDA静态调试
IDA查看该函数发现,主要功能就是创建两个线程函数
先看线程函数下方的sub_10001CF0()函数,这个函数主要的函数是GetMessage,观察函数上下文应该是从线程队列中检索消息,如果线程消息等于22(WM _ ENDSESSION 消息通知应用程序会话是否正在结束),会中断循环。
Thread1 StartAddress
先看第一个thread,一开始的sub_100010C0函数有两条命令行指令systeminfo和tasklist,进去详细查看发现先createpipe创建了个管道(匿名),启动cmd执行命令。systeminfo输出用ReadFile函数读出,tasklist同样
紧接着查看下面的函数sub_100013B0,初步猜测影噶是检索各个文件目录作为目标对象,结合OD看一下是哪些目录
目录获取完成后,我们继续看下面的函数sub_100016C0就是一些关于堆空间的的分配,猜测是为下面的函数申请空间
从Sub_10002900进去看到的函数分析这部分应该是网络连接操作
InternetOpenW API 初始化 WinINet 函数的使用(用户代理被硬编码为“Opera”),使用 InternetSetOptionW 例程(0x6 = INTERNET_OPTION_CONTROL_RECEIVE_TIMEOUT and 0x5 = INTERNET_OPTION_CONTROL_SEND_TIMEOUT)将发送和接收超时设置为 600 秒,InternetConnection用443端口与服务器updaterweb.com建立连接
Base64加密完数据后就要开始发送了,主要关注下面这个函数,(httpOpenRequestW 例程用于创建 (http POST 请求句柄,恶意软件在 (http 请求句柄中添加了一个 (http 请求标头(“application/x-www-form-urlencoded”),使用 (httpSendRequestExW API 将请求发送到 (http 服务器,如下图所示,看到网上的分析443端口连接失败的情况下,会尝试80端口,但是在动静态分析的时候并没有看到。
最后线程会将之前创建的事件置为信号状态
Thread2 sub_6BD71960
线程一开始就将事件之谓无信号状态
有一个类似的工作流程,从调用 InternetOpenW 函数开始,直到连接到端口 443(或端口 80,如果第一个不成功)上的 C2 服务器。这次的 POST 请求不同,因为它包含用于下载 DLL 文件的“cmd=y”命令:
恶意软件使用 InternetQueryDataAvailable 例程查询服务器以确定可用数据量,函数sub_10001FD0中有InternetReadFile函数读取dll文件,下前 4 个字节表示数据大小,还有 32 个字节表示内容的 SHA256 哈希值,图中还有一个CryptStringToBinaryA 函数,对base64编码后的文件进行解码(下图是网上分析)
CryptAcquireContextA 用于获取 Microsoft RSA 和 AES 加密提供程序 (0x18 = PROV_RSA_AES) 的句柄,CryptCreateHash 例程用于创建 CSP(加密服务提供程序)哈希对象 (0x800c = CALG_SHA_256) 的句柄,在 base64 编码的 DLL 文件被解码后,恶意软件会使用 SHA256 算法哈希应该包含 DLL 文件的缓冲区(CryptHashData),通过调用CryptGetHashParam API提取哈希值,(0x2 = HP_HASHVAL),恶意进程验证上面计算出的哈希值是否与 DLL 文件附带的 32 字节缓冲区重合
恶意进程会在%TEMP%目录下创建一个名为fvjoik.dll的文件,新创建的文件填充从 C2 服务器下载的潜在 DLL,使用 LoadLibraryW 例程将 DLL 文件加载到当前进程的地址空间中,恶意软件将使用序号 1 执行导出的函数
函数完成后,sub_10001000()函数中可以看到采用WinExec函数命令行执行cmd删除dll文件
最后还与C2服务器进行了通信,应该是传输了DLL执行的结果
OD动态调试
具体步骤参考博客:(https://www.cnblogs.com/feiyucq/archive/2010/06/07/1753465.html
拖进去一开始,如果F8或者F7的话进的是DLL的主函数,如果不想跟这些主函数的话可以直接F9,然后OD会再停下来,在最下方的消息栏会提示DLL初始化完成。
如下图的操作点击,然后选择导出函数,在导出函数的地址下个断点就可以直接调试了,点击调用按钮程序就断在这里了
结合静态分析,查找下图的字符串定位函数位置
调试f7进SHGetFolderPathW函数,可以看到该函数想获取的是桌面文件夹路径
由静态分析的图可以看出后一个函数PathAddBackslashW是在路径后加反斜杠,通过findfirstfile和findNextfile枚举桌面所有文件,并在文件夹名称前后添加了18个“#”字符然后再与提取的文件和目录列表和前面的字符串连接起来
以下目录也是后门的目标“C:\Program Files”, “C:\Program Files (x86)”, “C:\Users< User >\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Administrative Tools”, “C:\Users< User >\AppData\Roaming”, “C:\Users< User >\AppData\Roaming\Microsoft\Windows\Templates”, “C:\WINDOWS” and “C:\Users< User >\AppData\Local\Temp”
使用 GetComputerNameA API 检索本地计算机的 NetBIOS 名称;GetUserNameA 用于提取与当前线程关联的用户名;恶意软件通过调用 GetVolumeInformationW 的函数提取当前目录根目录的卷序列号;systeminfo 命令的输出加 tasklist 命令的输出加目标目录列表及其内容使用 CryptBinaryToStringA API (0x1 = CRYPT_STRING_BASE64) 进行 base-64 编码(IDA)
(上面这张图应该是第二个线程的,因为命令中包含cmd=y,该命令用于下载dll文件,因为两个线程在网络连接那一块是类似的,所以通过查找字符串定位函数位置的时候找错了)
主线程
主线程完成最后的收尾工作,将之前创建的事件设置为信号状态,使用GetExitCodeThread API获取两个线程的终止状态: