近日,Bazar Loader 启用了新版本的 DGA 算法。本版 DGA 算法仍使用相同的 .bazar 顶级域名,但二级域名只有短短 8 个字符,而不是先前版本的 12 个字符:
liybelac.bazarizryudew.bazarbiymudqe.bazarfuicibem.bazarbiykonem.bazaraqtielew.bazaryptaonem.bazarexyxtoca.bazariqfisoew.bazaraguponew.bazarexogelqe.bazarexybonyw.bazaretymonac.bazar
本次分析的样本并没有太多的混淆,还有许多其他样本具有其他对抗分析的手段,例如垃圾代码,但快速分析并未发现功能上的差异。
类型 | 值 |
---|---|
MD5 | c6502d4dd27a434167686bfa4d183e89 |
SHA1 | bddbceefe4185693ef9015d0a535eb7e034b9ec3 |
SHA256 | 35683ac5bbcc63eb33d552878d02ff44582161d1ea1ff969b14ea326083ea780 |
Size | 336 KB (344576 Bytes) |
Compile Timestamp | 2020-12-10 13:05:18 UTC |
Links | MalwareBazaar, Malpedia, Cape, VirusTotal |
Filenames | 1ld.3.v1.exe, 35683ac5bbcc63eb33d552878d02ff44582161d1ea1ff969b14ea326083ea780 (VirusTotal) |
Detections | Virustotal: 8/72 as of 2020-12-11 02:58:32 - Win64/Bazar.Y (ESET-NOD32), Backdoor.Win32.Bazdor.co (Kaspersky), Trojan.Win64.BAZALOADER.SMYAAJ-A (TrendMicro), Trojan.Win64.BAZALOADER.SMYAAJ-A (TrendMicro-HouseCall) |
类型 | 值 |
---|---|
MD5 | e44cfd6ecc1ea0015c28a75964d19799 |
SHA1 | cb294c79b5d48840382a06c4021bc2772fdbcf63 |
SHA256 | 52e72513fe2a38707aa63fbc52dabd7c7d2c5809ed7e27f384315375426f57bf |
Size | 96 KB (98816 Bytes) |
Compile Timestamp | 2020-12-09 10:16:56 UTC |
Links | MalwareBazaar, Malpedia, Cape, VirusTotal |
Filenames | content.28641.20903.13470.9122.7127 (VirusTotal) |
Detections | Virustotal: 4/75 as of 2020-12-15 21:30:37 |
逆向分析
除了利用常用的 Windows API 函数与动态加载加密字符串之外,Bazar Loader 还依赖于通过算术替换来进行代码混淆。特别经常使用以下方式:
a⊕b=(∼a⋅b)+(a⋅∼b)
Zloader 也使用相同的混淆方法,这使得代码很难阅读。以下是 DGA 的一小段代码:
IDA 的反编译也没有能够优化这部分混淆代码,因为算数替换没有被简化:
新版 DGA 算法使用当前月份和年份作为种子。种子以字符串形式存储,这四个 ASCII 字符是形成四个字符对的基础。将这四对字符对配对形成八个第二级字符。
通过计算辅音列表 “bcdfghklmnpqrstvwxz” 和元音列表 “aeiouy” 的笛卡尔积来生成字符串列表。双向计算乘积可得出 19·6·2 个字符对。然后,使用硬编码的随机数序列将它们连接成 456 个字符的大字符串:
qeewcaacywemomedekwyuhidontoibeludsocuexvuuftyliaqydhuizuctuiqowagypetehfubitiaziceblaogolryykosuptaymodisahfiybyxcoleafkudarapuqoawyluxqagenanyoxcygyqugiutlyvegahepovyigqyqibaeqynyfkiobpeepbyxaciyvusocaripfyoftesaysozureginalifkazaadytwuubzuvoothymivazyyzhoevmeburedeviihiravygkemywaerdonoyryqloammoseweesuvfopiriboikuzorruzemuulimyhceukoqiwfexuefgoycwiokitnuneroxepyanbekyixxiuqsias
然后使用相同长度的随机异或密钥对字符串进行加密。
除了基于日期的种子外,新版 DGA 算法还使用标准的线性同余生成器(LCG)来选择四个字符对。LCG 使用处理器时钟计数作为种子,因此不可预测。对于前两个字符对,随机数取 mod 19,将其余两个取 mod 6。对应于辅音和元音数组的长度,但是在这种情况下没有意义。由于随机数是不可预测的,因此可以选择 19·19·6·6 = 12996 个字符对的任意组合。Bazar Loader 每次运行会生成 10000 个域名,但不能保证它们是唯一的,大约有 6975 个唯一域名:
即使域名解析的速度很快,恶意软件也需要运行很长时间才能遍历完完整域名列表。
Python 实现
from itertools import product from datetime import datetime import argparse from collections import namedtuple Param = namedtuple('Param', 'mul mod idx') pool = ( "qeewcaacywemomedekwyuhidontoibeludsocuexvuuftyliaqydhuizuctuiqow" "agypetehfubitiaziceblaogolryykosuptaymodisahfiybyxcoleafkudarapu" "qoawyluxqagenanyoxcygyqugiutlyvegahepovyigqyqibaeqynyfkiobpeepby" "xaciyvusocaripfyoftesaysozureginalifkazaadytwuubzuvoothymivazyyz" "hoevmeburedeviihiravygkemywaerdonoyryqloammoseweesuvfopiriboikuz" "orruzemuulimyhceukoqiwfexuefgoycwiokitnuneroxepyanbekyixxiuqsias" "xoapaxmaohezwoildifaluzihipanizoecxyopguakdudyovhaumunuwsusyenko" "atugabiv" ) def dga(date): seed = date.strftime("%m%Y") params = [ Param(19, 19, 0), Param(19, 19, 1), Param(6, 6, 4), Param(6, 6, 5) ] ranges = [] for p in params: s = int(seed[p.idx]) lower = p.mul*s upper = lower + p.mod ranges.append(list(range(lower, upper))) for indices in product(*ranges): domain = "" for index in indices: domain += pool[index*2:index*2 + 2] domain += ".bazar" yield domain if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument( "-d", "--date", help="date used for seeding, e.g., 2020-06-28", default=datetime.now().strftime('%Y-%m-%d')) args = parser.parse_args() d = datetime.strptime(args.date, "%Y-%m-%d") for domain in dga(d): print(domain)
特征
属性 | 值 |
---|---|
类型 | 时间相关 |
生成方式 | 算术 |
种子 | 当前日期 |
域名变化频率 | 每个月 |
每个月唯一域名数量 | 12996 |
顺序 | 随机选择 |
域名间等待时间 | 10 秒 |
顶级域名 | .bazar |
二级域名 | a-z,除 j 外 |
正则表达式 | [a-ik-z]{8}.bazar |
二级域名长度 | 8 |
种子域名
Bazar Loader 的旧版 DGA 算法可从域名中提取种子: