Buffer overflow problem

Hi Guys,

I'm playing around with memory and trying to get a deeper understanding of how things function under the hood, I attempted this about a year ago but I decided to give it another shot.

So the problem:

I'm trying to overflow the buffer and overwrite the return address, my goal first of all (before attempting to execute my shell from the buffer overflow) is to overwrite the return address,

I manage to do this with a python script, I run the program in gdb and specify 500 A's to be printed, this seems to work as I then inspect the registers and the instruction pointer is 0x41414141 meaning it's overwritten it with 'A's

so next my shellcode takes up 53 bytes and I need some padding from what I heard to make sure the address I want to return to does so ( following this video - https://www.youtube.com/watch?v=1S0aBV-Waeo computerphile ), this padding will be 40 bytes,just an address 10 times.

so it will be 500(this is where the seg fault occurs) - 53 - 40 = 407 no ops,
in other words 407 no ops + 53 bytes of shellcode + 40 bytes of memory addresses = 500 bytes

when I run this in gdb I seem to get a seg fault but this time I get a seg fault and the return address is overwritten with no ops or /x90's.

I can't seem to figure out why the return address is being overwritten with no ops,

here are the the videos illustrating what is actually happening:
1) video of actual error - https://www.youtube.com/watch?v=XO7BmWOTqwU&feature=youtu.be
2) register info - https://www.youtube.com/watch?v=rcHndTwVEUk&feature=youtu.be

if anybody could give me some pointers (no pun) or some help getting to the bottom of this, that would be great, I'm seriously bored and decided to give this a shot again one year later.

*note all done on a virtual machine that I own and this thread is only for educational purposes (in reality a simple buffer overflow attack like this is extremely rare as protections are in place)

Thanks
when I run this in gdb I seem to get a seg fault but this time I get a seg fault and the return address is overwritten with no ops or /x90's.
If it was possible to crash a process as soon as it commits any kind of security violation then buffer overflows would not be a problem, as the process would crash as soon as they happen.
That the program crashed when you tried to write 500 bytes tells you absolutely nothing about where the return address for the current stack frame is.

You're doing it wrong. To write an exploit you need to understand the behavior of the program. Run it in a debugger and find the offset of the return adress relative to the buffer that receives the input.
that's the problem I can't seem to find the return address, I thought that if the eip is overwritten with the chosen characters in this case no ops (but I would like it to be A's)

You're doing it wrong. To write an exploit you need to understand the behavior of the program. Run it in a debugger and find the offset of the return adress relative to the buffer that receives the input.


the stack grows downwards right? so would that mean I should be looking at the lower addresses on the screen as opposed to the higher addresses on the screen in gdb?

https://ibb.co/CB1SjHW - the part that is highlighted with a yellow marking thus not the part marked with a red x, right?

also would ASLR be a problem with finding the return address here as it's not turned off.

thanks Helios
Last edited on
I thought the stack grew upwards and the heap grew downwards - but I'm not sure??
In general, no, the stack grows downwards. A few architectures allow the direction to be selected, but default to/prefer down. There aren't many architectures AFAIK of that have the stack grow upward exclusively (the Intel 8051 chips come to mind).

-Albatross
OK. I remembered it the wrong way around. The stack does come down and the heap goes upwards.

See
https://lambda.uta.edu/cse5317/notes/node33.html
https://www.cs.uleth.ca/~holzmann/C/system/memorylayout.gif
I thought that if the eip is overwritten with the chosen characters in this case no ops (but I would like it to be A's)
EIP is the program counter. Do you mean ESP? (It's still wrong.)

so would that mean I should be looking at the lower addresses on the screen as opposed to the higher addresses on the screen in gdb?

https://ibb.co/CB1SjHW - the part that is highlighted with a yellow marking thus not the part marked with a red x, right?
The yellow addresses are higher, not lower.
The return address will be at some point after the start of the input buffer. Note that the compiler may insert some padding, so the address may not appear as soon as might otherwise expect.

also would ASLR be a problem with finding the return address here as it's not turned off.
No, it doesn't matter.
but in theory shouldn't the return address be after (https://ibb.co/CB1SjHW) the yellow highlighted area? so by overwriting it with 'A's or \x41's shouldn't the program seg fault and return to what ever was overwritten to the return address?

and nope I meant the EIP, after or just before we return to the caller it (EIP) should be the address of where to continue in the caller after the callee function is finished ?
Last edited on
but in theory shouldn't the return address be after (https://ibb.co/CB1SjHW) the yellow highlighted area?
How would I know the specifics of where it is? There's no way to determine that from just a tiny memory dump. If it's your program then you should be able to know the return address at the call site and look for it in the stack.

so by overwriting it with 'A's or \x41's shouldn't the program seg fault and return to what ever was overwritten to the return address?
The order of events is wrong. The program counter will be set to whatever is at the top of the stack. If it's random garbage, when the CPU goes to fetch the next instruction it will throw an interrupt that will be caught by the kernel, which will then crash the program.
Oh, also, I just remembered, most likely the system will have set the NX bit of the pages containing the stack, thus if you try to jump to the stack the process will still crash. This why return-oriented- programming was invented.
here is the command I run in gdb to run the program with the no ops shellcode and 40 * 'A' https://ibb.co/3Ns6zLb ( pasted because I don't have copy and paste set between virtual machine and host )

when I run the above I get a seg fault with the address 0x90909090 which just happens to be 4 noops, here is the exact output (https://ibb.co/FJFcg98)

but oddly enough when run the following "run $(python -c 'print "\x41" * 500')"

I get a segfault and the memory address under it is 0x41414141 which just happens to be what I wrote past the buffer (well one past the buffer, I'd like to know where the extra 'A's are coming from)

Oh, also, I just remembered, most likely the system will have set the NX bit of the pages containing the stack, thus if you try to jump to the stack the process will still crash.
This why return-oriented- programming was invented.

oh ok, could this be possibly why this isn't working as I was expecting?

How would I know the specifics of where it is? There's no way to determine that from just a tiny memory dump. If it's your program then you should be able to know the return address at the call site and look for it in the stack.


Also sorry for my ignorance on the subject but how would I go about doing this in gdb? would I need to examine the assembly (disas )?


Last edited on
well one past the buffer, I'd like to know where the extra 'A's are coming from
You're clearly not writing just one byte past the buffer.

oh ok, could this be possibly why this isn't working as I was expecting?
No. It's not working as you expect because your expectation is wrong, because you don't sufficiently understand how your program works, certainly not at a low-enough level.

how would I go about doing this in gdb?
No idea. I don't use GDB.

would I need to examine the assembly (disas )?
That should have been the first thing you did no matter what. At least using a standalone disassembler.
Oh, also, I just remembered, most likely the system will have set the NX bit of the pages containing the stack, thus if you try to jump to the stack the process will still crash.

Compile with -zexecstack to fix this immediate problem.
Last edited on
No. It's not working as you expect because your expectation is wrong, because you don't sufficiently understand how your program works, certainly not at a low-enough level.


that's likely the main problem haha, is there anywhere (sources) that explains the layout of a program in memory and this type of thing,

I know the basics there is sections such as stack(local variables of functions and more information to allow callee to return to caller etc), heap (dynamic memory allocation), bss or static section (contains globals and static variables) and code( the actual machine code)

all of this is great to know but do you know of any good sources that explain this at a lower level,

I could look for it myself and I will but just would like to know if you have any preferred sources on the subject as a lot if not the majority of the results from a search engine are poor.

lastly and probably a seriously stupid question but what prerequisites would I need to know for trying to experiment with an overflow like this?
Last edited on
thanks :)
is there anywhere (sources) that explains the layout of a program in memory and this type of thing,
The compiled binary contains all the possible details about where the program stores datums.

what prerequisites would I need to know for trying to experiment with an overflow like this?
*Shrug* I couldn't say. Very broadly speaking, know how to use a disassembler and how to read a disassembly, and how your architecture works.
This video might interest you
How They Hack: Buffer Overflow & GDB Analysis - James Lyne
https://www.youtube.com/watch?v=V9lMxx3iFWU
thanks guys :)
Topic archived. No new replies allowed.