<pre id="vvttv"><mark id="vvttv"><progress id="vvttv"></progress></mark></pre>
    <pre id="vvttv"></pre>

      <p id="vvttv"></p>

          <p id="vvttv"></p>

                <p id="vvttv"></p>

                <pre id="vvttv"><cite id="vvttv"><progress id="vvttv"></progress></cite></pre>

                  <output id="vvttv"><dfn id="vvttv"><th id="vvttv"></th></dfn></output>

                    <p id="vvttv"></p>

                    原文地址:http://drops.wooyun.org/tips/5765

                    接著上一篇的來,本文多為Javascript的腳本閱讀和解釋,閱讀都是自行完成,所以不免可能會出現一些錯誤或者聯想過度的情況,如果你發現了哪兒有問題請重重地拍出來。

                    IV.1 HTML與網馬攻擊4 — Virus In the Wild


                    本篇中我們將從真實的Exploit Kit的利用代碼入手介紹分析方式,文中例子采用Angler Exploit Kit 和 Magnitude Exploit Kit(下簡稱為AEK和MEK)在2015年4月初最新的代碼。

                    AEK和MEK是互聯網上最著名的漏洞利用工具包,在Phoenix Exploit Kit作者鋃鐺入獄之后,這兩個Exploit Kit的“市場份額”一下子竄到了前面,因為作者更新快,采用加密方式繁多,導致殺毒軟件更新特征也較為困難,這讓它們有充足的機會去攻擊有漏洞的電腦。本文將介紹這兩個Exploit Kit的加密方式和解密方法。

                    首先,讓我們從AEK開始,AEK和MEK都需要有一個Landing Page,用于將用戶定向到惡意頁面上,打開Landing Page,我們會發現AEK為了做混淆,給Landing Page加了很多無用的垃圾數據,并將加密后的數據混淆插入在這些代碼中:

                    enter image description here

                    圖:code部分是加密后的代碼

                    將頁面向下拖動,快到最后的地方就是它的解密腳本了:

                    enter image description here

                    圖:AEK的腳本

                    是的,這就是一個高度混淆后的腳本,因為JavaScript代碼(或者說類C語言語法)的寬松性,作者在這里面使用了大量的空白、回車、縮進符,同時還替換了變量名,使用大量的數學函數來做混淆。

                    對于人來說,要閱讀這樣的代碼簡直是一個非常惡心的工作,所以在此推薦使用一些代碼規范化工具,例如Malzilla提供的js標準化,或者這里還有一個小技巧:使用Notepad++或者類似工具的括號匹配功能:

                    enter image description here

                    將光標移動到function的大括號處,此類軟件會自動標示出函數范圍,可見上圖中該函數范圍是LN268-LN385。這樣,我們就能清晰的知道這個代碼的結構了:

                    enter image description here

                    而之前我們也說過,Function除外的Global代碼,會從上往下執行,因此,攻擊者如果想要實現讀取-解密-執行的步驟,執行必然是最后一步,因此我們只需要在它執行之前將要執行的數據找到即可。

                    enter image description here

                    翻到最后,可以發現LN568-574的Script段其實和上面LN558-565幾乎一樣。這意味著這段代碼很可能包含著解密和執行兩步的內容。

                    從最后一句入手,

                    LN564:

                    rqNNhndhLxLVVb[nmfAbWwoA]('TQgaaGLDVYlaQT',QXuSacI)
                    

                    逐個查看變量的作用,

                    LN267表明:

                    rqNNhndhLxLVVb = window;
                    

                    這是因為Javascript中允許將任何對象賦值給某個變量,因此rqNNhndhLxLVVb此時實際上可以看作是window的“別名”或者“同義詞”。

                    看看第二個變量nmfAbWwoA的來源:

                    LN561可以發現是該變量的第一次使用的地方:

                    nmfAbWwoA = "ezVI"+"Migbc".substr(6,8)  //ezVI
                    
                    nmfAbWwoA = nmfAbWwoA+[].join(dLpy) + "xlyG"
                    

                    變量dLpy經過閱讀可知在:

                    LN437處賦值:

                    dLpy=  ('EoVzQHTfRyGU').substr(12,12)  //””
                    

                    因此nmfAbWwoA的值實際上只是“ezVIxlyG”。

                    第三個變量: LN558可以發現是該變量第一次賦值的地方:

                    #!javascript
                    var QXuSacI; 
                    QXuSacI= ['Y', 'r', 'a', 'd', 'P'].join(dLpy)
                    

                    由于dLpy我們已經知道是空字符了,所以實際上QXuSacI的值就是”Yradp”。

                    這樣,將三處組合,LN564的原始語句實際上是:

                    window[”ezVIxlyG”]('TQgaaGLDVYlaQT', ‘Yradp’);
                    

                    這個ezVIxlyG的原型是什么呢?搜索代碼,找到它的賦值點:

                    LN438:

                    #!javascript
                    var D1Kx; 
                    ezVIxlyG= !!D1Kx?true:( function (){ ……} );
                    

                    這里有一個約定俗成的內容,可以看到D1Kx是剛剛定義而且未賦值的,將其作為布爾型來處理時,其默認值是false,因此,!!D1Kx的值實際也是false。

                    這樣該三目表達式實際上只是相當于一個普通的賦值:

                    #!javascript
                    ezVIxlyG = function(){……}
                    

                    由于此時我們還沒處理該函數,因此這個混淆后的代碼應該是十分難讀的,所以,我們對其進行一個簡單的處理: 復制LN439-545

                    完成后,代碼如下所示:

                    enter image description here

                    可見代碼還是難以理解,這是因為其中包含了大量的變量:

                    enter image description here

                    你可以看到這個地方定義的變量大部分都會分散地被之后的代碼使用到。

                    所以我們要關注的還是函數的最后:

                    #!javascript
                    if(flag == 1)
                    {
                        rqNNhndhLxLVVb [YPub] ( UjcS )
                    }
                    else 
                    {
                        rqNNhndhLxLVVb [YPub] ( UjcS )
                    }
                    

                    這里又是一個無用分支,rqNNhndhLxLVVb我們已經知道是window對象了,YPub是什么呢,可以看看上面的代碼,最好倒著看,我的注也是從5開始倒著寫到1處的,請注意:

                    #!javascript
                    YPub=tP+yMwnso  (注:eval)
                    tP= 'e' 、 yMwnso= ('Rv'+('uapt') ['re'+'place'] ( 'u', dLpy)) [iCQl0] ( K1DMU, 2 ) +'l'   (注:val)
                    iCQl0= (wRxKW+'snubnstrn') [F9k2c] ( /n/g , qm3sXy)     (注:substr)
                    F9k2c=qm3sXy+'r'+ yMwnso + 'pl' + qm3sXy    + 'ac' +yMwnso   (注:replace)
                    K1DMU=3-2
                    

                    因此我們看到了這句實際上是:

                    window[”eval”](UjcS);
                    

                    現在知道做什么了嗎?對,先把eval換成alert!

                    enter image description here

                    然后,直接運行該HTML,得到解密后數據:

                    enter image description here

                    enter image description here

                    等等,共4次,將這些內容合起來就是解密后的代碼了。可以看到這個代碼利用了多個新漏洞,甚至包括卡巴斯基控件的安全漏洞。

                    IV.2 HTML與網馬攻擊5 - Virus In The Wild


                    讓我們再看看Magnitude Exploit Kit這款EK的代碼,相比AEK而言,難度是高還是低

                    enter image description here

                    圖:MEK的Landing Page

                    可以看出來,相比而言它的代碼貌似要簡單得多,可以清晰的看到document和eval被分別賦予了兩個不同的變量。

                    通過將eval修改為alert,執行后得到:

                    enter image description here

                    完了?顯然沒有,將eval換成alert之后得到的數據是一個function,而點擊確定之后,得到了一個腳本錯誤:

                    enter image description here

                    圖:腳本錯誤

                    仔細閱讀一下,首先,這個eval的范圍是:

                    enter image description here

                    在它之后出現了一個從未見到過的函數:

                    enter image description here

                    而對比我們之前彈出的alert可以發現,這個函數就是eval解出來的結果,因此,我們應該做的是把eval部分換成解密后的內容:

                    #!javascript
                    function t1g6(a,b){var inn = document.getElementById('avp6').innerText;var out='';var c=inn.split('*');for(var k=a;k<b;k++) out += String.fromCharCode(c[k]-21);return out;}
                    

                    用上述內容替換掉eval塊,得到:

                    enter image description here

                    但是之后顯然沒有eval了,這時,其實我們只需要了解document[”XXX”]將返回document下的XXX對象,這個對象是可以作為函數來調用的(或者不如說函數就是一個對象:) )就可以了:

                    enter image description here

                    因此后面的c1h82by0(document)就顯得很是危險,所以讓我們看看s4tb[0]的內容并注釋掉后面的內容,記得之前說的嘛?一個script塊中的代碼一直到出錯為止都是可以正常運行的,所以不用管之后的代碼會不會出錯了,主要是后面的代碼很可能是惡意代碼,不能讓惡意代碼在我們自己的電腦上跑起來。

                    enter image description here

                    圖:執行結果

                    因此,可以知道這里是在做document[”createElement”]這個操作,司馬昭之心,路人皆知,再將其內容改為alert(s4tb1),執行可得:

                    enter image description here

                    圖:執行結果

                    串上后面的內容可以知道,這段代碼事實上正在創建一個iframe,其src執行漏洞代碼頁面: hXXp://bf29df.e66.83.1c.3d8a.54.1393d.bc7dc6b.6.scg512374t1.changesmoves.in/47b1d0b4466375c9306821f48abcd6b5(放心,此時這個網站已經無法訪問了。)

                    至此,這個頁面的核心內容我們已經全部了解了,至于后面的幾個變量,解法也是一樣的,如果想要練手的話,可以試著將頁面內容全部還原成無混淆狀態試試看。頁面內容見附件。

                    IV.3 HTML與網馬攻擊6-利用arguments.callee實現“遞歸解密”的網馬以及解密


                    希臘神話中有一條名為Ouroboros的蛇,它咬著自己的尾巴,它的姿態象征著“不死”、“完全、“無限”、“世界”、“睿智”等種種意味。

                    enter image description here

                    圖:烏洛波洛斯,網絡圖

                    在編程中,稱作遞歸,遞歸在Javascript中可以像C的代碼一樣:

                    function a(){ a();}
                    

                    來調用,不僅如此,javascript還支持一種arguments.callee的方式來調用。callee為對當前函數的引用,故可以作為類似遞歸的方式來調用自身。

                    不過,遞歸還是需要謹慎的,稍有不慎,一個bug即可導致整個程序出現不可知的情況。

                    enter image description here

                    圖:IE10遞歸導致死循環,棧空間全部用完導致崩潰

                    言歸正傳,先讓我們看兩個例子大致理解一下普通遞歸和arguments.callee:

                    以下兩個例子輸出均為:1 2 3。

                    普通遞歸,

                    #!javascript
                    function?mylog(current,?max)
                    {
                    if(current?<=?max)?
                    {
                    console.log(current);?
                    add(current+1,?max);
                    }
                    }?
                    
                    mylog(1,3); 
                    

                    以及arguments.callee:

                    #!javascript
                    function?f(x)
                    {
                    console.log(x);
                    return?arguments.callee;    
                    }?    
                    f(1)(2)(3);
                    

                    從實際入手吧,請參考如下網馬的例子:

                    enter image description here

                    是否第一眼就看到了倒數第二行出現了

                    eval(I3qVh4gPT);
                    

                    如果你試圖將它改為alert(I3qVh4gPT);,那么這個函數的解密結果必然會失敗:

                    enter image description here

                    原因是什么呢?請看第一行出現了

                    #!javascript
                    v ar eJmF3VT3H=arguments.callee.toString().replace(/\W/g,'').toUpperCase();
                    

                    我們知道arguments.callee是對當前函數的引用,那么這個引用轉為字符串是什么呢?讓我們測試一下:

                    enter image description here

                    原來就是返回了當前函數。

                    enter image description here

                    仔細一看,這里會把函數自己當成參數來解密。

                    所以,如果我們想要解開這個腳本的加密應該怎么弄呢?

                    1. 簡單閱讀代碼


                    從最后來,①eval(I3qVh4gPT);引用了變量I3qVh4gPT。

                    ②I3qVh4gPT+=String.fromCharCode(EHxDfdAM5);引用了變量EHxDfdAM5。

                    ③EHxDfdAM5=e3FP5e1M6-IA17ef3d3[bqjtxUvBR];if(EHxDfdAM5<0) {EHxDfdAM5=EHxDfdAM5+256;} 引用了變量e3FP5e1M6、IA17ef3d3[0]。

                    ④e3FP5e1M6=parseInt(EWX1TnOBq,16); 引用了變量 EWX1TnOBq,將其作為十六進制解析。

                    ⑤var EWX1TnOBq=mXSYkqH0X.substr(PwgNCEKQL,2); 中,mXSYkqH0X是參數,PwgNCEKQL是計數器。

                    ⑥for(PwgNCEKQL=0;PwgNCEKQL<Oq32NWn5D;PwgNCEKQL+=2) 這段代碼在這個循環內,循環上限出現在:

                    ⑦Oq32NWn5D=mXSYkqH0X.length; ,也即參數的長度,因此,這段代碼在解密傳入的參數。

                    還有,③中出現了另一個變量IA17ef3d3,這個變量出現在⑧IA17ef3d3[PwgNCEKQL]=fgMN0vK2r.charCodeAt(va31p5um0);,這之中還引用了fgMN0vK2r、va31p5um0兩個變量

                    ⑨fgMN0vK2r=RsIkkqdYi[(fgMN0vK2r^eJmF3VT3H.charCodeAt(gMKy026SO))&255]^((fgMN0vK2r>>8)&16777215);中出現了fgMN0vK2r。RsIkkqdYi是一個預設密鑰組,eJmF3VT3H是當前函數(arguments.callee.toString()等處理后的結果),gMKy026SO是計數器。因此這句是在基于一個密鑰組產生一個密鑰組;

                    ⑩for(PwgNCEKQL=0;PwgNCEKQL<8;PwgNCEKQL++) {var va31p5um0=Oq32NWn5D+PwgNCEKQL;xy3D07u0l[PwgNCEKQL]=1;xy3D07u0l[PwgNCEKQL]=FSB4JaYie;if (va31p5um0>=8) {va31p5um0=va31p5um0-8;IA17ef3d3[PwgNCEKQL]=fgMN0vK2r.charCodeAt(va31p5um0);} 同樣,va31p5um0也在參與解密。

                    也即,將傳入參數每隔2個字符作為一個HEX,然后解出來,與將函數自身的字符串通過解密算法解出來的數據相減,兩者結果小于0的話,加上256,最終對所有字符都如此操作,將結果連接起來得到解密數據。

                    既然函數本身不能輕易修改,那么只好從最終的eval做突破了,javascript中允許“劫持”一個對象。即和操作普通變量的賦值一樣,函數也是可以通過賦值來覆蓋的,請看第二部分。

                    2. 函數劫持


                    enter image description here

                    針對這個代碼,因為最終它會通過eval來運行惡意代碼,所以添加eval=alert,在運行到eval之前將其劫持即可。

                    運行代碼可以得到:

                    enter image description here

                    最后,總結一下,在Jscript9.dll中,腳本的函數中調用arguments.callee.toString()時,大致經歷了如下幾個步驟: 解析腳本文字(ScriptSite::ParseScriptText); 送與解析內核,生成字節碼,通過字節碼解釋器(即Intepreter)來執行; 在處理到arguments.callee.toString()時,jscript會將函數自身marshal成BSTR,然后轉換成JsVar,傳遞給后續要使用它的代碼。

                    題外話,這個代碼其實是2010年發現的一個廣告軟件(是當時流行的Rogue antivirus,也就是偽裝成殺毒軟件的廣告程序)安裝頁的Landing Page,當時我還特地上論壇和大家討論了怎么解決,大家給出的思路也相當多,除了上述我說的方法之外,一些自動化解密工具也可以處理此類網馬,例如Malzilla。不過建議大家不要過于依賴工具,而是把工具當作可以簡化重復勞動的工具是最好。

                    到此為止,腳本先鋒系列的解密部分就告一段落了,下一篇開始,將簡單的介紹調試器的用法以及如何對網馬中使用的Shellcode進行調試,其中也包括簡單的對惡意SWF、PDF的分析的內容。

                    參考資料


                    (1] 文中惡意腳本打包,請在虛擬環境下測試與調試(密碼drops.wooyun.org ):Download

                      <pre id="vvttv"><mark id="vvttv"><progress id="vvttv"></progress></mark></pre>
                      <pre id="vvttv"></pre>

                        <p id="vvttv"></p>

                            <p id="vvttv"></p>

                                  <p id="vvttv"></p>

                                  <pre id="vvttv"><cite id="vvttv"><progress id="vvttv"></progress></cite></pre>

                                    <output id="vvttv"><dfn id="vvttv"><th id="vvttv"></th></dfn></output>

                                      <p id="vvttv"></p>

                                      这里只有精品视频