2015-09-28 90 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中打印该地址的行,查看谁执行了此操作并询问他。