# Reverse Engineering notes - x86 Course > note by y1w3n > 從基礎開始複習+新知識學習 ## 長度 * 記憶體以byte為主 * 1 byte = 8 bits * 2 byte = word * 4 byte = 2 word = double word * 每==一個==16進制數字長度 4 bits * 開頭``0x``表示他是16進制 * 每個 byte 在記憶體中都有自己唯一的位址 * 32位元的記憶體位址通常是 4 byte ## x86 基本架構 * **由 CPU 、記憶體、I/O 設備組成,由系統匯流排(System bus )連接** * CPU * Control Unit * 讀取指令 * Execution Unit * 真正執行操作的地方 * Registers * 暫時存放正在處理資料 * Flags * 用來記錄發生的事 ### **32位元x86 CPU 運作流程** 1. CPU 從記憶體取得 4 byte 機器指令 * 指令是一串 0 和 1 的組合 * 這筆資料會從記憶體讀取並載入到 CPU 中的暫存區 2. 指令解碼與執行 * Control Unit 解析 * Execution Unit 執行 3. EIP 暫存器更新為下一條指令的地址 * EIP 記錄下一條要執行指令位置的暫存器 * EIP 控制流程被劫持 -> buffer overflow 常見 ## 通用暫存器(General-purpose Registers) * 長度 4 bytes * EAX * 累加器 * 保存算術運算的結果和函數傳回值 * EBX * 基底暫存器 * 當作程式資料的起始位置 * ECX * 用於計數 * loop 次數、字串操作 * EDX * 一般用途、I/O 操作 * 將 EAX 擴展至 64 位元 * ||有點像「兩位數」的十位數,EAX 是個位,EDX 是進位的地方|| ![image](https://hackmd.io/_uploads/HyoS9Rbxgx.png) * ESI * 來源索引 * 字串和數組操作中的偏移位址 * ||你在複製文字,ESI 就像你拿著掃描器從哪裡開始掃|| * EDI * 目標索引 * EBP * 指向目前 Stack Frame 的最底下 * 存局部變數 * ESP * 指向目前 Stack Frame 的最上面 * push/pop 呼叫函數、回傳、儲存狀態 ![image](https://hackmd.io/_uploads/HJsVcCWxlg.png) ## 段暫存器 * 電腦的記憶體很大,為了讓 CPU 更有效率地處理資料,記憶體會被分段 * 用於引用記憶體位置 * 幾乎所有情況下都不能直接讀取或更改 --- * CS * 放程式碼的位置 * .text 段 * DS * 放變數或資料的位置 * .data 段 * ES * 字串操作期間使用額外段暫存器 * SS * 放暫存資料的位置 * 函式傳參數、區域變數 * FS * 額外段暫存器 * GS * 額外段寄存器 :::spoiler 使用範例 ``` DS + offset = 要讀的資料位置 SS + ESP = 要存取的堆疊資料 ``` ::: ## Pointer Register * EIP * 指向下一則要執行的指令 * 當我們能夠控制 EIP,就能控制程式的執行流程 ## 控制暫存器(Control Registers) * 用來控制 CPU 的運作模式和管理系統記憶體 * 更改 * 要先搬到 General-purpose Registers 後再搬回去 --- * CR0 * 決定 CPU 的工作模式 * ~~CR1~~ * 保留,目前沒用到 * CR2 * 儲存發生記憶體錯誤(Page Fault)時出錯的記憶體位置 * CR3 * 記住頁面目錄(Page Directory)的位置 * CR4 * 控制與顯示 CPU 的進階功能 ## Flags * 存在 EFLAGS 暫存器 * 32 bit 的暫存器,每一個 bit 就代表一種 flag * 三種 flag * status flags * control flags * system flags * 流程判斷、條件跳轉、錯誤偵測 --- ### Status flags * CF(Carry Flag) * 無號數運算 * 進位、借位 * PF(Parity Flag) * 奇偶校驗 * 偶: 設定 * 奇: 清除 * 可以確定暫存器自操作以來是否已損壞 * AF(Adjust Flag) * 二進位編碼的十進位數學運算 * 如果從第 3 位產生進位或借位時用 * ZF(Zero Flag) * 運算結果為 0 會用 * SF(Sign Flag) * 看正負,負會用 * OF(Overflow Flag) * 有號數運算 * 正值太大或負值太小而無法在暫存器中表示時用 * 例: 127 + 1,因為超出 8-bit 正整數範圍,會設 OF ### Control flags * DF(Direction Flag) * 控制 CPU 在處理字串時,是往前還是往後走 * 設的話是倒著處理,清掉就順著處理 ### System flags * TF(Trap Flag) * 一次只執行一個指令 * IF(Interrupt Enable Flag) * 控制能不能接收中斷 * IOPL(I/O Privilege Level) * 控制輸入/輸出的存取權限 * NT(Nested Task) * 控制目前正在執行的任務是否連結到先前執行的任務 * 連結或中斷呼叫 * RF(Resume Flag) * debugging mode 下 處理器異常 * VM(Virtual 8086 Mode) * 表示處理器正在 virtual-8086 mode 下運行 * 這個模式是在一般的保護模式下,模擬一個 8086 的執行環境,可以同時執行多個 8086 程式 (8086是x86第一代處理器) * AC(Alignment Check) * 對齊檢查 * VIF(Virtual Interrupt Flag) * virtual mode 下複製 ```IF flags``` * VIP(Virtual Interrupt Pending) * 是否有中斷正在等處理 * ID(ID Flag) * 是否支援 CPUID 指令 * 取得處理器的識別訊息,如製造商、型號、特性、性能指標等 ## Stack * ==先進後出== * 當Functions被呼叫時,會把跟這個Functions有關的資訊放到Stack裡面 ![image](https://hackmd.io/_uploads/Sy7MVtXgxe.png) * 從較高記憶體到較低記憶體==向下增長== * 操作 * push * pop ## heap * ==向上增長== * heap變數是全域變數 * 對變數大小沒有大小限制 ![image](https://hackmd.io/_uploads/HkplU34llg.png) * 手動管理 * ``malloc(size)``:配置一塊記憶體空間 * ``calloc(n, size)``:配置 n 個空間並初始化為 0 * ``realloc(ptr, new_size)``:改變已配置空間的大小 * ``free(ptr)``:釋放不需要的記憶體 :::spoiler 什麼時候用 Heap、什麼時候用 Stack? | 使用情境 | 選擇 | | ------------ | -------------------- | | 短期使用、變數生命週期短 | Stack(函式區域變數) | | 長期存在、跨多個函式使用 | Heap(需要 malloc) | | 需要很大的空間 | Heap(Stack 空間有限) | | 陣列長度不固定 | Heap(用 realloc 動態調整) | :::