2010-07-07 57 views
1

我想深入瞭解表示和運行程序的低級過程。我決定通過編寫程序來解析和顯示目標文件信息(標題,部分等)。我幾乎完成了這部分。一個自然的擴展是將其餘的相關數據反編譯成彙編指令。最初,我將專注於x86。用於x86反編譯的資源

從哪裏可以找到與此反編譯相關的資源(二進制 - > ASM)?我已經讀過x86與ASM有一對一的對應關係,但我不知道從哪個最佳參考拉動翻譯表。

另外,雖然我在這裏,但我有興趣跟蹤任何提供的調試信息。是否有任何有關此信息格式的參考(讓我們假設ELF和GCC帶-g選項)?

你們有沒有任何一般的建議?這裏的目標是增強我的理解力的實踐項目。

回答

1

x86是可變的指令長度,這意味着非常難以反彙編。如果這是您的第一個反彙編程序,不建議。

說了......我採取的方法是,您必須在二進制文件中標識操作碼第一個字節的字節,並將其與操作碼或數據中第二個或其他字節的字節分開。一旦您知道可以從二進制文件的開始處開始並反彙編操作碼。

喲如何找出其他字節的操作碼?你需要遍歷所有可能的執行路徑,聽起來像遞歸問題,可能並不是必須的。查看中斷向量表和/或代碼中的所有硬件入口點。這給你一個操作碼字節的簡短列表。非遞歸方法是在二進制文件上進行許多遍歷,查看標記爲操作碼的每個字節,對其進行解碼就足以知道它消耗了多少字節。您還需要知道它是否是無條件分支,條件分支,返回,調用等。如果它不是無條件分支或返回,則可以在該指令之後假定該字節是下一條指令的第一個字節。每當遇到某種分支或調用時,計算目標地址,將該字節添加到列表中。繼續進行傳球,直到你完成一個沒有添加新字節的傳球。你還需要確保如果說你發現一個字節是一個3字節的指令,但是它之後的字節被標記爲一條指令,那麼你就有問題了。諸如有條件的分支之類的東西確保它們永遠不會分支。如果高級代碼編譯爲二進制文件,但是手寫彙編程序的好時代,或者想要保護其代碼的人會做這樣的事情,您看不到這麼多。

不幸的是,如果你所擁有的是二進制,對於一個可變長度的instruciton集,你不會得到一個完美的反彙編。一些分支目的地是在運行時計算的,有時候手動編譯的程序集會在返回之前修改堆棧,然後再更改接下來執行的代碼,如果這是代碼的唯一路徑,那麼您可能不會編程計算出來,除非您儘可能來模擬代碼。即使使用模擬,你也不會涵蓋所有的執行路徑。

對於像ARM這樣的固定長度的指令集(只要它是手臂而不是手臂和拇指的混合),你可以簡單地從二進制的開始處開始並拆卸,直到用完字。您可能會將數據字反彙編爲有效或無效或不太可能被使用的指令,但這很好。

我不會感到驚訝,如果在精靈的某個地方有什麼指示二進制文件的哪些部分是可執行的,哪些部分是數據。也許甚至是你不必走數據路徑,我懷疑objdump執行一個任務,就像它可能使用了elf文件中的東西。

許多地方都記載了elf文件格式。有基本的結構,供應商可以添加供應商記錄的特定塊類型。

+0

很好的答案!非常感謝您抽出時間來貢獻 – 2010-10-02 20:46:17

1

看看我的虛擬機教程:http://www.icemanind.com

它教你一步一步如何建立自己的虛擬機和彙編。通過閱讀和教程完成課程,你將有怎樣的程序,彙編語言和二進制作品

以更加堅定的把握