github開源專案:CTF-we-are-one筆記
堆疊是計算機中最重要的資料結構之一,它是一個先入后出的資料結構,
堆疊空間是計算機記憶體中的一段確定的記憶體區域,也有著一些指標指向相應的記憶體地址,在x86架構中這個指標位于ESP暫存器,而在x86-x64平臺上的RSP暫存器,在計算機底層中:
(1)儲存區域變數
(2)執行CALL指令呼叫函式時,保存函式地址結束的時候,正確回傳,
(3)傳遞函式引數,
操作堆疊的常用指令是PUSH和POP,即入堆疊和出堆疊,PUSH指令會對ESP、RSP、SP暫存器的值進行減法運算,
下面得匯編將通過堆疊完成EAX和EBX值得交換,
MOV EAX,1234h
MOV EBX,5678h
PUSH EAX
PUSH EBX
POP指令則是PUSH指令的反操作,實質上PUSH和POP是兩個逆運算子:
POP EAX
POP EBX
使用堆疊保存函式回傳值
CALL指令呼叫某個子函式的時候,下一條的指令地址作為回傳地址保存在堆疊中,等價于PUSH回傳地址與JMP函式地址的指令序列,
以下通過匯編偽碼的方式說明CALL指令與RET指令在堆疊中的整個流程
0x00001023 CALL Function
0x00001024 MOV EAX,EBX
RET
Stack
————High address—————
00001024<——ESP
00002048<——EIP
————Low address—————
CALL指令的下一條指令00001024被壓入堆疊中,ESP指標指向這個記憶體地址,被呼叫函式Function的地址0x00001023被加入到EIP暫存器中,
Stack
————High address—————
… <————ESP
00001024
00001024<————EIP
————Low address——————
當程式執行到RET指令的時候,被分為兩個部分,
第一步:ESP指向的資料將被彈出至EIP暫存器
第二步:ESP的數值增加,將指向堆疊的上一個值,
使用堆疊傳遞函式引數
在x86平臺程式中,最常見的引數呼叫約定是cdecl,其他的還有stdcall,fastcall和thiscall,
我們可以使用stack進行傳遞引數,但并不代表stack是唯一引數的傳遞方
假設函式func有三個參arg1、arg2、arg3
push arg3
push arg2
push arg1
calll func
使用堆疊存盤變數
PUSHFD
POPFD
PUSHFD 指令把32位EFLAGS暫存器內容壓入堆疊中
POPFD指令則是把堆疊頂的資料彈出來到EFLAGS暫存器中
參考文獻:
Dolan S.mov is Turing-complete[J/OL].2013-07.
本文不夠權威,可以參考更多博文,如有問題歡迎各位學者指正批評,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/267481.html
標籤:其他
