2015-09-28 89 views
2

爲什麼GDB中的某些內存地址顯示比其他內存地址更短?爲什麼GDB中的一些內存地址比其他內存地址短?

在我的一個學校課程中,我得到了這段代碼,並要求給它輸入文字,以便對其執行緩衝區溢出攻擊,以使其打印出「You Won!」。當我運行它。下面是代碼:

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <time.h> 

void win() { 
    printf("You Won!"); 
} 
void lose() { 
    printf("You lost!"); 
} 
int check(char* name) { 
    char buffer[16]; 

    strcpy(buffer, name); 

    printf("Your name is: %s \n", buffer); 
    printf("The buffer address is [%p].\n", &buffer); 
    // Call the random function 
    srand(time(NULL)); 

    return rand(); 
} 
int main(int argc, char **argv) { 
    int randnum; 
    randnum = check(argv[1]); 
    if(randnum < 5) { 
     win(); 
    } else { 
     lose(); 
    } 

    // Return everything is OK 
    return(0); 
} 

我編這個用gcc -g -m32 -fno-堆棧保護Vulnerable.cpp

要查找的strcpy我用gdb查看棧和看到的返回地址內存填滿,直到我上了輸出這個錯誤,所以我知道返回地址已被覆蓋的返回地址:

Program received signal SIGSEGV, Segmentation fault. 
0x42424242 in ??() 

要寫入的利用,使其運行WIN()我知道我需要更換那些B在我的輸入中與win()關聯的內存地址。爲了找到與之相關聯的這個地址我拆開主,發現那裏贏得了電話是和內存地址:

0x00001ed7 <+55>: call 0x1db0 <win()> 

爲什麼內存地址0x1db0出現它的方式?不應該是0x00001db0嗎?

此外,如果任何人都可以解釋我如何在輸入結束時編寫該地址,以便它返回到勝利功能將是非常棒的。

我有點失落,我應該去這個任務的方向,所以任何幫助,將不勝感激。

回答

2

x86指令集有幾種不同的CALL指令變體,它們採用不同的參數大小。具有16位相對地址的CALL可用於調用地址與呼叫站點地址相近的函數。

+0

我不認爲這是相關的。是的,這個調用可能是相對的,但隻影響指令的編碼,當顯示跳轉目標時,gdb總是試圖將其解析爲完整的地址(當符號可用時,函數名稱)。對我來說,只是在那裏,他們使用了直接的'%x'而不是'%08x',這是偶然的,或者有一個更緊湊的列表(尤其是如果它的代碼與x86_64共享,其中全寬地址非常痛苦)。 –

0

爲什麼內存地址0x1db0出現它的方式?不應該是0x00001db0嗎?

這是一樣的;與正常的十進制數一樣,左側的零可以忽略。地址通常以零填充的方式打印,以保持列對齊(例如,在反彙編輸出左側的地址中),以幫助在視覺上或僅僅出於習慣的情況下查看地址。

在這種情況下,在已解決的跳轉目標中,它們沒有添加零填充;這不是什麼大不了的事情,要麼他們故意這樣做(因爲沒有什麼可以保持一致,並且保持較短的行數),或者「發生了」有人寫了%x而不是%08x。要知道的唯一方法是查找在gdb VCS中打印該地址的行,查看誰執行了此操作並詢問他。