1. 程式人生 > >第四章——64位軟體逆向技術-基本語法(上)

第四章——64位軟體逆向技術-基本語法(上)

1.暫存器     x64系統通用暫存器名稱,第一個字母從“E”改為“R”,數量增加了8個,(R8-R15),增加了8個128位XMM暫存器(XMM暫存器用來優化程式碼)   用表格示意:  說明:

2.棧平衡 棧的基本入棧出棧操作和32位一樣,需要注意就是在64位環境下,彙編指令對棧頂的對其值有要求,因此在VS編譯器申請空間的時候,會盡力保證棧頂地址為對其值16.(被16整除) 在逆向中發現棧空間不使用的情況,可能為了實現對齊   3.呼叫約定 64位應用程式只有1種暫存器快速呼叫,前4個引數使用暫存器傳遞,超過4個引數就放到棧裡,入棧的順序是從右往左, 前四個暫存器是固定的 RCX,RDX,R8,R9. 所有大於8位元組的,不是1.2.4.8位元組的引數都由引用來傳遞 所有的浮點引數的傳遞都是使用XMM暫存器完成,他們在XMM0,XMM1,XMM2,XMM3中傳遞   例如:如果存在一個函式為  void fun(float,int float,int)     那麼引數傳遞順序第一個引數(XMM0),第二個引數(RDX)  第三個引數(XMM2) 第四個引數(R9)   函式的前4個引數雖然使用暫存器來傳遞,但是棧還會為這4個引數保留空間(32位元組) 這裡稱為預留棧空間 為什麼要這麼做? 因為我們使用暫存器傳參的缺點是如果我們的函式呼叫較為複雜,暫存器會存在不夠用的情況(4個用來傳參了)這是就會利用棧空間暫時儲存暫存器的數值,當函式呼叫完畢再由呼叫者恢復堆疊。   4.64位的資料結構 區域性變數         例如函式入口指令為sub rsp,30h.從rsp+0h到rsp+20h為32位元組預留棧空間,rsp+20h到rsp+30h為區域性變數空間,也等於預留棧空間在低地址,區域性變數空間在高地址         區域性變數通常都在棧中儲存,如果是Release編譯並暫存器夠用,區域性變數可能會在暫存器中儲存   全域性變數         全域性變數的地址在編譯器時候就固定了,先定義的在低地址,後定義的在高地址。根據這個特徵可以確定定義順序   陣列         陣列的結構相對來說是較為“整齊”,陣列中的資料在記憶體中的儲存是線性連續的,從低地址到高地址的儲存。     Ps:int型資料在64位系統下還是32位的大小,如果要用64位則可以用long 或者 __int64     訪問陣列的時候就是陣列首地址+資料型別大小*下標   控制語句         if語句和32位一樣,不多贅述         switch-case效率高於if 。switch分支數小於6時,會直接用if else來實現,大於等於6時候會進行編譯器優化。優化方式就是case的值間隔比較小就會採用case表的方式去呼叫case內容         當case的內容較多的時候,就需要用二叉樹來講case比較次數進行優化(折中比較,逐漸縮小範圍)     64位下轉移指令機器碼的計算     JMP: 和32位的計算方式相同:              位移量=目的地址-起始地址-跳轉指令的長度                      轉移指令機器碼=轉移類別機器碼+位移量  (JMP xxxx   E9 xx)     CALL: call的使用方式和32位下略有不同                 32位下例如                 CALL dword ptr ds:[42413C]   對應的機器碼就是 FF15 3C414200.這裡的43413C是絕對地址                 64位就是相對地址:     
     相對地址=14000B388-1400018CB-指令長度=9ABD-6=9AB7           機器碼=FF15+相對地址=FF157B79A0000