为什么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功能将是非常棒的。
我对这项任务的指导方向有点失落,所以任何帮助都会受到赞赏。
答案 0 :(得分:2)
x86指令集具有CALL指令的几种不同变体,它们采用不同的参数大小。具有16位相对地址的CALL可用于调用地址接近呼叫站点的函数。
答案 1 :(得分:0)
为什么内存地址0x1db0会以它的方式出现?不应该是0x00001db0?
它是一样的;与常规十进制数字完全相同,左侧的零可以忽略。地址通常打印为零填充,以保持列对齐(例如在反汇编输出左侧的地址中),以帮助在视觉上或仅仅是出于习惯而发现地址。
在这种情况下,在已解析的跳转目标中,它们没有添加零填充;这不是什么大问题,要么他们故意这么做(因为没有什么可以保持对齐,并保持线条更短)或者“刚刚发生”有人写了%x
而不是%08x
。要知道的唯一方法是查找在gdb VCS中打印该地址的行,看看是谁做了提交并问他。