0
votes

Is it possible to do a buffer overflow (assuming no modern stack defenses like canaries, aslr, non-executable stack, etc. are on) by chaining stacks together? I tried to draw a diagram below to show what I mean:

(Edited; low address)


buffer A + ebp (8 bytes)


return address A


random memory (assume 40 bytes)


buffer B + ebp (40 bytes)


return address B


(high address)

Can I craft a payload like the following?
'A' * 8 + hex value for the start of buffer B + '\x90' * 50 + shellcode (assume 20 bytes)
The idea is that I return into a portion of the stack containing a nop sled and shellcode.

If I can execute the payload above, then as a follow up, what if I drop into random memory instead of buffer B? Will the nop sled carry me to my shellcode? Thank you!!!

1
The return address can't be at the start, that's not where the saved return address is on the stack. I don't understand what "chaining" you're talking about here; that sounds like just overwriting a return address normally to return into somewhere near your exploit payload, with the nop sled covering that area. If you know the approximate absolute address of the buffer, you know where to point the return address to hopefully hit inside the not sled. - Peter Cordes
Or is your diagram upside down, with lower addresses at the top? - Peter Cordes
I should have made it clear; lower addresses are at the top of the stack, and high addresses are at the bottom. - Math Student

1 Answers

1
votes

This is definitely possible, for the operating systems course I followed last year we even had to do this as an assignment. This is the entire reason the stack defenses you mention exist, so you usually can't do this. When you drop into random memory, then, if this portion is executable, writable etc etc. then you can indeed slide and run arbitrary shellcode in the process. However, even when the binary doesn't use these protective measures like canaries etc, the kernel has another trick up it's sleeve: address space randomization. It's usually pretty hard to figure out from the process you try to exploit where important functions are loaded and where important data is.

For the course this was our setup:


int main(int argc, char ** argv) {
    char buf[256];
    strcpy(buf, argv[1]);
    return 0;
}

void unused_function() {
    printf("exploit!");
}

Objective was of course to call unused_function. Address space randomization was turned off and stack protection as well.