匯編掌握程度
能看懂就行,絕大多數情況不需要真正的編程(shellcode題除外)
其實有時候也不需要讀匯編,ida F5
通常都是分析gadget,知道怎么用,
調試程序也不需要分析每一條匯編指令,單步執行然后查看寄存器狀態即可
但是必須得會,學pwn必須會匯編
前置準備
一些量詞
計算機尋址方式
在當前主流的操作系統中,都是以字節(B)為尋址單位進行尋址,
意味著計算機訪問的最小單位是一個字節(B)
類比于人口普查,普查員以每戶(B)為單位統計,而不是訪問到個人(b)?
計算機并不能直接運行高級語言
我們編寫的高級語言程序需要進行編譯后才能在計算機上運行。高級語言經過編譯之后,經過編譯器處理,被打包成一個可執行文件的格式,
那么,計算機真正能夠被運行的是機器碼01?
機器碼
深入底層后,計算機其實很笨,只能完成一些很基本的操作,但是速度很快機器碼就是一個個01組成的,為了方便人類閱讀,一般都以16進制呈現。
盡管如此,一個個16進制字符可讀性仍然很差
匯編語言就是把這些機器指令代碼以一個助記符的形式翻譯一下,方便人類閱讀。
匯編語言就是機器碼的一個助記符
寄存器
計算機的指令都是由CPU來執行
在計算機系統結構中,CPU和內存是分開的。
寄存器存在于CPU中,是CPU的直接操作對象
寄存器種類
上述的通用寄存器,通常用于參數傳遞以及算數運算等通用場合
RSP為棧頂指針,RBP為棧底指針,二者用于維護程序運行時的函數,在之后的調用約定一節會對其進行講解。
EFLAGS為標志位寄存器,用于存儲CPU運行計算過程中的狀態,:如進位溢出等。
RIP指針用于存儲CPU下一條將會執行的指針,不能直接修改,正常情況下會每一次運行一條指令自增一條指令的長度,當發生跳轉時才會以其他形式改變其值
尋址方式
匯編指令
intel中匯編兩個操作數指令的目的寄存器都是第一個寄存器
計算機只能完成很基本的操作。這些操作大多是對一些寄存器的值進行修改
這些指令通過排列組合,完成復雜的功能,
兩種格式:intel和AT&T
二者差別主要在于源和目的操作數順序上
可以通過立即數尋址來進行判斷?
計算機在執行匯編代碼時,只會順序執行,
通過call、jmp、ret這種指令來完成跳轉
所以匯編指令代碼的執行流并不像高級語言程序一樣流程明確
匯編指令代碼會經常跳轉導致可讀性差一些
-
AND(位與):
and
?指令對兩個操作數的相應位進行邏輯與運算。- 如果兩個相應的位都是1,則結果位為1;否則為0。
- 例如,如果?
rax = 1010
?(二進制),rbx = 1100
?(二進制),執行?and rax, rbx
?后,rax
?將變為?1000
?(二進制)。
-
XOR(異或):
xor
?指令對兩個操作數的相應位進行邏輯異或運算。- 如果兩個相應的位相同,則結果位為0;如果不同,則結果位為1。
- 例如,如果?
rax = 1010
?(二進制),rbx = 1100
?(二進制),執行?xor rax, rbx
?后,rax
?將變為?0110
?(二進制)。
數上下限?
如果是unsigned 也就是無符號數,數據的每一位都是代表數據
如果是signed有符號數,那么數據的最高位會被當作符號位處理
0代表正數,1代表負數。
溢出
數值有上下限范圍,那么就不可避免的會有溢出情況。
以32位int為例,有以下四種溢出:
無符號上溢:0xffffffff+1變成0
無符號下溢:0-1變成0xffffffff
簡單來說無符號溢出0=1+0xffffffff
有符號上溢:有符號正數0x7fffffff +1 變成負數0x80000000
有符號下溢:有符號數0x80000000-1變成正數0x7fffffff?
簡單來說有符號溢出0x80000000=0x7fffffff+1
這就是整數溢出。通常來說原因就是兩點
1.存儲位數不夠
2.溢出到符號位
整數溢出一般配合別的漏洞來使用。