關於實現 $edx = $eax+$ebx+8
lea
擅長處理複雜的地址處理,並且該操作不會改變旗幟(flag)的更動,相較於使用mov
,mov
會先進行add
、sub
等等的操作都會改變旗幟(flag)
先講結論,該Binary是PIC(Position Independent Code)的時候會使用,因為函數與位置無關,所以我們使用__x86.get_pc_thunk.ax
找到需要使用的函數、變數位置,加上偏移量就可以調用
先記住__x86.get_pc_thunk.ax
下一條指令(add eax, 0x2e27
)這個待會會用到,很重要
可以看到__x86.get_pc_thunk.ax
只做一件事
他把$esp
所指向的content放入$eax
因為call一個function會將下一條指令壓入stack中,所以此時$esp
所存的內容就是前面第一張圖所說的下一條指令(add eax, 0x2e27
)
這邊要注意,一般而言caller(呼叫function的function,這邊為main
)只會存next PC(也就是return address),而做stack操作(save $ebp
、create stack space)都是callee(這邊為_x86.get_pc_thunk.ax
)在做的,但可以看到他並沒有做stack的操作,所以$esp
是next PC,而$ebp
則沒有變動。
可以看到此時$eax
就如前面所說已經存好next PC了
return回main function後可以看到準備要執行add eax,0x2e27
,意思是基於add eax,0x2e27
這條指令的地址在加上一個0x2e27
的偏移
為什麼要這樣?
因為該binary是PIC,位置不是compiler time時就決定好的,但他的相對位置是固定的,譬如說我知道某個函數是在*main + 0x100
,那我就能透過main找到該函數,不管該binary是load到memory的哪裡,因為他們的相對位置都是固定的
可以看到$eax
現在指到GOT表,因為我們不知道GOT表的實際位置,所以我們使用這種方法去查找GOT表的位置,而這邊是因為我下面call了puts,所以他需要事先知道GOT表的位置
_x86.get_pc_thunk.ax
主要就是因為實現PIC而存在的,因為程式碼與位置無關所以我們使用一個function去查找該程式碼所需要的東西