簡體   English   中英

如何識別內存中的匯編“調用”指令?

[英]How to recognize an assembly “call” instruction within memory?

在進程的可執行存儲器中,如何區分匯編“調用”指令(E8 [地址])的操作碼與其他E8字節(例如,位於另一條指令中間的字節)? (最好是從C語言的角度來看)

驗證緊隨E8字節之后的四個字節是否指向有效地址是否足夠,然后驗證該區域(即被調用函數的開頭)是否以對應於操作碼“ push ebp”和“ mov ebp”的字節開頭,esp”(大多數功能使用此序言)? 還是有更好的選擇,例如檢查從入口點到出口點的每個操作碼?

順便說一下,我幾乎沒有這個主題的經驗,因此可以提供任何信息。

謝謝!

正確的解釋從一個已知的指令開始的地址開始。

(當然,此答案適用於具有可變長度指令的處理器,例如Intel的x86架構。)

處理器解釋指令時,它總是在特定位置開始解釋,因為:

  • 它是先前解釋的指令之后的下一個位置,
  • 它是跳轉指令(包括陷阱返回和其他特殊指令)的目標,
  • 它是處理器初始化時的初始起始位置,或者
  • 它是用於控制系統的中斷表或其他特殊數據結構中的地址。

所有這些都是已知的指令開始位置,因為它們是這樣設計的:我們編寫軟件,而這些位置就是我們放置指令的位置。

在解釋指令時,處理器遵循有關指令編碼的規則。 它查看第一個字節,該字節中的位指示接下來的幾個字節是當前指令的操作碼,修飾符還是操作數。 然后,它相應地解釋下一個字節。 因此,在指令的第一個字節的E8 16將受到不同從E8 16字節別處解釋。

反匯編程序在用戶指​​示的地方開始。 通常,它是由程序中的標簽給定的地址(例如函數的名稱)或其他信息,例如當前程序計數器的值或在堆棧上找到的返回地址。 這些地址都是指令的開頭,因此反匯編程序以與處理器相同的方式解釋字節。

有時,人們可能無法輕松訪問有關特定區域中指令從何處開始的信息,並且可能只是告訴反匯編程序在區域中間的任意地址開始反匯編。 在這種情況下,前幾條反匯編指令很可能是錯誤的,因為反匯編程序正在解釋通常不是指令起始位置的字節開始的字節。 (一個常見的示例是,正在調試並且知道當前程序計數器,但是想要向后看最近的十幾條指令,而不必從當前例程的開頭開始。在這種情況下,可能會告訴反匯編程序從當前程序計數器開始反匯編100個字節。)但是,經常發生的是,基本上是偶然的,其中一條被錯誤解釋的指令恰巧以適當的指令開始的地方結束。 然后,反匯編程序正確地反匯編該指令,並與正確的指令序列同步,其余的反匯編則正確進行。 只要大多數指令簡短且指令長度相差很大,那么在少數指令中很有可能會發生這種情況。

可以使用指令編碼,並根據要在其中開始執行的位置來編寫表示兩個不同指令流的字節序列,以便一個流的操作碼字節為另一個的修飾符/操作數字節,反之亦然。 這在常規編程中沒有完成,但是證明了指令字節的解釋取決於起始位置。

反匯編x86等可變長度指令集以及許多其他指令集,您必須從已知的良好入口點開始,並按執行順序進行反匯編,而不必線性執行。

不能保證該方法能正常工作,因為通常使跳開反匯編程序並導致其失敗很容易。

一個簡單的例子,有很多方法可以做到這一點。

set flag
blah
blah
jump if flag to hello
put the first opcode byte but not the rest of the instruction here as data
hello:
real stuff here

我傾向於跟蹤每條指令的第一個字節的位置,然后跟蹤指令中哪些字節是附加的,因此對於路徑或分支之后的每條指令,可以先檢查是否已經到達該路徑,如果第一個字節位於非第一個字節的頂部,則返回第二個。 這可能是使匯編程序絆倒的完全有效的手工代碼,也可能是您在其他地方絆倒的其他原因。

除非設計成或被告知傾向於不編寫具有反匯編問題(按執行順序不是線性的)的代碼,否則編譯器。 但是,如果您回過頭說反匯編經典的視頻游戲rom,您可能會發現這類反匯編問題,然后必須做更多的工作(主要是代碼分析)來確定哪個執行路徑正確。

固定長度的指令集,具有已知的對齊方式,您可以從幾乎任何地方線性分解,您必須容忍未知的指令,因為當您訪問數據部分時,您會看到很多東西,但是您可以采取不處理的捷徑與執行順序。

暫無
暫無

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

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