I understand that a typical stack based buffer overflow attack payload looks something like this:
(return address) (return address) ... (return address) (return address) (return address) (return address) (NOP) (NOP) (NOP) (NOP) ... (NOP) (NOP) (NOP) (NOP) (SHELLCODE)
I also understand that successful execution of the shellcode depends on a few things:
What I don't get is how malware that use this technique can always get these two things right. It seems to me that in order to craft a working payload, the attacker has to know the approximate address of the target buffer and its approximate distance from the return address.
Are these two usually pretty deterministic? For example, if the attacker does a few sessions of trial and error until it works on his machine, will that same payload work on all other machines with the exact same binaries?
The return address affects where the program should jump to when the function returns. If the return address field is modified due to a buffer overflow, when the function returns, it will return to a new place.
Buffer Overflow Solutions The most reliable way to avoid or prevent buffer overflows is to use automatic protection at the language level. Another fix is bounds-checking enforced at run-time, which prevents buffer overrun by automatically checking that data written to a buffer is within acceptable boundaries.
If the stack buffer is filled with data supplied from an untrusted user then that user can corrupt the stack in such a way as to inject executable code into the running program and take control of the process. This is one of the oldest and more reliable methods for attackers to gain unauthorized access to a computer.
If the return address is overwritten, then the return address will consist of some of the characters that were in the alphacode that was entered. This may cause a segmentation fault and crash our program if the memory allocated on the stack for the return address does not point to a valid address.
The accuracy of determining the layout of memory is entirely dependent on the function's stack frame that you are corrupting. Sometimes offsets can be very accurate and even a nop sled isn't required, but its a good idea to have one anyway. If you trigger the issue a couple of times in a debugger you can get an idea of how chaotic the stack is. Other factors can influence very the size of the offset. For instance if the offset can change for different versions of the program, such as an exploit written for windows 2000 and windows xp. Differing language distributions of the application can also affect the size of the offset.
However, ASLR causes serious problems for this exploitation method. Heap Spraying is commonly used by browser based exploits to bypass ASLR.
in order to craft a working payload, the attacker has to know the approximate address of the target buffer and its approximate distance from the return address.
You are right. In fact you have to play a bit with the debugger, in order to write a correct exploit. Once you have written it and tested, if the binary is the same on different machines, exploit should work fine.
(work fine is a bit optimistic. Let's say that the shellcode should be launched. The effectivity of the attack may depends on other factors..)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With