1、理解整個中斷/系統呼叫流程的關鍵是kernel_entry和kernel_exit,也就是如何儲存現場,並且恢復現場的。
我們先來看下armv8的暫存器,plr(x30)無論是使用者態還是核心態都用這個暫存器來儲存程式的返回值。
sp_el0,sp_el1分別是有使用者態和核心態的堆疊。
elr_el1用於儲存,當在發生系統呼叫、異常、中斷時,當前程式的pc值(無論是使用者態還是核心態)。
spsr_el1用於儲存,當在發生系統呼叫、異常、中斷時,當前程式的pstate(無論是使用者態還是核心態)。
2、當發生中斷、異常、系統呼叫時,硬體會自動:
1)把當前程式的pc值放入elr_el1中
2)把當前狀態pstate存入spsr_el1中
3)根據發生在核心態還是使用者態,中斷還是異常,會自動跳轉到el1_sync,el1_irq,el0_sync,el0_irq
4)改變pstate,如果是使用者態發生中斷、異常、系統呼叫,此時已經進入核心態,堆疊是sp_el1。
執行完kernel_entry的堆疊,elr_el1存放的是返回的pc值,spsr_el1存放的是返回的pstate。
如果是使用者態發生的中斷、異常、系統呼叫,則棧中儲存都是使用者態的暫存器資訊。
如果是核心態發生的中斷、異常,則棧中儲存的核心態的暫存器資訊。
4、kernel_exit
前面我們已經說過:
el1_sync,el1_irq呼叫的是kernel_entry 1,kernel_exit 1,也就是上面巨集el為1。
el0_sync,el0_irq呼叫的是kernel_entry 0,kernel_exit 0,也就是上面巨集el為0。
我們可以看到 .macro kernel_exit, el, ret = 0,還有乙個引數ret,只有在el0_sync處理系統呼叫時會被置成1。
發生中斷、異常、系統呼叫前是使用者態,則返回使用者態的暫存器(pc,lr,sp_el0,pstate)。注意還要把核心態的棧平衡了:ldr lr, [sp], #s_frame_size - s_lr // 恢復lr,恢復核心sp_el1
發生中斷、異常、系統呼叫前是核心態,則返回核心態的暫存器(pc,lr,sp_el1,pstate)。
如果處理系統呼叫x0存放的是系統的呼叫的返回值,所以不需要從堆疊中恢復。
更詳細分析見:
arm64入棧出棧 棧 ARM64
棧 棧 是一種具有特殊的訪問方式的儲存空間 後進先出,last in out firt,lifo sp和fp暫存器 sp暫存器在任意時刻會儲存我們棧頂的位址.fp暫存器也稱為x29暫存器屬於通用暫存器,但是在某些時刻我們利用它儲存棧底的位址 注意 arm64開始,取消32位的 ldm,stm,pus...
ARM64除錯環境
自從上一次zctf做了一道arm64的逆向題目後,我決定記錄下利用qemu搭建arm64的環境的過程,以後肯定會遇到更多arm平台下的reverse和pwn。我要模擬的是64位的arm環境,所以需要使用的是qemu system aarch64。在kali下,使用apt get install qe...
arm64 頁表對映
armv8最多支援48根位址,4級頁表,這樣最多支援user space和kernnel space 分別是256tb 其中user space佔據低端位址 kernel可以支援48 42 39 根位址 config arm64 va bits 39 is not set config arm64 ...