走近科學(xué):如何一步一步解碼復(fù)雜的惡意軟件
寫在前面的話
在檢測網(wǎng)站安全性的過程中,最麻煩的一部分工作就是要確保我們能夠找出網(wǎng)站中所有已存在的后門。絕大多數(shù)情況下,攻擊者會(huì)在網(wǎng)站各種不同的地方注入惡意代碼,并以此來增加再次感染該網(wǎng)站的成功率以及盡可能久地實(shí)現(xiàn)持續(xù)感染。
雖然我們之前已經(jīng)給大家介紹過數(shù)百種后門以及相應(yīng)的影響,但今天我們想跟大家更加深入地討論一些關(guān)于惡意軟件的分析技術(shù),即如何解碼復(fù)雜的高級(jí)惡意軟件。
本文所分析的惡意軟件感染樣例早在幾個(gè)月前就已經(jīng)出現(xiàn)了,但是受這種惡意軟件變種所感染的網(wǎng)站(例如WordPress和Joomla等CMS)數(shù)量卻一直在增加。
惡意軟件
成功感染目標(biāo)網(wǎng)站之后,攻擊者可能會(huì)進(jìn)行注入后門和Web Shell、以及添加偽造的管理員用戶等惡意操作。一般來說,攻擊者都會(huì)采用一種或多種技術(shù)來隱藏自己的惡意代碼,例如編碼、加密和混淆等等。
請(qǐng)大家先看下面給出的代碼段。其中,攻擊者同時(shí)使用上面舉例的三種技術(shù)。接下來,我們會(huì)一步一步地告訴大家如何對(duì)這段代碼進(jìn)行解碼和分析。
原始的惡意軟件代碼段:
簡化代碼
在解碼過程中,最重要的是要理解代碼的邏輯結(jié)構(gòu)。為此,我們使用了PHP Beautifier來將之前的代碼段轉(zhuǎn)換成了下圖所示的格式:
雖然目前為止代碼仍然是不可讀的,但是我們現(xiàn)在至少已經(jīng)了解了代碼的編程邏輯架構(gòu)。
攻擊者一開始聲明了一個(gè)名叫”$hc7e1d20″的變量,而這個(gè)變量是沒有任何實(shí)際意義的。根據(jù)我們的經(jīng)驗(yàn)來看,這個(gè)變量的值(406)可能是攻擊者用來標(biāo)識(shí)惡意軟件變種版本的。
- <?php
- $hc7e1d20 = 406;
- $GLOBALS['be10eb436'] = Array();
- global $be10eb436;
- $be10eb436 = $GLOBALS;
除此之外,還有一些全局變量也對(duì)我們理解代碼不會(huì)提供任何幫助,我們可以直接忽略它們。
這個(gè)惡意軟件樣本基本上使用的是字符/字符串修改技術(shù),攻擊者在變量中存放了很多十六進(jìn)制字符,然后再將它們編譯成不同的變量。
第一個(gè)樣例如下:
- ${"\x47\x4c\x4fB\x41\x4c\x53"}['tbb6a']
- ="\x2d\x3d\x3e\x35\x4e\x73\x7d\x4f\x65\x77\x59\x41\x5f\x70\x6a
- \x69\x23\x3b\x51\x21\x57\x74\x4b\x46\xd\x5b\x2b\x20\x38\x76\x68\x2e\x3f
- \x44\x4d\x34\x67\x6f\x6b\x7c\x64\x7a\x31\x24\x5c\x4c\x40\x3c\x28\x5a\x79
- \x2a\x58\x78\x7e\x6c\x63\x43\x71\x49\x33\x47\x54\x36\x53\x75\x27\x5e\x29
- \x56\x66\x26\x32\x2c\x62\x30\x2f\x6e\xa\x50\x22\x25\x52\x5d\x45\x60\x42
- \x48\x39\x61\x37\x7b\x4a\x9\x55\x3a\x6d\x72";
這段代碼可以直接通過下面的bash命令來進(jìn)行轉(zhuǎn)譯:
- $ echo -e"\x47\x4c\x4fB\x41\x4c\x53"
- GLOBALS
- $ php -r 'echo"\x47\x4c\x4fB\x41\x4c\x53";'
- GLOBALS
這個(gè)值(${GLOBALS}[‘tbb6a’])似乎使用了某些特殊字符來防止被轉(zhuǎn)譯,但是惡意軟件最終似乎并沒有使用這個(gè)值?,F(xiàn)在,我們就可以創(chuàng)建一個(gè)簡單的PHP腳本,然后自動(dòng)化地打印出所有的變量以及相應(yīng)的值。
查找和替換
得到這些信息之后,我們就可以使用查找和替換功能了。
第一個(gè)變量如下:
- $be10eb436[$be10eb436['tbb6a'][55] .$be10eb436['tbb6a'][75]
- . $be10eb436['tbb6a'][8] .$be10eb436['tbb6a'][63]] =$be10eb436['tbb6a'][56] .$be10eb436['tbb6a'][30] . $be10eb436['tbb6a'][97];
- $be10eb436['tbb6a'][55] = ‘l’
- $be10eb436['tbb6a'][75] = ‘0’
- $be10eb436['tbb6a'][8] = ‘e’
- $be10eb436['tbb6a'][63]] = ‘6’
- $be10eb436['tbb6a'][56] = ‘c’
- $be10eb436['tbb6a'][30] = ‘h’
- $be10eb436['tbb6a'][97] = ‘r’
我們可以得到下面的轉(zhuǎn)譯結(jié)果:
- $be10eb436[‘l . ‘0’ . ‘e’ . ‘6’] = ‘c’ .‘h’ . ‘r’; ---- $be10eb436[‘l0e6’] = ‘chr’;
為了增加代碼的可讀性,我們將’be10eb436′替換成了’arr’(因?yàn)樗宦暶鳛榱艘粋€(gè)array()),然后我們繼續(xù)對(duì)字符進(jìn)行轉(zhuǎn)譯。
幾分鐘之后,我們得到了如下所示的代碼:
現(xiàn)在一切已經(jīng)更加明朗了,接下來我們還要對(duì)代碼進(jìn)行一些調(diào)整。其中,前幾個(gè)變量可以直接替換成下列形式:
- $arr['l0e6'] = ‘chr’;
- $arr['ac6c24d1'] = ‘ord’;
- $arr['s8bb921e'] = ‘strlen’;
將代碼種各個(gè)變量和值調(diào)整到相應(yīng)位置之后,我們就得到了上述代碼中的第一個(gè)函數(shù):
- function l3f5($nd0f2d, $yaf8a49ab)
- {
- global$arr;
- $wb1a= "";
- for($a5be536 = 0; $a5be536 < strlen($nd0f2d);)
- {
- for($jd82720f = 0; $jd82720f < strlen($yaf8a49ab) && $a5be536 <$arr['s8bb921e']($nd0f2d); $jd82720f++,$a5be536++)
- {
- $wb1a.=chr(ord($nd0f2d[$a5be536]) ^ ord($yaf8a49ab[$jd82720f]));
- }
- }
- return$wb1a;
- }
惡意目的
替換了所有的函數(shù)以及變量之后,我們就可以得到如下所示的代碼段了:
得到了完整并且可讀的惡意代碼之后,我們發(fā)現(xiàn)了幾個(gè)有意思的地方:
1. 其中有一個(gè)名叫l(wèi)3f5() 的函數(shù),該函數(shù)負(fù)責(zé)通過按位異或計(jì)算來執(zhí)行加密和解密操作。
2. 函數(shù) q057860()采用了兩層異或加密/解密計(jì)算。
a) 第一層計(jì)算中,密鑰是一個(gè)預(yù)定義的常量: ($w158 = ‘2cef0f87-62fe-4bb9-a1de-4dc009e818ea’;)。
b) 第二層所使用的密鑰來自于POST參數(shù)或HTTP coockie。
c) 這個(gè)函數(shù)主要用來對(duì)經(jīng)過加密的序列化數(shù)據(jù)進(jìn)行解碼。其中,序列化數(shù)據(jù)是攻擊者通過cookie或POST參數(shù)傳遞給惡意腳本的。
3. 解碼數(shù)據(jù)可能包含:
a) 可執(zhí)行的PHP代碼。
b) 提供關(guān)于后門和PHP版本信息的命令。
總結(jié)
現(xiàn)在網(wǎng)上有很多不同類型的惡意軟件,但并非所有的惡意軟件都是直接通過腳本來執(zhí)行惡意命令的。比如說在這個(gè)樣本中,它可以通過$_POST或$_COOKIE請(qǐng)求來接收任意命令,而Web服務(wù)器默認(rèn)是不會(huì)記錄這種行為的。
為了防止網(wǎng)站被惡意軟件所感染,我們強(qiáng)烈建議管理員采用類似文件完整性監(jiān)測以及Web應(yīng)用防火墻(WAF)等安全措施。除此之外,我們還建議管理員定期檢查網(wǎng)站的日志記錄以盡早地發(fā)現(xiàn)可疑行為。