作者:莊曉立 (liigo),2010/7/5
本文首發地址:http://blog.csdn.net/liigo/archive/2010/07/04/5712547.aspx
轉載請註明出處:http://blog.csdn.net/liigo
易語言5.0靜態編譯版本發布以來,仍然有一些殺毒軟體誤判易語言編譯的程式為病毒或木馬。趁這兩天周末時間,我(liigo)按照自己的一個簡單到幼稚的思路,做了一些不成熟也尚未形成結論的研究。這個思路是:先用MyCCL定位特徵碼,然後看這個(這些)特徵碼位於EXE/PE檔案的什麼位置,如果是位於程式碼片段(.text)中的可執行指令的話,再進一步尋找這段指令來自於哪一個編譯單元中的哪一個函數,最後再視情況進行相應的技術性處理,直至達到從根本上解除誤判的目的。即使沒有達到最終目的,如果能夠大概總結出殺毒軟體誤判易語言程式的理由,也是不小的收穫。
因為不瞭解、不成熟,研究需要有一些前提條件,先做如下假設:
1、多數知名殺毒軟體是以特徵碼為主要查殺手段,修改檔案特定位移處的某段資料可以解除誤判。
2、連結器(linker)產生的EXE/DLL檔案中的可執行代碼,全部來自外部的編譯單元(.obj, .lib)。
分析易語言的靜態編譯連結過程,連結器使用的所有編譯單元,分為以下三大部分:1、易語言編譯器產生的OBJ檔案(這是易語言程式的主體代碼)和RES檔案;2、易語言支援庫的靜態庫(LIB檔案);3、連結器內建的其它靜態庫(LIB檔案),如C/C++基礎庫、MFC基礎庫、作業系統核心DLL的匯入庫(kernel32.lib, user32.lib)等。其中前兩部分由易語言提供,其餘由連結器生產商(如Visual Studio的生產商微軟/MicroSoft)提供。
根據前面的第2條假設,以及編譯連結過程的分析,得出以下推論:易語言靜態編譯產生的EXE/DLL檔案,其中的任意一段可執行代碼(X86指令集合),“必然”來自以上提到的連結器所使用的編譯單元的三個部分之一。只要此推論成立,就可以追蹤特徵碼的來源(詳見下文),源於編譯器則修改編譯器,源於哪支援庫則修改之,源於連結器內建的其它靜態庫則採用其它非常規手段處理。注意我在推論中使用了帶引號的“必然”這個詞,用“必然”是因為“依據理論推導理應如此”,加上引號則表示懷疑和否定,因為,我(liigo)暫時無法證實這個推論,更杯具的是,本文的後續進程甚至還一定程度上否定了這個推論,令我始料不及,以至無法繼續深入研究。
下面順序說說整個(應該是半個)研究流程吧。目標程式是一個使用易語言5.11正式版靜態編譯的空白視窗程序(EXE)(不寫任何代碼);殺毒軟體先後使用了360和江民(升級到最新版本和最新病毒庫),對目標程式都有誤判。
首先是用 MyCCL 軟體定位特徵碼,這個網上有很多教程,就不細說了,:
找到特徵碼後,看看它是在PE檔案(EXE/DLL)的什麼位置。
我先針對360殺毒軟體找到一處特徵碼,位於檔案位移0x01FC處2個位元組(值為 0x00,0x10),發現竟然位於PE標準程式碼片段(.text)的段頭中,再精確點就是IMAGE_SECTION_HEADER.PointerToRawData(DWORD)資料的一部分,天,這個也能做特徵碼(程式碼片段資料標頭檔位移為0x1000非常之普遍),先不管,隨便改一個值,通過了360殺毒軟體檢測,不再誤判了。可是這個360的特徵碼不是程式碼片段中的可執行代碼,無法追蹤其來源。換一個江民殺毒軟體,其中一個特徵碼定位到檔案位移0x052DEE處的24個位元組(手工修改開頭任意位元組值均可解除誤判),010 Editor中顯示如下:
OllyDbg中看到的反組譯碼指令如下:
下面追蹤特徵碼來源,本次研究的重頭戲。
根據本文前面的推論,程式碼片段中的特徵碼,應該來源於連結器所使用的某個.obj或.lib檔案中。都是哪些檔案呢,前面都已經分成三大塊一一指出了。我用易語言編寫了一個特徵碼掃描程式,去所有這些LIB和OBJ檔案中逐一掃描特徵碼,如果找到則記錄其所在LIB/OBJ檔案及檔案位移,以便進一步追蹤來源(定位到其所屬函數)。由於特徵碼裡面的可執行代碼中可能存在需要重定位的地址或相對位址(如前面特徵碼中檔案位移0x052DFE處E8位元組後面的四個位元組),不一定與LIB/OBJ中的代碼完全一致,掃描程式中已經對此做了過濾處理,以確保精確追蹤定位特徵碼。哎,找到一個,在LIB檔案GLAUX.lib中:
後來證實GLAUX.lib並未參與連結,因為把我它刪除或重新命名也能連結成功。除此之外,我的掃描程式沒有在其它所有可能的LIB/OBJ檔案中找到“確認在EXE程式碼片段出現過的”這段特徵碼!所以結果是令人遺憾的。我至今依然疑惑,這段代碼源於何處?難道是連結器(linker)自己產生的(最佳化整合代碼)?還是我掃描時漏掉了某些LIB/OBJ檔案(核心庫以外的支援庫LIB檔案因確認未用沒包括在內,連結器調用外部程式(CVTRES.EXE)從RES檔案產生的OBJ檔案因無可執行代碼沒包括在內)?掃描程式自身的BUG?雖然無法排除這種可能性,但可能性應該很小,因為有過仔細測試。這段特徵碼中有一個函數調用,去掃描那個函數體的頭部程式碼片段,也沒有追蹤到其來源LIB/OBJ。奇怪,怎麼會這樣?怎麼會是這個結果?為什嗎?……
2010/7/8 02:30 續:
失誤,失誤,上次的失誤,搜尋時竟然漏掉了MFC的靜態庫!哈哈,這次補上之後終於找到了“罪魁禍首”,NAFXCW.LIB(同時發現同樣包含相同特徵碼的LIB還有MFCS42.lib和UAFXCW.lib,已確認未參與連結):
我(liigo)會繼續這項工作,按原計划下一步將找到這段特徵代碼來自NAFXCW.lib中的哪一個函數。敬請期待。
2010/7/11 0:05 續:
下面附上搜尋定位特徵碼的核心原始碼,使用易語言編寫:
遍曆所有LIB檔案(主要是連結器的lib目錄和易語言的static_lib目錄),讀取檔案內容,並迴圈調用以上函數即可,非常之簡單,代碼就不貼了。
2010/7/12 續:
全文完。後續研究請看下一篇:在靜態庫LIB/OBJ檔案中搜尋定位病毒碼碼所屬函數,C/C++源碼。