想做外掛,先把彙編學好!反彙編跟蹤函數調用過程!

今天,我們來通過反彙編看一下函數調用的過程(順便學習下彙編),如下圖,為一個函數調用的例子。主函數里面調用了test()函數。

想做外掛,先把彙編學好!反彙編跟蹤函數調用過程!

在X86環境下,進入調試模式,反彙編代碼。然後我們從主函數看起,

想做外掛,先把彙編學好!反彙編跟蹤函數調用過程!

前面一些彙編代碼都是編譯器在調試模式下自動生成的調試信息代碼,我們主要看畫紅線的兩句代碼。哦,首先要看一下此時的棧空間狀況,此時的棧空間由EBP和ESP兩個寄存器來決定,EBP是棧底的內存地址,ESP是棧頂的內存地址。看一下吧。

想做外掛,先把彙編學好!反彙編跟蹤函數調用過程!

此時可以畫出這麼一幅內存結構圖。

想做外掛,先把彙編學好!反彙編跟蹤函數調用過程!

當執行一下語句時,很明顯看到,把3這個值放到ebp-8的內存單元中,佔四個字節(dword)。

想做外掛,先把彙編學好!反彙編跟蹤函數調用過程!

想做外掛,先把彙編學好!反彙編跟蹤函數調用過程!

然後執行下一條指令。

想做外掛,先把彙編學好!反彙編跟蹤函數調用過程!

調用test函數,彙編代碼為call 00D7121C,很明顯test函數的地址在00D7121C。call指令還有一個隱含的操作,就是把call指令下面的一條指令的內存地址壓入棧中,方便函數調用結束後找到下一條指令的位置。即將00D71844壓入棧中。然後棧頂指針esp往上走。

想做外掛,先把彙編學好!反彙編跟蹤函數調用過程!

然後開始執行test函數,test函數的反彙編代碼如下。還是看主要核心代碼。

想做外掛,先把彙編學好!反彙編跟蹤函數調用過程!

執行標號為1的指令,push ebp

將ebp的值入棧。ebp的值為0X010ff82c。

想做外掛,先把彙編學好!反彙編跟蹤函數調用過程!

然後執行2號指令,mov ebp,esp,此時ebp的值和esp的值相同,棧底指針和棧頂指針處於同一水平線上。

想做外掛,先把彙編學好!反彙編跟蹤函數調用過程!

緊接著執行3號指令,sub esp,0CCh,這一句指令將esp減去0CC然後再賦值給esp,它的含義就是:給test函數分配該函數的棧空間,大小為0CC個字節

想做外掛,先把彙編學好!反彙編跟蹤函數調用過程!

然後執行4、5、6號指令,分別將ebx、esi、edi寄存器壓入棧中,這三句指令就是為了保護現場用的,因為在test函數內可能會改變之前的寄存器的值,為了能夠讓test函數調用結束後,這些寄存器的狀態還能回到原來的樣子,所以要預先進行一份保留。

想做外掛,先把彙編學好!反彙編跟蹤函數調用過程!

然後執行7號指令,mov dword ptr [ebp-8],2。很明顯,將2的值放到ebp-8的內存單元中,佔4個字節。ebp-8的內存地址位於test函數的棧空間中。

想做外掛,先把彙編學好!反彙編跟蹤函數調用過程!

然後執行8、9、10號指令,把之前保存的寄存器值給重新取出來,恢復現場。

想做外掛,先把彙編學好!反彙編跟蹤函數調用過程!

然後執行11號指令,add esp,0CCH,還記得之前是怎麼分配test函數的棧空間的嗎,對就是sub esp,0CCH,現在這一條add esp,0CCH指令就是為了回收之前分配的棧空間。此時ebp和esp又回到了同一水平線上。

想做外掛,先把彙編學好!反彙編跟蹤函數調用過程!

然後執行13號指令,pop ebp,就是把調用test函數之前的棧起始內存地址彈出來,此時ebp的值為010ff82c。

想做外掛,先把彙編學好!反彙編跟蹤函數調用過程!

最後執行14號指令,ret,此時會進行一次pop操作,將之前保存的調用test函數的指令的下一條指令的內存地址(00D72844)彈出,此時CPU指針指向該位置,繼續執行後續代碼。並且,棧底指針,棧頂指針位置回到函數調用前的狀態,調用過程結束。

想做外掛,先把彙編學好!反彙編跟蹤函數調用過程!


可以看出,一次函數調用過程,在底層居然做了這麼多操作,而且函數調用會為每個函數調用分配棧空間,一旦調用結束之後,該棧空間便被回收掉。


分享到:


相關文章: