使用VS反彙編除錯
查找出錯誤的函式
查詢函式內某個出錯引數
2. 適用情況
比較適合於使用第三方庫或者其他dll檔案時,無法進入使用函式內部的情況。
3. 注意點:
call函式:函式的返回值能夠反映函式呼叫情況,如果出錯,則一般為函式返回值異常,函式返回值存放於EAX中。
出錯程式碼:VS中函式執行完成後會返回出錯程式碼,出錯程式碼可能為巨集定義值,此時可以結合原始碼(如果有的話),IDA反彙編出dll,具體一一對應。
彙編檢視跳轉:如果判定條件為≥,那麼在彙編中的跳轉指令可能是<。
4. 基礎知識:
1) 指令
ret:跳轉會呼叫函式的地方。對應於call,返回到對應的call呼叫的下一條指令,若有返回值,則放入eax中;
xor:異或指令,這本身是一個邏輯運算指令,但在彙編指令中通常會見到它被用來實現清零功能。用xor eax,eax這種操作來實現mov eax,0,可以使速度更快,佔用位元組數更少。
lea:取得第二個引數地址後放入到前面的暫存器(第一個引數)中。lea也同樣可以實現mov的操作,例如: lea edi,[ebx-0ch],方括號表示儲存單元,也就是提取方括號中的資料所指向的內容,然而lea提取內容的地址,這樣就實現了把(ebx-0ch)放入到了edi中,但是mov指令是不支援第二個運算元是一個暫存器減去一個數值的。
stos:序列儲存指令,它實現把eax中的資料放入到edi所指的地址中,同時edi後移4個位元組,這裡的stos實際上對應的是stosd,其他的還有stosb,stosw分別對應1,2個位元組。
jmp:無條件跳轉指令,對應於大量的條件跳轉指令。
jg:條件跳轉,大於時成立,進行跳轉,通常條件跳轉之前會有一條比較指令(用於設定標誌位)。
jl:小於時跳轉。
jge:大於等於時跳轉。
cmp:比較大小指令,結果用來設定標誌位。
彙編跳轉指令記憶
比較數目大小的 J == jump 比較標誌位的 C == Carry(進位) |
表 測試標誌位的JCC指令
指 令 |
描 述 |
條 件 |
別 名 |
相 反 指 令 |
||
JC |
如果進位位被置位則跳轉 |
進位標誌=1 |
JB,JNAE |
JNC |
||
JNC |
如果進位位沒有置位則跳轉 |
進位標誌=0 |
JNB,JAE |
JC |
||
JZ |
如果0標誌被置位則跳轉 |
0標誌=1 |
JE |
JNZ |
||
JNZ |
如果0標誌沒有置位則跳轉 |
0標誌=0 |
JNE |
JZ |
||
JS |
如果符號位被置位則跳轉 |
符號標誌=1 |
JNS |
|||
JNS |
如果符號位沒有被置位則跳轉 |
符號標誌=0 |
JS |
|||
JO |
如果溢位標誌置位則跳轉 |
溢位標誌=1 |
JNO |
|||
JNO |
如果溢位標誌沒有置位則跳轉 |
溢位標誌=0 |
JO |
|||
JP |
如果奇偶校驗位被置位則跳轉 |
奇偶校驗標誌=1 |
JPE |
JNP |
||
JPE |
如果奇偶校驗位為偶校驗則跳轉 |
奇偶校驗標誌=1 |
JP |
JPO |
||
JNP |
如果奇偶校驗位沒有被置位則跳轉 |
奇偶校驗標誌=0 |
JPO |
JP |
||
JPO |
如果奇偶校驗位為奇校驗則跳轉 |
奇偶校驗標誌=0 |
JNP |
JPE |
表 使用無符號數比較的JCC指令
指 令 |
描 述 |
條 件 |
別 名 |
相反指令 |
JA |
如果超過(>)則跳轉 |
進位標誌=0,0標誌=0 |
JNBE |
JNA |
JNBE |
如果不低於或等於(不 <=)則跳轉 |
進位標誌=0,0標誌=0 |
JA |
JBE |
JAE |
如果超過或等於(>=)則跳轉 |
進位標誌=0 |
JNC,JNB |
JNAE |
JNB |
如果不低於則跳轉(不 <) |
進位標誌=0 |
JNC,JAE |
JB |
JB |
如果低於(<)則跳轉 |
進位標誌=1 |
JC,JNAE |
JNB |
JNAE |
如果不超過或等於(不>=)則跳轉 |
進位標誌=1 |
JC,JB |
JAE |
JBE |
如果低於或等於(<=)則跳轉 |
進位標誌=1或0標誌=1 |
JNA |
JNBE |
JNA |
如果不超過(不>)則跳轉 |
進位標誌=1或0標誌=1 |
JBE |
JA |
JE |
如果相等(=)則跳轉 |
0標誌=1 |
JZ |
JNE |
JNE |
如果不相等(<>)則跳轉 |
0標誌=0 |
JNZ |
JE |
表 使用有符號數比較的JCC指令
指 令 |
描 述 |
條 件 |
別 名 |
相反指令 |
JG |
如果大於(>)則跳轉 |
符號標誌=溢位標誌或0標誌=0 |
JNLE |
JNG |
JNLE |
如果小於或等於(<=)則跳轉 |
符號標誌=溢位標誌或0標誌=0 |
JG |
JLE |
JGE |
如果大於或等於(>=)則跳轉 |
符號標誌=溢位標誌 |
JNL |
JGE |
JNL |
如果不小於(不<)則跳轉 |
符號標誌=溢位標誌 |
JGE |
JL |
JL |
如果小於(<)則跳轉 |
符號標誌<>溢位標誌 |
JNGE |
JNL |
JNGE |
如果大於或等於(>=)跳轉 |
符號標誌<>溢位標誌 |
JL |
JGE |
JLE |
如果小於或等於(<=)跳轉 |
符號標誌<>溢位標誌或0標誌=1 |
JNG |
JNLE |
JNG |
如果不大於(不>)則跳轉 |
符號標誌<>溢位標誌或0標誌=1 |
JLE |
JG |
JE |
如果等於(=)則跳轉 |
0標誌=1 |
JZ |
JNE |
JNE |
如果不等於(<>)則跳轉 |
0標誌=0 |
JNZ |
JE |
5. 具體內容及示例
首先是匯出表,能夠檢視具體對應的相關函式,可以與VS中的具體進行對應(主要使用了IDA能夠反彙編的功能,例如如下情況的對應)
可以看出IDA反彙編出的程式碼與原始碼基本上是一致的,當沒有原始碼的時候,就更多的需要使用IDA反彙編出的程式碼進行具體內容的查詢。
可以看出此處進入呼叫函式。
Mov一般是取具體的資料或引數內容,push為取對應的引數(例如上圖中的push 1 就是kPGPKeyDBObjType_Key所對應的定義值),因此可以一直執行到call指令處。
已知道函式會在此處出錯,因此到達此call指令時,使用F11進入。
對比可以發現,兩者一致。
原始碼和IDA反彙編出的程式碼相比較,兩者一致,這是就可以查詢具體對應的函式。