7.IDA-创建结构体
結構體分類
結構體的一個顯著特點在于,結構體中的數據字段是通過名稱訪問,而不是像數組那樣通過索引訪問。不好的是,字段名稱被編譯器轉換成了數字偏移量。結果,在反匯編代碼清單中,訪問結構體字段的方式看起來與使用常量索引訪問數組元素的方式極其相似。
注意的是,結構體中有個內存對齊規則,所以不要認為編譯器會利用所需的最小空間來分配結構體。默認情況下,編譯器會設法將結構體字段與內存地址對齊,以最有效地讀取和寫入這些字段
1. 全局分配的結構體
和全局分配的數組一樣,編譯器在編譯時可獲知全局分配的結構體的地址。這使得編譯器能夠在編譯時計算出結構體中每個成員的地址,而不必在運行時進行任何計算。
如下代碼:
[cpp]?view plaincopy對應匯編為:可以看到,在這個反匯編代碼清單中,訪問結構體成員不需要任何算術計算,如果沒有源代碼,你根本無法斷定這個程序使用了結構體。
[cpp]?view plaincopy
2. 棧分配的結構體
同樣,僅僅根據棧布局,同樣很難識別出棧分配的結構體。
[cpp]?view plaincopy對應匯編為:同樣,訪問結構體中的字段不需要進行任何算術計算,因為在編譯時,編譯器能夠確定棧幀內每個字段的相對偏移量
[cpp]?view plaincopy3. 堆分配的結構體
由于結構體的地址在編譯時未知,編譯器別無選擇,只有生成代碼來計算每個字段在結構體中的正確偏移量。
如果一個結構體在堆中分配,那么對編譯器來說,引用該結構體的唯一線索就是指向該結構體起始地址的指針。
[cpp]?view plaincopy對應匯編為:
[cpp]?view plaincopy4. 結構體數組
[cpp]?view plaincopy反匯編沒什么區別:與上面相比,每項加了24
[cpp]?view plaincopy
創建結構體
IDA之所以在分析階段無法識別結構體,可能源于兩個原因。首先,雖然IDA了解某個結構體的布局,但它并沒有足夠的信息,能夠判斷程序確實使用了結構體。其次,程序中的結構體可能是一種IDA對其一無所知的非標準結構體。在這兩種情況下,問題都可以得到解決,且首先從Structures窗口下手
1.添加結構體
Structures窗口的前4行文本用于提醒用戶該窗口中可能進行的操作。
使用熱鍵INSERT啟動
指定結構體的名稱并單擊OK按鈕后,IDA將在Structures窗口中創建一個空結構體定義
2.編輯結構體成員
(1)要給結構體添加新字段,將光標放在結構體定義的最后一行(包含ends的那一行)并按下D鍵。新字段的大小取決于你在數據轉盤上選擇的第一個大小
(2)如果需要修改字段的大小,首先將光標放在新字段的名稱上,然后重復按下D鍵,使數據轉盤上的數據類型開始循環,從而為新字段選擇正確的數據大小。另外,你還可以使用Options?Setup Data Types來指定一個在數據轉盤上不存在的大小。如果新字段是一個數組,右擊其名稱并在上下文菜單中選擇Array
(3)要更改一個結構體字段的名稱,單擊字段名稱并按下N鍵,或者右擊該名稱并在上下文菜單中選擇ReName,然后在輸入框中輸入一個名稱即可。
?
以下是幫助說明:
??一個字段的字節偏移量在Structures窗口的左側顯示。
?
??結構體的新大小會在結構體定義的第一行及時更新出來。
?
? ?可以給一個結構體字段添加注釋,就像給任何反匯編行添加注釋一樣。?
?
? ?只有當一個字段是結構體中的最后一個字段時,使用U鍵才能刪除該字段。對于其他字段,按下U鍵只是變成undefined,可以通過D鍵恢復
?
??IDA并不區分已壓縮和未壓縮的結構體。為將字段適當對齊,如果你需要填補字節,那么你必須負責添加這些字節。填補字節最好作為適當大小的啞字段添加。在添加額外的字段后,你可以選擇取消或保留這些字段的定義。
?
?分配到結構體中間的字節只有在取消關聯字段的定義后(undefined狀態),Edit?Shrink Struct Type(縮小結構體類型)即可刪除被取消定義的字節。
?
??也可以在結構體的中間添加新的字節:選擇新字節后面的一個字段,然后使用Edit?Expand Struct Type(擴大結構體類型)在選中的字段前插入一定數量的字節。
?如果知道結構體的大小,而不了解它的布局,你需要創建兩個字段。第一個字段為一個數組,它的大小為結構體的大小減去1個字節(size-1);第二個字段應為1個字節。創建第二個字段后,取消第一個(數組)字段的定義。這樣,結構體的大小被保留下來,隨后,當你進一步了解該結構體的布局后,你可以回過頭來定義它的字段及其大小。
創建完成后如下:
?
3.折疊打開結構體
可以選擇結構體中的任何字段并按下數字鍵盤中的減號鍵,將結構體的定義折疊成一行摘要,雙擊結構體名稱也可以打開該定義。(或ctrl+/ctrl-)
?
使用結構體模板
1.右擊中,可在上下文菜單上看到Structure offset選項:很明確的說明了它可以是stTest.f5+24(pst[1].f5 = 50.0;)
2.另一種方法,可以將棧和全局變量格式化成整個結構體,雙擊該變量,打開詳細棧幀視圖,然后使用Edit?Struct Var(ALT+Q)命令顯示一組已知的結構體
之后上面結構體數組匯編變為:重新格式化之后,IDA認識到,任何對分配給var_8的24個字節塊的內存引用,都必須引用該結構體中的一個字段。如果IDA發現這樣一個引用,它會盡一切努力,將這個內存引用與結構體變量中的一個已定義的字段關聯起來
[cpp]?view plaincopy將全局變量格式化成結構體的過程與格式化棧變量所使用的過程幾乎完全相同
導入新的結構體
在創建新結構體方面,IDA確實提供了一些捷徑。IDA能夠解析C(而非C++)數據聲明,以及整個C頭文件,并自動為在這些聲明或頭文件中定義的結構體創建對應的IDA結構體。如果你碰巧擁有你正進行逆向工程的二進制文件的源代碼,或者至少是頭文件,那么,你就可以讓IDA直接從源代碼中提取出相關結構體,從而節省大量時間。
使用View?Open Subviews?Local Types(查看?打開子窗口?本地類型)命令,可以打開Local Types子窗口,其中列出了所有解析到當前數據庫中的類型。
通過INSERT鍵或上下文菜單中的Insert選項解析:
?------------->
?
?解析C頭文件
要解析頭文件,可以使用File?Load File?Parse C HeaderFile(文件?加載文件?解析C頭文件)選擇你想要解析的頭文件。如果一切正常,IDA會通知你Compilation successful(編譯完成)。如果解析器遇到任何問題,IDA將會在輸出窗口中顯示錯誤消息
IDA會將所有被成功解析的結構體添加到當前數據庫的標準結構體列表中(具體地說,是列表的末尾)。如果新結構體的名稱與現有結構體的名稱相同,IDA會用新結構體布局覆蓋原有結構體定義。除非你明確選擇添加新的結構體,否則,新結構體不會出現在Structures窗口中
?默認情況下,解析器會建立4字節對齊的結構體,當然,你可以使用pack改變它
??解析器只能理解C標準數據類型。但是,解析器還能夠理解預處理器define指令和C typedef語句。因此,如果解析器之前遇到過適當的typedef,它將能夠正確解析unit32_t之類的類型。
??如果你沒有源代碼,那么你會發現,使用文本編輯器以C表示法迅速定義一個結構體布局,并解析得到的頭文件或把聲明粘貼為一個新的本地類型,會比使用IDA煩瑣的手動結構體定義工具更加方便。
添加到Local Types(本地類型)窗口中的數據類型不會立即在Structures(結構體)最簡單的方法是在類型上單擊鼠標右鍵,并選擇Synchronize to idb。
使用標準結構體
IDA能夠識別大量與各種庫和API函數有關的數據結構。當IDA在反匯編代碼清單中操縱結構體時,它會在Structures窗口中添加相應的結構體定義。因此,Structures窗口中顯示的是應用于當前二進制文件的已知結構體的子集。除了創建自定義結構體外,你還可以從IDA的已知結構體列表中提取出其他標準結構體,并將其添加到Structures窗口中。
首先,在Structures窗口中按下IN-SERT鍵。在Create structure/ union對話框中,包含一個Add standard structure(添加標準結構體)按鈕。單擊這個按鈕,IDA將顯示與當前編譯器(在分析階段檢測出來)和文件格式有關的結構體主列表。這個結構體主列表中還包含通過解析C頭文件添加到數據庫中的結構體。
示例:(分析文件頭)
默認情況下,在創建后,文件頭不會立即加載到數據庫中。但是,如果你在最初創建數據庫時選擇Manual load(手動加載)選項,就可以將文件頭加載到數據庫中。加載文件頭可確保只有與這些頭部有關的數據類型才出現在數據庫中。多數情況下,文件頭不會以任何形式被格式化,因為通常程序并不會直接引用它們自己的文件頭。因此,分析器也沒有必要對文件頭應用結構體模板。
?
對一個PE二進制文件進行一番研究后,你會發現,PE文件的開頭部分是一個名為IMAGE_DOS_HEADER的MS-DOS頭部結構體。另外,IMAGE_DOS_HEADER中的數據指向一個IM-AGE_NE_HEADER結構體的位置。
第一步是添加標準的IMAGE_DOS_HEADER結構體(你可以在打開IMAGE_NT_HEADER結構體的同時添加該結構體)。
第二步是使用Edit?Struct Var(ALT+Q),將從_Image-Base開始的字節轉換成一個IMAGE_DOS_HEADER結構體
?
總結
以上是生活随笔為你收集整理的7.IDA-创建结构体的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 5.IDA-文本搜索、二进制搜索(16进
- 下一篇: 8.IDA-数据与代码、函数互相转换