vc 獲取函數名稱真實地址

    首先寫一個很簡單的main函數:html

 

int main(){
    printf("main的地址(?):%08x",main);
}


單步調試,可得知 main函數的真實入口地址是:00be91a0算法

  然而咱們控制檯輸出的值是函數

爲何會出現這樣的差異呢?院子裏有一篇大牛寫的有關注入的文章:http://www.cnblogs.com/fanzhidongyzby/archive/2012/08/30/2664287.html,裏面就提到了這個問題。編碼

其中提到一個解析真實地址的算法:spa

//將函數地址轉換爲真實地址
unsigned int getFunRealAddr(LPVOID fun)
{
    unsigned int realaddr = (unsigned int)fun;//虛擬函數地址
    // 計算函數真實地址
    unsigned char* funaddr = (unsigned char*)fun;
    if (funaddr[0] == 0xE9)// 判斷是否爲虛擬函數地址,E9爲jmp指令
    {
        int disp = *(int*)(funaddr + 1);//獲取跳轉指令的偏移量
        realaddr += 5 + disp;//修正爲真實函數地址
    }
    return realaddr;
}

相信新手朋友都和我同樣爲這段代碼怎麼來的摸不着頭腦。特此我單步調試研究了一番,才大體明白原理:指針

main函數名的地址其實就是一個 Jmp xxx的指令,調試

從vs的反彙編調試代碼能夠看出,第一個參數main入棧,對應彙編代碼就是 push 0be135Ch ,這個入棧的數字,其實就是剛剛控制檯輸出的那個地址。因此很顯然這個地址就是函數main的「函數名」所在的地址(其實在彙編裏應該是不存在 「main」這樣的字符串的,之因此可能能夠在vs或在od這樣的調試器裏看到,是這些調試器經過經驗推斷出來的結果。)。而後 咱們在地址欄裏輸入 0be135Ch這個地址,就能夠跳到 相對的位置處。code

jmp 對應的彙編碼爲 E9, 然後面的4個字節"3F 7E 00 00",其實是倒序的相對地址 0x00007e3f.也就是咱們看到是main。固然這個地址只是代碼的相對位置,若是運行以後,就要加上當前模塊的基址纔是絕對地址。htm

那麼既然,這個「main」的位置只是一個跳轉指令(JMP),確定是跳轉到了jmp後面跟的這個地址的位置了,也就是說這個地址就是真正的main函數的地址了。blog

固然,0be135Ch是從e9 3F 7E 00 00這條指令開始算的。也就是說,從e9 3F 7E 00 00的位置開始算,跳過去0x00007e3f個字節,就到了真正的main函數入口處。

因此真正的地址就是

0be135Ch+5(指令佔的字節數 JMP main)+0x00007e3f=00be91a0.

因此咱們再回到函數部分來。

    UINT realaddr = (UINT)main;// 拆箱轉換成 unsigned int 數據。表明main函數名所表明的地址
    unsigned char* funcaddr = (UCHAR*)main; //這裏是獲取main地址所在的字節內容,其內容爲「e9 3F 7E 00 00」(JMP main),因此只要判斷前面的字節指令是不是e9就知道是否是真實地址了,若是是Jmp(e9)的話就不是真正的地址。
    if (funcaddr[0] == 0xE9){  //由於 
        UCHAR* fa = funcaddr + 1;//指針移後一位,從e9到 3f.
        int* as = (int*)(fa); //取指針=處的int數據(共4個字節),實際上這裏就是一個跳轉地址。
        int disp = *as; //取指針的內容
        realaddr += 5 + disp;//在main地址的基礎上+JMP main所佔的字節+要正向跳轉的字節數
    }
相關文章
相關標籤/搜索