我正在尝试执行一个非常简单的缓冲区溢出攻击。我几乎是新手。所以,如果这个问题很愚蠢,请原谅: - )
代码:
#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()',并将返回地址覆盖到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语句打印“Done”,但它会跳回victim_func()并输出“Enter n:”
我做错了什么?任何帮助将不胜感激!
PS:我不确定我是否提出了正确的问题。如果需要更多信息,请告诉我。答案 0 :(得分:9)
缓冲区溢出攻击要比这复杂得多。首先,您需要了解汇编程序才能执行此操作。在反汇编您想要定位的程序和函数后,您需要在执行该函数时确定堆栈布局。 这是一个缓冲区溢出的示例,它使用visual studio,但原理是相同的。
#include "stdafx.h"
#include <math.h>
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]中写的任何地址。
希望这有帮助。
答案 1 :(得分:1)
首先,在我看来,你不应该在你的样本输入中输入数字5。你的数组声明为[4],因此元素索引为0-3 - 所以你的攻击输入对我来说似乎不对。
在我看来,你的程序假设了几个关于架构的东西:
如果其中一个假设是不真实的,它就永远不会起作用。
这似乎是一项非常辛苦的工作任务。
缓冲区溢出攻击的例子比更改代码的控制流更容易。例如,您可能能够覆盖应该受到用户保护的另一段数据(例如安全设置)
答案 2 :(得分:1)
现在,我想要的是通过溢出缓冲区来从victim_func()跳转到'confused()'函数,并将返回地址覆盖到confused()的地址......
在现代Linux平台上,您还需要确保关闭两个安全功能以进行测试。首先是NX-stacks,第二个是Stack Protectors。
要关闭NX-Stacks,请使用-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
编译该程序。
默认情况下会启用安全功能,因为过去存在很多问题。一般来说,它是一件好事,因为它可以解决许多问题(比如你正在试验的问题)。
答案 3 :(得分:0)
您没有向我们展示带有[i]地址的程序输出。我怀疑编译器正在做一些事情,比如将堆栈上的数据与16对齐。返回地址可能远远超出预期。