# 零散沒用的小知識 ## x86組語中的 lea mov 關於實現 ` $edx = $eax+$ebx+8` ``` 1 add eax, ebx 2 add eax, 8 3 mov edx, eax ``` ``` 1 lea edx, [eax+ebx+8] ``` `lea`擅長處理複雜的地址處理,並且該操作不會改變旗幟(flag)的更動,相較於使用`mov`,`mov`會先進行`add`、`sub`等等的操作都會改變旗幟(flag) ## __x86.get_pc_thunk.ax 先講結論,該Binary是PIC(Position Independent Code)的時候會使用,因為函數與位置無關,所以我們使用`__x86.get_pc_thunk.ax`找到需要使用的函數、變數位置,加上偏移量就可以調用 ![image](https://hackmd.io/_uploads/B1-mOxPP0.png) 先記住`__x86.get_pc_thunk.ax` 下一條指令(`add eax, 0x2e27`)這個待會會用到,很重要 ![image](https://hackmd.io/_uploads/B1OqVgwPR.png) 可以看到`__x86.get_pc_thunk.ax`只做一件事 ``` ---> 0x5655621d <__x86.get_pc_thunk.ax> mov eax, DWORD PTR [esp] 0x56556210 <__x86.get_pc_thunk.ax> ret ``` 他把`$esp`所指向的*content*放入`$eax` ![image](https://hackmd.io/_uploads/B1xQ8evP0.png) 因為call一個function會將下一條指令壓入**stack**中,所以此時`$esp`所存的內容就是前面第一張圖所說的下一條指令(`add eax, 0x2e27`) :::info 這邊要注意,一般而言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`則沒有變動。 ::: ![image](https://hackmd.io/_uploads/B1SeolvDA.png) 可以看到此時`$eax` 就如前面所說已經存好next PC了 ![image](https://hackmd.io/_uploads/S1qmilvPC.png) return回main function後可以看到準備要執行`add eax,0x2e27`,意思是基於`add eax,0x2e27`這條指令的地址在加上一個`0x2e27`的偏移 > 為什麼要這樣? > 因為該binary是PIC,位置不是compiler time時就決定好的,但他的相對位置是固定的,譬如說我知道某個函數是在`*main + 0x100`,那我就能透過main找到該函數,不管該binary是load到memory的哪裡,因為他們的相對位置都是固定的 ![image](https://hackmd.io/_uploads/r186nlPwA.png) 可以看到`$eax`現在指到GOT表,因為我們不知道GOT表的實際位置,所以我們使用這種方法去查找GOT表的位置,而這邊是因為我下面call了puts,所以他需要事先知道GOT表的位置 `_x86.get_pc_thunk.ax` 主要就是因為實現PIC而存在的,因為程式碼與位置無關所以我們使用一個function去查找該程式碼所需要的東西