走近科學:如何一步一步解碼復雜的惡意軟件
寫在前面的話
在檢測網站安全性的過程中,最麻煩的一部分工作就是要確保我們能夠找出網站中所有已存在的后門。絕大多數情況下,攻擊者會在網站各種不同的地方注入惡意代碼,并以此來增加再次感染該網站的成功率以及盡可能久地實現持續感染。
雖然我們之前已經給大家介紹過數百種后門以及相應的影響,但今天我們想跟大家更加深入地討論一些關于惡意軟件的分析技術,即如何解碼復雜的高級惡意軟件。
本文所分析的惡意軟件感染樣例早在幾個月前就已經出現了,但是受這種惡意軟件變種所感染的網站(例如WordPress和Joomla等CMS)數量卻一直在增加。
惡意軟件
成功感染目標網站之后,攻擊者可能會進行注入后門和Web Shell、以及添加偽造的管理員用戶等惡意操作。一般來說,攻擊者都會采用一種或多種技術來隱藏自己的惡意代碼,例如編碼、加密和混淆等等。
請大家先看下面給出的代碼段。其中,攻擊者同時使用上面舉例的三種技術。接下來,我們會一步一步地告訴大家如何對這段代碼進行解碼和分析。
原始的惡意軟件代碼段:
簡化代碼
在解碼過程中,最重要的是要理解代碼的邏輯結構。為此,我們使用了PHP Beautifier來將之前的代碼段轉換成了下圖所示的格式:
雖然目前為止代碼仍然是不可讀的,但是我們現在至少已經了解了代碼的編程邏輯架構。
攻擊者一開始聲明了一個名叫”$hc7e1d20″的變量,而這個變量是沒有任何實際意義的。根據我們的經驗來看,這個變量的值(406)可能是攻擊者用來標識惡意軟件變種版本的。
- <?php
- $hc7e1d20 = 406;
- $GLOBALS['be10eb436'] = Array();
- global $be10eb436;
- $be10eb436 = $GLOBALS;
除此之外,還有一些全局變量也對我們理解代碼不會提供任何幫助,我們可以直接忽略它們。
這個惡意軟件樣本基本上使用的是字符/字符串修改技術,攻擊者在變量中存放了很多十六進制字符,然后再將它們編譯成不同的變量。
第一個樣例如下:
- ${"\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命令來進行轉譯:
- $ echo -e"\x47\x4c\x4fB\x41\x4c\x53"
- GLOBALS
- $ php -r 'echo"\x47\x4c\x4fB\x41\x4c\x53";'
- GLOBALS
這個值(${GLOBALS}[‘tbb6a’])似乎使用了某些特殊字符來防止被轉譯,但是惡意軟件最終似乎并沒有使用這個值。現在,我們就可以創建一個簡單的PHP腳本,然后自動化地打印出所有的變量以及相應的值。
查找和替換
得到這些信息之后,我們就可以使用查找和替換功能了。
第一個變量如下:
- $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’
我們可以得到下面的轉譯結果:
- $be10eb436[‘l . ‘0’ . ‘e’ . ‘6’] = ‘c’ .‘h’ . ‘r’; ---- $be10eb436[‘l0e6’] = ‘chr’;
為了增加代碼的可讀性,我們將’be10eb436′替換成了’arr’(因為它被聲明為了一個array()),然后我們繼續對字符進行轉譯。
幾分鐘之后,我們得到了如下所示的代碼:
現在一切已經更加明朗了,接下來我們還要對代碼進行一些調整。其中,前幾個變量可以直接替換成下列形式:
- $arr['l0e6'] = ‘chr’;
- $arr['ac6c24d1'] = ‘ord’;
- $arr['s8bb921e'] = ‘strlen’;
將代碼種各個變量和值調整到相應位置之后,我們就得到了上述代碼中的第一個函數:
- 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;
- }
惡意目的
替換了所有的函數以及變量之后,我們就可以得到如下所示的代碼段了:
得到了完整并且可讀的惡意代碼之后,我們發現了幾個有意思的地方:
1. 其中有一個名叫l3f5() 的函數,該函數負責通過按位異或計算來執行加密和解密操作。
2. 函數 q057860()采用了兩層異或加密/解密計算。
a) 第一層計算中,密鑰是一個預定義的常量: ($w158 = ‘2cef0f87-62fe-4bb9-a1de-4dc009e818ea’;)。
b) 第二層所使用的密鑰來自于POST參數或HTTP coockie。
c) 這個函數主要用來對經過加密的序列化數據進行解碼。其中,序列化數據是攻擊者通過cookie或POST參數傳遞給惡意腳本的。
3. 解碼數據可能包含:
a) 可執行的PHP代碼。
b) 提供關于后門和PHP版本信息的命令。
總結
現在網上有很多不同類型的惡意軟件,但并非所有的惡意軟件都是直接通過腳本來執行惡意命令的。比如說在這個樣本中,它可以通過$_POST或$_COOKIE請求來接收任意命令,而Web服務器默認是不會記錄這種行為的。
為了防止網站被惡意軟件所感染,我們強烈建議管理員采用類似文件完整性監測以及Web應用防火墻(WAF)等安全措施。除此之外,我們還建議管理員定期檢查網站的日志記錄以盡早地發現可疑行為。