I have constructed a model stack frame based on debugging information that I extracted from the executable using GDB. While not an expert, I can follow the assembly code enough to pinpoint the location of some local variables, and, of course, I can use symbol table information to directly query the address of variables and arrays. Unfortunately, I can not account for two "slots" (two 32-bit words [8bytes]) of memory immediately following the $EBP of the stack frame. From my understanding, a standard stack frame for, 32-bit Linux, is laid out, in order of increasing stack (i.e. growing towards lower memory address), as follows:
- function arguments (parameters)
- Return address (EIP value of next instruction of the calling function)
- frame base pointer (stores the address of the calling functions frame base)
- exception handler information (if applicable)
- Register values (if pushed onto the stack)
- local variables
- allocated buffer space and/or temporary data storage
The 'C' program does not define exception handling information so I'm sure that I can rule that out. Furthermore, I do not see in the assembly code that any registers apart $EBP are pushed onto the stack. Of course, $EAX is used as a workhorse to store many value and perform computations but is never pushed onto the stack. While $ESP is used it is never pushed onto the stack either. The source code is provided below:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
long n = 0, c = 0, d = 0;
FILE *fp = NULL;
void bubble_sort()
{
long swap = 0;
long array[39];
// loading data to array
printf("Source list:\n");
char line[sizeof(long) * 2 + 1] = {0};
while(fgets(line, sizeof(line), fp))
{
if (strlen((char *)line) > 1)
{
sscanf(line, "%lx", &(array[n]));
printf("0x%lx\n", array[n]);
++n;
}
}
fclose(fp);
// bubble sort
for (c = 0 ; c < ( n - 1 ); c++)
{
for (d = 0 ; d < n - c - 1; d++)
{
if (array[d] > array[d+1])
{
swap = array[d];
array[d] = array[d+1];
array[d+1] = swap;
}
}
}
//output result to stdout
printf("\nSorted list in ascending order:\n");
for ( c = 0 ; c < n ; c++ )
printf("%lx\n", array[c]);
}
int main(int argc, char **argv)
{
/* a main program further up stack memory that calls bubble sort
code omitted because it is not relevant*/
}
Unfortunately, there is too much assembly to post here. There are only five local variables allocated in bubble_sort: swap, array[], line[], rawtime, timeinfo. I can account for all of them in GDB using the assembly and source tables. What are those mystery 8 bytes immediately following $EBP on the stack? Is it some predefined offset allowed for by the compiler? Does it have to do with default system alignment? I'm pretty new to these things. Any help is greatly appreciated. Thank You.
FYI, this code was not compiled with optimization turned on. ASLR is off as is stack canary support because this is a buffer overflow lesson.