ios安全攻防之匯編

越底層越單純!真正的程序員都需要了解的一門非常重要的語言,匯編!

機器語言

  • 我們所寫的語言最終安裝在機器上的是什么東西?
  • 是機器語言,一堆的0和1.
    如0101 001 1101 0110,由0和1組成的機器指令,說白了還是電信號.
    這些指令讓我們的cup執行

匯編語言

  • 使用符號代替機器語言,也稱符號語言.如 mov ax,bx
  • 匯編和機器指令是一一對應的,每一條機器指令都有與之對應的匯編指令
  • 匯編語言可以通過編譯得到機器語言,機器語言可以通過反匯編得到匯編語言
  • 高級語言可以通過編譯得到匯編語言,但機器語言/匯編語言不能還原成高級語言

高級語言

  • 我們平時寫的Oc/swift/C/C++都屬于高級語言,更加接近人類的自然語言
我們的代碼在終端設備上是這樣的過程

匯編語言的特點

  • 可以直接訪問、控制各種硬件設備,比如存儲器、CPU等,能最大限度地發揮硬件的功能
  • 能夠不受編譯器的限制,對生成的二進制代碼進行完全的控制
  • 目標代碼簡短,占用內存少,執行速度快
  • 每一種CPU都有自己的機器指令集\匯編指令集,所以匯編語言不具備可移植性
  • 知識點過多,開發者需要對CPU等硬件結構有所了解,不易于編寫、調試、維護
  • 不區分大小寫,比如mov和MOV是一樣的
  • 在匯編中,大部分指令都是和CPU與內存相關的

匯編的用途

  • 編寫驅動程序、操作系統(比如Linux內核的某些關鍵部分)
  • 對性能要求極高的程序或者代碼片段,可與高級語言混合使用(內聯匯編)
  • 軟件安全
  • 病毒分析與防治
  • 逆向\加殼\脫殼\破解\外掛\免殺\加密解密\漏洞\黑客
    哇...破解 哇...外掛 哇...黑客 來自小學生的驚嘆 前段時間我弟弟讓我幫他盜號...! 我很無奈啊有木有...??
  • 理解整個計算機系統的最佳起點和最有效途徑
  • 為編寫高效代碼打下基礎
  • 弄清代碼的本質
  • 函數的本質究竟是什么?
  • sizeof
  • ++a + ++a + ++a 底層如何執行的?
  • 編譯器到底幫我們干了什么?
  • DEBUG模式和RELEASE模式有什么關鍵的地方被我們忽略

匯編語言的種類

  • 討論最多的匯編語言
  • 8086匯編(8086處理器是16bit的CPU)
  • Win32匯編
  • Win64匯編
  • ARM匯編(嵌入式、Mac、iOS)
  • ......
架構 設備
armv6 iPhone, iPhone2, iPhone3G, 第一代、第二代 iPod Touch
armv7 iPhone3GS, iPhone4, iPhone4S,iPad, iPad2, iPad3(The New iPad), iPad mini, iPod Touch 3G, iPod Touch4
armv7s iPhone5, iPhone5C, iPad4(iPad with Retina Display)
armv64 iPhone6s , iphone6s plus,iPhone6, iPhone6 plus,iPhone5S ,iPad Air, iPad mini2
APP/程序的執行過程

總線

  • 每一個CPU芯片都有許多管腳,這些管腳和總線相連,CPU通過總線跟外部器件進行交互
  • 總線:一根根導線的集合
  • 總線的分類
  • 地址總線
  • 數據總線
  • 控制總線
地址總線
  • 它的寬度決定了CPU的尋址能力
  • 8086的地址總線寬度是20,所以尋址能力是1M( 2^20 )
2 ^ 10  == 1024
2 ^ 20  == 2 ^ 10 * 2 ^ 10 = 1024 * 1024 = 1M
16^5 == 2^4^5 == 2^(4*5) == 2 ^ 20

2^20 == 1M
2^30 == 1G
2^32 == 1G*2^2 == 4G


數據總線
  • 它的寬度決定了cup單次傳輸數據的大小,也就是數據傳送速度
  • 數據總線直接影響cpu的吞吐量
  • 8086數據總線寬度是16,所以單次最大傳送2個字節的數據.
  • 1根數據總線代表一個bit位 十根 = 1KB
每一個16進制位代表4個bit,因為兩個16進制位位代表一個字節,一個字節8個bit

一個16進制位 = 4 bit
兩個16進制位 = 1字節
1字節 = 8bit

一個字節 = 8個bit = 2個16進制位
一個字 = 2個字節 (分別為高字節和低字節)

1 Byte == 8 bit
1B == 1Byte == 一個字節
1KB  == 1024 Byte
8KB == 1024 * 2^3
1MB  == 1024 * 1024 Byte
控制總線
  • 它的寬度決定了CPU對其他器件的控制能力、能有多少種控制

練習

  • 一個CPU 的尋址能力為8KB,那么它的地址總線的寬度為 (13)
尋址能力均是以字節為單元的
1KB = 10根線
1KB = 1024Byte
8=2^3
1024=2^10
8KB = 8*1024=2^3*2^10=2^(3+10)=2^13
  • 8080,8088,80286,80386 的地址總線寬度分別為16根,20根,24根,32根.那么他們的尋址能力分別為多少(64)KB, (1)MB
16根 = 2^6 = 64KB
20根 = 2^20 = 1MB
24根 = 2^24 = 2^20 * 2^4 = 16MB
32根 = 2^32 = 1G*2^2 = 4G  
  • 從內存中讀取1024字節的數據,8086至少要讀(512)次,80386至少要讀取(256)次.
8086數據總線寬度是16,單次最大傳送2個字節的數據
```


#寄存器
* 對程序員來說,CPU中最主要部件是寄存器,可以通過改變寄存器的內容來實現對CPU的控制
* 不同的CPU,寄存器的個數、結構是不相同的(8086是16位結構的CPU)
* 8086有14個寄存器
  * 都是16位寄存器,可以放兩個字節
![8086內部寄存器](http://upload-images.jianshu.io/upload_images/6990647-3392e0666c641b12.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

#####通用寄存器
* AX、BX、CX、DX這4個寄存器通常用來存放一般性的數據,稱為通用寄存器(有時也有特定用途)
* 通常,CPU會先將內存中的數據存儲到通用寄存器中,然后再對通用寄存器中的數據進行運算

  * 假設內存中有塊紅色內存空間的值是3,現在想把它的值加1,并將結果存儲到藍色內存空間
![](http://upload-images.jianshu.io/upload_images/6990647-aaa413d7a51629bc.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

  * 過程
    * cpu通過地址總線找到紅色內存空間
    * 再通過控制總線告訴內存條我要讀
    - 再通過數據總線讀給cpu(cpu通過運算器+1 )
    - 在通過cpu通過地址總線找到藍色內存
    - 通過控制總線告訴內存我要寫
    - 通過數據總線把值傳給藍色內存
  * 代碼過程
    - mov ax,紅色內存空間
    - add ax,1
    - mov 藍色內存,ax

- 上一代8086的寄存器都是8位的,為了保證兼容, AX、BX、CX、DX都可分為2個獨立的8位寄存器來使用
 - H代表高位寄存器
 - L代表低位寄存器

![](http://upload-images.jianshu.io/upload_images/6990647-608b1e8abe5aa552.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![](http://upload-images.jianshu.io/upload_images/6990647-0775d3c4209e7cbe.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

#8086的尋址方式
* CPU訪問內存單元時,要給出內存單元的地址,所有的內存單元都有唯一的地址,叫做物理地址
* 8086有20位地址總線,可以傳送20位的地址,1M的尋址能力
* 但它又是16位結構的CPU,它內部能夠一次性處理、傳輸、暫時存儲的地址為16位。如果將地址從內部簡單地發出,那么它只能送出16位的地址,表現出來的尋址能力只有64KB

**8086采用一種在內部用2個16位地址合成的方法來生成1個20位的物理地址**
![](http://upload-images.jianshu.io/upload_images/6990647-423c026e836e94ea.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![](http://upload-images.jianshu.io/upload_images/6990647-27dfee5fbe7449b3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

#內存分段管理
- 8086是用“基礎地址(段地址×16) + 偏移地址 = 物理地址”的方式給出物理地址
- 在編程時可以根據需要,將若干連續地址的內存單元看做一個段,用段地址×16定為段的起始地址(基礎地址),用偏移地址定位段中的內存單元

#段寄存器
 * 8086有4個段寄存器:CS、DS、SS、ES,當CPU需要訪問內存時由這4個段寄存器提供內存單元的段地址
  - CS (Code Segment):代碼段寄存器
  - DS (Data Segment):數據段寄存器
  - SS (Stack Segment):堆棧段寄存器
  - ES (Extra Segment):附加段寄存器

#CS和IP
 - CS為代碼段寄存器,IP為指令指針寄存器,它們指示了CPU當前要讀取指令的地址
 - 任意時刻,8086CPU都會將CS:IP指向的指令作為下一條需要取出執行的指令 (指向下一條指令的地址)

#指令和數據
 * 在內存或者磁盤上,指令和數據沒有任何區別,都是二進制信息
 - CPU在工作的時候把有的信息看做指令,有的信息看做數據,為同樣的信息賦予了不同的意義
 - CPU根據什么將內存中的信息看做指令?
  - CPU將CS:IP指向的內存單元的內容看做指令
  - 如果內存中的某段內容曾被CPU執行過,那么它所在的內存單元必然被CS:IP指向過

#jmp指令<修改cs、ip的值>
- CPU從何處執行指令是由CS、IP中的內容決定的,我們可以通過改變CS、IP的內容來控制CPU執行目標指令
- 8086提供了一個mov指令(傳送指令),可以用來修改大部分寄存器的值,比如
 - mov ax,10、mov bx,20、mov cx,30、mov dx,40
- 但是,mov指令不能用于設置CS、IP的值,8086沒有提供這樣的功能
- 8086提供了另外的指令來修改CS、IP的值,這些指令統稱為轉移指令,最簡單的是jmp指令

#DS和[address]
- CPU要讀寫一個內存單元時,必須要先給出這個內存單元的地址,在8086中,內存地址由段地址和偏移地址組成
- 8086中有一個DS段寄存器,通常用來存放要訪問數據的段地址
```
mov bx,1000H
mov ds,bx
mov al,[0]
```
 - 上面3條指令的作用將10000H(1000:0)中的內存數據賦值到al寄存器中
 - mov al,[address]的意思將DS:address中的內存數據賦值到al寄存器中
 - 由于al是8位寄存器,所以是將一個字節的數據賦值給al寄存器

- 8086不支持將數據直接送入段寄存器中,mov ds,1000H是錯誤的

---
 ** 寫幾條指令,將al中的數據送入內存單元1000H中 **
```
mov bx,1000H
mov ds,bx
mov [0],al
```
>注意:“mov 內存單元, 內存單元”是不允許的,比如mov[0], [1]

#大小端
 - 大端模式,是指數據的高字節保存在內存的低地址中,而數據的低字節保存在內存的高地址中(高低\低高)(Big Endian)
 - 小端模式,是指數據的高字節保存在內存的高地址中,而數據的低字節保存在內存的低地址中(高高\低低) (Little Endian)

>注意:ARM既可以工作在大端模式,也可以工作在小端模式

#棧

![表情最豐富的羽毛球](http://upload-images.jianshu.io/upload_images/6990647-4f53a210562f1591.gif?imageMogr2/auto-orient/strip)

- 棧:是一種具有特殊的訪問方式的存儲空間(后進先出, Last In Out Firt,LIFO)
- 8086會將SS作為棧段的段地址,任意時刻,SS:SP指向棧頂元素(偏移地址)
- 8086提供了PUSH(入棧)和POP(出棧)指令來操作棧段的數據
 - 比如push ax是將ax的數據入棧,pop ax是將棧頂的數據送入ax

![](http://upload-images.jianshu.io/upload_images/6990647-c89e59550c287bca.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

>棧是沒有底的,底是我們自己想象的,棧頂是有的,就是sp指針
內存里是絕對有數據的,哪怕是00它也是數據,push相當于改變內存里的數據,我們平時所說的新開辟一塊內存空間,里面沒有數據并不是里面就是0000,而是對于我們來說,這里面我可以改它而不去讀它,讀的話就讀了一個野指針,讀的這塊野指針已經被釋放了,所謂的野指針報錯,就是我們的地址被釋放了,里面并沒有存任何的數據,這時候去拿野指針里的面的東西,我不認識!這叫野.??

- 棧大小可以叫內存的大小嗎?
  - 8086 棧大小只有64K

- 內存區域里越往高地址走,我們系統自帶的一些內容不讓我們修改(系統不讓我們修改的內容在高地址)
- pop的時候sp是加(也就是往高地址走)

>pop和push只是偏移我們的sp指針
  pop僅僅是讀數據,并沒有改,把sp偏移的數據讀出來
  push是改數據,把sp偏移的內存改數據
  pop越讀越大
  push越改越小

###棧越界
- 當棧滿的時候在使用push指令入棧,或??盏臅r候再使用pop指令出棧,都將發生棧頂超界的問題

- push超界比pop越界要危險的多,因為pop只是讀,而push是改,一旦push越界他有可能把別人的數據改掉(我這個app本來好好的你過來把我的數據改了,那這個app就完蛋了)
 >棧以外的地址很有可能存放著具有其他用途的數據,代碼等.這些數據代碼可能在我們的程序中,也有可能在別的程序中(但是由于我們入棧時不小心修改這些代碼,數據,會引發一連串的錯誤)


#棧段
- 對于8086來說,在編程時,可以根據需要,將一組內存單元定義為一個段
- 我們可以將一組長度為N(N<=64KB)、地址連續、起始地址為16倍數的內存單元,當做??臻g來使用,稱為棧段。比如用10010H~1001FH這段內存空間當做棧來使用,我們就可以認為10010H~1001FH是一個棧段,它的段地址為1001H,長度為16字節
- 如何使用push、pop等棧操作指令訪問我們定義的棧段
 - 用SS存放棧段的段地址,用SP存放棧頂的偏移地址

#Loop指令
- loop指令和cx寄存器配合使用,用于循環操作類似高級語言的for,while
- 使用格式
```
mov cx,循環次數
標號:
    循環執行的程序代碼
    loop 標號
```

- loop指令執行流程
步驟1 先將cx寄存器的值 - 1, cx = cx - 1
步驟2 判斷cx 的值
   - 如果不為零執行標號的代碼,又執行 步驟 1
   - 如果為零執行loop后面的代碼

>補充:
獲取數據,除了通過ds段來獲取.還可以利用其它段地址來獲取
mov ax,ds:[0]
mov ax,cs:[0]
mov ax,ss:[0]
mov ax,es:[0]

#8086偽指令
- db(define byte) 自定義字節
- dw(define word)自定義字

#Call和ret指令
 - call指令  (相當于執行一個函數)
   - call標號
   - 將下一條指令的偏移地址入棧
   - 跳轉到定位的地址執行指令!

- ret指令
  - ret指令就是將棧頂的值POP給IP,也就是執行下一條指令
  - 棧頂得值是什么?
    - 下一條指令的偏移地址 











###**此文章用作學習筆記**
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,967評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,273評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 175,870評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,742評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,527評論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,010評論 1 322
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,108評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,250評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,769評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,656評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,853評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,371評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,103評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,472評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,717評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,487評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,815評論 2 372

推薦閱讀更多精彩內容