反組譯器(disassembler)是一種將機器語言轉換為匯編語言電腦程式——這與組譯器的目的相反。反組譯器與反編譯器不同,反編譯器的目標是高階語言而非匯編語言。反組譯器的反組譯輸出通常格式化為適合人類閱讀,而非用作組譯器的輸入源,因此它主要是一個逆向工程工具。

匯編語言原始碼通常允許使用常數和程式設計師註釋,而這些通常會在組譯器組譯的機器語言中被移除。因此,以機械碼為基礎完成的反組譯結果將沒有這些常數和註釋,閱讀輸出結果將比閱讀原始碼更有難度。一些反組譯器提供了內建的代碼註釋功能,其生成的輸出增補了有關被呼叫API函數或被呼叫函數參數的註釋。一些反組譯器會利用對象檔案(例如ELF)中存在的符號除錯英語Symbolic debugging資訊。例如,IDA允許人類用戶在互動式對談中為代碼的值或區域標記輔助記憶碼號。

反組譯不是一門精準科學:在有可變寬度指令的複雜指令集(CISC)平台上,使用操作碼英語Opcode級編程或存在程式自修改代碼時,單個程式可能有兩個或多個合理的反組譯結果。程式在執行期間決定實際執行哪個指令被歸約停機問題,這是已知無法解決的問題。

反組譯的問題

編輯

編寫一個反組譯器,使其產生的代碼在組譯時與原始二進制檔案完全一樣是可能的;但是,往往這兩者之間會有差異。這就對組譯器的表達能力提出了要求。例如,一個x86組譯器對哪怕像MOV AX,BX這樣簡單的事情,都要在兩個二進制代碼中任意選擇一個。如果原始代碼使用的是另一種選擇,那麼原始代碼在任何的時間點上都不能被反組譯器生成。然而,即使產生了一份完全正確的反組譯代碼,如果需要修改程式,那麼問題仍然存在。例如,同樣的機器語言跳轉指令可以由跳轉到一個指定的位置(例如,執行特定的代碼),或者跳轉指定的位元組數(例如,跳過一個不需要的分支)的組譯代碼生成。反組譯器不知道目的是什麼,它可以使用任何一種語法來生成一個重現原始二進制的反組譯。然而,如果程式設計師想在跳轉指令和它的目標之間增加指令,就必須了解原程式的操作,以確定跳轉應該是絕對的還是相對的:也就是說,它的目的地應該被保持在一個固定的位置,還是被移動以便跳過原來的和增加的指令。

反組譯的例子

編輯

反組譯器可能獨立執行,也可能互動操作。獨立的反組譯器被執行時將生成可以查閱的匯編語言檔案;互動式反組譯器則立即顯示用戶所做更改的結果。例如,反組譯器起初可能不知道程式的某一部分是代碼,而將其視為數據;如果用戶將其指定為代碼,則可立即顯示據其所生成的反組譯代碼,從而使用戶儘快查閱和採取進一步行動。

任何互動式除錯工具都包含一些檢視被除錯程式的反組譯結果的方法。通常,相同的反組譯工具會被打包成單獨的反組譯器,與除錯器分開發布。例如,objdumpGNU Binutils的一部分,而它與互動式除錯器gdb相關。[1]

反組譯器和仿真器

編輯

動態反組譯器可以併入到一個仿真器管理程式的輸出中,從而步進、逐行執行要即時執行的機器指令。在此情況下,其包含反組譯後的機械碼行,以及可顯示每條指令所引發的暫存器和/或數據改變(或者其他任何狀態英語State (computer science)的改變,例如有條件代碼),各個指令的變化都可以在反編譯後的指令旁邊或下方顯示。這從而提供了極為強大的除錯資訊,有助於最終解決問題,儘管這些資訊有時可能非常大,尤其是如果程式很活躍。

參見

編輯

參考資料

編輯
  1. ^ Archived copy. [2022-01-25]. (原始內容存檔於2022-01-08). 
  2. ^ Archived copy. [2022-01-25]. (原始內容存檔於2022-01-24). 

拓展閱讀

編輯
  • L. Vinciguerra, L. Wills, N. Kejriwal, P. Martino, and R. Vinciguerra, "An Experimentation Framework for Evaluating Disassembly and Decompilation Tools for C++ and Java", Proc. of 10th Working Conference on Reverse Engineering (WCRE) 2003.
  • B. Schwarz, S. Debray, and G. Andrews, "Disassembly of Executable Code Revisited", Proc. of 9th Working Conference on Reverse Engineering (WCRE), pp. 45–54, 2002.

外部連結

編輯