簡體   English   中英

PE文件操作碼

[英]PE file opcodes

我正處於編寫PE文件解析器的過程中,我已經達到了解析和解釋PE文件中的實際代碼的程度,我假設它存儲為x86操作碼。

例如,DLL中的每個導出都指向函數將存儲在內存中的RVAs(相對虛擬偏移),並且我編寫了一個函數來將這些RVA轉換為物理文件偏移。

問題是,這些是真正的操作碼,還是其他的?

是否依賴於編譯器/鏈接器關於函數如何存儲在文件中,或者它們是一個還是兩個字節的X86操作碼。

例如,Windows 7 DLL“BWContextHandler.dll”包含四個加載到內存中的函數,使它們在系統中可用。 第一個導出的函數是'DllCanUnloadNow',它位於文件中的偏移0x245D處。 該數據的前四個字節是: 0xA1 0x5C 0xF1 0xF2

這些一個或兩個字節的操作碼是這樣的,還是完全不同的?

如果任何人都可以提供有關如何檢查這些信息的任何信息,我們將不勝感激。

謝謝!

經過一些進一步的閱讀,並通過IDA的演示版本運行文件,我認為我說第一個字節0xA1是一個單字節操作碼,這意味着mov eax。 我從這里得到了它: http//ref.x86asm.net/geek32.html#xA1 ,我認為它暫時是正確的。

但是,我對下面的字節如何構成指令的其余部分感到困惑。 從我所知道的x86匯編程序來看,移動指令需要兩個參數,即目標和源,因此指令是將(某些)移動到eax寄存器中,並且我假設某些內容來自以下字節。 但是我不知道如何閱讀這些信息:)

x86編碼是復雜的多字節編碼,您不能簡單地在指令表中找到單行來解碼它,就像在RISC(MIPS / SPARC / DLX)中一樣。 一條指令甚至可以有16字節編碼:1-3字節操作碼+幾個前綴(包括多字節VEX )+幾個字段用於編碼立即或存儲器地址,偏移,縮放(imm,ModR / M和SIB; moff)。 單個助記符有時會有幾十個操作碼。 而且,對於幾種情況,有兩種編碼可能是相同的asm行(“inc eax”= 0x40和= 0xff 0xc0)。

一個字節的操作碼,意思是mov eax。 我從這里得到了它: http//ref.x86asm.net/geek32.html#xA1 ,我認為它暫時是正確的。

我們來看看桌子:

po; flds; 助記符 op1; op2; grp1; grp2; 描述

A1; W; MOV; eAX; Ov; gen; 數據; 移動;

(提示:不要使用geek32表,切換到http://ref.x86asm.net/coder32.html#xA1 - 具有更少解碼的字段,例如“A1 MOV eAX moffs16 / 32 Move”)

有op1和op2列, http ://ref.x86asm.net/#column_op用於操作數。 A1操作碼的第一個始終是eAX ,第二個(op2)是Ov。 根據表http://ref.x86asm.net/#Instruction-Operand-Codes

O / moffs原始指令沒有ModR / M字節; 操作數的偏移量在指令中被編碼為字,雙字或四字(取決於地址大小屬性)。 不能應用基址寄存器,索引寄存器或縮放因子(僅MOV(A0,A1,A2,A3))。

因此,在A1操作碼之后,存儲器偏移被編碼。 我認為,x86(32位模式)有32位偏移量。

PS:如果您的任務是解析PE而不是發明反匯編程序,請使用一些x86反匯編庫,如libdisasm或libudis86或其他任何東西。

PPS:原始問題:

問題是,這些是真正的操作碼,還是其他的?

是,“A1 5C F1 F2 05 B9 5C F1 F2 05 FF 50 0C F7 D8 1B C0 F7 D8 C3 CC CC CC CC CC”是x86機器代碼。

反匯編很困難,特別是對於Visual Studio編譯器生成的代碼,特別是對於x86程序。 有幾個問題:

  1. 指令是可變長度的,可以從任何偏移量開始。 一些架構需要指令對齊。 不是x86。 如果您從地址0開始閱讀,那么如果您開始在偏移1處讀取,則會得到不同的結果。您必須知道有效的“起始位置”(功能入口點)是什么。

  2. 並非可執行文件部分的所有地址都是代碼。 有些是數據。 Visual Studio將在讀取它們的過程下的文本部分中放置“跳轉表”(用於實現switch語句的數組)。 將數據誤解為代碼會導致產生錯誤的拆卸。

  3. 你不可能擁有適用於所有可能程序的完美dis-assemby。 程序可以自行修改。 在這些情況下,你必須運行程序才能知道它的作用,最終導致“暫停問題”。 您可以期待的最好的解決方案是“大多數”程序。

通常用於嘗試解決這些問題的算法稱為“遞歸下降”拆卸。 它類似於遞歸下降解析器,因為它以已知的“入口點”(exe的“main”方法或dll的所有導出)開始,然后開始反匯編。 在拆卸過程中發現了其他入口點。 例如,給定“調用”指令,目標將被假定為入口點。 反匯編程序將迭代地反匯編已發現的入口點,直到找不到更多入口點。

然而,這種技術存在一些問題。 它不會找到僅通過間接執行的代碼。 在Windows上,一個很好的例子是SEH異常的處理程序。 分派給它們的代碼實際上是在操作系統內部,因此遞歸下降分解將無法找到它們,也不會對它們進行反匯編。 然而,它們通常可以通過增加模式識別(啟發式匹配)的遞歸下降來檢測。

機器學習可用於自動識別模式,但許多反匯編程序(如IDA pro)使用手寫模式並取得了很大成功。

在任何情況下,如果要反匯編x86代碼,則需要閱讀“ 英特爾手冊” 有很多場景需要支持。 根據修飾符,前綴,處理器的隱式狀態等,可以以各種不同的方式解釋指令中的相同位模式。這些都在手冊中有所涉及。 首先閱讀第一卷的前幾節。這將介紹基本的執行環境。 你需要的大部分其他東西都在第二卷。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM