Dies ist eine alte Version des Dokuments!


Program Execution Details

Program Startup

Upon startup, the executable file is loaded into the main memory. Knowing the address of the entry point _start of the executable from the ELF format, the operating system is able to start the execution. C developers might wonder why the execution entry point is called _start and not main(), which is what they are used to. Although the runtime environment C programs have is minimal in comparison to other languages, its setup is done within each application's code. Classical examples for runtime environment features of C are the access to command line arguments via argc and argv, as well as access to environment variables via envp. To save C programmers the effort of writing these routines for every program by hand, compilers link ready-made code taking care of these tasks. This predefined code is called crt0 and fills the functional gap between the raw execution entry point _start and the C entry point main().

:!: Concluding from the reasoning above, command line arguments and environment variables are among the first values pushed to the stack of an application. Due to that, in comparison to other variables their offsets are relatively easy to calculate. Keep this fact in mind, it will be important later when calculating stack addresses and using these locations for exploitation.

Function Calls

Another important aspect of program execution is the way that functions are called. Parameter passing depends on the applied calling convention. On x86 systems the cdecl calling convention, which is also used by GCC, requires the parameters to be put on the stack in reverse order. When a call instruction is encountered, the address of the instruction executed directly after the function call is pushed to the stack. Execution is continued with the code of the function.

Usually, inside the function the stack is prepared first. After saving the base pointer at the stack, it is overwritten with the current stack pointer.

push ebp
mov  ebp, esp

By decreasing the value of the stack pointer, n bytes of memory for local variables are allocated.

sub esp, n

At this point the stack setup is done and the actual content of the function is next to be executed. The base pointer can now be used to reference function parameters and local variables. While parameters have a positive offset, variables are referenced by a negative offset. After the function execution is finished the stack pointer and base pointer are reset.

mov esp, ebp
pop ebp

Lastly, the return address is read from the stack and written to the instruction pointer register.

ret

Execution continues with the code at the saved address. The information on the stack belonging to a particular function call is called the stack frame of the function.

A visualization of the stack frame of a single function is shown below.

Keep in mind that function calls are nested in every non-trivial program. Thus there are several stack frames located on the stack.