0x01 前言
PWN知識全制霸這系列是為了教導大家如何從一個PWN萌新成為佼佼者那樣的大佬。那麼是什麼是PWN呢?PWN就是利用各種漏洞攻擊系統主機從而獲得系統管理員的權限。
而Part 1就是一些你們得懂的匯編基本和常用到的知識。
我能在這系列的的教學到什麼?
- x86 & x86-64的匯編語言。
- 程序常用的保護機制:CANNARY,FORTIFY,NX(DEP),PIE(ASLR),RELRO等等
- 各種Pwn工具的應用:Pwntools,GDB,checksec,IDA Pro,Peda等等。
- Pwn類型Wargame/CTF題目的應對方式與解答。
- ELF和PE文件格式。
- 程序執行,加載和鏈接詳解。
- 各種二進制漏洞:栈溢出,堆溢出,返回導向編程(ROP),格式化字符串漏洞,整數溢出等等。
- 其他大佬的在挖掘漏洞以及利用Pwn的思路。
0x02 基礎知識
本文參考:王爽-匯編語言第三版 & 小信豬原始部落的學習筆記
機械語言是機械指令的集合。
例子指令: 01010000 (PUSH AX)
左部分為機械語言括號裡面則是所謂的匯編語言。
匯編語言就是能在硬件上直接工作的編程語言。而匯編語言的出現是為了讓人們用容易理解的方式去表達出機器指令代表的意思。雖然電腦只能讀懂0和1,然而,通過編譯器,我們輸入的匯編語言最終會轉譯成電腦所理解的機械語言。
由3種匯編指令:匯編指令,偽指令和其他符號。
- 匯編指令:mov,add,sub….等等
- 偽指令:偽指令是對匯編起某種控制作用的特殊命令,其格式與通常的操作指令一樣,並可加在彙編程序的任何地方,但它們並不產生機器指令。
- 符號:例如運輸符號加減乘除,邏輯符號等等。
存储器(寄存器)
也就是平常大家所說的內存,用來存放指令和需要運算的數據。
存儲單元
存儲器能被劃分成幾個單元,每個存儲器單元從0開始順序編號,如一個存儲器有128個存儲單元,編號從0到127微型機存儲器的存儲單元可以存儲一個Byte(1位元組=8bit,即8個二進位)。含有128個存儲單元的存儲器可以存儲128個Byte。
數據的表達單位
二進位制是由0和1組成。
- 位元組(byte)8個bit位組成
- 字(WORD)16位:2個位元組組成
- 雙字(DWORD)32位:兩個字組成
- 四字(QWORD)64位元: 四個字組成
字節順序
大端模式 Big Endian:低位放低位地址,高位放到高位地址。
低地址 ——– 高地址 (比如存放0x01234567)0x01 0x02 0x03 0x04 0x05 0x06 0x07
小端模式 Small Endian:低位放高地址,高位放低地址
低地址 ——– 高地址 (比如存放0x01234567)0x07 0x06 0x05 0x04 0x03 0x02 0x01
讀寫存储器數據
CPU要從讀寫數據的需要知道存儲單元所在的地址,到底指明的是哪一個存儲器,進行怎樣的操作。而它會和電腦裡面的芯片進行以下3種的信息交互。
- 存儲單元的地址(地址信息) 走地址總線
- 器件的選擇,讀取還是寫入命令(控制信息) 走控制總線
- 讀或寫的數據(數據信息) 走數據總線
CPU從3號地址讀取數據8的過程
1.CPU透過地址線發出地址訊息3。
2.CPU通過控制線發出記憶體讀命令,選中存儲器晶片,並通知它,將要從中讀取數據。
3.存儲器將3號單元中的數據8通過傳輸線送入CPU。
CPU將數據26寫入3號地址的過程
1.CPU透過地址線發出地址訊息3。
2.CPU通過控制線發出記憶體命令,選中存儲器晶片,並通知它,要想其中寫入數據。
3.CPU透過傳輸線將數據26送入記憶體的3號單元中。
地址總線
CPU通過地址總線來指定存儲器單元。地址總線上能傳送多少個不同的信息,CPU就可以對多少個存儲單元進行尋址。
一個CPU有N根地址線,則可以說這個CPU的地址總線的寬度為N。這樣的CPU最多可以尋找 $ \ 2^N \ $ 個內存單元.
決定了CPU的尋址能力。
數據總線
CPU與內存或其他器件之間的數據傳送是通過數據總線來進行的。數據總線的寬度決定了CPU和外界的數據傳送速度。8根數據總線一次可傳送一個8位二進制數據(即一個字節)。16根數據總線一次可以傳送兩個字節,32的話就是4個字節,最後,64就會是8個字節了。
決定了CPU與其他器件進行數據傳送時的一次數據傳送量。
控制總線
CPU對外部器件的控制是通過控制總線來進行的。在這裏控制總線是一個總稱,控制總線是一些不同控制線的集合。有多少個控制總線,就意味着CPU提供了對外部器件的多少種控制。所以,控制總線的寬度決定了CPU對外部器件的控制能力。
決定了CPU對系統中其他器件的控制能力
內存地址空間
舉例來說,一個CPU的地址總線寬度為10,那麼可以尋址$ \ 2^10 = 1024\ $個內存單元,這1024個可尋到的內存單元就構成這個CPU的內存地址空間。
寄存器
在CPU裡面,寄存器的作用是用來暫存指令、數據和位址。它們分別是:
1 | 64-bit register | Lower 32 bits | Lower 16 bits | Lower 8 bits |
http://slideplayer.com/slide/4194257/14/images/11/Register+Layout+RAX+EAX+AX+AH+AL.jpg
EAX:称为累加器,常用于算数运算、布尔操作、逻辑操作、返回函数结果等。
EBX:称为基地址寄存器,常用于存档内存地址。
ECX:称为计数寄存器,常用于存放循环语句的循环次数,字符串操作中也会常用。
EDX:称为数据寄存器,常常和EAX一起使用。
对于寄存器%eax、%ebx、%ecx和%edx,各自可作为两个独立的16位寄存器使用,而低16位寄存器还可继续分为两个独立的8位寄存器使用。
注意:
上面所述的4个通用寄存器的专门用途不是一成不变的,编译器在编译程序的时候会根据很多因素,例如编译器、编译条件、操作系统等做出相应的改变,读者要知道着手研究的程序是用什么编译器编译,然后针对具体的编译器参考该编译器的说明。
EIP(Instruction Pointer):是指令寄存器,指向处理器下条等待执行的指令地址(代码段内的偏移量),每次执行完相应汇编指令EIP值就会增加。
ESP(Stack Pointer):是栈指针寄存器,存放执行函数对应栈帧的栈顶地址(也是系统栈的顶部),永遠指向栈区域的栈顶位置。
EBP(Base Pointer):是扩展基址指针寄存器,存放执行函数对应栈帧的栈底地址,用于C运行库访问栈中的局部变量和参数。
变址寄存器:顾名思义,变址的含义是内存地址会变动,也就是说变址寄存器中存放在变动的内存地址。80386架构中有两个变址寄存器,分别为ESI和EDI。
- ESI寄存器:称为源变址寄存器,通常存放要处理的数据的内存地址。
- EDI寄存器:称为目的变址寄存器,通常存放处理后的数据的内存地址。
用途:ESI和EDI通常用来配合使用完成数据的赋值操作,下面是一个EIS和EDI配合使用的例子。
Rep movs dword ptr [edi],dword ptr [esi]
上面的指令把ESI所指向的内存地址中的内容复制到EDI所指向的内存中,数据的长度在ECX寄存器中指定。