IDA PRO權(quán)威指南--閱讀筆記(一)

站在巨人的肩膀上——IDA PRO權(quán)威指南閱讀筆記


一漾峡,窗口

view->open subviews ?打開(kāi)/關(guān)閉各種窗口

IDA文本視圖(反匯編視圖)

地址顯示格式 ?區(qū)域名稱(chēng):虛擬地址

箭頭顯示格式 ? ?虛線(xiàn)條件跳轉(zhuǎn)终惑,實(shí)現(xiàn)非條件跳轉(zhuǎn) ?若加粗則

arg_X ?函數(shù)棧幀

;CODE XREF:_XX ? 交叉引用

Names窗口

D:數(shù)據(jù)

A:字符串

F:常規(guī)函數(shù)恒削,非庫(kù)函數(shù)

I:共享庫(kù)導(dǎo)入的函數(shù)名稱(chēng)

L:庫(kù)函數(shù)

未知名稱(chēng):

sub_XXXXX ? 地址XXXX的子例程

loc_XXXXX? 地址XXXX的一個(gè)指令

byte/word/dword_XXXXX? 地址XXXX的8/16/32位數(shù)據(jù)

unk_XXXXX? 地址XXXX的未知數(shù)據(jù)

底部消息窗口

IDA開(kāi)發(fā)腳本插件的輸出窗口

Strings窗口

從二進(jìn)制文件中提取的字符串

右鍵->setup可配置

導(dǎo)出/入窗口

導(dǎo)出窗口列出文件的入口點(diǎn)

導(dǎo)入窗口列出由被分析的二進(jìn)制文件導(dǎo)入的所有函數(shù)

函數(shù)窗口

函數(shù)名稱(chēng),區(qū)域径密,起始位置,長(zhǎng)度坤按,描述函數(shù)的標(biāo)記

<返回調(diào)用方(R),使用ebp(B)寄存器引用局部變量>

結(jié)構(gòu)體窗口

分析數(shù)據(jù)結(jié)構(gòu)弃衍,雙擊數(shù)據(jù)結(jié)構(gòu)名稱(chēng)展開(kāi)惊豺,查看詳細(xì)布局

枚舉窗口 enums

可列舉燎孟,定義枚舉類(lèi)型

段窗口 segmentation

段的簡(jiǎn)單列表

簽名窗口

右鍵->應(yīng)用新簽名

類(lèi)型庫(kù)窗口,函數(shù)調(diào)用窗口(先選中函數(shù))尸昧,問(wèn)題窗口等

二揩页,反匯編導(dǎo)航

雙擊導(dǎo)航

最基本的為雙擊導(dǎo)航,任意可雙擊的地址均能跳轉(zhuǎn)到目標(biāo)

跳轉(zhuǎn)

快捷鍵 G 或Jump->Jump to Address跳轉(zhuǎn)到名稱(chēng)或十六進(jìn)制地址

導(dǎo)航欄前進(jìn) 后退按鈕實(shí)現(xiàn)跳轉(zhuǎn)

棧幀

棧幀

棧幀也叫過(guò)程活動(dòng)記錄烹俗,是編譯器用來(lái)實(shí)現(xiàn)過(guò)程/函數(shù)調(diào)用的一種數(shù)據(jù)結(jié)構(gòu)爆侣。

棧幀就是一個(gè)函數(shù)執(zhí)行的環(huán)境:函數(shù)參數(shù)、函數(shù)的局部變量幢妄、函數(shù)執(zhí)行完后返回到哪里等等兔仰。

實(shí)現(xiàn)上有硬件方式和軟件方式(有些體系不支持硬件棧)

首先應(yīng)該明白,棧是從高地址向低地址延伸的蕉鸳。每個(gè)函數(shù)的每次調(diào)用乎赴,都有它自己獨(dú)立的一個(gè)棧幀,這個(gè)棧幀中維持著所需要的各種信息潮尝。寄存器ebp指向當(dāng)前的棧幀的底部(高地址)榕吼,寄存器esp指向當(dāng)前的棧幀的頂部(低地址)。

注意:EBP指向當(dāng)前位于系統(tǒng)棧最上邊一個(gè)棧幀的底部勉失,而不是系統(tǒng)棧的底部羹蚣。嚴(yán)格說(shuō)來(lái),“棧幀底部”和“棧底”是不同的概念;ESP所指的棧幀頂部和系統(tǒng)棧的頂部是同一個(gè)位置戴质。

棧幀是程序運(yùn)行時(shí)棧中分配的內(nèi)存塊度宦,用于特定函數(shù)的調(diào)用

調(diào)用函數(shù):

1.調(diào)用方將被調(diào)用函數(shù)所需的參數(shù)放入調(diào)用約定指定的位置踢匣。

2.調(diào)用方將控制權(quán)轉(zhuǎn)交給被調(diào)用函數(shù)告匠,即x86 CALL 與 MIPS JAL等指令執(zhí)行戈抄。返回地址被保存到程序棧或CPU寄存器中后专。

3.有時(shí)划鸽,被調(diào)用的函數(shù)會(huì)配置一個(gè)棧指針,并保存調(diào)用方希望保持不變的寄存器的值戚哎。

4.被調(diào)用的函數(shù)為它可能需要的任何局部變量分配空間裸诽,一般通過(guò)調(diào)整程序棧指針在運(yùn)行時(shí)棧上保留空間來(lái)完成這一任務(wù)。

5.被調(diào)用的函數(shù)可能訪(fǎng)問(wèn)調(diào)用函數(shù)傳遞給它的參數(shù)型凳,可能生成一個(gè)結(jié)果丈冬。如果返回一個(gè)結(jié)果,此結(jié)果通常放置在一個(gè)特定的寄存器中甘畅,或放置到函數(shù)返回后調(diào)用方可立即訪(fǎng)問(wèn)的寄存器中埂蕊。

6.函數(shù)完成操作后,任何為函數(shù)保留的検柰伲空間將被釋放蓄氧。通常,逆向執(zhí)行4步驟即可實(shí)現(xiàn)槐脏。

7.如果某個(gè)寄存器的值還為調(diào)用方保存(即3中情況)喉童,那么恢復(fù)原始值。這包括恢復(fù)調(diào)用方的棧指針寄存器顿天。

8.被調(diào)用函數(shù)將控制權(quán)返還給調(diào)用方堂氯。主要指令x86 RET 和 MIPS JR 。根據(jù)調(diào)用約定牌废,還可能會(huì)從程序棧中清除一個(gè)或多個(gè)參數(shù)祖灰。

9.調(diào)用方一旦重新獲得控制權(quán),它可能需要?jiǎng)h除程序棧中的參數(shù)畔规。這是可能需要對(duì)棧進(jìn)行調(diào)整局扶,將程序棧指針恢復(fù)到1步驟之前的值。

3叁扫,4在進(jìn)入函數(shù)時(shí)執(zhí)行三妈,稱(chēng)為序言;6~8一般在函數(shù)結(jié)束是執(zhí)行莫绣,稱(chēng)為尾聲畴蒲;5為函數(shù)主體,表示調(diào)用函數(shù)執(zhí)行的全部操作对室。

調(diào)用約定(常用)

cdecl調(diào)用約定:

調(diào)用方按從右到左的順序?qū)⒑瘮?shù)參數(shù)放入棧中模燥,在被調(diào)用的函數(shù)完成其操作時(shí)咖祭,調(diào)用方負(fù)責(zé)從棧中清除參數(shù)。

stdcall調(diào)用約定:

按從右到左的順序?qū)⒑瘮?shù)參數(shù)放入棧中蔫骂,函數(shù)結(jié)束時(shí)么翰,被調(diào)用方負(fù)責(zé)刪除棧中的參數(shù)。

fastcall調(diào)用約定:

傳遞給函數(shù)的前兩個(gè)參數(shù)分別位于exc,edx(非程序棧)辽旋,剩余其他參數(shù)類(lèi)似stdcall浩嫌,由于有兩個(gè)參數(shù)被傳遞到寄存器中(傳參2以上),被調(diào)用函數(shù)只需從棧中清除8字節(jié)补胚。

c++調(diào)用約定:

this指針指向用于調(diào)用函數(shù)的對(duì)象码耐,c++并未規(guī)定如何向非靜態(tài)成員函數(shù)傳遞this指針,不同編譯器有不同解釋溶其。

棧幀示例:

棧指針骚腥,就是棧頂指針

“序言”部分:

push ebp ? ? ? ? ? ? ? ;儲(chǔ)存調(diào)用者ebp值

mov ebp,esp ? ? ? ? ;使用ebp儲(chǔ)存esp的值

sub esp,76 ? ? ? ? ? ?;給本地變量分配空間

如果希望ebp作為棧指針,修改它之前必須保存ebp的當(dāng)前值瓶逃,并且在返回調(diào)用方時(shí)恢復(fù)ebp(保存其他寄存器如esi或edi也是這樣束铭,或推遲操作),即棧幀中沒(méi)有用于存儲(chǔ)被保存寄存器的標(biāo)準(zhǔn)位置金闽。ebp被保存后纯露,就可以對(duì)其修改,使它指向當(dāng)前的棧位置代芜。

“尾聲”部分:

add ? esp,76 ? ? ? ?;調(diào)整esp到初始

ret ? ? ? ? ? ? ? ? ? ? ? ?;返回

使用一個(gè)專(zhuān)用的棧幀埠褪,所有變量相對(duì)于棧指針寄存器的偏移量都可計(jì)算。許多時(shí)候挤庇,正偏移量用于訪(fǎng)問(wèn)函數(shù)參數(shù)钞速,負(fù)偏移量用于訪(fǎng)問(wèn)局部變量。


調(diào)用:

push sword [ebp-72] ? ? ;push y

push sword [ebp-76]? ? ;push z

call bar?

add esp,8 ? ? ? ? ? ? ? ? ? ? ? ?;cdecl要求調(diào)用者清除參數(shù)

“尾聲”

mov esp,ebp ? ? ? ? ? ;利用重置esp清除局部變量

pop ? ebp ? ? ? ? ? ? ? ? ;還原調(diào)用者ebp值

ret ? ? ? ? ? ? ? ? ? ? ? ? ? ?;彈出返回地址返回給調(diào)用者

由于這項(xiàng)操作十分常見(jiàn)嫡秕,x86體系提供leave指令

leave ? ? ? ? ? ? ? ? ? ;同上兩行

ret ? ? ? ? ? ? ? ? ? ? ?;同上

IDA棧視圖:

從開(kāi)始渴语,IDA提供了一個(gè)摘要棧視圖

局部變量以var_為前綴,跟一個(gè)表示變量與被保存的棧指針之間的距離(以字節(jié)為單位)的十六進(jìn)制后綴

函數(shù)參數(shù)(傳入?yún)?shù))名以arg_為前綴昆咽,后面跟表示其與最頂端的參數(shù)之間的相對(duì)距離的十六進(jìn)制后綴驾凶,因此最頂端4字節(jié)參數(shù)名為arg_0,而隨后為arg_4等

IDA只會(huì)為在函數(shù)中直接引用的棧變量自動(dòng)生成名稱(chēng)

雙擊任一變量掷酗,即可進(jìn)入詳細(xì)視圖

標(biāo)記:dd一個(gè)儲(chǔ)存字節(jié) dw兩個(gè)儲(chǔ)存字節(jié)(也叫字) dd四個(gè)儲(chǔ)存字節(jié)调违,雙字

數(shù)據(jù)庫(kù)搜索:

search->text ? 啟動(dòng)文本搜索

search->sequence of bytes ?搜索字節(jié)序列 : ?搜索十六進(jìn)制序列,應(yīng)將搜索字符串指定為以空格分隔的兩位十六進(jìn)制值組成的列表泻轰;要搜索內(nèi)嵌字符串?dāng)?shù)據(jù)技肩,必須將搜索字符串用引號(hào)括起來(lái)

三,反匯編操作

暫時(shí)不用

四浮声,數(shù)據(jù)類(lèi)型與數(shù)據(jù)結(jié)構(gòu)

數(shù)組成員訪(fǎng)問(wèn):

edit->array ?格式化數(shù)組操作 ? ? ?可使數(shù)組看上去更明顯(按地址順序mov虚婿,全局?jǐn)?shù)組可計(jì)算出地址)

棧分配數(shù)組 ? 沒(méi)有絕對(duì)地址旋奢,編譯器無(wú)法計(jì)算地址,處理方法類(lèi)似全局?jǐn)?shù)組?

堆分配數(shù)組 ?使用動(dòng)態(tài)內(nèi)存分配函數(shù)然痊,所以必須根據(jù)內(nèi)存分配函數(shù)返回的地址值至朗,生成對(duì)數(shù)組的所有引用。如果能確定數(shù)組的總大小和每個(gè)元素的大小玷过,可以計(jì)算該數(shù)組包含的元素?cái)?shù)量爽丹。


只有當(dāng)變量用作數(shù)組的索引時(shí)筑煮,才容易確定數(shù)組的存在辛蚊;要訪(fǎng)問(wèn)數(shù)組中的元素,首先要用索引乘以數(shù)組元素的大小真仲,計(jì)算出相應(yīng)偏移量袋马,與數(shù)組基址相加,得到數(shù)組元素的訪(fǎng)問(wèn)地址秸应。

(常量索引值訪(fǎng)問(wèn)數(shù)組時(shí)虑凛,很少能確定是數(shù)組)

結(jié)構(gòu)體成員訪(fǎng)問(wèn):

特點(diǎn):結(jié)構(gòu)體中數(shù)據(jù)字段通過(guò)名稱(chēng)訪(fǎng)問(wèn),字段名稱(chēng)被編譯器轉(zhuǎn)換成數(shù)字偏移量

默認(rèn)情況软啼,編譯器會(huì)設(shè)法將結(jié)構(gòu)體字段與內(nèi)存地址對(duì)其桑谍,最有效的讀取和寫(xiě)入這些字段。

全局分配結(jié)構(gòu)體:與全局分配數(shù)組一樣祸挪,編譯器編譯時(shí)計(jì)算出結(jié)構(gòu)體中每個(gè)成員的地址(僅從匯編無(wú)法判斷使用了結(jié)構(gòu)體)

push? ? ebp

mov?????ebp,?esp

mov?????dword_403018,?10?;intf1?=?10

mov?????eax,?20

mov?????word_40301C,?ax?;?word?f2?=?20

mov?????byte_40301E,?30?;?byte?f3?=?30

mov?????dword_403020,?40?;intf4?=?40

fld?????ds:dbl_4020E0???;?f5?=?dbl_403028?=?50.0

fstp????dbl_403028

pop?????ebp

retn

棧分配結(jié)構(gòu)體:根據(jù)棧布局很難識(shí)別出棧分配結(jié)構(gòu)體锣披,編譯器能計(jì)算出起始位置與相關(guān)棧幀的幀指針ebp ? ?(其中棧指針:esp和幀指針:ebp)

000 push? ? ebp

004?mov?????ebp,?esp

004?sub?????esp,?18h

01C?mov?????[ebp+var_18],?10

01C?mov?????eax,?14h

01C?mov?????[ebp+var_14],?ax

01C?mov?????[ebp+var_12],?30

01C?mov?????[ebp+var_10],?40

01C?fld?????ds:dbl_4020E0

01C?fstp????[ebp+var_8]

01C?mov?????esp,?ebp

004?pop?????ebp

000?retn

堆分配結(jié)構(gòu)體:由于結(jié)構(gòu)體的地址在編譯時(shí)未知,編譯器別無(wú)選擇贿条,只有生成代碼來(lái)計(jì)算每個(gè)字段在結(jié)構(gòu)體中的正確偏移量雹仿。如果一個(gè)結(jié)構(gòu)體在堆中分配,那么對(duì)編譯器來(lái)說(shuō)整以,引用該結(jié)構(gòu)體的唯一線(xiàn)索就是指向該結(jié)構(gòu)體起始地址的指針胧辽。

push? ? ebp

mov?????ebp,?esp

sub?????esp,?8

push????24??????????????;?unsignedint

call??????2@YAPAXI@Z????;?operatornew(uint)

add?????esp,?4

mov?????[ebp+var_8],?eax?;?eax為pst指針,var_8也是

mov?????eax,?[ebp+var_8]

mov?????[ebp+var_4],?eax

mov?????ecx,?[ebp+var_4]?;?ecx?=?pst

mov?????dword?ptr?[ecx],?10?;?(int*)pst?=?10

mov?????edx,?20

mov?????eax,?[ebp+var_4]?;?eax?=?pst

mov?????[eax+4],?dx?????;?(word*)(pst+4)?=?20

mov?????ecx,?[ebp+var_4]?;?ecx?=?pst

mov?????byte?ptr?[ecx+6],?30?;?(byte*)(pst+6)=30,驗(yàn)證了第二個(gè)是word字節(jié)

mov?????edx,?[ebp+var_4]?;?edx?=?pst

mov?????dword?ptr?[edx+8],?40?;?(int*)(pst+8)?=?40

mov?????eax,?[ebp+var_4]?;?eax?=?pst

fld?????ds:dbl_4020F0

fstp????qword?ptr?[eax+10h]?;?(dq)(pst+16)=50.0

mov?????esp,?ebp

pop?????ebp

retn

結(jié)構(gòu)體數(shù)組:找到堆請(qǐng)求的字節(jié)數(shù),數(shù)組索引數(shù)公黑,加上數(shù)組起始地址mov xxxx ptr[ecx+eax],xx邑商;可判斷數(shù)組大小和元素個(gè)數(shù)

push? ? ebp

mov?????ebp,?esp

sub?????esp,?8

push????48??????????????;?48/2?=?24

call??????2@YAPAXI@Z????;?operatornew(uint)

add?????esp,?4

mov?????[ebp+var_8],?eax

mov?????eax,?[ebp+var_8]

mov?????[ebp+var_4],?eax

mov?????ecx,?[ebp+var_4]

mov?????dword?ptr?[ecx+24],?10?;?pst+24,注意+24

mov?????edx,?20

mov?????eax,?[ebp+var_4]

mov?????[eax+1Ch],?dx

mov?????ecx,?[ebp+var_4]

mov?????byte?ptr?[ecx+30],?30?;?pst+24+6

mov?????edx,?[ebp+var_4]

mov?????dword?ptr?[edx+32],?40?;?pst+24+8

mov?????eax,?[ebp+var_4]

fld?????ds:dbl_4020F0

fstp????qword?ptr?[eax+40]?;?pst+14+16

mov?????esp,?ebp

pop?????ebp

retn

創(chuàng)建結(jié)構(gòu)體:

IDA之所以在分析階段無(wú)法識(shí)別結(jié)構(gòu)體,可能源于兩個(gè)原因凡蚜。首先人断,雖然IDA了解某個(gè)結(jié)構(gòu)體的布局,但它并沒(méi)有足夠的信息番刊,能夠判斷程序確實(shí)使用了結(jié)構(gòu)體含鳞。其次,程序中的結(jié)構(gòu)體可能是一種IDA對(duì)其一無(wú)所知的非標(biāo)準(zhǔn)結(jié)構(gòu)體芹务。在這兩種情況下蝉绷,問(wèn)題都可以得到解決鸭廷,且首先從Structures窗口下手

打開(kāi)structures窗口,edit->add struct type ? 創(chuàng)建結(jié)構(gòu)體

要給結(jié)構(gòu)體添加新字段熔吗,將光標(biāo)放在結(jié)構(gòu)體定義的最后一行(包含ends那一行)并按下D鍵

如果需要修改字段的大小辆床,首先將光標(biāo)放在新字段的名稱(chēng)上,然后重復(fù)按下D鍵桅狠,使數(shù)據(jù)轉(zhuǎn)盤(pán)上的數(shù)據(jù)類(lèi)型開(kāi)始循環(huán)讼载,從而為新字段選擇正確的數(shù)據(jù)大小。另外中跌,你還可以使用Options->Setup Data Types來(lái)指定一個(gè)在數(shù)據(jù)轉(zhuǎn)盤(pán)上不存在的大小咨堤。如果新字段是一個(gè)數(shù)組,右擊其名稱(chēng)并在上下文菜單中選擇Array漩符;要更改一個(gè)結(jié)構(gòu)體字段的名稱(chēng)一喘,可右擊該名稱(chēng)并在上下文菜單中選擇ReName

省略一些詳細(xì)幫助說(shuō)明

可以使用結(jié)構(gòu)體模版等,右擊中嗜暴,可在上下文菜單上看到Structure offset選項(xiàng)對(duì)指令操作數(shù)進(jìn)行格式化凸克;可以將棧和全局變量格式化成整個(gè)結(jié)構(gòu)體,雙擊該變量闷沥,打開(kāi)詳細(xì)棧幀視圖萎战,然后使用Edit?Struct Var顯示一組已知結(jié)構(gòu)體,重新格式化之后IDA將這個(gè)內(nèi)存引用與結(jié)構(gòu)體變量中的一個(gè)已定義的字段關(guān)聯(lián)起來(lái)

var_8= stTest ptr -8

push????ebp

mov?????ebp,?esp

sub?????esp,?8

push????48??????????????;?unsignedint

call??????2@YAPAXI@Z????;?operatornew(uint)

add?????esp,?4

mov?????[ebp+var_8.f1],?eax

mov?????eax,?[ebp+var_8.f1]

mov?????dword?ptr?[ebp+var_8.f2],?eax

mov?????ecx,?dword?ptr?[ebp+var_8.f2]

mov?????dword?ptr?[ecx+(size?stTest)],?10

mov?????edx,?20

mov?????eax,?dword?ptr?[ebp+var_8.f2]

mov?????[eax+1Ch],?dx

mov?????ecx,?dword?ptr?[ebp+var_8.f2]

mov?????byte?ptr?[ecx+30],?30

mov?????edx,?dword?ptr?[ebp+var_8.f2]

mov?????[edx+(stTest.f4+18h)],?40

mov?????eax,?dword?ptr?[ebp+var_8.f2]

fld?????ds:dbl_4020F0

fstp????[eax+(stTest.f5+18h)]

mov?????esp,?ebp

pop?????ebp

retn

將全局變量格式化成結(jié)構(gòu)體的過(guò)程與格式化棧變量所使用的過(guò)程幾乎完全相同

導(dǎo)入新的結(jié)構(gòu)體:

IDA能夠解析C(而非C++)數(shù)據(jù)聲明舆逃,以及整個(gè)C頭文件蚂维,并自動(dòng)為在這些聲明或頭文件中定義的結(jié)構(gòu)體創(chuàng)建對(duì)應(yīng)的IDA結(jié)構(gòu)體。如果你碰巧擁有你正進(jìn)行逆向工程的二進(jìn)制文件的源代碼颖侄,或者至少是頭文件鸟雏,那么,你就可以讓IDA直接從源代碼中提取出相關(guān)結(jié)構(gòu)體

解析C結(jié)構(gòu)體聲明:View?Open Subviews?Local Types览祖,通過(guò)INSERT鍵或上下文菜單中的Insert選項(xiàng)解析

解析C頭文件:可以使用File?Load File?Parse C HeaderFile選擇你想要解析的頭文件孝鹊。如果一切正常,IDA會(huì)通知你Compilation successful(編譯完成)展蒂。如果解析器遇到任何問(wèn)題又活,IDA將會(huì)在輸出窗口中顯示錯(cuò)誤消息。IDA會(huì)將所有被成功解析的結(jié)構(gòu)體添加到當(dāng)前數(shù)據(jù)庫(kù)的標(biāo)準(zhǔn)結(jié)構(gòu)體列表中(具體地說(shuō)锰悼,是列表的末尾)柳骄。如果新結(jié)構(gòu)體的名稱(chēng)與現(xiàn)有結(jié)構(gòu)體的名稱(chēng)相同,IDA會(huì)用新結(jié)構(gòu)體布局覆蓋原有結(jié)構(gòu)體定義箕般。除非你明確選擇添加新的結(jié)構(gòu)體耐薯,否則,新結(jié)構(gòu)體不會(huì)出現(xiàn)在Structures窗口中

使用標(biāo)準(zhǔn)結(jié)構(gòu)體:

除了創(chuàng)建自定義結(jié)構(gòu)體外,你還可以從IDA的已知結(jié)構(gòu)體列表中提取出其他標(biāo)準(zhǔn)結(jié)構(gòu)體曲初,并將其添加到Structures窗口中体谒。

首先,在Structures窗口中按下IN-SERT鍵臼婆。在Create structure/ union對(duì)話(huà)框中抒痒,包含一個(gè)Add standard structure(添加標(biāo)準(zhǔn)結(jié)構(gòu)體)按鈕。單擊這個(gè)按鈕颁褂,IDA將顯示與當(dāng)前編譯器(在分析階段檢測(cè)出來(lái))和文件格式有關(guān)的結(jié)構(gòu)體主列表故响。這個(gè)結(jié)構(gòu)體主列表中還包含通過(guò)解析C頭文件添加到數(shù)據(jù)庫(kù)中的結(jié)構(gòu)體。

默認(rèn)情況下颁独,在創(chuàng)建后彩届,文件頭不會(huì)立即加載到數(shù)據(jù)庫(kù)中。但是奖唯,如果你在最初創(chuàng)建數(shù)據(jù)庫(kù)時(shí)選擇Manual load(手動(dòng)加載)選項(xiàng)惨缆,就可以將文件頭加載到數(shù)據(jù)庫(kù)中糜值。加載文件頭可確保只有與這些頭部有關(guān)的數(shù)據(jù)類(lèi)型才出現(xiàn)在數(shù)據(jù)庫(kù)中丰捷。多數(shù)情況下,文件頭不會(huì)以任何形式被格式化寂汇,因?yàn)橥ǔ3绦虿⒉粫?huì)直接引用它們自己的文件頭病往。因此,分析器也沒(méi)有必要對(duì)文件頭應(yīng)用結(jié)構(gòu)體模板

til文件處理

ida中所有的數(shù)據(jù)類(lèi)型和函數(shù)原型都儲(chǔ)存在til文件中骄瓣,types窗口(View->Open subview->Type Libraries)列出了當(dāng)前加載til文件停巷,并可用于加載想要使用的til文件(types窗口中按下INSERT)

還可以共享til文件(tilib)

C++逆向工程基礎(chǔ)

所有非靜態(tài)c++成員函數(shù)都使用this指針,任何時(shí)候調(diào)用這樣一個(gè)函數(shù)榕栏,this都被初始化指向用于調(diào)用該函數(shù)的對(duì)象

vc++將this傳遞到ECX寄存器中畔勤,GUN g++則把this看成非靜態(tài)成員函數(shù)的第一個(gè)(最左邊)參數(shù),并在調(diào)用該函數(shù)前將用于調(diào)用函數(shù)對(duì)象的地址作為最后一項(xiàng)壓入棧中扒磁;也就是說(shuō)庆揪,在調(diào)用函數(shù)之前,將一個(gè)地址轉(zhuǎn)移到ECX意味著可能使用vc++編譯妨托,函數(shù)是一個(gè)成員函數(shù)缸榛,如果同一個(gè)地址被傳遞給兩個(gè)或更多函數(shù),那這些函數(shù)全都屬于同一個(gè)類(lèi)層次結(jié)構(gòu)兰伤。函數(shù)初始化前使用ECX則調(diào)用方必定已經(jīng)初始化ECX

虛函數(shù)内颗,虛表:

虛函數(shù)為了重載和多態(tài)的需要,在基類(lèi)中是由定義的敦腔,即便定義是空均澳,所以子類(lèi)中可以重寫(xiě)也可以不寫(xiě)基類(lèi)中的函數(shù)!

編譯器會(huì)為每個(gè)包含虛函數(shù)的類(lèi)(或通過(guò)繼承得到的子類(lèi))生成一個(gè)表,其中包含指向類(lèi)中每一個(gè)虛函數(shù)的指針找前,這就是虛表(vtable)筒捺,每個(gè)包含虛函數(shù)的類(lèi)都獲得另外一個(gè)數(shù)據(jù)成員(也就是虛表指針),用于在運(yùn)行時(shí)指向適當(dāng)?shù)奶摫怼?/p>

使用虛表指針的后果纸厉,操縱IDA中的類(lèi)時(shí)系吭,必須考慮虛表指針。


下面的例子動(dòng)態(tài)創(chuàng)建了SubClass 的一個(gè)對(duì)象颗品,它的地址保存在BaseClass 的一個(gè)指針中肯尺。然后,這個(gè)指針被傳遞給一個(gè)函數(shù)(ca11_vfunc ),它使用該指針來(lái)調(diào)用vfunc3躯枢。

void call_vfunc(BaseClass *b) {

? ?b->vfunc3() ;

? ?}

int main() ?{

? ?BaseClass *bc= new SubClass() ;

? ?call_vfunc(bc) ;

}

由于vfunc3 是一個(gè)虛函數(shù)则吟,因此,在這個(gè)例子中锄蹂,編譯器必須確保調(diào)用SubC1ass :: vfunc3氓仲,因?yàn)橹羔樦赶蛞粋€(gè)SubC1ass 對(duì)象。下面ca11_vfunc 的反匯編版本說(shuō)明了如何解析虛函數(shù)調(diào)用:

.text :004010A0 call_vfunc ? ? ? proc near

.text :004010A0?

.text :004010A0 b ? ? ? ? ? ? ? ? ? = dword ptr,8

.text :004010A0

.text :004010A0 ? ? ? ? ? ? ? ? ? ? ? ? ?push ? ? ? ? ?ebp

.text :004010A1 ? ? ? ? ? ? ? ? ? ? ? ? ? mov? ? ? ? ? ebp,esp

.text :004010A3 ? ? ? ? ? ? ? ? ? ? ? ? ? mov ? ? ? ? ?[ebp+b]

.text :004010A6 ? ? ? ? ? ? ? ? ? ? ? ? ? mov ? ? ? ? ?edx,[eax]

.text :004010A8 ? ? ? ? ? ? ? ? ? ? ? ? ? mov ? ? ? ecx,[ebp+b]

.text :004010AB ? ? ? ? ? ? ? ? ? ? ? ? ? mov? ? ? ? eax,[edx+8]

.text :004010AE ? ? ? ? ? ? ? ? ? ? ? ? ?call ? ? ? ? eax

.text :004010B0 ? ? ? ? ? ? ? ? ? ? ? ? ??pop ? ? ? ?ebp ?

.text :004010B1 ? ? ? ? ? ? ? ? ? ? ? ? ?retn

.text :004010B1 ?call vfunc ? ? ? endp

在A6處,虛表指針從結(jié)構(gòu)體中讀取出來(lái)得糜,保存在EDX 寄存器中敬扛。由于參數(shù)b 指向一個(gè)SubClass對(duì)象,這里也將是SubClass 的虛表的地址朝抖。在AB處啥箭,虛表被編入索引,將第三個(gè)指針(在本位中為SubClass ::vfunc3 的地址) 讀人EAX 寄存器治宣。最后急侥,在AE處調(diào)用虛函數(shù)。

AB處的虛表索引操作非常類(lèi)似于結(jié)構(gòu)體引用操作侮邀。我們可以定義一個(gè)結(jié)構(gòu)體來(lái)表示一個(gè)類(lèi)的虛表的布局坏怪,然后利用這個(gè)已定義的結(jié)構(gòu)體來(lái)提高反匯編代碼清單的可讀性,如下所示:

00000000 ? SubClass vtable struc ;(sizeof=0x14)

00000000 vfunc1 ? ? ? ? ? ?dd?

00000004 vfunc2 ? ? ? ? ? ?dd?

00000008 vfunc 3 ? ? ? ? ?dd?

0000000C vfunc4 ? ? ? ? ? ? dd?

00000010 vfunc5? ? ? ? ? ? dd?

00000014 SubClass vtable ends

結(jié)構(gòu)體允許將虛表引用操作重新格式化成:

mov ? eax,[edx+SubClass_vtable.vfunc3]

對(duì)象生命周期:對(duì)全局和靜態(tài)分配的對(duì)象绊茧,構(gòu)造函數(shù)中程序啟動(dòng)并進(jìn)入main函數(shù)之前被調(diào)用铝宵;棧分配的對(duì)象的構(gòu)造函數(shù)在對(duì)象進(jìn)入聲明對(duì)象的函數(shù)作用域中時(shí)被調(diào)用。一般對(duì)象一進(jìn)入聲明它的函數(shù)按傅,它的構(gòu)造函數(shù)就被調(diào)用捉超,如果對(duì)象在一個(gè)塊語(yǔ)句中聲明,它的構(gòu)造函數(shù)知道塊被輸入時(shí)才被調(diào)用(確實(shí)被輸入)唯绍。如果對(duì)象在程序堆中動(dòng)態(tài)分配則有二:一拼岳,調(diào)用new操作符分配對(duì)象的內(nèi)存,二况芒,調(diào)用構(gòu)造函數(shù)來(lái)初始化對(duì)象惜纸。vc++與gun g++主要區(qū)別:前者可確保在調(diào)用構(gòu)造函數(shù)之前new的結(jié)果不為null(空)

執(zhí)行一個(gè)構(gòu)造函數(shù)時(shí)叶撒,將會(huì)發(fā)生以下操作。

(1) 如果類(lèi)擁有一個(gè)超類(lèi)耐版,則調(diào)用超類(lèi)的構(gòu)造函數(shù)祠够。

(2) 如果類(lèi)包含任何虛函數(shù),則初始化虛表指針粪牲,使其指向類(lèi)的虛表古瓤。注意,這樣做可能會(huì)覆蓋一個(gè)在超類(lèi)中初始化的虛表指針腺阳,這實(shí)際上是希望的結(jié)果落君。

(3) 如果類(lèi)擁有本身就是對(duì)象的數(shù)據(jù)成員,則調(diào)用這些數(shù)據(jù)成員的構(gòu)造函數(shù)亭引。

(4) 最后绎速,執(zhí)行特定于代碼的構(gòu)造函數(shù)。這些是程序員指定的焙蚓、表示構(gòu)造函數(shù)C++行為的代碼纹冤。

構(gòu)造函數(shù)并未指定返回類(lèi)型,但由Microsoft Visual C++生成的構(gòu)造函數(shù)實(shí)際上返回到EAX寄存器中的thi s 指針购公。無(wú)論如何萌京,這是一個(gè)Visual C+實(shí)現(xiàn)細(xì)節(jié),并不允許C++程序員訪(fǎng)問(wèn)返回值君丁。析構(gòu)函數(shù)基本上按相反的順序調(diào)用枫夺。對(duì)于全局和靜態(tài)對(duì)象,析構(gòu)函數(shù)由在main函數(shù)結(jié)束后執(zhí)行的清理代碼調(diào)用绘闷。棧分配的對(duì)象的析構(gòu)函數(shù)在對(duì)象脫離作用域時(shí)被調(diào)用。堆分配的對(duì)象的析構(gòu)函數(shù)在分配給對(duì)象的內(nèi)存釋放之前通過(guò)delete 操作符調(diào)用较坛。

析構(gòu)函數(shù)執(zhí)行的操作與構(gòu)造函數(shù)執(zhí)行的操作大致相同印蔗,唯一不同的是,它以大概相反的順序執(zhí)行這些操作丑勤。

(1) 如果類(lèi)擁有任何虛函數(shù)华嘹,則還原對(duì)象的虛表指針,使其指向相關(guān)類(lèi)的虛表法竞。如果一個(gè)子類(lèi)在創(chuàng)建過(guò)程中覆蓋了虛表指針耙厚,就需要這樣做。

(2) 執(zhí)行程序員為析構(gòu)函數(shù)指定的代碼岔霸。

(3) 如果類(lèi)擁有本身就是對(duì)象的數(shù)據(jù)成員薛躬,則執(zhí)行這些成員的析構(gòu)函數(shù)。

(4) 最后呆细,如果對(duì)象擁有一個(gè)超類(lèi)型宝,則調(diào)用超類(lèi)的析構(gòu)函數(shù)。

通過(guò)了解超類(lèi)的構(gòu)造函數(shù)和析構(gòu)函數(shù)何時(shí)被調(diào)用,我們可以通過(guò)相關(guān)超類(lèi)函數(shù)的調(diào)用鏈趴酣,跟蹤一個(gè)對(duì)象的繼承體系梨树。有關(guān)虛表的最后一個(gè)問(wèn)題涉及它們?cè)诔绦蛑腥绾伪灰谩R粋€(gè)類(lèi)的虛表被直接引用岖寞,只存在兩種情況: 在該類(lèi)的構(gòu)造函數(shù)中引用和在析構(gòu)函數(shù)中引用抡四。定位一個(gè)虛表后,可以利用IDA 的數(shù)據(jù)交叉引用功能迅速定位相關(guān)類(lèi)的所有構(gòu)造函數(shù)和析構(gòu)函數(shù)

名稱(chēng)改編(名稱(chēng)修飾):是c++編譯器用于區(qū)分重載函數(shù)的機(jī)制仗谆,為了給重載函數(shù)生成唯一的名稱(chēng)編譯器用其他字符來(lái)修飾函數(shù)名稱(chēng)床嫌,用來(lái)編碼關(guān)于函數(shù)的各種信息,編碼后的信息描述函數(shù)的返回類(lèi)型胸私,所屬的類(lèi)和調(diào)用該參數(shù)所需的參數(shù)序列(類(lèi)型和順序)厌处。名稱(chēng)改編是C++程序的一個(gè)編譯器實(shí)現(xiàn)細(xì)節(jié),本身并不屬于C++語(yǔ)言規(guī)范岁疼,但通常IDA理解阔涉,并以注釋的形式顯示原始名稱(chēng)。

Options->Demangled Names 可選擇 demangle選項(xiàng)

改編名稱(chēng)能提供大量與函數(shù)簽名有關(guān)的信息捷绒,方便ida自己去識(shí)別函數(shù)

運(yùn)行時(shí)類(lèi)型識(shí)別(RTTI)也是編譯器實(shí)現(xiàn)細(xì)節(jié)瑰排,不是語(yǔ)言問(wèn)題。下面有例子:

class abstract_class{

public :

? ? ? ? ?virtual int vfunc()= o;

};

class concrete_class: public abstract_class {

public :

? ? ? concrete_class() ;

? ? ? int vfunc( );

};

void print_type(abstract_class*p) {

? ? ? ?cout << typeid(*p).name() < endl;

};

int main() {

? ? ? ? abstract_class *sc = new concrete_class();

? ? ? ? print_type(sc);

};

print_type 函數(shù)必須正確打印指針P 所指向的對(duì)象的類(lèi)型暖侨。在這個(gè)例子中椭住,基于main 函數(shù)創(chuàng)建了一個(gè)concrete_class 對(duì)象這個(gè)事實(shí),concrete_class 必須被打印字逗。那print_type,更具體的說(shuō)是typeid,如何知道p 指向的對(duì)象的類(lèi)型京郑?

因?yàn)槊總€(gè)多態(tài)對(duì)象都包含一個(gè)指向虛表的指針,編譯器將類(lèi)的類(lèi)型信息與類(lèi)虛表存儲(chǔ)在一起葫掉。具休來(lái)說(shuō)些举,編譯器在類(lèi)虛表之前放置一個(gè)指針,這個(gè)指針指向一個(gè)結(jié)構(gòu)體俭厚,其中包含用于確定擁有虛表的類(lèi)的名稱(chēng)所需的信息户魏。在g++代碼中,這個(gè)指針指向一個(gè)type_info結(jié)構(gòu)體挪挤,其中包含一個(gè)指向類(lèi)名稱(chēng)的指針叼丑。在VC+代碼中,指針指向一個(gè)微軟RTTCompleteObjectLocator 結(jié)構(gòu)體扛门,其中又包含一個(gè)指向TypeDescriptor 結(jié)構(gòu)體的指針鸠信。TypeDescriptor結(jié)構(gòu)體中則包含一個(gè)指定多態(tài)類(lèi)名稱(chēng)的字符數(shù)組。只有使用typeid 或dynamiCast 操作符的C++程序才需要RTT信息尖飞。多數(shù)編譯器都提供一些選項(xiàng)症副,禁止不需要RTTI 的二進(jìn)制文件生成RTT 店雅。

繼承關(guān)系:從RTTI出發(fā)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市贞铣,隨后出現(xiàn)的幾起案子闹啦,更是在濱河造成了極大的恐慌,老刑警劉巖辕坝,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件窍奋,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡酱畅,警方通過(guò)查閱死者的電腦和手機(jī)琳袄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)纺酸,“玉大人窖逗,你說(shuō)我怎么就攤上這事〔褪撸” “怎么了碎紊?”我有些...
    開(kāi)封第一講書(shū)人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)樊诺。 經(jīng)常有香客問(wèn)我仗考,道長(zhǎng),這世上最難降的妖魔是什么词爬? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任秃嗜,我火速辦了婚禮,結(jié)果婚禮上顿膨,老公的妹妹穿的比我還像新娘锅锨。我一直安慰自己,他們只是感情好虽惭,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布橡类。 她就那樣靜靜地躺著,像睡著了一般芽唇。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上取劫,一...
    開(kāi)封第一講書(shū)人閱讀 52,156評(píng)論 1 308
  • 那天匆笤,我揣著相機(jī)與錄音,去河邊找鬼谱邪。 笑死炮捧,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的惦银。 我是一名探鬼主播咆课,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼末誓,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了书蚪?” 一聲冷哼從身側(cè)響起喇澡,我...
    開(kāi)封第一講書(shū)人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎殊校,沒(méi)想到半個(gè)月后晴玖,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡为流,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年呕屎,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片敬察。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡秀睛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出莲祸,到底是詐尸還是另有隱情蹂安,我是刑警寧澤,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布虫给,位于F島的核電站藤抡,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏抹估。R本人自食惡果不足惜缠黍,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望药蜻。 院中可真熱鬧瓷式,春花似錦、人聲如沸语泽。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)踱卵。三九已至廊驼,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間惋砂,已是汗流浹背妒挎。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留西饵,地道東北人酝掩。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像眷柔,于是被迫代替她去往敵國(guó)和親期虾。 傳聞我的和親對(duì)象是個(gè)殘疾皇子原朝,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容