I've been reading Aleph One's paper on Smashing the Stack for Fun and Profit. I wrote down example1.c
from his paper, modified it a bit to see what the stack looks like on my system.
I'm running Ubuntu (64-bit) on a VM on an Intel i5 M 480.
The paper says that a stack will have the following structure. It also says that the word size is 4 bytes. I read up on word sizes and determined that on a 64-bit OS that is not "long-enabled" the word size is still 32 bits or 4 bytes.
However, when I run my custom code:
void function(int a, int b, int c) {
char buffer1[5];
char buffer2[10];
memset(buffer1, "\xaa", sizeof(buffer1));
}
void main() {
function(1, 2, 3);
}
I do not get the same stack structure as the paper. Yes, I'm aware that the paper was published in 1998 but I haven't found any article on the internet stating that the stack structure has been modified greatly. Here's what my stack looks like (I'm also uploading GDB screenshots for verification, in case I've misinterpreted the stack):
Lower memory Higher memory
-------------------------------------------------------------------------
| int c | int b | int a | buffer1 | buffer2 | RBP | RET |
| 4 bytes | 4 bytes | 4 bytes | 16 bytes | 16 bytes | 8 bytes | 8 bytes |
-------------------------------------------------------------------------
Now for my questions:
- Why has the stack structure changed?
- What is with the extra space given to buffer1 and buffer2? According to the paper they should have only 8 bytes and 12 bytes allotted. However, buffer2 gets an extra 6 bytes and only then does buffer1 begin and even buffer1 is allotted 16 bytes. Am I missing something here? I read about slack space being given as a protective mechanism, is this it?
[EDIT]
The x64 ABI says that the stack is always eightbyte aligned (page 17, footnote number 9).
So, if the parameters and the 2 character buffers are pushed onto the stack then the total space occupied by the stack is 48 bytes (or 0x30 bytes). Since, it is 8 bytes for 3 integers amounting to a total and 24 bytes and 8 bytes for buffer1 and 16 bytes for buffer2, we arrive at our grand total of 48 bytes which is corroborated by the GDB screenshot.
However, the GDB stack also shows that the integers (a, b and c) have only been allotted 4 bytes each. The buffers also occupy the size declared in the program (obviously). Is this why I see the slack?
Slack = 48 - (5 + 10 + 4 + 4 + 4) = 21 bytes
Am I right?