14.IDA-XREF(交叉引用)概述

XREF分類

CODE XREF:代碼交叉引用 
DATA XREF:數據交叉引用

XREF描述含義

è¿éåå¾çæè¿°

  1. 這是個代碼交叉引用
  2. sub401000是被引用者,main+2A是引用者(引用sub401000的位置)
  3. 下箭頭表示引用者的地址比sub401000高,你需要向下滾動才能到達引用者地址(main+2A),上行反之~ 
  4. 每個交叉引用註釋都包含一個單字符後綴(箭頭後面),用以說明交叉引用的類型,這裏是↓P

CODE XREF

代碼交叉引用用於表示一條指令將控制權轉交給另一條指令。在IDA中,指令轉交控制權的方式叫做流(flow) 
IDA中有3種基本流:

普通流 
調用流 
跳轉流

 示例代碼:

int read_it; 
int write_it; 
int ref_it; 
void callflow() {} 

int main()
{
    int *p = &ref_it;
    *p = read_it;
    write_it = *p;
    callflow();
    if (read_it == 3)
    {
        write_it = 2;
    }
    else
    {
        write_it = 1;
    }
    callflow();
}

示例彙編:

.text:00401010 ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:00401010 _main           proc near               ; CODE XREF: __tmainCRTStartup+10Ap
.text:00401010
.text:00401010 p               = dword ptr -4
.text:00401010 argc            = dword ptr  8
.text:00401010 argv            = dword ptr  0Ch
.text:00401010 envp            = dword ptr  10h
.text:00401010
.text:00401010                 push    ebp
.text:00401011                 mov     ebp, esp
.text:00401013                 push    ecx
.text:00401014                 mov     [ebp+p], offset int ref_it
.text:0040101B                 mov     eax, [ebp+p]
.text:0040101E                 mov     ecx, int read_it
.text:00401024                 mov     [eax], ecx
.text:00401026                 mov     edx, [ebp+p]
.text:00401029                 mov     eax, [edx]
.text:0040102B                 mov     int write_it, eax
.text:00401030                 ③call    callflow(void)
.text:00401035                 cmp     int read_it, 3
.text:0040103C                 jnz     short loc_40104A
.text:0040103E                 mov     int write_it, 2
.text:00401048                 jmp     short loc_401054
.text:0040104A ; ---------------------------------------------------------------------------
.text:0040104A
.text:0040104A loc_40104A:                             ; CODE XREF: _main+2C↑j
.text:0040104A                 mov     int write_it, 1
.text:00401054
.text:00401054 loc_401054:                             ; CODE XREF: _main+38↑j
.text:00401054                 ③call    callflow(void)
.text:00401059                 xor     eax, eax
.text:0040105B                 mov     esp, ebp
.text:0040105D                 pop     ebp
.text:0040105E                 retn
.text:0040105E _main           endp
.text:0040105E

普通流

普通流表示由一條指令到另一條指令的順序流。這是所有非分支指令(如ADD)的默認執行流。

調用流

如果IDA認爲某個函數並不返回(在分析階段確定,注意不是運行階段),那麼,在調用該函數時,它就不會爲該函數分配普通流

.text:00401030 ③call callflow(void)

.text:00401054 ③call callflow(void)

指令用於調用函數,如③處的 call指令,它分配到一個調用流(call flow),表示控制權被轉交給目標函數 
callflow函數的反彙編:

.text:00401000 void __cdecl callflow(void) proc near   ; ①CODE XREF: _main+20↓p
.text:00401000                                         ; ①_main:loc_401054↓p
.text:00401000                 push    ebp
.text:00401001                 mov     ebp, esp
.text:00401003                 pop     ebp
.text:00401004                 retn
.text:00401004 void __cdecl callflow(void) endp

callflow所在的位置顯示了兩個交叉引用(①處),表示這個函數被調用了兩次

由函數調用導致的交叉引用使用後綴↓p(看做是Procedure)。

跳轉流

每個無條件分支指令和條件分支指令將分配到一個跳轉流(jump flow)

.text:00401048                 jmp     short loc_401054
.text:0040104A ; ---------------------------------------------------------------------------
.text:0040104A

無條件分支並沒有相關的普通流,因爲它總會進入分支。上處的虛線表示相鄰的兩條指令之間並不存在普通流(也就是00401048後沒有跟着順序執行的指令)

跳轉交叉引用使用後綴↑j(看做是Jump)。

DATA XREF

數據交叉引用用於跟蹤二進制文件訪問數據的方式。數據交叉引用與IDA數據庫中任何牽涉到虛擬地址的字節有關(換言之,數據交叉引用與棧變量毫無關係) 
最常用的3種數據交叉引用:

address何時被讀取(讀取交叉引用) 
address何時被寫入(寫入交叉引用) 
address何時被引用(偏移量交叉引用)

.data:00403378 int ref_it      db    ? ;               ; DATA XREF: _main+4↑o
.data:00403379                 db    ? ;
.data:0040337A                 db    ? ;
.data:0040337B                 db    ? ;
.data:0040337C int write_it    dd ?                    ; DATA XREF: _main+1B↑w
.data:0040337C                                         ; _main+2E↑w ...
.data:00403380 int read_it     dd ?                    ; DATA XREF: _main+E↑r
.data:00403380                                         ; _main+25↑r

 

讀取交叉引用

讀取交叉引用(read cross-reference)表示訪問的是某個內存位置的內容 
可以看到read_it在_main+E處、_main+25被讀取,如下

.text:0040101E mov ecx, int read_it

.text:00401035 cmp int read_it, 3

讀取交叉引用使用後綴↑r(看做是Read)。 

寫入交叉引用

寫入交叉引用指出了修改變量內容的程序位置 
可以看到write_it在_main+1B、_main+2E處被寫入,如下

.text:0040102B mov int write_it, eax

.text:0040103E mov int write_it, 2

 寫入交叉引用使用後綴↑w(看做是Write)。

偏移量交叉引用

偏移量交叉引用表示引用的是某個位置的地址(而非內容) 
可以看到ref_it在_main+4處被引用

.text:00401014 mov [ebp+p], offset int ref_it

偏移量交叉引用使用後綴↑o(看做是Offset)。

與僅源自於指令位置的讀取和寫入交叉引用不同,偏移量交叉引用可能源於指令位置或數據位置,例如虛表 
回溯偏移量交叉引用是一種有用的技術,可迅速在程序的數據部分定位C++虛表。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章