A?share?of?knowledge?I?have,[email protected]
[email protected]??于其它國產ELF DDos惡意軟件,Linux/XOR.DDoS更具威脅性,而且它仍在擴散中。最近我收到一個很好的問題(一個受到感染的研究人員問的):為什么找到的惡意二進制文件跟首次執行的惡意二進制文件不一樣?非常好!這篇文章比較短,只包含這個問題的答案。但那些可能對緩解/檢測病毒的重要信息和技術我會分享給NIX的小伙伴們,因此文章中還包含了我對ELF惡意軟件進行逆向,調試和取證的三個過程。最后,請原諒我糟糕的措辭,因為我幾乎沒有時間去檢查和校驗這篇文章。
多態(Polymorphic)是指惡意軟件在自我繁殖期間不斷改變(“morphs”)其自身文件特征碼(大小、hash等等)的特點,衍生后的惡意軟件可能跟以前副本不一致。因此,這種能夠自我變種的惡意軟件很難使用基于簽名掃描的安全軟件進行識別和檢測。
多態型惡意軟件在Window中是一種很常見的病毒,但在Unix中這類惡意軟件可能還比較少聽說。本質上NIX的惡意軟件也是來自于網絡,從感染文件提取或通過其它惡意軟件下載。所以,我猜我們有許多默認哈希樣本。但在這篇文章中,我們實際上是在處理一個像Windows上能夠自我拷貝感染的多態行為惡意軟件。所以我覺得值得寫一寫。
這篇報告是一個真實的感染事件,一個已知的gang/crook案例,我得以發布如下的攻擊日志:
上面的日志是典型的Linux/ Xor.DDOS hostasa.org ssh暴力攻擊模式。不久之前我在這里發布過(同一個攻擊者)一個案例還有最近發生的一個案例。另外,我把這個惡意軟件上傳到了virustotal。
Linux/XOR.DDos執行的時候會尋找一個自我拷貝的地方,通過下面的系統調用可以看到它正在努力地寫文件中:
open("/usr/bin/lgjgjmkkgd", O_WRONLY|O_CREAT, 0777) ; depends, in mine is -1 EACCES (Permission denied)
open("/bin/lgjgjmkkgd", O_WRONLY|O_CREAT, 0777) ; depends, in mine is -1 EACCES (Permission denied)
在一個良好的Linux系統中,如果惡意軟件不是通過root用戶執行的話你會看到上面的結果。這時,惡意軟件拷貝向它最喜歡的/tmp目錄當中:
open("/XOR.DDOS.SAMPLE", O_RDONLY) ; initial exec malware open itself
lseek(3, 0, SEEK_SET); ; set LSET to OFFSET to READ
open("/tmp/lgjgjmkkgd", O_WRONLY|O_CREAT, 0777); open self-copy target w/perm 777
read(3, "\177ELF\1\1\1\0\.."); ; read the malware bin
lseek(4, 0, SEEK_SET) ; set LSET to OFFSET to WRITE
14878 read(3, "\177ELF\1\1\1\0\… ; copy process read..
14878 write(4, "\177ELF\1\1\1\0\… ; copy process write
通過逆向ELF惡意軟件,以下的操作就是上述惡意軟件在尋找安裝目錄到執行整個過程(大圖點擊這里):
可以看到惡意軟件通過級聯的方式去尋找一個可以自我拷貝的地方,程序最開始從嘗試往/usr/bin目錄拷貝,然后嘗試往/bin目錄拷貝。在我的測試過程中,它最終選擇了/tmp/[randomname]。目標文件名是隨機的,然后通過返回的全路徑執行execve()。我們稍后再討論這個話題。
通過Linux內存取證工具可以比較清楚地看到復制blob數據的整個過程,使用hexdump這個老牌工具就行了:
Copy process illustration (read and write of copy process) in the end of file:
[...]
00098bd0 6d 65 00 5f 64 6c 5f 6d 61 70 5f 6f 62 6a 65 63 |me._dl_map_objec|
00098be0 74 5f 64 65 70 73 00 5f 6e 6c 5f 43 5f 4c 43 5f |t_deps._nl_C_LC_|
00098bf0 49 44 45 4e 54 49 46 49 43 41 54 49 4f 4e 00 5f |IDENTIFICATION._|
00098c00 64 6c 5f 6e 73 00 5f 6e 6c 5f 6c 6f 61 64 5f 6c |dl_ns._nl_load_l|
00098c10 6f 63 61 6c 65 5f 66 72 6f 6d 5f 61 72 63 68 69 |ocale_from_archi|
00098c20 76 65 00 77 63 74 72 61 6e 73 00 |ve.wctrans.|
00098c2b
debug的時候可以看到復制進程是優雅結束的:
read(3, "", 4096): ; EO/termination w/no space
close(3); ; end of copy (reading)
close(4); ; end of copy (writing)
上面并沒有什么特別的操作,現在我們運行到這里已經完成惡意軟件自我拷貝了,但是為什么文件會不同?我們繼續向下走,發現下文有一個系統調用在使用SEEK_END標志:
open("/tmp/lgjgjmkkgd", O_WRONLY); ; opening the copied file
lseek(3, 0, SEEK_END) = 625707 <==size ; set LSET to the EOF for writing
; SEEK_END = *) ; note the size of original malware
它看起來是使得文件偏移量指向了文件結束處。下圖顯示了使用了SEEK_END標志之后文件偏移量的位置(*所指之處):
Illustration of the LSET set in the end of file..
00098bd0 6d 65 00 5f 64 6c 5f 6d 61 70 5f 6f 62 6a 65 63 |me._dl_map_objec|
00098be0 74 5f 64 65 70 73 00 5f 6e 6c 5f 43 5f 4c 43 5f |t_deps._nl_C_LC_|
00098bf0 49 44 45 4e 54 49 46 49 43 41 54 49 4f 4e 00 5f |IDENTIFICATION._|
00098c00 64 6c 5f 6e 73 00 5f 6e 6c 5f 6c 6f 61 64 5f 6c |dl_ns._nl_load_l|
00098c10 6f 63 61 6c 65 5f 66 72 6f 6d 5f 61 72 63 68 69 |ocale_from_archi|
00098c20 76 65 00 77 63 74 72 61 6e 73 00 *<==== |ve.wctrans.*) <==
00098c2b
繼續走,程序調用了timeoftheday(),然后向文件結尾處寫入一個字符串:
gettimeofday({1442479267, 397488}, NULL) ; for randomid() seed..
write(3, "wlpvpovdvi\0", 11) ; 'size is set to 11'
; write string "wlpvpovdvi\0"-
; in the LSET position (EOF)
下圖是文件寫入前和寫入后的對比:
可以看到,文件被多添加了11個字節,這意味著會比自我拷貝之前的惡意軟件多出11個字節。
下一步,程序調用close保存并關閉文件:
close(3) ; end of writing process..
接著,調用execve()函數創建一個shell command執行它:
execve("/tmp/lgjgjmkkgd", ..); ; main running process of XOR.DDOS in new PID
; with new size (& hash)
你可以在/proc看到它保存的進程數據,相信我,這個操作不需要借助任何Unix取證工具,因為Unix已經幫我們提供好這一切:
lgjgjmkkg 14881 MMD cwd DIR 8,6 4096 7209106 /TESTDIR
lgjgjmkkg 14881 MMD rtd DIR 8,1 4096 2 /
lgjgjmkkg 14881 MMD txt REG 8,1 "625718 <== NEW SIZE" 829 /tmp/lgjgjmkkgd
lgjgjmkkg 14881 MMD 0u CHR 1,3 0t0 1028 /dev/null
lgjgjmkkg 14881 MMD 1u CHR 1,3 0t0 1028 /dev/null
lgjgjmkkg 14881 MMD 2u CHR 1,3 0t0 1028 /dev/null
現在它擁有一個全新的PID,不是通過clone或fork/thread,而是運行在一個新的進程。另外還可以看到它比原文件多了11個字節:
下面是原始文件和拷貝后的文件的md5值:
$ md5sum XOR.DDOS.SAMPLE lgjgjmkkgd
"7642788b739c1ee1b6afeba9830959d3" XOR.DDOS.SAMPLE
"df50d096fb52c66b17aacf69f074c1c3" lgjgjmkkgd
$ ls -l XOR.DDOS.SAMPLE lgjgjmkkgd| awk '{print $5, $6, $7, $9}'
"625718" Sep 17 lgjgjmkkgd
"625707" Sep 17 XOR.DDOS.SAMPLE
它們有著不同的hash和大小。
ok,我們已經完成了調試和取證,現在逆向工程來看一下這個ELF惡意軟件是如何完成上述的所有操作。
下面是我的惡意樣本一部分自我拷貝的過程。注意:自我拷貝級聯了幾種情況,我大概數了一下有至少四層級聯。惡意軟件的作者真的計算了所有可能性以確保他的代碼能夠運行。
跳轉到0x804dfc2進行處理下個任務。
下面展示了惡意軟件在完成拷貝文件之后修改文件的過程。11個隨機字符沒有直接使用的,而是跟一個硬編碼在0x080cf120(str.Ff4VE.7)的字符串做xor加密運算。
snprintf()函數結果最終被SYS_write系統調用所使用,在逆向靜態編譯的ELF惡意樣本的時候可以看到一些來自libc的函數,后面還可以看到很多調用libc的代碼。
上面調試中所看到的timeoftheday()正是被這里的randomid()函數所調用的。
很明顯,這里調用了timeoftheday()取得系統時間來作為randomid()函數的隨機種子。
這里有一個驚訝的信息是(我想這消息對于社區很有幫助):Linux/XOR.DDoS ELF惡意軟件使用非常罕見的執行shell命令方法,它調用了LinuxExec_Argv()和LinuxExec_Argv2(),而這兩個函數都是直接使用系統調用(靜態編譯),這些函數一個典型的特點是:用起來非常簡單,而且容易找出哪些是負責調用execve()。下面展示了在解析完路徑之后使用execvp()函數進行感染。
關于execvp詳細信息可以直接參考man(2),是的,Unix系統已經提供給我們最好的參考資料。
Linux/XOR.DDos在自我拷貝(成功感染)之后的文件跟原文件有不同的大小(多了11個字節...另外,我只檢查了這一個樣本)和hash。這意味著對于那些使用hash掃描的安全軟件來說是無法掃描出變種后的Linux/XOR.DDos。
很多人認為,無所謂咯,ELF反正侵害不到我自己的電腦(Windows)。但是記住:目前IoT和路由器領域基本都是基于Linux系統,而ELF惡意軟件的感染方法越來越先進/完美(我們數據顯示有6個新的ELF惡意軟件僅半年就更新了兩個)。因此我們(MalwareMustDie)建議盡可能早點更新對這類惡意軟件的檢測質量。如果讓這些惡意軟件扎根在服務器領域,那么影響比感染PC機嚴重太多了。
下面是以前的Linux/XOR.DDos分析文章:
還有來自新的CNC威脅:
Will #USA be nice to clean: 192.126.126.64 & 107.160.40.9 < China crook's #malware #CNC? http://t.co/fTD0V57ySc pic.twitter.com/ZmabDO9aoP
— MalwareMustDie (@MalwareMustDie) September 15, 2015
順便說一下,CNC現在非常的活躍,下面是一些關于它們活動的截圖:
最后,希望這篇短文章能夠幫助到做安全的朋友。