1. 程式人生 > >逆向學習筆記(1)函式引數

逆向學習筆記(1)函式引數

菜雞剛學彙編,總結下。

函式引數傳遞:
分值傳遞和地址傳遞。
值傳遞只是將數複製一份當做引數,壓入堆疊,例如

  function(int a,int b)
    {
     	...
    }

呼叫函式前的彙編程式碼是

mov eax,dword ptr ds:[...]
push eax
mov ecx,dword ptr ds:[...]
push ecx

地址傳遞:是將地址壓入堆疊,效率更高。
函式引數個數的判斷:

一般情況下:
首先觀察函式呼叫前的程式碼:

例如

push 1
push 2
call 函式

再看堆疊平衡處:
如果 是add esp,0x8

或者是 ret 0x8
由於0x8/4=2 則傳入的引數的個數就是2個。
以上是一般情況下。

但是由於函式呼叫約定的不同
例如__ fastcall約定,最左邊的兩個引數用 ecx,edx來傳遞,其餘的引數通過堆疊push傳遞(由右往左)。那麼上述的一般判斷就不可靠了。

再例如某些情況看不到 呼叫函式前的資訊,不能看到push傳參,和用暫存器來傳參,只有一個光禿禿的call 呼叫時,這時就需要更深入的判斷了。

  • 則首先跳到函式中,看函式的內容,首先需要脫去__fastcall約定的思維定式,不要覺得只有ecx,edx可以傳參。
    eax,ecx,edx,edi,esi,ebx 等暫存器都可能用來傳遞引數(不考慮ebp和esp)。
  • 由於引數是從外界傳遞到函式內部使用的,除了特殊情況,則很少有給引數賦值的情況,所以可以基本排除被賦值的暫存器。然後觀察給別的東西賦值的暫存器,如果有暫存器給別的東西賦值,那麼這個暫存器就是引數。
  • 判斷完暫存器再看是否有 [EBP-xxx](release版是 [esp+xxx])給別的東西賦值,如果有,那麼這個也是引數。最後再結合 堆疊平衡 來綜合判斷引數的個數。
    則總結下即是
    找到給別人賦值的暫存器,且這個暫存器的值不是在函式中賦的值,那麼這個暫存器就是傳進來的引數,然後再看 [ebp-xxx]和 ret xxx 綜合判斷函式的引數個數。