從jscript腳本混淆說起
腳本病毒是一個一直以來就存在,且長期活躍著的一種與PE病毒完全不同的一類病毒類型,其制作的門檻低、混淆加密方式的千變萬化,容易傳播、容易躲避檢測,不為廣大網民熟知等諸多特性,都深深吸引著各色各樣的惡意軟件制作者 …
小到一個不起眼的lnk快捷方式,大到一個word文檔,都是腳本的載體。本文主要以 js腳本為例(特指JScript,下同 ),具體結合實際樣本,講述混淆方式及其混淆類型檢測相關知識,文章受限於樣本個數及其種類,存在一定的局限性,但大致情況應當不會相差太大。本系列首先會對jscript及其腳本進行簡單介紹,之後對采用不同混淆操作的樣本進行分析以及總結,後續系列會引入腳本動態鑒定技術即 虛擬執行行為檢測技術的介紹與實現。
前言
jscript是由微軟公司開發的腳本語言,是對ECMAScript語法規範的實現,最初是隨著 IE 3.0於1996年8月發布,和其所開發的其他腳本語言一樣,後來被 Windows ScriptHost(WSH)和Active Server Pages所支持,其典型的擴展名稱為.js 。Windows上的.js文件運行是這樣的( 實際後綴還有可能是.jse,.wsf, .wsh),在你雙擊這類文件時,通常的操作是由代理程序傳給宿主進程作為參數運行,這個宿主進程也通常為 wscript.exe或者cscript.exe(實際根據註冊表中 HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.js\OpenWithList中給定的值)。 wscript與cscript的區別就在於前者是在窗口中運行,後者是在命令行中運行。那麽是不是所有js 的腳本必須要有後綴?當然不是,你可以使用wscript //e:jscript 文件名稱的形式執行。是不是還要問 jscript和javascript是不是同一個?當然不是! 但他們確實屬於同一類語言,因為都是對ECMAScript語法規範的不同實現版本,大體語法都一樣,但各自的實現卻也存在著很多差異,具體差異可在網上查閱資料進行了解。
正文
jscript不知是什麽時候被微軟開始邊緣化的技術產品(或許是javascript 太強了),隨著老一批的微軟開發者的淡出,jscript也離開了人們的視線。但也可能正是如此,它獲得了惡意軟件編寫者的青睞。
什麽是混淆
混淆:指迷惑,將一樣東西誤認為另一樣東西(本解釋來自百度百科 )。由於腳本語言絕大多數是基於解釋器的運行方式,所以其在進入解釋器之前多為源代碼形式存在,通過源代碼可以清楚知道腳本的意圖,所以為了對抗分析,采用了各種方式將源代碼進行 混淆操作(當然也可能是正常功能的腳本不想被輕易看穿的不得已之為)。通過金山毒霸安全實驗室對全球非 PE樣本的監控數據來看,目前對jscript腳本的混淆方式變化如下:
下面通過不同混淆操作的特點,結合實際樣本案例進行分析總結,最後給出針對不同混淆方式的檢測思路。
腳本混淆
腳本混淆的方式比較繁多,常采用編碼、加密、 變形,切分等操作進行
編碼: 將信息從一種形式或格式轉換為另一種形式的過程
加密: 通過某種特殊算法,改變信息的原有結構
變形: 改變原來形態的過程
切分: 通常為拆分操作
上述操作是常見混淆的采用的技術操作,但實際上,對這些操作運用的載體,通常是變量 ,字符串,函數(或方法,統稱函數)、數組、對象, eval等。下文針對這些不同的載體,具體結合樣本進行分析討論。
1. 變量的混淆
變量混淆,通常針對變量的名稱、個數進行操作,目的是去掉變量名稱的詞義。這種操作的極端情況有個數極少、個數極多、名稱長度普遍較短(<6)、名稱長度普遍較長(>41) 、隨機名稱等特性。通常,單一的針對變量的混淆都是配合其他形式同時出現的,例如:
這個腳本的特點很明顯,就是變量名稱都是e構成的,而且超級多,其後續執行的代碼如下:
具體含義就是根據變量名稱中e的長度從低到高的順序,通過this 訪問當前環境變量,之後拼接完整代碼塊,使用eval進行動態執行。通過這個規律可輕易寫出代碼還原工具(但可能適用的範圍很小 )。針對變量的混淆檢測,主要從變量的個數 、名稱長度分布及名稱字符串特征這三個維度去檢測。上述例子中,很明顯的發現,這裏對代碼進行了 變形,代碼塊切分技術。
2. 字符串操作的混淆
字符串,很大程度上能夠幫助代碼閱讀人員快速定位關鍵代碼段,從而加快分析。當然,惡意腳本也會更加註意對字符串的保護 。對字符串的常見混淆操作有加密、編碼、替換等操作。常見的針對字符串的操作函數有substr、substring、 unescape、fromcharcode、replace 、split以及正則表達式等操作。如下代碼片段就是使用了字符串解密函數 exq在運行時對字符串進行了解密。
當然,也有如下這種通過字符串常用操作進行字符串解密的
實際運行後b的值是
還有比較常見的編碼方式的
通過收集到的樣本來看,其中使用正則表達式的樣本也是比較多的,限於篇幅長度,這裏就不一一列舉了。
針對字符串混淆,大多數都會有字符串操作函數(或正則對象 )的使用,通過對這些函數(對象)的追蹤,統計其出現的次數,能從一方面說明這類混淆的特性,當然如果不對語法進行深層次的分析,很容易將 循環中的操作個數統計為一次,而實際可能執行了好多次操作。
3. 函數、數組、對象的混淆
正常腳本中函數、數組、對象的個數都是有一個上限的,但混淆後的腳本往往會超過這個上限,從而變的異常。例如:一個腳本中出現了1000次函數聲明以及函數表達式操作,一個數組的索引超過了 10000,以及一個對象中都是number:string。針對數組的混淆,看這個例子,
其中BOql這個數組,最大索引竟然達到19027,人工編寫的代碼一般來說是不能達到如此程度的,所以極有可能是通過代碼生成的。實際運行後 eval傳入的UTf代碼片段如下:
當然,對函數的混淆也是比較多的,比如直接作為數組中的元素
或是返回對象中的某個元素
總體來講,函數的混淆通常結合對象與數組同時進行。對於對象來說,比較意外,這種混淆通常是針對number,string 進行,很少發現裏面有函數的出現,比如下面這個
同函數一樣,對象的混淆大多數也是與數組一同出現的,核心原理是代碼切分,這類混淆後的代碼很明顯的體現了這個概念 ,盡可能多的減少信息聚合,當然這也構成了這類混淆的檢測特征索引過多但實際內容很少。
4. eval的混淆
eval函數可以動態執行一段代碼,基於這個特性,可以說,很受惡意腳本的喜愛。常常是拼接代碼段 + eval的方式執行完整腳本,也會被用來執行某一段代碼。比較典型的 packed混淆屬於第一種情況,如下:
實際執行的代碼在p變量中。也有執行某一段代碼的
eval的這類混淆,並不能作為一種獨立特征來評判某腳本是否被混淆,通常是作為一種輔助特征而存在。
5. 其他類型混淆
上文講了4種常見混淆方式,當然,很多特殊腳本,會使用一些其他技巧繞過檢測,例如:直接使用 eval可能會被檢測,那麽轉而使用this[e + val ]也是能達到相同特點的,這是this的一種特性,能訪問當前環境的全部變量。或者,如下代碼可能會被檢測到存在風險
var sh = WScript.CreateObject("wscript.shell" )
sh.run(‘cmd‘)
但通過如下混淆
var o = this[‘e‘ + ‘val‘]( ‘th‘+‘is‘)
var sh = o[‘WS‘+ ‘cript‘][‘Create‘ + ‘Ob‘ + ‘ject‘]("wsc" + "ript" + "." + "shELl" )
sh[‘R‘+‘un‘ ](‘C‘ + ‘m‘ + ‘d‘ )
是不是很難被檢測到了?當然,沒有絕對檢測不到的混淆,但是一定程度上,這種已經不能輕易從靜態(代碼執行之前)特征上進行判定,關於這些的檢測判定會在本系列的第二篇中進行介紹。
環境檢測
一個腳本的行為特性,有時會受到當前運行環境影響,比如說,去下載一個文件,但鏈接文件不存在,通常做法是直接提示然後結束,又或者說,去創建一個文件,之後去判斷是否創建成功,成功之後做剩余操作,失敗則直接提示後結束。所以總體來講,腳本的行為會受到環境的影響。所以,惡意軟件也會去嘗試進行環境判斷,從而判定當前的環境是否正常,例如是否允許在查殺引擎 中,下面列出了幾種常見的對抗檢測技術。
1. 時間檢測
在一般情況下,查殺引擎對一個腳本的掃描時長都會限定在一個範圍之內,沙盒也是如此。惡意腳本會通過延遲執行的方式,從使檢測程序超時退出,達到對抗的效果,例如:
這段代碼出現在腳本的最前端,保證在延遲大於6s後繼續運行。
2. 執行結果檢測
現在對嚴重混淆腳本的檢測大多是基於虛擬執行技術(詳見本系列的第二篇 ),由於引擎自身對實際環境的虛擬程度有限,往往存在某些對象、函數的模擬不到位,導致在惡意腳本執行時觸發異常(或直接崩潰) ,從而發生流程轉移,例如:
實際xuzydfej9函數執行的代碼如下:
var luzpal9 = WScript.CreateObject(‘WScript.Shell’);
var pniwinosu8 = luzpal9.CreateShortcut(‘\qvertyd.lnk’);
if(pniwinosu8.TargetPath == ”) return 1;
通過探測是否成功創建lnk文件來判斷是否處於真實環境,與這種類似,還有一些是通過設置時間來進行探測,總之這類統稱為執行結果檢測。
3. 其他
/*@cc_on @*/形式的條件編譯,只有支持jscript語法的宿主中才會執行,所以如果某 虛擬執行引擎不支持這類語法規則的話,則會直接以/**/註釋的形式跳過這段代碼,從而對腳本實際行為出現錯覺 。
最後
本文是<從jscript腳本混淆說起 >的系列文章第一篇,主要目的是以科普為主,簡單介紹jscript的背景、常見混淆方式以及環境檢測相關的內容。通過這些的介紹,希望能讓大家對jscript 惡意腳本,非PE病毒目前的發展趨勢有一個初步了解,本系列的後續文章將繼續深入探討通過虛擬執行技術來檢測惡意腳本。最後,感謝閱讀本文。
從jscript腳本混淆說起