第四章——64位軟體逆向技術-基本語法(上)
阿新 • • 發佈:2018-12-10
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