样本来自于 vx-underground,此勒索软件相对比较简单。
分析
DIE 查询基本信息
是一个由 C# 编写的 32 位控制台程序。程序入口在 A.E.S.R.T.Program.Main 处,开始运行后在 C:\Program Files 下创建 Temp 目录及 Temp 下的 AESRT 子目录,随后提取自身资源并在 AESRT 目录下释放 AESRTback.png 和 refresh.bat 两个文件
AESRTback.png
refresh.bat
refresh.bat 内容意为强制刷新 Windows 的用户界面设置,例如主题、桌面、图标等 (在生成勒索信息框初始化组件会调用)。随后在 Software\Microsoft\Windows\CurrentVersion\Policies 下创建 System 和 ActiveDesktop 项,设置 Wallpaper、WallpaperStyle 和 NoChangingWallPaper 键及值
设置好后隐藏控制台,随即调用 Worm 类中的 Infectrandomusbfile() 方法,此操作会感染 USB 设备中的随机可执行文件 (随机选择一个文件并将其替换为当前正在运行的程序的副本)
最后调用 Encrypt 开始执行加密操作,在 Encrypt 中,删除系统中的所有卷影副本,设置系统启动时忽略所有失败,禁用启动恢复选项,删除备份目录
cmd.exe /c vssadmin delete shadows /all /quiet & wmic shadowcopy delete & bcdedit /set {default} bootstatuspolicy ignoreallfailures & bcdedit /set {default} recoveryenabled no & wbadmin delete catalog -quiet
随后在 HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\System 下设置 DisableTaskMgr 的值为 1,禁用任务管理器
在 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon 下修改 ShellExperience 的值为 ShellExperience.exe,此举更改了处理系统界面元素进程
注册表操作后,便开始加密以下 5 个位置中没有以 .AESRT 结尾的文件
%USERPROFILE%\Desktop;
%USERPROFILE%\Download;
%USERPROFILE%\Videos;
%USERPROFILE%\Music;
%USERPROFILE%\Pictures
每个位置下文件都是通过一个 for 循环进行加密操作,调用自身类中 EncryptFile 方法,采用的是 AES 加密,CBC 模式,将 password 转为字节序列,计算此字节序列的 SHA256 值,基于此 sha256 值生成 Key 及 IV 值
在完成加密后,设置注册表 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System 中 EnableLUA 的值为 0,禁用 UAC,HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon 下 Userinit 的值为 C:\windows\system32\userinit.exe,+自身程序所在路径,实现持久化,在 windows 启动时执行勒索软件本身。
最后生成勒索信息提示框,黑客邮箱:OfficialAESRT@outlook.de
Key 及 Password 都硬编码在程序中,Key 为 678123,Password 为 736457983546798345679547968257986453798346598732456934527986534798652467983546798234597682534976823456798967584,输入 Key 后执行 OFF_Encrypt 方法
修复系统启动
cmd.exe /c bootrec /rebuildbcd
根据此解密过程编写了一个通用解密器 (无需 Key),以下为解密器代码
import os
import argparse
import hashlib
from Crypto.Cipher import AES
from Crypto.Protocol.KDF import PBKDF2
from Crypto.Util.Padding import unpad
password = '736457983546798345679547968257986453798346598732456934527986534798652467983546798234597682534976823456798967584'
def aes_decrypt(bytes_to_be_decrypted, password_bytes):
salt = bytes([1, 2, 3, 4, 5, 6, 7, 8])
key_iv = PBKDF2(password_bytes, salt, dkLen=48, count=1000)
key = key_iv[:32]
iv = key_iv[32:48]
cipher = AES.new(key, AES.MODE_CBC, iv)
decrypted_data = cipher.decrypt(bytes_to_be_decrypted)
unpadded_data = unpad(decrypted_data, AES.block_size)
return unpadded_data
def decrypt_file(filename):
if filename.endswith('.AESRT'):
print('[🌟] decrypting %s' % filename)
with open(filename, 'rb') as f:
encrypted_data = f.read()
password_bytes = bytes.fromhex(hashlib.sha256(password.encode(encoding='utf-8')).hexdigest())
decrypted_data = aes_decrypt(encrypted_data, password_bytes)
with open(filename, 'wb') as f:
f.write(decrypted_data)
os.rename(filename, filename.rstrip('.AESRT'))
print('[✅] %s decrypt success' % filename)
else:
print('[❌] %s not decryted file' % filename)
if __name__ == '__main__':
parser = argparse.ArgumentParser(
formatter_class=argparse.RawDescriptionHelpFormatter,
description='''AESRTRansomware Decryptor
by:zer0daysec''')
group = parser.add_mutually_exclusive_group()
group.add_argument('-s', '--single', type=str, help='decrypt single file')
group.add_argument('-t', '--table', type=str, help='decrypt entry table of contents')
group.add_argument('-a', '--all', action='store_true', help='default decrypt file')
args = parser.parse_args()
if args.single:
filename = args.single
decrypt_file(filename)
if args.table:
table = args.table
for file in os.listdir(table):
file_path = os.path.join(table, file)
if os.path.isfile(file_path):
decrypt_file(file_path)
if args.all:
print('decrypting file ......')
userprofile = os.getenv('USERPROFILE')
contents = ['Desktop', 'Downloads', 'Videos', 'Music', 'Pictures']
for content in contents:
temp = userprofile + '\\' + content
for file in os.listdir(temp):
file_path = os.path.join(temp, file)
if os.path.isfile(file_path):
decrypt_file(file_path)
yara
rule Win_Ransom_AESRT : Ransom AESRT
{
meta:
author = "zer0daysec"
hash_1 = "05072a7ec455fdf0977f69d49dcaaf012c403c9d39861fa2216eae19c160527f"
hash_2 = "b6743906c49c1c7a36439a46de9aca88b6cd40f52af128b215f808a406a69598"
strings:
$wallpaper = "AESRTback.png"
$refresh = "refresh.bat"
$email = "OfficialAESRT@outlook.de" wide
$soglan = "Get Hacked By A.E.S.R.T" wide
condition:
uint16(0) == 0x5a4d and all of them
}
IoCs
HASH
b6743906c49c1c7a36439a46de9aca88b6cd40f52af128b215f808a406a69598
OfficialAESRT@outlook.de