概述
笔者之前写过一篇关于BITTER的分析报告,但上次写的比较简单,只是初略的分析了各个类型的样本,在本文中记录下关于提取bitter样本特征的一些过程。
BITTER又名蔓灵花、APT-C-08,疑似来自南亚地区,主要攻击目标为巴基斯坦和中国。BITTER最早的攻击可追溯到2013年11月份,活跃高峰期为2015年至2016年。
BITTER 主要针对政府、军工业、电力、核等单位进行攻击,窃取敏感资料,具有强烈的政治背景。该组织最早在2016由美国安全公司Forcepoint进行了披露,并且命名为“BITTER”,同年360也跟进发布了分析报告,命名为“蔓灵花”。
由于该组织早期特马数据包头部以”BITTER”作为标识,因此国外厂商将其命名为BITTER,但是值得注意的是,自从该活动被曝光后,该组织就修改了数据包结构,不再以”BITTER”作为数据包的标识,改为五字节的随机字符进行代替。
ArtraDownloader
A
原始样本MD5:72eb6896fa9326f38d3745cc442611dc
创建时间:2019-0502
上传时间:2019-0515
此类样本是比较典型,也比较简单的BITTER样本,样本WinMain进来就有比较明显可作为特征的opcode
程序开始会注册一个窗体以执行后面的恶意代码,首先是通过LoadString从资源表中加载序号0x67的字符串作为WindowName,然后加载0x6d的字符串作为ClassName,通过查看资源表可以得到对应的字符串信息
通过比较分析,可以得知不同样本的字符串资源不同,但是序号却相等,所以可以将WinMain入口处加载字符串表的序号作为一个特征点
字符串资源加载之后,程序将会设置WndProc为wub_4025C0,在该函数中通过setTimer设置一个名为TimerFunc的计时器,该计时器的间隔为0x1770,也就是6000毫秒,6秒。
TimerFunc用于实现网络请求,这个函数后面再分析。
在窗体创建完成之后,程序将会尝试获取csidl 为 0x13的系统路径,若获取失败则获取0x15,该路径用于保存后面下载的文件。由于SHGetFolderPathA由shlobj_core.h定义,则可以查看shlobj_core.h文件以获取CSIDL的定义:
此样本中成功获取0x13对应的系统路径
成功获取之后,程序将会计算预定义的字符串得到新的字符串,第一个字符串为后续下载的文件名,计算方法为ascii-1
然后通过同样的方法计算出请求的C2:
接着获取计算机名、操作系统版本和计算机用户名:
获取计算机的GUID并将所有获取到的信息拼接起来
若成功获取GUID,则通过计算机名##用户名@@GUID的格式拼接,拼接之后如下
最后通过DispatchMessage的Callback调用上面设置的TimerFunc
在该函数中与C2建立连接并将上面获取到的基本信息ASCII自增1以避免明文传输
接着格式化请求数据并send
接受返回值并判断返回值中是否包含了 “DFCB=” ,这是比较明显的流量特征
若返回值不包含”DFCB=” 则说明不是预期返回,程序退出本次循环,若相等,则判断后面的值是否为DWN,也即是Download
若返回的值是DWN,则说明C2可以正常通信并且预期客户端下载后续payload,程序则会重新调用函数进行第二次网络请求以下载后续文件
第二次网络请求时,程序会首先创建之前计算出来的文件路径
解码并请求新的请求路径 ehRecvr.php
若返回值接收成功,则将返回值写入到文件中,最后解密并创建进程加载该文件。
小结
- 样本通过注册窗体,设置计时器实现恶意功能
- 注册窗体的名称和类名不同,但是字符串表的序号固定
- “加解密”的方法为ASCII自增/减1
- 返回值通过判断 DFCB= 以验证是否为预期返回
- 样本基本功能为Downloader
B
7b711b794d3607babcb0917134099f31
创建时间:2017-0508
上传时间:2017-0707
原始样本包含了一个pdb路径:C:\intelc\Release\crystal.pdb
样本入口点依旧是通过注册窗体启动恶意代码, 窗体名的字符串表和上面保持一致
TimeStamp
样本的创建时间对应关系如下:
2017—03—06 18:01:19 ./be15e8ed4f245b41a6168e6719c6058f
2017—08—05 19:24:43 ./bfc8d68fca03f4752897c552b7984523
2018—01—12 14:51:43 ./c838173e082861089416b5e37244efb9
2015—07—06 19:55:16 ./3c4bed8d649375050dba3a3a8df87d12
2015—10—16 14:31:22 ./dbd3b380a3fca0ca33362027bd1ba7a3
2016—05—03 01:54:27 ./c669a30e0ade24502415868b282d111d
2017—09—13 17:46:01 ./ae5f389be9058c241a237965304d7bf5
2018—02—03 17:35:44 ./9d5be49ad857e5d5fcea6c897d72bc25
2016—03—22 16:42:56 ./ec9734731dc25a3fd84582f7060c6bac
2017—05—12 15:22:53 ./10cacca80ef5767206969f75e03432f1
2018—01—17 20:22:27 ./a57c1e4d6c0b040337fa110b8ec4345b
2016—06—28 17:13:40 ./d4a0aef19d9e284faf4854c8f4fc660d
2016—04—29 17:02:22 ./546df801ab370bc8062f15b2ac723572
2016—09—02 18:38:44 ./a1a5416f6e9c20cb370d6a9152c3e2e7
2016—09—05 15:14:02 ./c1958fa4ce470358407083ef394bbd54
2014—12—04 17:22:31 ./f099cd511e9d10d80105d96f29dd28b7
2016—07—22 18:11:09 ./bb450ecec5321cf2c9fc098309a47fa7
2017—07—12 01:13:05 ./2fcfae21ccf1dfd106aef422a27560bf
2017—05—04 14:40:07 ./c009cc06ea2a0bf320884700a48ab835
2016—05—05 07:13:04 ./8f2036f35444c8ac5c33de4806d4c4f4
2017—04—17 16:34:45 ./33b1e07651f7b8654e8174de8415c134
2015—06—10 19:49:51 ./38ba17b9ae3a4a4733d716c2ecade70d
2016—09—02 18:38:44 ./db0f6127448c0f798d853ff672194237
2017—05—08 17:44:36 ./7b711b794d3607babcb0917134099f31
2017—03—29 14:24:43 ./20472cf5d5d8328387f824b12f6b39ca
2018—12—06 19:14:45 ./5d8b4fae792e009e8be4d3f2cab38de0
2016—10—25 12:08:43 ./9e8a774f352d8819528c8bfc12d7097b
2014版
MD5:f099cd511e9d10d80105d96f29dd28b7
样本时间戳显示创建于2014年12月,18年首次上传到VT,此时间真假性未知,但样本至少是18年11月之前创建的
此样本依旧是加载0x67和0x6d的字符串资源作为窗体名和类名
和上面样本不同的是,此样本在初始化窗体时并没有设置Timer计时器以连接C2
窗体初始化完成之后,程序会查找avg进程以判断当前主机是否安装了卡巴杀软,若找到则返回1,未找到则返回0
接着程序将会尝试获取0x1A对应的系统路径,若获取失败则获取0x2E对应的路径,这两个路径分别是:
0x1A Application Data
0x2E All Users\Documents
若两个路径都失败,函数retn,返回值为0.
路径获取成功,则会在该路径后面拼接igfxdrv.exe、igfxdcs.exe、igfxdvv.exe
路径拼接成功之后,程序会根据byte_429D80的值执行不同的操作,由于在上面代码byte_429D80已经被赋值为1,这里不会跳转
接着程序比较当前路径是否为%appdata%\igfxdrv.exe或%appdata%\igfxdcs.exe
若均不存在,则说明程序是第一次运行,程序则会取data节的数据并调用两个自定义的Decode函数进行解码
解码之后的字符串为添加开启自启动的注册表键值
接下来程序打开Run注册表键值并查询igfxdrv键值是否存在
若该项不存在,函数会返回错误码,eax不等于0,不跳转执行。
程序则会尝试删除%appdata%路径下的igfxdrv.exe和igfxdcs.exe
接着通过创建管道的方式完成注册表的写入
写入之后,通过自定义函数解码出reg.exe并尝试查找reg.exe,若找到则结束reg进程
接着程序创建线程,该线程主要功能是通过管道,将当前进程所对应的文件拷贝到%appdata%路径下并重命名为三个不同名的文件。
在该线程中,程序会通过管道将当前进程拷贝到%appdata%路径下并重命名为igfxdrv.exe和igfxdcs.exe
接着尝试打开igfxdvv.exe
打开失败,则会再次复制当前进程文件并重命名为igfxdvv.exe,线程功能执行完毕。
创建线程的同时,程序还会调用网络请求函数以访问C2并接受返回值,请求的C2依旧通过自定义函数解码
解码之后的C2为:johnywalter[.]webatu[.]com
完整请求路径为:
hxxp[:]//johnywalter[.]webatu[.]com/muzicmazic/Payloads/
尝试连接解析C2域名
socket连接C2,若连接成功则会调用函数获取计算机的基本信息并进行编码,然后格式化准备请求
获取的信息有:计算机名、用户名、操作系统版本、计算机GUID,获取到之后通过&符号拼接
拼接之后如下,程序会通过GET请求访问accept.php页面
若成功请求则调用recv函数接收返回
解析函数返回值
后面主要是请求细节和通信协议相关的分析,文章篇幅限制这里就不继续了,后面还会遇到很多,可能会单独写个短文对比分析请求协议。