导语:Check Point研究任意发现一个通过RIG利用套件和其他源进行传播的在野Azorult新版本。
上周,Check Point研究人员发现一个通过RIG利用套件和其他源进行传播的在野Azorult新版本。Azorult是一款著名的信息窃取器和恶意软件下载器,最新的3.3版本从10月4日起就在黑市论坛上打起了广告。
3.3版本与之前版本还是有很大的区别,最明显的区别就是嵌入的C2域名字符串的新加密方法、新的连接C2的方法、以及对加密货币钱包的窃取器和加载器的改善。
论坛广告
10月4日,用户CrydBrox在https://exploit.in/ 地下论坛上发布广告称更新了Azorult,更新的版本是3.3。
图1: 地下论坛Azorult v3.3更新的广告
帖子中描述了3.3版本的更新以及特征:
· 支持窃取BitcoinGold、electrumG、btcprivate (electrum-btcp)、bitcore、Exodus Eden钱包的凭证;
· 改进了加密货币钱包窃取器组件;
· 修复了加载器模块,允许加载和执行bat文件;
· 减缓被反病毒软件检测的速率,增加了成功安装的比例;
· 改善了管理面板的性能。
与之前版本比较
3.2版本中,C2域名会硬编码的进行XOR操作,之后再用base64编码。当前3.3版本中使用了新的加密方法来混淆域名。域名字符串解密的脚本见附件。
每个版本的Azorult都有一个唯一的XOR key用于与C2进行连接。在v3.3版本中,连接key是[0x3, 0x55, 0xae]。在与连接key进行XOR之前,每个版本的连接消息含有一个前缀(3.1版本中是“getctf=”,3.2版本中是“G”)会被添加到id哈希值中。V3.3版本中的前缀是连接key,会将连接消息发送给3个0字节开始的C2。
图2: 将connection key作为前缀
Azorult的C2服务器响应被标签分为3个部分:
· <c></c> – 配置部分,用base64编码
· <n></n> –Azorult复制到%TEMP%文件夹中创建的新目录的DLL文件。每个版本中创建的新目录也是不同的,v3.1版本是1M0,v3.2版本是2fda,v3.3版本中目录名是根据受害者计算机的id哈希值生成的。因此,不同受害者的目录名是不同的。
生成目录名的算法如下:
Id_hash=hash_func(guid)-hash_func(product_name)-hash_func(user_name)- hash_func(computer_name)-hash_func(guid+product_name+user_name+computer_name) Directory_name = hash_func(hash_func(Id_hash))
hash_func方法的实现见附件中的脚本。
· <d></d> –Azorult窃取数据的应用路径名,v3.3版本中加入了下列应用名:
%appdata%\ElectrumG\wallets\ \ElectrumG %appdata%\Electrum-btcp\wallets\ \Electrum-btcp BitcoinGold\BitcoinGold-Qt BitCore\BitCore-Qt BitcoinABC\BitcoinABC-Qt %APPDATA%\Exodus Eden\
Azorult的作者修复了加载器函数的bug,该bug使恶意软件不能成功加载和执行bat文件。Bug出现的原因是因为错误的比较了被加载文件的扩展,使所有用CreateProcessW API启动的文件都作为可执行文件而不是ShellExecuteExW。在新版本中,作者修复了比较方法来避免该漏洞的出现。
图3: 3.2和3.3版本的加载器扩展比较
附
C2域名解密python代码
def decrypt_domain_method_v3_3(encrypted_domain): decrypted_domain_array = [] key_buffer = [0x1e, 0x15, 0x34, 0x49, 0x5e, 0x37, 0x24, 0x2f, 0x58, 0x27, 0x6e, 0xd3, 0xd4, 0x71, 0xd6, 0x73, 0xd8] index = 0 sum = 0 while index < len(encrypted_domain): cur_byte = encrypted_domain[index] if cur_byte == key_buffer[0]: sum += 0x64 elif cur_byte == key_buffer[1]: sum += 0x5a elif cur_byte == key_buffer[2]: sum += 0x50 elif cur_byte == key_buffer[3]: sum += 0x46 elif cur_byte == key_buffer[4]: sum += 0x3c elif cur_byte == key_buffer[5]: sum += 0x32 elif cur_byte == key_buffer[6]: sum += 0x28 elif cur_byte == key_buffe[7]: sum += 0x1e elif cur_byte == key_buffer[8]: sum += 0x14 elif cur_byte == key_buffer[9]: sum += 0x0a elif cur_byte == key_buffer[10]: sum += 0x8 elif cur_byte == key_buffer[11]: sum += 0x6 elif cur_byte == key_buffer[12]: sum += 0x5 elif cur_byte == key_buffer[13]: sum += 0x4 elif cur_byte == key_buffer[14]: sum += 0x2 elif cur_byte == key_buffer[15]: sum += 0x1 elif cur_byte == key_buffer[16]: decrypted_domain_array.append(chr(sum)) sum = 0 elif cur_byte == 0: break index += 1 decrypted_domain = ”.join(decrypted_domain_array) return decrypted_domain
计算生成目录名的hash_func方法。
def hash_func(value): xor_key = 0x6521458a hash_output = 0 for index in range(len(value)): cur_byte = ord(value[index]) xor_value = cur_byte ^ xor_key hash_output = (hash_output + xor_value) % (2**32) right_value = (hash_output << 0xd) % (2**32) left_value = (hash_output >> 0x13) % (2**32) diff_value = right_value | left_value % (2**32) hash_output = (hash_output – diff_value) % (2**32) hash_string = hex(hash_output)[2:-1] if len(hash_string) < 8: diff = 8 – len(hash_string) output_string = (‘0’ * diff) + hash_string else: output_string = hash_string output_string = output_string.upper() return output_string
IOCs
Md5:
11147fd9ac12eec66d35b4d483aae71f
d893d8347ecad1a3d85064d2f5bded4f
a8d3e403995132f9af33e4557be301a0
C2:
http://infolocalip.com/index.php