所以我正在做一个练习,我试图让以下程序通过使用缓冲区溢出更改相关变量来输出Welcome to Overflow。这是代码。
#include <stdio.h>
int main(){
int a = 10;
char c = 'X';
char array2[] = {'A', 'B', 'C', 'D', 'E', 'F'};
char array[4];
printf("please enter: \n");
scanf("%s", array);
printf("c = %c\n", c);
printf("a = %d\n", a);
printf("array = %s\n", array);
printf("array2 = %s\n", array2);
printf("array[2] = %x\n", *(array + 2));
printf("array2[3] = %x\n", array2[3]);
if (c == 'X' && a == 11999 && *(array + 2) == 0x99 - 0x34 && array2[3] == 'X') {
printf("Welcome to overflow!\n");
} else {
printf("This is normal output!\n");
}
}
c == 'X' && a == 11999 && *(array + 2) == 0x99 - 0x34 && array2[3] == 'X'
我需要的是什么
所以我得到的每个变量都是我想要的,除了一个
通过输入以下内容,我可以更改它们。我输入“XXeXXXXXXXXB”这会将array[2]
更改为 65 ,array2[3]
为 X ,{{1} }到'X'但是我无法改变的变量是'a'。通过输入c
B 的第12 个字符,它将a
更改为'66',这是char'B'的十进制等效值。如果我输入第13个字符,变量a
将被更改为char * 257的十进制等效。由于a
需要为11999,我将丢失。
我尝试将11999除以257,但它出现了46.6因此没有具有该值的字符,我甚至尝试了最接近46.6的字符''。和'/'然后a
太大或太小。
为了将a
更改为11999,我可以输入第12和第13个字符或字符?此外,如果你不想给我一个平坦的答案,我会很感激正确的方向。
答案 0 :(得分:0)
这是一项有趣的练习。因为您正在调用未定义的行为,所以对您的问题没有一个答案,它必须根据具体情况进行评估。这种攻击甚至可能无法在某些机器上运行。
首先,对于这种测试,您应该使用printf来查看数据的位置:
printf("a is at %p\n", &a);
printf("array is at %p\n", array);
...
这可以让您了解需要偏移的字节数。接下来确定您是在使用little-endian还是big-endian系统。如果你正在使用little-endian,那么11999就是0xDF2E0000,如果你使用的是big-endian则它是向后的。
因此,在小端系统上给出你的程序,假设所有数据在内存中的顺序正确,并且整数是4个字节,你需要字符串“ - ”+(0x99-0x34) +“-... X..X”+ 0xDF2E0000
编辑:此字符串的原因如下:
您可以通过添加以下内容来测试:
#include <string.h>
char str[] = {16};
sprintf(str, "--%c-...X..X%c%c\0\0", 0x99 - 0x34, 0xDF, 0x2E);
memcpy(array, str, 14);
printf("The string is: \"%s\"", str);
代替您的scanf。显然,您可以找出与这些值相关联的字符并粘贴它们,但这是获取正确数据的最快方法。
当然,这是基于系统更改的主观内容,我上面的代码甚至可能无法在您的计算机上运行。这仍然是一个非常真实的东西,并且很好地证明了为什么你应该总是限制你正在阅读和写作的字符数,以及确保你使用正确的结尾字符。
如果我错过了上述任何假设/因素,我会很感激,如果有人让我知道,我可以添加它们。