IDA逆向技巧之美

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。  

相關文章
相關標籤/搜索