上次講完要Call一個Function時Stack會做的變化,重點就在於會先存Return回來的Address以及Old RBP,接下來我們讓程式跑到Function A的結束行,看一個Function要結束時,它的Stack與暫存器的變化。
先來看GDB,可以發現GDB並沒有在A Function使用到Stack空間,因為他直接把字串放到了RDI暫存器中,並沒有使用到Stack空間也因此MOV RBP,RSP後沒有做SUB RSP的動作。
IDA就不一樣了,IDA拉出了0x20的空間給Function A使用,雖然可以發現到在程式當中並沒有將String儲存在Stack內,而且做完puts後就做ADD RSP 20h了,而程式當中的nop是No Operation的意思,意思就是不會進行動作,這可能是Assembler或編譯器等做的事,但這邊沒有任何影響,我們直接看到POP RBP的部分。
這次我們先來看IDA,因為IDA多了將RSP加回去的動作,RSP加回0x20之後就會跟RBP的值一樣了。
接下去兩個都做POP RBP,意思是把Stack上的值,POP到RBP上,IDA剛剛Stack上是CC10,POP後RSP會往下走,然後暫存器上的RBP會變成CC10,也就是最一開始main的RBP。
GDB也是一樣,先看一下目前的狀態,現在的RSP指向de80這個值。
做了POP RBP後,RBP就變成原本main的RBP de80了。
最後就是要做ret了,ret也是需要用到Stack中的值,我們在Call function時,放Old RBP之前還放了Return回去的Address,現在Old RBP使用掉了,接下來就要將Return address給送到RIP裡了,可以看到GDB做完ret後,RSP指向的4011a9也就是Call function前 main的下一行,被放到RIP內了。
IDA亦是如此,會將RSP指向的1004010D4放入RIP當中。