題:
Ida Pro:使用Idapython解析複雜的操作數表達式
langlauf.io
2015-06-01 19:00:03 UTC
view on stackexchange narkive permalink

在Ida Pro中給出以下代碼:

  mov [rsp + 3F8h + var_3F8],0  

如何解析和訪問 [] 中的項目?我嘗試過什麼:

  • idc.GetOpnd(addr,n)#返回字符串' [rsp + 3F8h + var_3F8] '
  • idc.GetOperandValue(addr,n)#返回 4 ,具體說明請參見 idc.py文件如下

def GetOperandValue(ea,n):“”“
獲取操作數中使用的數字

此函數返回操作數中使用的立即數

@param ea:指令@param的線性地址n:操作數

@return:

值操作數是立即數=>立即值

操作數具有位移=>位移

操作數是直接存儲器ref =>存儲器地址

operand是一個寄存器=>寄存器編號

operand是一個寄存器短語=>短語編號

否則=> -1 “”“

如何訪問“短語”的元素,即 rsp 3F8h 和 var_3F8 ?我正在尋找這樣的東西:

  my_op_phrase = idc.ParseOperandPhrase(ea,n)my_op_phrase [0]#->'rsp'my_op_phrase [0] .type#-> idaapi.o_regmy_op_ase [1]#-> 0x3F8hmy_op_phrase [1] .type#-> idaapi.o_immmy_op_phrase [2]#->'var_3F8'...  

這是否可能還是我誤會了? / p>

二 答案:
Guntram Blohm supports Monica
2015-06-01 19:17:14 UTC
view on stackexchange narkive permalink

請注意,原始彙編指令可能是 mov [rsp + 4],0 (*)。這就是為什麼 idc.GetOperandValue 返回4的原因。

尤其是對於較舊的編譯器,這些編譯器經常使用 push pop ,在執行函數期間, rsp 的值變化很大。現在, esp + 8 現在是 esp + 12 ;彈出後,現在 rsp + 8 現在將是 rsp 。因此,在讀取一段(普通的)彙編代碼時,很難跟踪何時訪問哪個堆棧位置。

(最近有所改善; x64 abis使用寄存器來傳遞參數,因此代碼不會不再需要 push pop ,並且像 gcc 這樣的編譯器會在堆棧上留出足夠的空間,並將參數直接放在相對於的地址中> esp 甚至在32位上也是如此,因此 esp / rsp 不再有太大變化了,但是仍然有很多舊的代碼需要反轉。

為改善這種情況,IDA將變量名稱分配給堆棧位置,例如您的 var_3F8 。每當指令執行某些 sp 相對尋址時,IDA就會使用變量名稱,並發出一個額外的偏移量以說明自函數啟動以來對堆棧指針的更改。因此,如果您的原始代碼是

  mov [rsp + 8],raxsub rsp,128mov [rsp + 136],rbxpush rcxmov [rsp + 144],rdx  

在每種情況下都訪問相同的內存地址。 Ida將其轉換為

  mov [rsp + 0 + var_8],raxsub rsp,128mov [rsp + 128 + var_8],rbxpush rcxmov [rsp + 136 + var_8],rdx  

但是,這些更改僅顯示,它們不會更改您的二進製文件!獲取操作數仍將返回 8 136 144 ,而不是ida向您顯示的值。

如果要自動分析此問題,可以任一自己跟踪堆棧指針的偏移量,並相應地調整或的結果/ em>您將必須在 GetOpnd 的輸出上使用python字符串函數,丟棄中間部分,然後比較右側部分(變量名稱)。

(*)現在我想起來似乎有點奇怪,因為您顯然使用的是64位,因為您的堆棧指針是 rsp ,暗示8字節對齊。

這是您所指的“當前堆棧增量”嗎?可以用`GetSpd`來檢索。
@Guntram Blohm:您確定`GetOperandValue()`返回4的原因嗎? idc.py說:“操作數是一個註冊短語=>短語編號”。我的理解是:“如果有一個寄存器'phrase',`GetOperandValue()`返回* phrase number *。“我不知道這個“短語號”是什麼意思。你怎麼看?
我目前無法訪問安裝了IDA的辦公室計算機,但是我假設`register statement'與`register name'幾乎相同,因此為每個處理器寄存器分配一個數字,然後ida返回如果操作數是寄存器名稱,則該數字,或者類似的表示外來硬件上的寄存器的名稱。
Jason Geffner
2015-06-01 19:22:44 UTC
view on stackexchange narkive permalink

假定 addr mov [rsp + 3F8h + var_3F8],0 的EA:

  re.findall('\ [(。*)\]',idc.GetDisasm(addr))[0] .split('+') 

產生列表

  ['rsp','3F8h','var_3F8']  
這一直有效,直到您遇到減法或乘法,例如`mov edx,[eax + ecx * 4]`。正則表達式在這裡並不是一個很好的選擇,但是不幸的是,它似乎並沒有像IDA那樣給我們帶來很多選擇。
_“這有效,直到您進行減法或乘法運算為止” _-是的,但這不是要問的問題:)
@JasonGeffner **(a)**易於執行正則表達式GetOpnd(ea,0)==`[rsp + 3F8h + var_3F8]`**(b)**如何獲取var_x的值(* guessable *)和arg_x(*不太多)**(c)**在這種情況下(* register +置換*)如果GetOpType(ea,1)== o_displ else None` ==則只是GetOperandValue(ea,1)。 `48`。
@Polynomial:可以通過`GetOpnd(ea,1)== o_phrase`來檢測該操作數的類型,它可能是唯一要使用正則表達式的操作數,除了可能用於o_displ。雖然,由於無法將其解析為實際值,所以它可能永遠不會成為問題。


該問答將自動從英語翻譯而來。原始內容可在stackexchange上找到,我們感謝它分發的cc by-sa 3.0許可。
Loading...