缓冲区溢出攻击
我正在尝试执行一个非常简单的缓冲区溢出攻击。我对此几乎是新手。所以,如果这个问题很愚蠢,请原谅我:-)
代码:
#include<stdio.h>
#include<stdlib.h>
int i, n;
void confused(int i)
{
printf("**Who called me? Why am I here?? *** %x\n ", i);
}
void shell_call(char *c)
{
printf(" ***Now calling \"%s\" shell command *** \n", c);
system(c);
}
void victim_func()
{
int a[4];
printf("Enter n: "); scanf("%d",&n);
printf("~~~~~~~~~~~~~ values and address of n locations ~~~~~~~~~~");
for (i = 0;i <n ;i++)
printf ("\n a[%d] = %x, address = %x", i, a[i], &a[i]);
printf("\nEnter %d HEX Values \n", n);
// Buffer Overflow vulnerability HERE!
for (i=0;i<n;i++) scanf("%x",&a[i]);
printf("Done reading junk numbers\n");
}
int main()
{
victim_func();
printf(“\n done”);
return 0;
}
当我使用 objdump 获取函数地址时,我有以下内容:
main(): 0x804854d
Address of main() where printf() is called: 0x8048563
victim_func(): 0x8048455
confused(): 0x8048414
现在,我想要的是从victim_func跳转到函数“confused()” () 方法是溢出缓冲区,并将返回地址覆盖为fused() 的地址。我想从confused()返回到main中的printf()语句,并正常退出。因此,我提供以下输入
Enter n: 7
Enter 7 HEX values:
1
2
3
4
5
8048414 (This is to jump to confused)
8048563 (this is to jump to printf() in main)
虽然程序从该 printf 语句打印“Done”,但它跳回到victim_func() 并打印“Enter n:”
我做错了什么?任何帮助将不胜感激!
PS:我不确定我的问题是否正确。如果需要更多信息,请告诉我。
I'm trying to execute a very simple buffer overflow attack. I'm pretty much a newbie to this. So, if this question is stupid, please excuse me :-)
The code:
#include<stdio.h>
#include<stdlib.h>
int i, n;
void confused(int i)
{
printf("**Who called me? Why am I here?? *** %x\n ", i);
}
void shell_call(char *c)
{
printf(" ***Now calling \"%s\" shell command *** \n", c);
system(c);
}
void victim_func()
{
int a[4];
printf("Enter n: "); scanf("%d",&n);
printf("~~~~~~~~~~~~~ values and address of n locations ~~~~~~~~~~");
for (i = 0;i <n ;i++)
printf ("\n a[%d] = %x, address = %x", i, a[i], &a[i]);
printf("\nEnter %d HEX Values \n", n);
// Buffer Overflow vulnerability HERE!
for (i=0;i<n;i++) scanf("%x",&a[i]);
printf("Done reading junk numbers\n");
}
int main()
{
victim_func();
printf(“\n done”);
return 0;
}
When I use objdump to get the function addresses, I have the following:
main(): 0x804854d
Address of main() where printf() is called: 0x8048563
victim_func(): 0x8048455
confused(): 0x8048414
Now, what I want is to jump to the function 'confused()' from victim_func() by overflowing the buffer there, and overwriting the return address to the address of confused(). And I want to return back from confused() to the printf() statement in main, and exit normally. So, I provide the following input
Enter n: 7
Enter 7 HEX values:
1
2
3
4
5
8048414 (This is to jump to confused)
8048563 (this is to jump to printf() in main)
Although, the program prints "Done" from that printf statement, it is jumping back to victim_func() and prints "Enter n:"
What am I doing wrong? Any help would be greatly appreciated!
PS: I'm not sure if I have put the question right. Please let me know, if any more information is needed.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
缓冲区溢出攻击比这复杂得多。首先,您需要了解汇编程序才能执行此操作。反汇编您想要定位的程序和函数后,您需要确定执行该函数时的堆栈布局。
这是使用 Visual Studio 的缓冲区溢出示例,但原理是相同的。
通过反汇编,我们知道函数 1 中的 a 是在函数保存堆栈帧指针的位置之前分配的。该值后面的值是 function1 完成后应前往的返回地址。
由此我们可以得出结论,如果我们用不同的地址覆盖 a[7],该函数将不会返回到 main,而是会返回到我们在 a[7] 中写入的任何地址。
希望这有帮助。
A buffer overflow attack is a lot more complex than this. First of all you need to understand assembler in order to perform this. After you disassemble the program and function you want to target you need to determine the stack layout when it's executing that function.
Here's a sample of a buffer overflow it's using visual studio but principle is the same.
Thanks to disassembly we know that a in function1 is allocated before where the function saved the stack frame pointer. The value after that one is the return address where function1 should go to if it is finished.
From this we can conclude if we overwrite a[7] with a different address, the function will return not to main but with whatever address we wrote in a[7].
Hope this helps.
在现代Linux平台上,您还需要以确保关闭两项安全功能进行测试。第一个是 NX 堆栈,第二个是堆栈保护器。
要关闭 NX-Stack,请使用
-Wl,z,execstack
(而不是-Wl,z,noexecstack
)。要关闭堆栈保护器,请使用-fno-stack-protector
(而不是-fstack-protector
或-fstack-protector-all
) 。您可能需要关闭第三种保护。这种保护就是 FORTIFY_SOURCE。 FORTIFY_SOURCE 使用高风险函数的“更安全”变体,例如
memcpy
和strcpy
。当编译器可以推断出目标缓冲区大小时,它会使用更安全的变体。如果副本超出目标缓冲区大小,则程序将调用abort()
。要禁用 FORTIFY_SOURCE,请使用 -U_FORTIFY_SOURCE 或 -D_FORTIFY_SOURCE=0 编译程序。安全功能默认打开,因为过去存在很多问题。总的来说,这是一件好事,因为它可以解决许多问题(就像您正在尝试的问题)。
On modern Linux platforms, you will also need to ensure two security features are turned off for testing. First in NX-stacks, and second is Stack Protectors.
To turn off NX-Stacks, use
-Wl,z,execstack
(as opposed to-Wl,z,noexecstack
). To turn off Stack Protectors, use-fno-stack-protector
(as opposed to-fstack-protector
or-fstack-protector-all
).There's a third protection you might need to turn off. That protection is FORTIFY_SOURCE. FORTIFY_SOURCE uses "safer" variants of high risk functions like
memcpy
andstrcpy
. The compiler uses the safer variants when it can deduce the destination buffer size. If the copy would exceed the destination buffer size, then the program callsabort()
. To disable FORTIFY_SOURCE, compile the program with-U_FORTIFY_SOURCE
or-D_FORTIFY_SOURCE=0
.The security features are turned on by default because there's been so many problems in the past. In general, its a good thing because it stops many problems (like the one you are experimenting with).
首先,在我看来,您不应该在示例输入中输入数字 5。你的数组被声明为a[4],因此元素索引为0-3 - 所以你的攻击输入对我来说似乎是错误的。
在我看来,您的程序假设了有关架构的几件事:
如果这些假设之一不正确,则它永远不会起作用。
这似乎是一项非常艰苦的工作任务。
缓冲区溢出攻击的示例比更改代码的控制流更简单。例如,您可能能够覆盖另一条应该受到用户保护的数据(例如安全设置)
First of all it seems to me that you shouldn't enter the number 5 in your sample input. Your array is declared a[4] thus has elements indexed 0-3 - so your attack input seems wrong to me.
It also seems to me that your program assumes several thing about the architecture:
If one of these assumptions is untrue it's never going to work.
This seems like a very hard work work assignment.
There are easier examples of buffer overflow attacks than changing the control flow of the code. For example you might be able to overwrite another piece of data which is supposed to be protected from the user (such as a security setting)
您没有向我们展示带有 a[i] 地址的程序输出。我怀疑编译器正在执行诸如将堆栈上的数据对齐到 16 之类的操作。它可能比您预期的返回地址更远。
You didn't show us the output of the program with the addresses of a[i]. I suspect that the compiler is doing something like aligning the data on the stack to 16. It could be much further to the return address than you expect.