IDA的逆向分析水平就是一個逆向工程師的水平;
7.1 IDA與OD的聯合使用html
通常使用OD下斷點,找到關鍵代碼位置,而後使用IDA靜態看流程。
須要注意的是IDA須要與OD基地址對齊,這樣才方便在IDA中查找代碼位置,具體方式以下:算法
Edit ---> Segment ----- Rebase Program : 設置基地址;數據庫
在WINdbg中基地址在「符號」中查看;在OD中基地址在Model中查看;數組
IDA中G + 地址,便可找對對應位置;sass
7.2 數據不當心轉換成爲函數,如何處理?數據結構
若是不當心使用P將數據識別成了函數,可使用D,轉換成數據,再用C轉換成爲代碼;app
畢竟IDA不存在撤銷功能;ide
7.3 IDA如何建立結構體?函數
7.3.1 結構體的建立 工具
IDA中結構體成員通常出如今:類初始化的地方(XX.dll);
根據成員的多少,咱們建立結構體的大小,注意虛表vt佔4個字節;通常有三個地方有助於咱們建立結構體:初始化函數成員列表、memcpy函數的使用、數據庫字段;
在初始化函數中看見最後一個成員爲V1[239],能夠 使用「Reset Point Type」 能夠改成:v1-> 1036,這樣就能看到成員在的偏移,就能夠設置結構體大小爲1036 + 4.。
建立告終構體後,structure窗口中能夠N改寫字段的名稱;
7.3.2 結構體的使用
建立好結構體後,咱們就可使用Y來修改分析的數據類型;
7.3.3 結構體的導入和導出使用
有時咱們須要在一個數據庫中建立結構體,在另外的一個數據庫中使用,具體方法:
在數據庫A的localtype視圖中選中須要導出的數據類型,右鍵 --- 「export to header」,若是是多個結構體寫到同一個文件,請選擇追加方式(Append),導出到一個.h文件;
接下來是導入到另一個數據庫,具體方法:
Ctrl + F9 :」選擇一個C文件頭去解析」,選擇須要導入的一個文件,這樣咱們就會能夠在LocalType中查看咱們自建的結構體;
7.3.4 建立結構體 例子
通常方法構建結構體(方法1):在structure窗口,Insert 一個結構,本身命名(如struct_4),在end處使用D添加結構體數據,在成員處D 切換佔有的字節數(db、dw、dd),在成員處使用Y來改變識別類型(int、float、double、LPVOID、BYTE field_60[1024]、)
使用: 在相應的rdata處,使用Y改變當前位置的識別類型爲struct_4;
例如:
建立結構體數組:
00000000 struc4 struc ; (sizeof=0x28, mappedto_194)
00000000 ; XREF: .data:stru_A47A220/r
00000000 field_0 dw ?
00000002 field_2 db ?
00000003 field_3 db ?
00000004 field_4 dd ?
00000008 field_8 dd ?
0000000C field_C db ?
0000000D field_D db ?
0000000E field_E db ?
0000000F field_F db ?
00000010 field_10 dd ?
00000014 field_14 dd ?
00000018 field_18 dd ?
0000001C field_1C dd ?
00000020 field_20 dd ?
00000024 field_24 dd ?
00000028 struc4 ends
例子: struc4 stru_A47A220[77]
數據區的 stru_A47A220 struc4 <0FC39h, 0, 0, 100h, 0, 0, 0, 0, 0, 1.0, 1.0, 0, 0, 1, 1>....
7.4 IDA如何建立虛表
虛表的建立方式與結構體很相似,關鍵是要找到虛表的位置,須要使用 OD來進行跟蹤,虛表的地址通常存在於EAX中,對應找過去就能知道是那個庫裏面的函數集合;
虛表的獲取: 都是先獲得this 指針,而後獲得虛表指針,再成員函數調用須要傳遞this指針到ecx,最後間接調用,具體:
mov ecx, dword ptr[ebp - 14h] ; ecx 獲得this指針
mov edx, dword ptr [ecx] ; 獲得虛表地址,this指針指向的第一個4字節就是虛表地址; edx 就是虛表地址;
mov esi,esp
mov ecx, dword ptr [ebp -14h] ;成員函數調用,須要ecx保存this指針;
call dword ptr [edx + 4] ;間接調用 虛函數;
能夠直接寫一個虛函數的調用例子,使用IDA來分析;
7.4.1 建立虛表 例子
創建虛表:
00000000 functionVT struc ; (sizeof=0x34, align=0x4, copyof_192)
00000000 sub_10001110 dd ?
00000004 sub_10002210 dd ?
00000008 sub_100010D0 dd ?
0000000C sub_10001000 dd ?
00000010 sub_10001090 dd ?....
functionVT ends
上面這個函數的虛表來自於rdata 中的虛函數列表:
.rdata:0A46F570 ??_7CJ2190_PID_Decoder@@6B@ dd offset sub_A411110
.rdata:0A46F570 ; DATA XREF: sub_A452B00+C
.rdata:0A46F574 dd offset f_baseFuncton_sub_E282210 ;
.rdata:0A46F578 dd offset sub_A4110D0
.rdata:0A46F57C dd offset sub_A411000
.rdata:0A46F580 dd offset sub_A411090
…..
創建類:
00000000 basestructure struc ; (sizeof=0x51C, align=0x4, mappedto_193)
00000000 VT dd ? ; offset
00000004 field_4 dd ?
00000008 field_8 dd ?
basestructure…ends
將:VT 識別爲:functionVT* 就能夠獲得basestructure的虛表;
例如:
result =(*(unsigned __int8 *)(*(_DWORD *)a1 + 0x20))(a1);
將a1定義爲 basestructure * 類型,就能識別成爲:
result = a1->VT->sub_1000CAD0(a1);
優勢:看到調用的函數,方便靜態分析;
7.4.2 快捷添加虛表結構體的快捷的方式(方法二)
咱們知道編譯後虛表存在數據區,找到虛表頭就能夠看到當前類中的全部虛函數列表;這樣咱們在LocalType中 建立一個結構體,XXXVT ,將全部的虛表名稱off_XXX 都賦值到結構體中,添加上類型int ,肯定,而後雙擊結構體名,此時,會提示是否導入結構體到數據庫,YES,而後再structure 窗口中就能夠看到定義的虛表結構體了,這樣,就能夠Y來識別虛表了;
這樣經過C的方式導入結構體的方式比在structure窗口中逐個添加成員要快不少;
7.5 IDA如何肯定數據是數組類型?
Data區中被引用的地方通常是數組;
見:《如何提取DLL中的數據》
見:《如何訪問DLL的函數》
7.6 IDA 如何使用UTF-8 顯示中文字符
Alt + A 能夠改變字符顯示 格式,在DLL中全部的data區都是使用十六進制的數值顯示的;
Alt + A : 設置---- 「ASCII String style 」-----「set default encoding」。
若是想要在Hex -rays的僞代碼中顯示出字符串,能夠設置:「Edit」---plugins ---- Option----Analysis --- 「Print only constant string literals」
7.7 IDA 的強大之處---- 交叉引用
X:一個地方引用另一個地方;
體現:雙擊、X、subView-Cross ref
在IDA-View-A 模式下,Xrefs graph to :表示該函數被其餘哪些函數調用的信息;Xrefs graph from :函數調用其餘函數的信息;
字符串窗口和交叉引用 是IDA的強大之處,經常用於代碼片斷定位,很是關鍵;
7.8 IDA 反編譯失敗1--- Decomplication failure
IDA常常會解析錯誤,咱們要學會如何處理這些錯誤,才能獲得僞代碼;
可能緣由1:函數約定的錯誤;
可能緣由2:函數參數識別錯誤;
解決方法:分析函數的參數個數和調用約定,Y從新定義函數;
若是判斷不出是哪一種約定,能夠D成數據,再用tab進行轉成僞代碼,能夠看到反編譯後成爲了Jumpout(xxxxx),屏蔽了細節,這種方式,只是用來隨便看看代碼;
7.9 IDA 反編譯失敗2--- SP- analysis failed
使用IDA -- Options ---Disassembly ---Display disassenmly Line Parts ---- Stack Pointer,勾上能夠看到SP,正常狀況下SP的值在函數頭和尾都是0000 ,表示堆棧是平衡的;
若是函數識別錯誤,Alt + p: 能夠指定函數的頭尾;
7.10 IDA 反編譯失敗3--- Positive sp value has been found
有些彙編指令無函數名,表示是虛函數,IDA很容易出錯;
如: call dword ptr[eax + 4]
V解決:ALT + K,設置SP當前爲0x4X,這裏X表示的是Call 以前有幾個push。這樣作能識別代碼,能分析,可是會引發堆棧不平衡。
7.11 IDA 自動優化: Debug 和Release版本的不一樣
常量、簡單算法,在生成Release 版本的時候被優化; 相對而言, debug版本中有不少的無關邏輯的代碼,例如:判斷越界的函數等;
7.12 IDA 能夠識別當前文件的類型
C#: Mircosoft.net assembly [peldw]
7.13 IDA 如何修改數據庫
方式1、找到須要修改的位置,Edit---Patch pragram ----Assemble ;加入彙編語言,例如:給函數的返回值直接修改成2,反回;
mov eax,2
retn
若是是stdCal 的話,須要使用retn 4
修改後,在函數頭P,函數對齊後,當前函數直接返回 2,而原先的邏輯都被註釋掉了;
注意,此時修改並不會更新原始程序文件,實際只是修改了IDA的項目文件 idb。
最後,使用Edit---Patch pragram ----Apply patch to input file,這樣就能修改原始文件。
方式2、使用UE打開,直接找到須要修改的函數的字節碼,修改字節碼也是同樣的,例如 0x90 ----nop;
再使用Edit--- patch program ----Apply patches to input file ,OK 便可;
7.14 IDA Send Data 的識別
從Write File回溯,SendData通常被不少的地方調用;
7.15 IDA 取一個富含意義的名稱,有助於理解。
7.16 IDA 跟蹤技巧:註釋+ 更名 : 雁過留聲 很重要...
7.17 IDA 變量靜態分析
7.17.1 X : type = W/O 時能夠找到當前變量寫的地方,能夠直接看到關鍵邏輯,進而進行猜想;
7.17.2 數組的靜態分析
dword_1002FEBE8 = HeapAlloc(hHeap, 8u, 8*g_count);
表示:分配內存8*count,每一個元素有8字節,分配的內存每每與數據庫對應;
*(_BYTE*)(dword_10031AC4 + 8*V7 + 1) = g_DataArry[V8].size
表示:元素8字節,V7是偏移元素個數,1表示元素內偏移,_BYTE 表示取出的是一個字節,賦值給size;
7.17.3 函數的靜態分析
一、看懂函數流程後肯定函數的意義;
二、若是調用dll中的函數,GetProAddress,函數名每每都是直接能夠看到的;
7.18 根據lib文件製做sig文件(參考IDA權威指南)
Sig文件能使得IDA識別更多的符號,便於分析,F5刷新;
一、使用IDA打開lib,能夠看出lib裏面有多少個obj文件;
二、使用link.exe 將lib中的obj文件導出來(這個link.exe 來自於哪裏?)
命令:link -lib /extract:testCplusplusCollect.obj testCplusplusCollect.lib
獲得的是testCplusplusCollect.obj
沒找到Link.exe ,
其實,這個obj文件在lib文件編譯生成時會在debug目錄生成(我是直接拷過來的哈);
據說VC裏面的Lib.exe 也有這個功能。據說能夠直接使用pcf.exe [lib文件名].lib ,會生成[lib文件名].pat 。
沒試過,讀者能夠試試;
三、使用pcf.exe 將obj文件製做成爲pat文件。
從IDA安裝目錄中找到pcf.exe,拷貝到testCplusplusCollect.lib 同級目錄下;
命令:pcf testCplusplusCollect.lib
在同級目錄獲得了testCplusplusCollect.pat。
四、使用sigmake.exe將PAT文件轉換成爲sig文件。
IDA_65_Utils\flair65\bin\win\sigmake.exe
命令:sigmake.exe testCplusplusCollect.pat testCplusplusCollect.sig
在同級目錄獲得了testCplusplusCollect.sig。
五、在IDA中去加載sig文件
將testCplusplusCollect.sig 拷貝到IDA的sig目錄,再使用FILE -> LoadFile àFILTER signature File;
7.19 IDA反編譯失敗:too big Funtion
解決方法: MAX_FUNCSIZE 改大便可;
7.20 結構體:若是知道告終構體的C表示,IDA如何添加
在TypeLocal(shift + F1 )的界面,insert 跳出輸入對話框,在裏面複製結構體就好了。
雙擊添加後的類型,提示「是否加入當前的數據庫」,選擇能夠,那麼在structure試圖中就能獲得咱們想要的類型,能夠在反編譯試圖中使用Y設置此類型;
7.30 若是將全局的字符串,顯示在代碼中?
Edit ---plugins --- Hex-Rays decomplier -Option -
Print only constant string literals 」把這個勾去掉就能,將全局的字符串給顯示出來了。
7.31 打標籤與修更名字
修更名字:N
打標籤:JUMP/Mark postion 中「標記當前的位置」而後可使用Ctrl + M 來快速跳轉到標籤的位置;
之前我一直這麼作的: 分析到了哪一個函數,就將函數名字N一下,改爲YY開頭,這樣我就能夠在FUnctionList中快速找到我分析過的函數;
7.32 如何解決IDA key黑名單檢測
提示:「sorry, this database has been created by a pirate version of IDA」
這是由於IDA的key 黑名單檢測,解決方法以下:十六進制工具將ida.dll 或 ida64.dll的地址0x277560 ~ 0x277750 的數據改成0 便可經過檢測;這部分是全部的黑名單Key的MD5值。
7.33 如何使得IDA將全部的數值都用十六進制表示;
插件: Edit ---Plugins --- Hex-Rays Decompiler ---- options ---「Default radix」 填上16便可;
7.34 如何在僞代碼中將全局的dword_454670 改成字符串顯示?
將數據A轉換爲c-typle 字符串;而後:在僞代碼中F5 就能將dword_454670 轉成:
7.35 F5 反編譯後提示: 「Out of memory」
有時候函數太大,會這樣提示,打開Hex-ray的選項,提示咱們能夠在 HexXXX.cfg中修改max_funcszie.
好像只有7.0以後的IDA配置文件中有這個屬性。
7.36 F5 反編譯的代碼分支太多,代碼太長,如何作?
將分析過的分支縮進,方法: 右鍵--collapse item 就行,若是想看裏面的內容,同樣操做選uncollapse;
7.37 F5 的僞代碼加上註釋後,有時候註釋不見了;
當僞代碼很大的時候,你走過一遍流程,寫下了不少的註釋(特別是多行的註釋),當分析清除一個數據結構體,改變代碼的數據類型的是,就會發現字節寫下的註釋,莫名其妙的就沒了,並且IDA不提供撤銷功能。
緣由:多是識別爲多行的僞代碼,改變數據結構類型後,引發行數的變化,通常爲縮減了不少行,此時會致使註釋被掩住;
解決方法:沒有想到好的方法,當須要逆向分析代碼量大的時候,能夠每作一個步驟,處處.c備份一次。
7.36 can't load file
當打開idb的時候,顯示不能加載數據,那麼,可能有兩個緣由:
一、IDA是低版本的,idb是高版本生成的; 據說是有解決這個問題的插件;
二、IDA的路徑不能爲中文,改成英文目錄;
7.38 在彙編處按Tab鍵發現反彙編的C預研與彙編指令對不上。
緣由:彙編指令沒有識別成函數,因此反彙編不會顯示對應的C僞代碼。未識別的彙編指令段地址是暗紅色的,識別出來的是黑色(顏色是默認色,能夠設置);
7.38 arm 與 thumb 之間指令轉換 按快捷鍵 Alt+g, Value 填 0,切換爲 arm, Value 填 1,切換爲 thumb。