缓冲区溢出攻击

我正在尝试执行一个非常简单的缓冲区溢出攻击。 我几乎是新手。 所以,如果这个问题很愚蠢,请原谅:-)

代码:

#include #include 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 ("\na[%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()’,并将返回地址覆盖到confused()的地址。 我想从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语句打印“完成”,但它会跳回victim_func()并打印“输入n:”

我究竟做错了什么? 任何帮助将不胜感激!

PS:我不确定我是否提出了正确的问题。 如果需要更多信息,请告诉我。

缓冲区溢出攻击要比这复杂得多。 首先,您需要了解汇编程序才能执行此操作。 在反汇编您想要定位的程序和函数后,您需要在执行该函数时确定堆栈布局。 这是一个缓冲区溢出的示例,它使用visual studio,但原理是相同的。

 #include "stdafx.h" #include  volatile double test; double function3() { test++; return exp(test); } double function2() { return log(test); } double function1() { int a[5] = {0}; a[7] = (int)&function3; return exp(function2()); } int _tmain(int argc, _TCHAR* argv[]) { double a = function1(); test = a; return a; } 

由于反汇编,我们知道函数1在函数保存堆栈帧指针之前被分配。 该值之后的值是function1应该完成的返回地址。

 00401090 55 push ebp <- we save the stack pointer 00401091 8B EC mov ebp,esp 00401093 83 EC 1C sub esp,1Ch <- save space to allocate a[5] 00401096 B8 CC CC CC CC mov eax,0CCCCCCCCh 0040109B 89 45 E4 mov dword ptr [ebp-1Ch],eax <- crt debug init a[5] 0040109E 89 45 E8 mov dword ptr [ebp-18h],eax 004010A1 89 45 EC mov dword ptr [ebp-14h],eax 004010A4 89 45 F0 mov dword ptr [ebp-10h],eax 004010A7 89 45 F4 mov dword ptr [ebp-0Ch],eax 004010AA 89 45 F8 mov dword ptr [ebp-8],eax 004010AD 89 45 FC mov dword ptr [ebp-4],eax 

由此我们可以得出结论,如果我们用不同的地址覆盖[7],函数将不返回main,而是返回我们在[7]中写入的任何地址。

希望这可以帮助。

首先,在我看来,你不应该在你的样本输入中输入数字5。 你的数组声明为[4],因此元素索引为0-3 – 所以你的攻击输入对我来说似乎不对。

在我看来,您的程序假设有关架构的几个方面:

  • sizof(int)== sizeof(内存地址)
  • 环境堆栈实现的增长方向和机制

如果其中一个假设是不真实的,它永远不会起作用。

这似乎是一项非常艰苦的工作任务。

缓冲区溢出攻击的简单示例比更改代码的控制流更容易。 例如,您可能能够覆盖应该受到用户保护的另一段数据(例如安全设置)

现在,我想要的是通过溢出缓冲区来从victim_func()跳转到函数’confused()’,并将返回地址覆盖到confused()的地址……

在现代Linux平台上,您还需要确保关闭两个安全function以进行测试。 首先是NX-stacks,其次是Stack Protectors。

要关闭NX-Stacks,请使用-Wl,z,execstack (而不是-Wl,z,noexecstack )。 要关闭堆栈保护器,请使用-fno-stack-protector (与-fstack-protector-fstack-protector-all相反)。

您可能需要关闭第三种保护措施。 这种保护是FORTIFY_SOURCE。 FORTIFY_SOURCE使用“更安全”的高风险函数变体,如memcpystrcpy 。 当编译器可以推导出目标缓冲区大小时,编译器会使用更安全的变体。 如果副本超过目标缓冲区大小,则程序调用abort() 。 要禁用FORTIFY_SOURCE,请使用-U_FORTIFY_SOURCE-D_FORTIFY_SOURCE=0编译程序。

默认情况下会启用安全function,因为过去存在很多问题。 一般来说,它是一件好事,因为它可以阻止许多问题(比如你正在试验的问题)。

你没有向我们展示带有[i]地址的程序输出。 我怀疑编译器正在做一些事情,比如将堆栈上的数据与16对齐。它可能比返回地址远远超出预期。