new 一个结构体数组_每天一个IDA小技巧(四):结构体识别
之前提到IDA可以將一長串的數組數據聲明變成一行數組聲明,簡化反匯編代碼,對于結構體,IDA也同樣支持通過各種設置工具來改善結構體代碼的可讀性。
這篇文章的目標是將[edx+10h]之類的結構體元素訪問 變成 [edx+struct_filed5]之類。
只要發現一個程序正操縱某種數據結構,你就需要確定:你是否希望將結構體的字段名稱合并到反匯編代碼清單中,或者你是否理解分散在代碼清單中的所有數字偏移量。
如果是C標準庫或者IDA能夠確定的已知結構體,IDA會自動將數字偏移量轉換成更加符號化的字段名稱,但如果是自定義的結構體,就需要我們手動幫助IDA進行識別。
IDA之所以在分析階段無法識別結構體,可能源于兩個原因。首先,雖然IDA了解某個結構體的布局,但它并沒有足夠的信息,能夠判斷程序確實使用了結構體。其次,程序中的結構體可能是一種IDA對其一無所知的非標準結構體。在這兩種情況下,問題都可以得到解決,且首先從Structures窗口下手。
創建一個新的結構體(或Union)
在IDA Structures窗口(默認展示,如果沒有可以在View -> Open SubViews里打開)中,列舉了當前反匯編文件的所有已知結構體,并且在注釋中也提示了我們如何在該窗口中添加/刪除/編輯一個結構體:
00000000 ; Ins/Del : create/delete structure 或者 Edit -> Add struct type
00000000 ; D/A/* : create structure member (data/ascii/array)
00000000 ; N : rename structure or structure member
00000000 ; U : delete structure member
注意:只有當一個字段是結構體中的最后一個字段時,使用U鍵才能刪除該字段。對于所有其他字段,按下U鍵將取消該字段的定義,這樣做僅僅刪除了該字段的名稱,并沒有刪除分配給該字段的字節。
為了創建一個新的結構體,你必須首先在Structure name(結構體名稱)字段中指定結構體的名稱。前兩個復選框用于決定新結構體在Structures窗口中的顯示位置,或者是否在窗口中顯示新結構體。第三個復選框Creat union(創建聯合),指定你定義的是否為C風格聯合結構體(Union和結構體的區別在于union中字段相互重疊,因此總大小等于其中最大字段的大小)。
此外還有一個按鈕「add standard structure」,用于添加標準結構體。IDA內置了大量的各種庫和API函數有關的數據結構,IDA會嘗試確定與二進制文件有關的編譯器和平臺,并加載適當的結構體模板。單擊這個按鈕,IDA將顯示與當前編譯器(在分析階段檢測出來)和文件格式有關的結構體主列表。這個結構體主列表中還包含通過解析C頭文件添加到數據庫中的結構體。
編輯結構體成員
為了給新結構體添加字段,你必須利用字段創建命令D、A和數字鍵盤上的星號鍵(*),需要注意的是D快捷鍵還可用于為當前光標所所在的字段調整數據大小。所以推薦的創建結構體的步驟為:
在結構體定義的最后一行(包含ends的那一行)按下D鍵,這時候,IDA會在結構體末尾添加一個新字段,默認的字段名稱為filed_N,N為結構體開頭到字段開頭的數字偏移量。
如果需要修改字段大小,可以重復按D,循環數據轉盤上的數據類型,或者通過Options->Setup Data Types來指定一個在數據轉盤上不存在的大小,如果是數組,右鍵名稱然后選擇Array。
如果要更改字段名稱,使用N或者右鍵然后Rename
如果知道結構體的大小,而不了解它的布局,你需要創建兩個字段。第一個字段為一個數組,它的大小為結構體的大小減去1個字節(size-1);第二個字段應為1個字節。創建第二個字段后,取消第一個(數組)字段的定義。這樣,結構體的大小被保留下來,隨后,當你進一步了解該結構體的布局后,你可以回過頭來定義它的字段及其大小。
此外,在你定義和編輯結構體時,IDA會有一些提示:
一個字段的字節偏移量以一個8位十六進制值在Structures窗口的左側顯示。
每次你添加或刪除一個結構體字段,或更改一個現有字段的大小時,結構體的新大小都會在結構體定義的第一行反映出來。
你必須對一個結構體定義中的所有字段進行適當的對齊。如果你需要填補字節,那么你必須負責添加這些字節。填補字節最好作為適當大小的啞字段添加。
分配到結構體中間的字節只有在取消關聯字段的定義后才能刪除,使用Edit?Shrink Struct Type(縮小結構體類型)即可刪除被取消定義的字節。
你也可以在結構體的中間添加新的字節:選擇新字節后面的一個字段,然后使用Edit?Expand Struct Type(擴大結構體類型)在選中的字段前插入一定數量的字節。
通過重復應用這些步驟(添加字段,設置字段大小,添加填補字節等),就可以完成IDA結構體定義的創建。接下來就可以利用這些定義好的結構體改善反匯編代碼。
使用結構體模版
前面提到這篇文章的目標是將[edx+10h]之類的結構體元素訪問 變成 [edx+struct_filed5]之類。
此時有了結構體定義之后,就可以右鍵10h,選擇Structure Offset(結構體偏移量)選項,然后就可以進行格式化了,如果有多個結構體中字段匹配上了偏移量,則會有多個選擇。
如果是棧變量或者全局變量,則可以直接將棧和全局變量格式化為整個結構體,首先打開棧幀的詳細視圖(雙擊函數棧幀中的變量),然后使用ALT+Q(Edit->Struct Var)命令顯示一組已知的結構體并選擇對應想要格式化的結構體即可。如果是全局變量,則選擇要格式化的全局變量或者表示結構體開頭部分的地址,再使用ALT+Q(Edit->Struct Var)即可。
重新格式化之后,IDA認識到,任何對分配給var_18的24個字節塊的內存引用,都必須引用該結構體中的一個字段。如果IDA發現這樣一個引用,它會盡一切努力,將這個內存引用與結構體變量中的一個已定義的字段關聯起來。
導入結構體
IDA能夠解析C(而非C++)數據聲明,以及整個C頭文件,并自動為在這些聲明或頭文件中定義的結構體創建對應的IDA結構體。如果你碰巧擁有你正進行逆向工程的二進制文件的源代碼,或者至少是頭文件,那么,你就可以讓IDA直接從源代碼中提取出相關結構體,從而節省大量時間。
解析C結構體聲明
如果我們已經有某個結構體的聲明代碼,那可以直接在View?Open Subviews?Local Types(查看?打開子窗口?本地類型)窗口中,輸入我們的結構體聲明代碼,例如:
注意,IDA解析器使用4字節的默認結構體成員對齊方式。如果你的結構體需要其他對齊方式,你可以包括該對齊方式,IDA認可使用pragma pack指令來指定所需的結構體成員對齊方式。
添加到Local Types(本地類型)窗口中的數據類型不會立即在Structures(結構體)窗口中出現。有兩種方法可以將本地類型聲明添加到Structures窗口中。最簡單的方法是在相關本地類型上單擊鼠標右鍵,并選擇Synchronize to idb。或者,由于每個新類型均被添加到標準結構體列表中,因而也可將新類型導入到Structures窗口中即add standard structure。
解析C頭文件
要解析頭文件,可以使用File?Load File?Parse C Header File(文件?加載文件?解析C頭文件)選擇你想要解析的頭文件。如果一切正常,IDA會通知你Compilation successful(編譯完成)。如果解析器遇到任何問題,IDA將會在輸出窗口中顯示錯誤消息。
IDA會將所有被成功解析的結構體添加到當前數據庫的標準結構體列表末尾,此時同樣需要手動從標準結構體列表中添加到Structures窗口中。如果新結構體的名稱與現有結構體的名稱相同,IDA會用新結構體布局覆蓋原有結構體定義。
一般而言,要最大限度地提高成功解析一個頭文件的幾率,你需要使用標準C數據類型,并盡可能地減少使用include文件,從而最大程度地簡化結構體定義。記住,在IDA中創建結構體時,正確布局最為重要。正確的布局更多地取決于每個字段的正確大小和結構體的正確對齊,而不只是對每個字段都使用正確的類型。
IDA TIL文件(Type Library)
IDA中的所有數據類型和函數原型信息都存儲在TIL文件中。IDA擁有存儲在/til目錄中的許多主要編譯器和API的類型庫信息。Types窗口(View?Open subview?Type Libraries)列出了當前加載的.til文件,并可用于加載你想要使用的其他.til文件。IDA將根據在分析階段發現的二進制文件屬性,自動加載類型庫。正常情況下,一般不需要直接處理.til文件。
IDA還利用.til文件存儲你在Structures窗口中手動創建的或者通過解析C頭文件獲得的任何自定義結構體定義。這些結構體存儲在一個與創建它們的數據庫有關的專用.til文件中。該文件的名稱與其相關數據庫的名稱相同,擴展名為.til。
例如,如果數據庫名為some_file.idb,則相應的類型庫文件則為some_file.til。
.idb文件實際上是一個歸檔文件(類似于.tar文件),用于保存不使用的數據庫組件。打開一個數據庫時,其組件文件(.til文件為其中之一)將被提取出來,成為IDA中的運行文件。
在其他數據庫中共享til文件
有兩種共享方法。第一種方法有些不太正規,即將.til文件由打開的數據庫復制到另一個目錄中,然后再通過Types窗口,在任何其他數據庫中打開這個.til文件。第二種是一種正式的方法,即從一個數據庫中提取出自定義類型信息,生成一段IDC腳本,用于在任何其他數據庫中重建自定義結構體。使用File?Produce File?Dump Type. into to IDC File(文件?生成文件?轉儲類型信息到IDC文件)命令可生成該腳本。但是,與第一種方法不同的是,這種方法只能轉儲Structures窗口中列出的結構體,但并不轉儲通過解析C頭文件得到的結構體(而復制.til文件卻可以轉儲這類結構體)。
總結
以上是生活随笔為你收集整理的new 一个结构体数组_每天一个IDA小技巧(四):结构体识别的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java finalize 何时被调用_
- 下一篇: 树叶贴画机器人_洪山广场举办“落叶节”,