为什么GDB中的某些内存地址看起来比其他内存短?

时间:2015-09-28 03:37:10

标签: c++ gdb buffer-overflow

为什么GDB中的某些内存地址看起来比其他内存短?

在我上学的一个课程中,我得到了这个代码,并要求给它输入文本,以便对它进行缓冲区溢出攻击,使其打印出“你赢了!”当我运行它。这是代码:

#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-stack-protector Vulnerable.cpp

要查找strcpy的返回地址,我使用GDB查看堆栈并查看内存填充,直到我在输出中出现此错误,因此我知道返回地址已覆盖了返回地址:

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

要编写漏洞利用以使其运行win()我知道我需要将输入中的B替换为与win()关联的内存地址。为了找到这个地址,我反汇编了main,找到了win的调用位置以及与之关联的内存地址:

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

为什么内存地址0x1db0会以它的方式出现?不应该是0x00001db0?

此外,如果有人能够解释我如何在输入结束时写入该地址,以便返回到win功能将是非常棒的。

我对这项任务的指导方向有点失落,所以任何帮助都会受到赞赏。

2 个答案:

答案 0 :(得分:2)

x86指令集具有CALL指令的几种不同变体,它们采用不同的参数大小。具有16位相对地址的CALL可用于调用地址接近呼叫站点的函数。

答案 1 :(得分:0)

  

为什么内存地址0x1db0会以它的方式出现?不应该是0x00001db0?

它是一样的;与常规十进制数字完全相同,左侧的零可以忽略。地址通常打印为零填充,以保持列对齐(例如在反汇编输出左侧的地址中),以帮助在视觉上或仅仅是出于习惯而发现地址。

在这种情况下,在已解析的跳转目标中,它们没有添加零填充;这不是什么大问题,要么他们故意这么做(因为没有什么可以保持对齐,并保持线条更短)或者“刚刚发生”有人写了%x而不是%08x。要知道的唯一方法是查找在gdb VCS中打印该地址的行,看看是谁做了提交并问他。