Each vulnerability has a specific cause, which in turn leads to ways of exploiting the vulnerability. It is hard to understand how one can exploit something abstract and gain some abstract results, but it is way easier to understand when illustrated with examples. The simplest would be the classical stack-based buffer overflow:
void f(const char *str) {
char buf[10];
strcpy(buf, str);
}
This is a primitive example that should be sufficient to demonstrate the issue. Suppose the str
argument points to a NULL-terminated string longer than the 10 chars allocated for the variable it is being copied into. What will happen? strcpy()
will blindly copy the data over the end of the buffer, overwriting whatever was there. But what exactly is there?
On x86, for example, the buf
variable would be allocated on the stack. The stack is also used to save the return address when a CALL
instruction is executed. So the (simplified) stack layout would look like this (addresses are increasing top to bottom):
...
buf[0..3]
buf[4..7]
buf[8..9]
return address
...
So, by supplying an overly long string via the str
argument, we would be able to overwrite the return address from f()
. If the attacker is able to control the string, then he can control where the control flow will go after f()
returns. This may occur when parsing a specially crafted file, for example.
The next thing would be to direct the control to a JMP ESP
instruction or similar in effect, causing code from the stack to be executed. This "direct" code execution is prevented by DEP.
Of course, the example above doesn't include bypassing any of modern mitigations (stack canaries, SafeSEH, DEP). This does not mean it is globally impossible, but it may be impossible in certain cases. Bypassing DEP usually involves Return-oriented programming -- instead of code itself, specially crafted data is placed on the stack, which utilises fragments of already existing functions in the process image (called gadgets) to execute code. This, in turn, is mitigated by ASLR, making the gadget addresses somewhat unpredictable. There are techniques of bypassing ASLR as well.
If you would like to get your hands on exploiting real-life programs, I would suggest corelanc0d3r's tutorials as a starting point.
EDIT: Replaced the offending part.