There is a binary file i am working on . It has a function with the address starting at 123. I need to get my code to execute this function.
Binary file accepts a byte array of size 'n' and does not check for bounds. Entire task is actually to overflow the buffer and cause bad things to happen.
Again, the job is to call address 123 and get it to execute. I was under impression that if a buffer size is , say "4", and i pass 9 characters .., 5 characters will be placed on the stack and executed. (is it true?)
Additionally, in order for me to get to address to be executed, i'd like to say "call 123". From what i understand "call" is "e8", no?
This problem is a bit confusing for me. If someone could help me better understand it, i would very much appreciate it
(Yes, this is a homework question)
I strongly recommend that you read Smashing the Stack for Fun and Profit. It describes in great detail exactly the steps you need to do to do this.
The stack does not contain code, but it does contain the return address for the function. Typical stack structure is:
<stack data> <old frame pointer> <return address>
<old frame pointer> is omitted sometimes and I think would have to for this, so all you have to provide is the data to fill the array then 123.
A common strategy is to find a call ESP opcode in a fixed memory address, and overwrite return address with this address. In this way the execution will continue on the stack. It will work if there is no DEP activated (or supported).
In your case you could also look for an abs_jump 123 in memory.
EDIT:
#Loren It would work only if stack can be executed. call esp has only two bytes opcode, so there is high probability to find it somewhere in memory. The second approach does not execute code from stack, but requires a 5 byte opcode, that is very unlikely to be found.
Related
I am trying to understand the buffer overflow exploit and more specifically, how it can be used to run own code - e.g. by starting our own malicious application or anything similar.
While I do understand the idea of the buffer overflow exploit using the gets() function (overwriting the return address with a long enough string and then jumping to the said address), there are a few things I am struggling to understand in real application, those being:
Do I put my own code into the string just behind the return address? If so, how do I know the address to jump to? And if not, where do I jump and where is the actual code located?
Is the actual payload that runs the code my own software that's running and the other program just jumps into it or are all the instructions provided in the payload? Or more specifically, what does the buffer overflow exploit implementation actually look like?
What can I do when the address (or any instruction) contains 0? gets() function stops reading when it reads 0 so how is it possible to get around this problem?
As a homework, I am trying to exploit a very simple program that just asks for an input with gets() (ASLR turned off) and then prints it. While I can find the memory address of the function which calls it and the return, I just can't figure out how to actually implement the exploit.
You understand how changing the return address lets you jump to an arbitrary location.
But as you have correctly identified you don't know where you have loaded the code you want to execute. You just copied it into a local buffer(which was mostly some where on the stack).
But there is something that always points to this stack and it is the stack pointer register. (Lets assume x64 and it would be %rsp).
Assuming your custom code is on the top of the stack. (It could be at an offset but that too can be managed similarly).
Now we need an instruction that
1. Allows us to jump to the esp
2. Is located at a fixed address.
So most binaries use some kind of shared libraries. On windows you have kernel32.dll. In all the programs this library is loaded, it is always mapped at the same address. So you know the exact location of every instruction in this library.
All you have to do is disassemble one such library and find an instruction like
jmp *%rsp // or a sequence of instructions that lets you jump to an offset
Then the address of this instruction is what you will place where the return address is supposed to be.
The function will return then and then jump to the stack (ofcourse you need an executable stack for this). Then it will execute your arbitrary code.
Hope that clears some confusion on how to get the exploit running.
To answer your other questions -
Yes you can place your code in the buffer directly. Or if you can find the exact code you want to execute (again in a shared library), you can simply jump to that.
Yes, gets would stop at \n and 0. But usually you can get away by changing your instructions a bit to write code that doesn't use these bytes at all.
You try different instructions and check the assembled bytes.
I have browsed the internet a lot and still could not understand the way it works
No success with this link either:
How does a NOP sled work?
Okay, let's say we have a buffer char a[8]; in the function foo()
and the stack frame for foo() looks like this (32-bit):
Now, what we want to do, is to overwrite 'return' value, saved on the stack when foo() was called
They say that the problem is, we cannot predict the location of saved 'return' value
But why? For example, if function foo() has the buffer defined prior to all other local variables, like in the picture above, then we always know that we need to fill 8 bytes allocated for buffer, then 4 bytes of saved EBP and then we got 'return'
Alternatively, if there are other local variables defined before the buffer, say 2 ints, then we consider 8 bytes allocated for buffer, then 8 bytes of those 2 local ints, then 4 bytes of saved EBP and then we got 'return'
We always know how far is the saved 'return' from our overflown buffer, don't we ? :/
If we don't, please explain. That's my question 1.
My question 2 is, okay, let's assume that we don't know where the value for 'return' is saved. Then if we have a large array of NOPs coming before the shellcode, we have a high chance of writing NOP (i.e. 0x90) value into location of 'return', hence overwriting the original value
Now, when the function foo() returns, the value of 0x90 is loaded into EIP (instruction pointer) and instead of resuming its normal flow, the program is going to be executed from address 0x90, isn't it?
I think I've misunderstood something here
Please, don't close my question, even though there is a similar question that I've provided the link to, at the very beginning,
I guess this question will be far more comprehensive and clearer
First we assume there is no address space randomization and the stack is executable.
We always know how far is the saved 'return' from our overflown buffer, don't we ? :/
No, we don't know. There is an unspecified number of padding bytes between the local variables and the saved EBP and the return address. This number of bytes may depend on the compiler version.
Then if we have a large array of NOPs coming before the shellcode, we have a high chance of writing NOP (i.e. 0x90) value into location of 'return', hence overwriting the original value
The idea is to have all NOP values after the return address. This way we can overwrite the return address with an "approximate" address of the shellcode in the stack. The exact shellcode address may depend on the OS version but also on program arguments and the size and number of the environment variables because they are in the stack address space.
Can someone suggest me any exercise or code to help me understand heap and stack memory better? I have read about this in textbooks a lot, just wanted to see some code to understand better. Maybe some stack overflow example or something like that. I assume C/C++ would be an ideal candidate.
Both the stack and the heap reside in memory. Where exactly isn't necessarily important but you should seek to understand their data structure.
Heap:
For the Heap you should read this example implementation of malloc and it should give you an idea of how it works (code included).
Stack (theory):
The stack (the basic data structure) is a rather simple concept to understand and is explained well enough here. That link also briefly covers how it is used in your program. I haven't found something that I think describes it in a nice way so I'll include the following as additional references to follow up:
There is a simple power point about it available here,
an interesting (and quite involved) video here
and a simplified explanation here.
If these don't quite explain it right, you should try and find something that explains the call stack and the stack frame in a way you will understand.
Stack (code):
All the links I pointed out explain the theory and don't give you the code. My understanding of the stack was significantly improved after I learned about computer architecture and assembly language.
So if you want a code example you should try and implement a simple assembly function and link it to a C program. Here is an example (with a brief intro into assembly).
Java and C++:
Java and C++ hide this stuff from you so if this is a learning exercise I recommend C and assembly. I'm not sure if it is even possible to do it in Java. You can in C++ but it gets complicated...
My explanation of the Call Stack:
I will try and give a short explanation of the call stack and the stack frame with respect to the C programming language and Assembly.
To do that lets define a simple machine so that we can begin on the same page.
Our processor has a finite number of registers, lets say 8. Operations like add, subtract, compare and others can ONLY be done on registers. There are only two instructions that you can execute on memory and they are load and store. These instructions copy from memory to a register, or from a register to memory respectively.
Now, if we want to add 2 numbers we have plenty of variables. We will load one number into register 1 and the other into register 2, add them and put the result into register 3. Now, if we do another operation on registers 4 and 5, store the result in register 6 and then want to add registers 7 and 8 where do we put the result? We have run out of variables...
Clearly we need to use memory and save information there when we are not processing it. To do that we need to know where in memory each variable lives.
You could remember the address of each variable and manually type them in every time, possibly writing it down next to a sensible name on a piece of paper on your desk. But that would be tedious and would pose a serious limitation on functions.
Functions have local variables. If these variable's addresses were hardwired they would always be allocated to the function and would pose a big problem to recursion. If a function were to call itself it would overwrite the values that it's caller (itself) was using.
To solve this the simplest way is to use a stack. However, to do so we need to keep the Stack Pointer address somewhere. So lets just agree that from now on we will use register 8 as our stack pointer.
Also lets say that when you push stuff onto the stack we will subtract the number of bytes we want from the stack pointer and when we want to pop we will add the number of bytes to the stack pointer.
Every time we call a function we will put its local variables on the stack. Since we know what variables we want, we know how much memory we need.
But to access each local variable we need to know its address... Let us set up an example.
Lets say that we have 2 variables, both of which have 2 bytes in our function and that the stack pointer is 18.
As per our agreement lets subtract 4 bytes from the stack pointer, making the stack pointer equal 14.
Now to access the first variable we will simply use the stack pointer. To access the second we will subtract 2 from the stack pointer.
As long as our function is running this will be true, but before our function exits we will free our local variables from the stack by adding 4 to it again, making the stack pointer 18 (like it was before we started).
I'm sorry if this question is stupid or has been asked, but I couldn't find it.
I have a program that I was attempting to use a buffer over flow. It is a simple program that uses getchar() to retrieve the input from the user. The buffer is set to size 12. I can get the program to crash by typing >12 x's or using >12 \x78's, but it won't seg fault if I type in hundreds of A's or \x41's.
Any help or pointing in the right direction would be greatly appreciated.
0x41414141 may be a valid address within a text page of the process. Look at the segment map of the process for details.
To eliminate guessing, look at the assembly code and then at machine instructions of your program. Run it in a debugger and see what happens in the memory. You can see at what addresses on the stack local variables are placed and and what addresses registers and especially the instruction pointer are saved on a function call.
Have you look at examples like the stack overflow on Wikipedia?
I read many articles about unsafe functions like strcpy, memcpy, etc. which may lead to security problems when processing external data, like the content of a file or data coming from sockets. This may sound stupid, but I wrote a vulnerable program but I did not manage to "hack" it.
I understand the problem of buffer overflow. Take this example code:
int main() {
char buffer[1];
int var = 0;
scan("%s", &buffer);
printf("var = 0x%x\n", var);
return 0;
}
When I execute the program and type "abcde", the program outputs 0x65646362 which is "edcb" in hexadecimal + little-endian. However I read that you could modify the eip value that was pushed on the stack in order to make the program execute some unwanted code (eg. right before a call to the system() function).
However the function's assembly starts like this:
push %ebp
mov %ebp, %esp
and $0xfffffff0, %esp
sub $0x20, %esp
Since the value of %esp is random at the start of the function and because of this "and", there seems to be no reliable way to write a precise value into the pushed eip value.
Moreover, I read that it was possible to execute the code you wrote in the buffer (here the buffer is only 1 byte long, but in reality it would be large enough to store some code) but what value would you give to eip in order to do so (considering the location of the buffer is random)?
So why are developpers so worried about security problems (except that the program could crash) ? Do you have an example of a vulnerable program and how to "hack" it to execute unwanted code? I tried this on linux, is Windows less safe?
Read the excellent article by Aleph One: Smashing the Stack for Fun and Profit.
Well for one thing, don't under estimate the hazards associated with being able to unreliably place a value inside EIP. If an exploit works one in 16 times, and the service it is attacking automatically restarts, like many web applications, then an attacker that fails when trying to get access can always try, try again.
Also in a lot of cases the value of ESP is less random than you think. For starters on a 32-bit system it is nearly always a multiple of four. That means that the extra padding offered by the and $0xfffffff0, %esp instruction will be either 0, 4, 8 or 12 bytes. That means that it is possible to just repeat the value that is to be written into the return EIP four times to cover all possible offsets to the address of return EIP.
There are actually much more aggressive stack protection / buffer overflow detection mechanisms around. However, there are ways and means around even these.
Also, for an example of where this sort of thing can be dangerous, consider if the value of var was important to you logic as in the following toy example.
int main() {
char buffer[1];
int var = 0;
var = SecurityCheck();
scan("%s", &buffer);
if (var != 0)
GrantAccess();
else
DenyAccess()
}
Further you don't have to overwrite EIP with a pointer to something in your string. For example you could overwrite it with a pointer to system() and overwrite the next word with a pointer to /bin/sh at a fixed location in the program image.
Edit: Note that system uses the PATH (actually it runs the command via a shell), so "sh" would be just as good; thus, any English word ending in "sh" at the end of a string provides the argument you need.
A classic example of an actual exploit based on buffer overruns is the Morris Worm of 1988.
As mentioned in other answers, absolute reliability is not always essential for the attack to succeed. Applications that restart automatically are an example. Locally exploitable buffer overflows on suid programs would be another. And there's the NOP sled technique to increase chances of successful exploitation, put a lot of NOPs before your shellcode so you have a much better chance to correctly guess the "start" of your shellcode.
There are many more techniques for increasing the reliability of attacks. On Windows, back in the day, many exploits overwrote the return address with the address of a "jmp %esp" located somewhere in the program (trampoline).
"Insecure programming by example" had a nice trick for Linux. Clean your environment and put your shellcode in an environment variable. Back in the day, this would lead to a predictable address near the top of the stack.
And there are also variants like return-into-libc and return-oriented programming.
There was even an article on Phrack on how to exploit 1-byte stack overflows (meaning the buffer was overrun by only one byte) (btw, 1-byte heap overflows are also exploitable in the vast majority of cases, barring protections).
To sum up, it's not that developers are paranoid, there are lots of ways to exploit even the strangest cases, and remember:
A program is of good quality when it does what it is supposed to do.
A program is secure when it does what it is supposed to do, and nothing more.
Here's a windows version and tutorial:
http://www.codeproject.com/KB/winsdk/CodeInject.aspx
The general case I was always warned about was:
printf( string );
Because the user can provide a "%n" in there, which allows you to insert anything you want into memory. All you need to do is find the memory offset for a system call, pass a few "%n"'s and junk characters, and thus insert the memory address onto the stack where the return vector would normally be. Voila -- insert any code you like.