<span id="7ztzv"></span>
<sub id="7ztzv"></sub>

<span id="7ztzv"></span><form id="7ztzv"></form>

<span id="7ztzv"></span>

        <address id="7ztzv"></address>

            原文地址:http://drops.wooyun.org/papers/13686

            Author: MalwareBenchmark

            0x00 簡介

            《編譯原理》課程在大學本科階段就難道了很多計算機專業的同學。而反編譯技術更需要從事者具有深厚的編譯技術基礎,因此一直是很多業內人士希望能夠深入了解和掌握的一門技術。

            從現在開始,我們討論反向編譯的一些內容。顧名思義,反編譯可以認為是編譯的逆過程,這一點從編譯和反編譯(Compile and De-compile,英文中也有用De-compilation來表示反編譯的)的中英文描述都可看出。但這看似只有一字之差的名稱,在實際應用中并不是簡單的“逆流而上”。因為在多數時候“創造”遠比“恢復”來得簡單,就好像您不小心打碎了家里的花瓶,想要通過修復和粘接把碎片恢復成原樣,幾乎是不可能辦到的。即便能夠基本復原,但粘接的花瓶與它原來的樣子也不會完全一樣。與碎片到花瓶的變化類似,反編譯過程遠比編譯過程復雜和繁瑣,而且反編譯的結果也遠遠不如您原來編寫的代碼那么“美妙”。但是反向編譯卻能在程序功能分析、惡意代碼發現、二進制翻譯等特殊工作中發揮重要作用,這也是筆者仍然致力于研究這一并不十分完善的技術的重要原因。

            0x01 反編譯的概念和基本過程


            1.什么是反編譯

            在這一節里我們將對反編譯做出一個基本的說明,給出反編譯的概念,使讀者們可以對反編譯有一個初步的理解。我們給出的概念不是學術研究中嚴謹的定義,只是作者基于相關文獻和多年來的研究心得所給出的一段說明。此外,我們還會揭示一個事實,盡管編譯與反編譯看起來是正反兩項技術,但有趣的是:反編譯器的編寫方法卻恰恰依賴于編譯器的編寫技術。

            反編譯概念

            反編譯技術是通過對低級語言代碼(二進制代碼或者匯編代碼等)進行分析轉化,得到等價的高級語言(不限制語言類型,本書的描述主要以C語言為例)代碼的過程。它涉及指令系統,可執行文件格式,反匯編技術,數據類型分析技術,控制流分析技術和高級代碼生成技術等。

            編譯與反編譯

            反編譯的本質是編譯的逆過程。從二十世紀五十年代第一個編譯器出現開始,將機器碼轉換成為高級語言的期望就引發了人們廣泛的興趣。圖1揭示了編譯器同反編譯器之間的關系。

            可以看到編譯器同反編譯器都將程序從一種形式轉換到另外一種形式,而且在轉換的步驟中,都使用了類似的中間表示。差別只是在于編譯器的總體方向是從源程序到機器碼,而反編譯器的總體方向則是從機器碼到源程序。盡管在整體方向上兩者是相反的,但編譯器和反編譯器往往在分析階段使用類似的技術,例如數據流分析。

            編譯器通過對源代碼進行解析得到中間表示(IR,intermediaterepresentation),反編譯器通過對指令進行解碼得到中間表示。類似的,編譯器的低級代碼生成同反編譯器的高級代碼生成恰好對應。

            1-1

            圖1 編譯器同反編譯器在結構上的對應性

            編譯的過程為源程序打上了機器屬性,比如CPU及寄存器的使用、機器指令的使用、以及內存地址的分配等;而反編譯過程則需要剝離機器相關的細節,盡可能地區分指令和數據,通過逆向分析,重建高級數據結構和程序結構。

            反編譯器

            反編譯器是利用反編譯技術實現的具體軟件系統。它讀入一個機器語言的程序(被編譯器編譯生成的二進制編碼,即源語言),并把它翻譯為一個等價的高級語言程序(即目標語言)。反編譯器或反向編譯器,嘗試逆向一個編譯器的過程,把一個二進制程序或可執行程序翻譯成一個高級語言程序。它應用基本的反編譯器技術,把多種多樣的機器語言二進制程序反編譯成某種高級語言。反編譯器的結構是基于編譯器的結構,而且應用類似的原理和技術進行程序分析。

            2.反編譯的基本過程

            在這一小節,我們按照三種不同的分類,從多個角度闡述反編譯的基本過程。

            1. 如果按照反編譯技術實施的順序劃分,則可以分為7個階段,它們是:句法分析、語義分析、中間代碼生成、控制流圖生成、控制流分析、代碼生成。如圖所示。

              1-2

              圖2 按照反編譯技術實施的順序劃分

            2. 如果按照實踐中的具體操作劃分,一般也可以分為7個不同的步驟,分別是:文件裝載,指令解碼,語義映射,相關圖構造,過程分析,類型分析和結果輸出等。如圖 3。

              1-3

              圖3 反編譯操作

              以逆向分析為目的,反編譯的各個階段并不是一個嚴格的一遍順序,而是存在著一些并行的模塊,并且也需要通過循環執行分析過程來針對某些特殊問題(例如非N分支代碼產生的間接跳轉指令)進行分析和恢復。

            3. 反編譯的處理過程,如果按功能區分,可以分為:前端、中端和后端三個部分。其實這種劃分方式是將上述兩種過程的階段進行合并,也就是將幾個反編譯器階段組合在一起。這樣劃分的好處是:通過設計不同的前端、中端和后端以實現針對多種源和目標的反編譯器。

            0x02 反編譯的前世今生


            1.建立——20世紀60年代

            隨著第一臺計算機的誕生,硬件與軟件就成了構成計算機系統的兩個重要組成部分,它們相伴而生、相互促進,它們分工迥異、各司其職。為了使用和驅動不斷演化的硬件系統,通過計算機語言來編寫系統和應用程序的方式逐漸確立了主流的地位。伴隨著高級編程語言的出現,第一代編譯器也在20世紀50年代產生了,它實現了高級語言到機器代碼的等價轉換,完成了人類認知到機器“認知”的轉換。而幾乎與此同時,將機器碼還原成為高級語言的逆向思考也引發了研究人員的求知欲望。

            在第一代編譯器出現十年之后的20世紀60年代,以小規模集成電路為特征的第三代計算機開始出現。由于其與第二代晶體管計算機的差異較大,使得運行在第二代計算機上的軟件幾乎面臨著即將被全部淘汰的危險。然而基于當時的軟件開發技術和開發成本,淘汰軟件意味著巨大的損失。為了挽救這些價值不菲的軟件,同時也為了加速開發第三代機器的軟件,與軟件移植技術相關的研究逐漸興起,例如:程序轉換器、交叉匯編器、翻譯器、反編譯器等。其中反編譯器成了最初的研究熱點。

            1) D-Neliac——反編譯器的開山祖師

            一些美國公司和研究機構開始著手進行軟件移植工具的研究,并且由美國海軍電子實驗室的J.K.Donally和H.Englander在1960年實現了第一代反編譯器D-Neliacdecompiler。由此我們的反編譯器鼻祖正式“粉墨登場”了,比它的兄弟“編譯器”整整小了10歲。Donnelly-Neliac(D-Neliac)可以將機器代碼反編譯成Neliac(類似于Algol的一種編程語言,是NEL在1955年開發的一個Algol-Algorithmiclanguage類型語言)程序代碼。

            2) Sassaman的Fortran反編譯器——不是一個人的江湖

            無獨有偶,1966年Sassaman在TRW公司開發了一個反編譯器,該反編譯器以IBM 7000序列的符號化匯編程序做為輸入并產生Fortran程序,是第一個使用匯編程序而非純二進制代碼作為輸入的反編譯器。它是有據可查的第二個正式的反編譯器,但是由于它以包含大量有用信息的符號化匯編程序作為輸入,而省卻了反匯編的過程,也因此降低了反編譯的難度。這是第一個使用匯編程序而非純二進制代碼作為輸入的反編譯器。匯編程序包含名字、宏、數據和指令形式的有用信息,在二進制程序或者可運行程序中是沒有這些信息的,因此避免了在反編譯器的語法分析階段區分數據和指令的問題。

            又因為該反編譯器的輸出是1960年代的標準編程語言Fortran程序(第二代、第三代計算機上都在使用Fortran),所以使得它看起來更具有實用意義。該反編譯器面向的是涉及代數運算的工程應用程序,使用者需要掌握一定的相關知識,并能夠為子程序的識別自定義規則。在熟練的程序員干預下,該反編譯器的正確率可以達到90%,因此它是屬于少數人的“陽春白雪”。

            3)Lockheed Neliac——開山祖師的傳人

            1967年,洛克希德導彈與空間公司在海軍電子實驗室開發的Neliac編譯器上做了一些增強,我們稱它為Lockheed Neliac。

            反編譯器LockheedNeliac與D-Neliac類似,它們都可將機器代碼程序轉換成Neliac程序代碼,特別是它們可以將非Neliac語言生成的機器代碼轉換為Neliac程序代碼。這一時期的反編譯器采用模式匹配的方法進行反編譯,把許多復雜的問題留給程序員手工解決。

            4)小結——De-compiler的拓荒者們

            整個60年代,反編譯方面的研究主要集中在研制專門用途的反編譯器上,并希望其可以作為軟件移植的工具來使用。但是受限于當時計算機發展水平,以及體系結構的影響,這一時期的反編譯器主要采用模式匹配的方法進行反編譯,需要較多的人工干預;并且反編譯的結果通常不經過優化處理,所以輸出的結果代碼效率較低、可讀性較差。

            從前邊的敘述中可以看出,盡管從編譯器被發明以來,人們就對編譯的逆過程倍感興趣,但真正邁出這關鍵的一步卻是由于進行“軟件移植”的訴求。那個年代的計算機程序停留在大型商業公司和高等院校的實驗室里,只有很少的人能接觸和掌握高級語言的編程,程序的復雜程度也較為有限,也沒有大量出現病毒,因此利用反編譯進行程序分析并沒有那么重要。

            2.發展——20世紀70年代

            反編譯技術建立初期,并沒有很快成為通用的商業軟件流行起來。大學校園的理論研究,成為推動這項技術發展的主要動力。下面我們按照時間的脈絡,走進歷史進程中的“象牙塔”,回顧一下反編譯技術的發展過程。反編譯理論方面的研究成為這個時期的熱門,隨著美國多位博士以反編譯作為博士研究課題,一些對逆向編譯和程序移植有一定影響的理論和技術被相繼提出。在這個研究領域,豁然呈現出百花齊放的景象。

            1)花開一朵——博士們的研究

            1973年,DoctorHollander首次針對反編譯方式生成的代碼,使用控制流與數據流分析相結合的技術手段來進行優化。此外,他還基于元語言描述定義了一個反編譯過程的五級模型,并且實現了從IBM System360匯編子集到類ALGOL語言的反編譯。該反編譯器雖然引入了一些新的技術,即綜合利用數據流和控制流分析技術來改善反編譯器的輸出代碼,并使用形式化方法來分析代碼,但其核心依然是構筑在模式匹配技術基礎之上。

            幾乎在同時,DoctorHousel的博士論文對反編譯進行了較系統的論述,文中描述了一種可行的反編譯方法,并通過實驗驗證了部分理論。Housel的反編譯方法借用編譯器、圖、和優化理論的概念,并據此設計了一種包括部分匯編、分析器、代碼生成等三個主要步驟的反編譯器。然而受限于當時實驗平臺和目標程序,Housel僅僅測試了6個程序。實驗中,有88%的指令可以通過反編譯器自動生成,剩余的指令則需要程序員進行手工干預。這個反編譯器證明,通過使用已知的編譯器和圖的方法,可以實現生成良好高級代碼的反編譯器。中間表示法的使用使得分析完全不依賴機器。這個方法學的主要缺陷在于源語言的選擇,MIX匯編語言,在這些程序中不僅帶有大量可用信息,而且它是一個簡單化的、非現實的匯編語言。

            1974年,DoctorFriedman在他的博士學位論文中描述了一個反編譯器,用于在相同體系結構等級內的小型計算機操作系統的遷移。該編譯器包含四個主要部分:前期處理器、反編譯器、代碼生成器、和編譯器,它是Housel反編譯器的一個改寫版。Friedman在反編譯操作系統代碼的方向上邁出了第一步,而且它例證了在反編譯機器依賴的代碼時反編譯器面對的困難。不足的是,該遷移系統對輸入程序有所要求,即需要對輸入程序做大量格式化工作;同時,該系統最后產生的程序代碼具有較大的空間膨脹率,而代碼膨脹率高又帶來了執行時間和效率的低下。

            1978年,DoctorHopwood所做的工作實現了從匯編語言程序到MOL620語言程序的翻譯功能。他引入了控制流圖的概念,即指定一條指令作為控制流圖的一個節點。與現在廣為采用的以基本塊為節點的方式相比,Hopwood的方案對內存的要求會更高一些。Hopwood的博士學位論文描述了有關其設計的一個包含七個步驟的反編譯器的內容,他的研究的主要缺點是控制流向圖的粒度和在最后的目標程序中寄存器的使用。其中控制流向圖的粒度的使用,導致該反編譯器處理大規模程序的時候開銷太大;而在其所生成的目標高級語言代碼中使用了寄存器,導致反編譯結果并非純正的高級代碼。

            2)花開二朵——反編譯技術在工程上的應用

            20世紀70年代的十年是反編譯技術發展的一個黃金時期,當時的反編譯器并未局限在對高級編程語言的恢復上,而是引入了“翻譯”的特征。在這個時期,除了一些以理論研究為主的反編譯器模型被提出以外,還有一些具有代表性的實用系統被開發出來。

            1974年,由Barbe開發的Piler系統是第一個實現的X型通用反編譯器架構,它的設計目標是實現從多種機器級代碼到與其各自對應的高級語言程序的反編譯。但是這種多源到多目標的反編譯實現起來具有極高的難度,直接導致Piler系統最終實現時,僅能支持從通用公司的Honeywell 600機器代碼到Fortran和COBOL兩種高級語言程序的反編譯。可見,當時的反編譯器如果能夠實現對“翻譯”輸出的高級語言再次編譯,并且編譯后程序的運行結果與反編譯前一致的話,就幾乎相當于一個二進制翻譯器了。

            3)花開三朵——反編譯技術在軍事上的應用

            反編譯技術同樣被軍方慧眼識珠,在上世紀70年代多項軍事應用中可以看到它的身影。

            1974年,Ultrasystems公司的一個反編譯工程中也用到了反編譯器。這個反編譯器作為三叉戟 (Trident)潛艇射擊控制軟件系統的一個文檔編寫工具。它以Trident匯編程序作為輸入,產生這個公司開發的Trident高級語言程序。該編譯器分成四個主要階段:規格化、分析、表達式凝聚和代碼生成。該系統的輸入為經過“規格化預處理”的匯編程序,其目的是為了解決部分指令和數據的區分問題;與此同時,預處理過程還會生成一種中間表示,并對數據進行分析;然后,在表達式凝聚的過程期間,算術表達式和邏輯表達式將被還原并建立;最后,再通過和THLL(Ultra systems公司的名為Trident的高級語言)匹配控制結構,而生成輸出的高級語言程序。

            1978年,D.A.Workman主導了一項有軍方背景的反編譯應用研究,目的是為美國軍方實時訓練裝置系統設計適用的高級語言。該應用在F4型教練機的相關設計中發揮了作用。F4教練機的操作系統是用匯編語言編寫的,因此這個反編譯器的輸入語言是匯編語言。由于這項應用的目標是用于設計,因此沒有確定輸出語言,沒有實現代碼生成,僅僅實現了反編譯器的兩個階段:階段一,把匯編程序映射為一個中間語言并收集關于源程序的統計信息;階段二,產生基本塊的控制流向圖,依據它們的可能類型來劃分指令,并且分析控制流以確定高級控制結構。這項成果的貢獻在于,提出了一種在當時看起來十分獨特的反編譯技術應用。即這個反編譯器,并未以輸出高級語言代碼為最終目的,而是通過把指令分類來進行數據分析。從這一案例,可以看出反編譯技術的先進性在當時得到了美國軍方的認可,并且在實際應用中催生出了代碼分析的功能,值得后續研究的借鑒。

            4)小結

            有了1960年代的技術積累,反編譯技術在高等院校得到了理論和實踐的雙重推進。在理論研究的支撐下,越來越多的實用系統中都使用了反編譯技術。以至于被大家公認的高科技技術集散地的美國軍方,也將反編譯技術投入到軍事訓練和實戰中。因此,在1970年代反編譯技術擁有自己完美的發展期,并獲得了長足的進步。

            3.瓶頸期——20世紀80年代

            之所以將1980年代稱為反編譯發展的瓶頸期,主要是這項技術所能實現的功能的合法性問題。畢竟隨著計算機的普及和發展,軟件知識產權逐步被人們所重視。反編譯技術可以逆向獲得程序源代碼的特性,與軟件知識產權的保護存在著一定的矛盾。如何界定科學研究和非法獲利,一時沒有定論,但是這個十年中,相關研究也沒有完全停滯,仍然有一些具有代表性的工作。

            1) Zebra

            1981年,美國軍方的另一個反編譯實例:美國海軍水下系統中心開發的Zebra樣機試圖實現匯編程序的可移植性。Zebra的主要功能是把ULTRA/32匯編語言的一個名叫AN/UYK-7的子集作為輸入語言,進而產生PDP-11/70的匯編程序輸出。盡管Zebra并不是傳統意義的反編譯器,更像是單純的程序移植和變換,但是該系統的實現方式與反編譯并沒有什么不同,即Zebra的實現主要由三大步驟構成。第一階段,詞匯和流分析:對原程序進行解析,并在基本塊內做控制流分析;第二階段,程序被翻譯為中間形式;第三階段,做中間表示的化簡。

            Zebra利用已知的技術來開發一個匯編程序的反編譯器,整個研發過程并沒有引入新的概念。但是Zebra提出一個觀點值得我們回味,也就是說:從Zebra的研發過程中看出,反編譯應該作為一個工具幫助解決某個問題,而不是完全解決該問題的工具。這個結論,源于科研人員對反編譯的了解而提出的假設,即假如反編譯器不可能達到100%正確。雖然這是一個上世紀80年代初就提出的論斷,但我們仍然可以從中一窺反編譯發展至今的主要作用——程序分析(相關的討論,我們放到相應的章節來具體討論)。

            2)Forth Decompiler

            1982到1984年,Forth Decompiler系統具有一定的代表性。它是一種可以通過遞歸掃描Forth語言編譯字典條目,而把單詞反編譯成原語和地址的一個工具。但是Forth Decompiler并不是一個純正的反編譯器,它更像是一個逆語法分析工具,該工具遞歸地掃描一個字典表并且返回與給定單詞有關的原語或地址。

            3)STS(SoftwareTransport System)

            1985年,C.W. Yoo介紹了軟件傳輸系統STS (SoftwareTransport System),實現匯編代碼從一機器到另一機器的自動轉換。STS的轉換思路是:將機器m1的匯編代碼反編譯成高級語言程序,然后將獲得的程序在機器m2上編譯成新的匯編代碼。一個實驗型的STS系統是針對Z-80處理器而研發的C語言交叉編譯器,但是由于STS系統缺少數據類型信息導致此項目擱淺。

            4)Decomp

            1988年,Reuter編寫了一套反編譯器,并命名為Decomp,它是一種專用于Vax BSD 4.2機器的反編譯器。Decomp需要帶有符號信息的目標文件作為反編譯的輸入,而通過反編譯生成類C源碼程序,部分輸出的C源碼經過手工編輯后可以被再次編譯。Decomp做了一件今天看起來十分有趣的事情,也就是它為了一款游戲而生,它在沒有可用源代碼的情況下把帝國游戲(Empire)移植到VMS環境。這件事情與筆者目前從事的二進制翻譯相關研究非常類似,即實現了應用程序級別的移植,并以游戲這種生動的形式加以展示。

            Decomp反編譯器在當時的條件下,花費了大概5人月的工作量,并且可以從因特網上免費獲取它。昆士蘭大學的Cristina Cifuentes在她的博士論文中,成功地重現了Decomp的反編譯過程。從實驗中可以看出,Decomp反編譯生成的程序有正確的控制結構、正確的變量數據類型、庫例程和子過程的名字,甚至用戶程序入口點也得到了還原。當然上述功能的取得,都需要滿足一定的先決條件,但僅從功能上來看,Decomp是一個又實用價值的反編譯器。

            5)小結

            經過20年的技術積累,1980年代本來應該成為反編譯技術的爆發期,但是由于它天生的逆向屬性,導致其與軟件知識產權的保護產生了矛盾。在法律監管的空白時間里,并沒有產生一些讓我們記憶猶新的優秀系統和應用。整個1980年代的研究延續了不溫不火的態勢,但是對反編譯完備性的討論和實用化的驅使,仍然使得這個方向的研究延續下來。這個10年的研究比1970年代更注重實用性,并從專用這個角度加以體現。

            4.反編譯的春天——20世紀90年代

            1990年代,反編譯技術作為一個主體終于有了可以依據的法律——許多國家針對軟件逆向工程進行立法,以規范該領域的研究工作。從一篇美國研究者Pamela Samuelson的文章“Reverse-engineering SomeoneElse's Software: Is It Legal?”中,可以重現當時美國對“反編譯”這一類技術的法律定義:根據美國聯邦法律,對擁有版權的軟件進行逆向工程操作,例如反匯編、反編譯,若其目的不是通過剖析原軟件,來研制新產品與之竟爭,所進行的逆向操作是合法的。仔細品味這句話可知,只要是非盈利性的軟件分析和源代碼獲取是被允許的。在上述背景下,反編譯技術迎來了發展的春天,一批國家層面的綜合性研究項目代表了反編譯在當時的地位,比如:由11個歐洲工業和學術組織合作研究的REDO計劃,主要是以調查研究軟件的維護、有效性和軟件系統文檔化為目標。他們在軟件逆向工程研究主題下對反編譯進行了大量研究,從邏輯語義上給出反編譯的一些實現方法和本質描述,并將其結果應用于英國核工業部。既然春天來了,除了上述枝葉返青的參天大樹,哪能沒有百花齊放呢?我們再把1990年代的反編譯發展脈絡梳理一下。

            此外,在這個十年中,反編譯這項技術與另外一項稱作“二進制翻譯”的技術結合的越來越緊密。反編譯技術作為二進制翻譯的一種重要實現方式,我們將在后文詳細介紹二者的聯系和區別,同時也會花一定篇幅,著重揭開一下能夠體現反編譯技術實用性的“二進制翻譯”的神秘面紗。

            1) Exe2c

            1990年,由AustinCode Works公司推出的實驗項目Exe2c可以將Intel80286/DOS可執行程序反匯編,并轉換為內部格式代碼,最終轉換成C程序。從Exe2c的輸出代碼看出,它并沒有實現數據流分析,而僅僅實現了部分控制流分析。C語言使用的一些控制結構被恢復,如:if-then和循環。它生成的C語言程序的大小是匯編程序的3倍。這個反編譯器的積極意義在于,它是在過去的若干年中第一個嘗試反編譯可運行文件的反編譯器。其成果表明,為了產生更好的C代碼需要引入一個較為完善的數據流分析和啟發式功能。而且,建立一個忽略所有由編譯器引進的外來代碼和發現庫子程序的機制會很有幫助。這一點可以大大降低反編譯的工作量,同時提升反編譯輸出的可用性。

            2) PLM-80 Decompiler

            1991年研發的PLM-80Decompiler反編譯器也是一款具有國家支持和軍事應用背景的軟件,它是澳大利亞國防部的信息技術司研究的一個反編譯的國防應用,也是在“反編譯的春天”里值得一提的一項研究。PLM-80Decompiler研發的主要目的是針對廢棄代碼的維護、具有科技情報產品的分析、以及針對信息系統的安全和保密風險的評估,其中除了第一點以外,其它的目的都與反編譯在當今時代的需求所契合,可見該項目在當時是具有前瞻意義的一項研究。

            雖然研發目標具有重要意義,但最終由于技術實現的難度,PLM-80Decompiler只實現了一個樣機。該樣機是用Prolog語言編寫的,針對特定機器PLM-80編譯器編譯的Intel 8085匯編程序,可以產生一種稱作“Small-C語言”的目標程序(Small-C代表所生成的代碼是標準C語言的子集)。從公開可以查閱的文獻中,可以了解到PLM-80Decompiler可以從輸入的匯編程序中識別出部分if..then和while()等簡單結構,可以還原一些int和char等簡單的數據類型,以及一些全局和局部變量。除此之外,PLM-80Decompiler還設計了一個圖形化用戶界面用于顯示匯編程序和偽C程序,并且用戶還可以通過圖形界面編輯變量的名字、增加注解,以及支持手工確定主程序的入口點等功能。

            總的來說,PLM-80Decompiler所做的分析局限于控制結構和簡單數據類型的識別,并沒有引入針對寄存器使用的分析。同時,該反編譯器也不支持分析編譯器生成的優化代碼。但值得稱道的是,PLM-80Decompiler對圖形界面的引入,是對用戶體驗的一次提升,也是對反編譯這種需要人工反饋參與工作的一種新的支持手段。

            3) 8086 C Decompiling System

            1991年推出的8086C Decompiling System是一個將Intel 8086/DOS可執行程序翻譯成C程序的反編譯器。它實現了庫函數的識別以減少生成代碼的量,同時它基于規則識別出了數組和結構體的指針等數據類型。不出意外的是,這個反編譯器同樣對輸入文件有特殊的要求——輸入文件必須是由Microsoft C V5.0版本小存儲器模型編譯所生成的。這一點再一次印證了:一個反編譯器的可用性受限于它對源編譯器的依賴。多數反編譯器只能針對特定的編譯器類型(或者編譯器版本)完成正確的反編譯動作。

            8086 C Decompiling System描述了五個階段:庫函數的識別、符號執行、數據類型識別、程序轉換和C語言代碼生成。

            該系統在庫函數識別階段所做的工作具有一定代表性,很多反編譯器和后來的二進制翻譯器都采用類似的方法。有必要單獨說明一下:8086 C DecompilingSystem主要實現了對Microsoft C庫函數的識別,用來區分哪些是系統調用的庫函數,哪些是用戶自己編寫的函數。這么做的目的是為了在反編譯時只處理用戶函數,生成相應的C代碼,而所有庫函數則不必被反編譯。識別庫函數是通過模板匹配的形式完成,即預先構造一個所有C語言的庫函數表,包含一些特殊信息,這部分工作是反編譯器作者手工實施的。

            除了庫函數識別階段以外,該反編譯器其余階段的實施中規中矩。它的符號執行是將機器指令完全用特有符號來表示,形成一套中間指令;而對數據類型的識別則是通過兩套規則配合來實現的,即首先通過一組規則對于不同數據類型進行信息收集,然后再根據所收集的信息和另外一組分析規則共同確定數據類型;程序轉換則把存儲計算轉變成各種地址表達式,例如數組尋址;最后,C語言代碼生成器通過識別控制結構,繼而轉換成相應的程序結構,并且生成C語言代碼。

            8086 C Decompiling System是由我國合肥工業微機所科研人員開發的一套較早的反編譯系統,代表了當時我國的反編譯研究的方向和水平。

            4) Alpha AXP Migration Tools

            數字裝備公司(Digital Equipment Corporation)在設計Alpha AXP體系結構的時候,需要能夠在“新”的Alpha AXP計算機上運行“現有”的VAX和MIPS代碼。正是由于這個動議,使得Alpha AXP MigrationTools作為一套可以完成上述功能的二進制翻譯工具被開發出來。Alpha AXPMigration Tools可以實現舊體系結構的指令序列轉換成新體系結構的指令序列,即實現不同體系結構間二進制級代碼的無縫移植。這個移植過程中被開發者定義成兩個部分,分別是:二進制翻譯過程和運行時環境。為了保證二進制翻譯過程的全自動執行,同時能夠實現執行期間創建或修改代碼的功能,該移植工具在二進制翻譯部分使用了反編譯技術。

            Alpha AXP Migration Tools中反編譯技術的應用,主要體現在機器指令的潛在含義理解和分析上。例如:原體系結構上的條件碼分析,以便后續翻譯過程中可以轉化為Alpha體系結構上的相應操作;通過代碼分析,確定函數的返回值或者發現代碼中的錯誤;MIPS中標準庫例程的發現和定位,以減少代碼翻譯的工作量,因為庫例程絕大多數情況下是可以在新體系架構中找到類似庫函數實現其功能的;發現代碼中的“成語”(可以理解為在特定體系結構上,完成特定功能的一組指令序列),并使用目標體系結構中功能等價的指令組合來實現該“成語”的功能。通過上述一系列的分析工作,以及其他翻譯工作,最終以AXP操作碼的形式組成翻譯后的二進制編碼,并由運行時環境執行翻譯的代碼。

            這個工程舉例說明在一個現代翻譯系統中反編譯技術的使用。證明對于眾多類別的二進制程序來說它是成功的。一些無法翻譯的程序是在技術上不可翻譯的程序,比如使用特權操作碼的程序或者以超級用戶特權運行的程序。

            5) 其它反編譯器產品和研究

            在這一階段還有眾多公司紛紛推出自己的反編譯器產品,具體情況如表所示。

            表1 20世紀90年代部分反編譯器產品

            產品名稱 年份 用途 廠商
            Valkyrie 1993 用于 Clipper Summer '87 的可視化反編譯器 CodeWorks
            OutFox 1993 用于加密的FoxBASE+程序的反編譯器 不詳
            ReFox 1993 用于反編譯加密的FoxPro文件 Xitech
            DOC 1993 用于 AS/400 和 System/38 的COBOL反編譯器 Harman Resources
            Uniclip 1993 用于 Clipper Summer '87 EXE 文件的反編譯器 Stro Ware
            Clipback 1993 用于Summer '87 可執行文件的反編譯器 Intelligent Information Systems
            Brillig 1993 用于 Clipper 5.X .exe文件和.obj文件的反編譯器 APTware

            同時也有一批大學的實驗室,發表自己的試驗系統,其中在這一領域Cifuentes博士的研究成果,成為以后反編譯研究的主要參考方向。Cifuentes在自己的博士論文中指出,可以通過數據流分析識別參數和返回值,通過控制流分析將代碼恢復成具有結構的C程序。研究型反編譯器dcc展現了她的工作,但它只能處理很小的Intel 80286/DOS可執行程序。

            在dcc的基礎上,反編譯器REC(Reverse Engineering Compiler)基于Cifuentes的工作在幾個方面進行了擴展,但是它生成的類C程序比較難讀,因為包含了寄存器符號。它可以處理多個處理器(如:Intel 386、Motorola 68K)上運行的多種格式的可執行文件(如:ELF和Windows PE等)。像數組等復雜的數據類型保留為訪問內存的表達式。

            5.持續的研究——進入21世紀

            時間荏苒,當歷史的腳步進入新世紀,反編譯的相關研究也隨之更進一步,本節我們將用簡單的筆觸介紹2000年后的相關研究和商用產品。

            2001年,Guilfanov介紹了IDA Pro反匯編器使用的類型傳播系統,并著重講解了庫函數的識別工作。IDA Pro利用庫函數的簽名信息來恢復庫函數調用語句使用的參數的數據類型,然后使用類型傳播技術處理賦值語句來進行數據類型恢復。上述事實說明,沒有一種數據類型恢復不是根據庫函數類型信息進行的。

            2002年,Morisada發布了處理32位Windows可執行程序的反編譯器Anatomizer。對某些Windows可執行程序它表現的很出色,可以恢復參數和返回值,條件語句和switch語句也得到了很好的處理。當使用Anatomizer處理Cygwin程序時,庫函數printf無法被恢復。另外,Anatomizer無法處理浮點指令和間接調用,數組仍然被保留為訪問內存的表達式。當寄存器在某些過程體中未被定值而先使用時,它無法將其識別成參數。反編譯器Anatomizer經常會異常終止。

            2002年,Tr?ger和Cifuentes給出一個分析間接調用指令的方法。如果由虛函數產生的間接調用被成功識別,那么關于此間接調用的諸多信息都會獲得。然而,此方法受限于一個基本塊的范圍,導致無法處理所有的情況。

            2004年,RaimarFalke基于Mycroft的理論并進行擴展開發了反編譯器Yadec,用于恢復數組數據類型。但需要一個相當于用戶抉擇的文件來處理沖突。

            2004年,由AndreyShulga編寫的反編譯器Andromeda一直沒有公開發行,但從網站可以獲得一個GUI程序對應反編譯生成程序。生成程序給人的印象非常深刻,但不能僅憑一個反編譯生成程序來斷定反編譯器的優劣,可能它恢復出的數據類型是經過手工編輯的。

            2007年,IlfakGuilfanov發布一個集成反匯編器IDA Pro的反編譯器Hex-Rays,用來處理32位Windows可執行程序。反編譯器Hex-Rays可以在窗口中展示反編譯生成的類C代碼,通過點擊函數名跳到函數體視窗。所有函數的參數和返回值都得到了恢復,但作者聲明反編譯生成的程序僅用于閱讀,不能對其進行編譯。

            遺憾的是,2008年后國外與反編譯緊密的相關的重要研究很難再被檢索到。筆者分析,其主要原因是反編譯本身的復雜性,不完備性,以及在逆向分析實踐中不如反匯編實用的現實所造成的。此外,虛擬化技術的日漸成熟,也分化了相當一部分使用反編譯形式進行二進制翻譯的研究資源。

            6.身邊的反編譯——我國對反編譯的研究

            國內從事反編譯方面研究的團隊較少,能夠在公開報道中查證的有:從1984年開始,合肥工業大學微機所開展了一系列與反編譯相關的研究工作:在國家自然科學基金的資助下,以Dual-68000為硬件平臺,研制T 68000 C反編譯系統;用手工的方法反編譯了UNIX操作系統部分組件;七?五期間,他們還進行了8086 C語言反編譯系統的研究;隨后,他們還發布了商業化的反編譯系統DECLER V1.0和V1.1。1991年發表的文獻中提及,武漢大學從1986年起就開始研制VAX機上的C語言反編譯系統。同年發表的另外一篇文獻中提及,北京控制工程研究所在PC機上開發TC語言反編譯系統。1992年,上海交通大學的科研人員也發表了關于VAX機器上C語言反編譯系統研究與實現的論文。1994年哈爾濱工業大學的研發團隊開發了一款基于Turbo C的小模式反編譯系統。2001年,解放軍信息大學開始研發ITA二進制翻譯系統(歷時五年),該系統可以實現將IA64/Lunix架構下由C語言編制的可執行程序反編譯到SW/Lunix下執行。2006年,北京大學計算機科學研究所研發了匯編級別的分析工具BESTAR。該工具實現了Linux平臺上的輕量級匯編代碼結構化表示功能,它能夠實現利用控制流和數據流分析技術識別通用控制結構。該工具還可以分析程序執行流,重構表達式和函數,發現數據依賴關系,將匯編代碼轉換成一個結構化、易理解的中間語言程序。

            當然前文還提到了8086 CDecompiling System也是國內非常重要的研究和工作,尤其8086 C Decompiling System還在Cifuentes的論文中被提及。

            最后 ,致謝 小楠楠,借鑒了他大段文字。經過博士論文撰寫,發現你文筆水平大增啊!

            <span id="7ztzv"></span>
            <sub id="7ztzv"></sub>

            <span id="7ztzv"></span><form id="7ztzv"></form>

            <span id="7ztzv"></span>

                  <address id="7ztzv"></address>

                      亚洲欧美在线