Buffer Overflow Attack
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");
}
开发者_StackOverflow社区
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.
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.
#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;
}
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.
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
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.
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()...
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
and strcpy
. 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 calls abort()
. 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).
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:
- sizof(int)==sizeof(memory address)
- The direction of growth and mechanism of the environments stack implementation
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)
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.
精彩评论