我有一个小的C程序被利用。而且我也理解了要执行的攻击背后的逻辑。然而,尽管我尝试过,但这对我来说并不起作用。
#include <stdio.h>
#include <stdlib.h>
#define SECRET1 0x44
#define SECRET2 0x55
int main(int argc, char *argv[]) {
char user_input[100];
int *secret;
int int_input;
int a, b, c, d; /* other variables, not used here.*/
/* The secret value is stored on the heap */
secret = (int *) malloc(2*sizeof(int));
/* getting the secret */
secret[0] = SECRET1; secret[1] = SECRET2;
printf("Please enter a decimal integer\n");
scanf("%d", &int_input); /* getting an input from user */
printf("Please enter a string\n");
scanf("%s", user_input); /* getting a string from user */
printf(user_input);
printf("\n");
/* Verify whether your attack is successful */
printf("The original secrets: 0x%x -- 0x%x\n", SECRET1, SECRET2);
printf("The new secrets: 0x%x -- 0x%x\n", secret[0], secret[1]);
return 0;
}
我只需要使用格式字符串“printf(user_input);”
打印secret [0]的地址和值我尝试过提供类似“\ x6e \ xaf \ xff \ xff%x%x%x%x%s”的内容。但它不起作用。任何建议将不胜感激。非常感谢。
答案 0 :(得分:8)
这看起来像是一个类的练习,所以我会提供一些指示,但没有实际的解决方案。
您正在尝试通过提供不受信任的输入来利用此程序。这里有两个相当明显的错误;一个是使用scanf()
的{{1}},因为您可以溢出缓冲区并覆盖堆栈。另一种是格式字符串漏洞。在函数返回之前,覆盖堆栈可能不会让你做任何有趣的事情。基于“验证您的攻击是否成功”部分,您可能希望在此之前利用此漏洞,因此我猜它应该是格式字符串漏洞。
根据验证部分,您需要覆盖%s
指向的内存。导致secret
写入内存中受控位置的唯一方法是使用printf
格式说明符,它会写入给定的指针。
现在的诀窍是弄清楚如何在我们找到合适的指针之前向上走。方便的是,在堆栈上的指针之前有一个用户控制的整数。因此,我们输入一个带有易于点模式的数字(可能为65535,十六进制为%n
),并使用带有大量ffff
s的格式字符串来查看堆栈中的内容。一旦我们找到了,堆栈上的下一件事应该是指针。
嗯。我刚试过这个,结果证明它并不那么简单。堆栈帧的确切布局实际上与声明的顺序无关;它对我来说在不同系统之间有所不同。相反,我必须在开头使用大量的%x
和一个众所周知的字符串,并添加一行来打印实际的指针,所以我知道什么时候找到它。然后用%lx
替换相应的%lx
以通过该指针进行写入。最简单的方法是尝试大约20个%n
,并用%lx
逐个替换,直到您设法覆盖该指针。
无论如何,希望这足以让你开始。如果您有任何问题,请告诉我。