The almighty stack 
Introduction to the cdecl ABI and the x86 stack 
Alex Moneger 
Security Engineer
Chapter structure 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 2
Chapter structure 
 Brief description of the x86 ASI and cdecl ABI 
 Data and code segregation 
 Into cdecl 
 The stack frame (holy noises) 
 Exercise 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 3
Bytes and AAAAAAhhhhhSM 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 4
All starts with ISA 
 ISA stands for Instruction Set Architecture 
 Specified by the CPU : 
1. Registers (ie: eax, ebp, esp…) 
2. Instruction set (ie: add, sub, mov, call) 
 Specifies the CPU capabilities 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 5
The ABI 
 ABI stands for Application Binary Interface 
 Specified by each OS 
 Can have multiple ABIs per OS 
 Specifies: 
 How the OS expects programs to use the ISA 
 What standard binaries must adhere to to run on the OS 
 How compilers need to compile programs to enable them to run 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 6
The x86 cdecl ABI 
 Used by Linux 
 Dictates how function calls are made: 
 eax holds the return value of the function 
 Function parameters are pushed on the stack by the caller 
 The callee is in charge of reserving space on the stack 
 The callee is in charge of freeing the reserved space on the stack 
 More on this later… 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 7
Code vs Data 
 In a binary, code (machine instructions) is segregated from data 
(values manipulated) 
 In short, code is RE, data is RW 
 Code (.text section, dynlibs, …) has it’s own space 
 Data (.data section, …) has it’s own space 
 Data and code are never mixed together: 
cisco@kali:~/src/seccon$ readelf -l ch2 | egrep -i "LOAD|Addr" 
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align 
LOAD 0x000000 0x08048000 0x08048000 0x00588 0x00588 R E 0x1000 
LOAD 0x000588 0x08049588 0x08049588 0x0011c 0x00120 RW 0x1000 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 8
What about “dynamic” data? 
 What about runtime dynamic data? 
 Introduce the 2 dynamic memory sections: 
1. The stack, contains data for which size is known at compile time. It is 
tracked by the compiler. 
2. The heap, contains data which size is know at runtime. It is tracked by the 
libc. 
 Dynamic data is marked as RW: 
cisco@kali:~/src/seccon$ readelf -l ch2 | egrep -i "STACK|Addr" 
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align 
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 9
Introducing the stack 
 Stack is a LIFO structure. It grows towards lower addresses 
 Stack holds the return address (where the program needs to ret 
following a call) 
 Each function gets a space where it can store it’s local data => The 
stack frame 
 The amount of local storage a function needs determines the size of 
the stack frame 
 When function exits, the stack frame is removed (popped) from the 
stack 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 10
Stack: the high level view 
 Pseudocode:  Stack 
cisco@kali:~/src/seccon$ pygmentize -g ch2-pc.c 
void func3(void) { 
} 
void func2(void) { 
} 
void func1(void) { 
func2(); 
func3(); 
} 
int main(void) { 
func1(); 
} 
Top of stack (High address) ie: 0xbfffffff 
int main(void) 
void func1(void) 
void func3(func2(void) 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 11
I’m ESP, I’m really special 
 By convention, special registers are used to manage 
the stack: 
1. EBP, the stack base pointer: 
 Used to index function parameters and local variables 
 Does not move during the life of the stack frame 
2. ESP, always indexes the top of the stack 
 Controlled by pop, push instructions 
 Shifted down the stack at function entry to reserve space for 
local variables 
void 
func1(void) 
EBP 
ESP 
0x01020304 
0xffffffff 
ESP 
ESP 
cisco@kali:~/src/seccon$ pygmentize -g ch2-ex.asm 
push 0x01020304 
push 0xffffffff 
pop eax 
pop ebx 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 12
Unwinding the frame 
 On function exit, the stack frame is removed 
 But how much space to remove? 
 But how does the code know where to return? 
 Enter Saved EBP and mostly Saved EIP 
 Saved EBP remembers where the previous frame pointer was 
 Saved EIP tells the ret instruction where to return: 
 Ret = pop eip; jmp eip 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 13
Unwinding the frame - 2 
 On function return: 
 esp = ebp => remove all local storage 
 pop ebp => Set the base stack pointer to the previous frame 
 leave = mov ebp, esp; pop ebp 
 Called function epilogue: 
mov esp,ebp 
pop ebp 
ret 
leave 
ret 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 14
Example: Winding the stack 
 Stack 
cisco@kali:~/src/seccon$ pygmentize -g ch2-pc.c 
void func1(int a) { // 0x080483dc 
char c = 'A'; 
} 
int main(void) { // 0x080483e8 
func1(0x1234); 
} 
Top of stack (High address) ie: 
0xbfffffff 
Saved EIP of main 
Saved EBP – (stack frame -1) 
0x1234 
0x080483e8 
EBP=0xbffff6b4 
0xbffff6b4 
0x00000000 
dahtah@kali:~/src/seccon$ objdump -d -j .text -M intel ch2-pc2 | grep 'func1>:' 
-A 15 
080483dc <func1>: 
80483dc: 55 push ebp 
80483dd: 89 e5 mov ebp,esp 
80483df: 83 ec 10 sub esp,0x10 
80483e2: c6 45 ff 41 mov DWORD PTR [ebp-0x4],0x41 
80483e6: c9 leave 
80483e7: c3 ret 
080483e8 <main>: 
80483e8: 55 push ebp 
80483e9: 89 e5 mov ebp,esp 
80483eb: 83 ec 04 sub esp,0x4 
80483ee: c7 04 24 34 12 00 00 mov DWORD PTR [esp],0x1234 
80483f5: e8 e2 ff ff ff call 80483dc <func1> 
80483fa: c9 leave 
80483fb: c3 ret 
EBP=0xbffff6c4 
ESP 
0x00000041 
0x00000000 
0x00000000 
0x00000000 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 15
Example: Unwinding the stack 
 Stack 
cisco@kali:~/src/seccon$ pygmentize -g ch2-pc.c 
void func1(int a) { // 0x080483dc 
char c = 'A'; 
} 
int main(void) { // 0x080483e8 
func1(0x1234); 
} 
Top of stack (High address) ie: 
0xbfffffff 
Saved EIP of main 
Saved EBP – (stack frame -1) 
0x1234 
0x080483e8 
EBP=0xbffff6b4 
0xbffff6b4 
dahtah@kali:~/src/seccon$ objdump -d -j .text -M intel ch2-pc2 | grep 'func1>:' 
-A 15 
080483dc <func1>: 
80483dc: 55 push ebp 
80483dd: 89 e5 mov ebp,esp 
80483df: 83 ec 10 sub esp,0x10 
80483e2: c6 45 ff 41 mov DWORD PTR [ebp-0x4],0x41 
80483e6: c9 leave 
80483e7: c3 ret 
080483e8 <main>: 
80483e8: 55 push ebp 
80483e9: 89 e5 mov ebp,esp 
80483eb: 83 ec 04 sub esp,0x4 
80483ee: c7 04 24 34 12 00 00 mov DWORD PTR [esp],0x1234 
80483f5: e8 e2 ff ff ff call 80483dc <func1> 
80483fa: c9 leave 
80483fb: c3 ret 
ESP 
ESP 
EBP=0xbffff6c4 
ESP 
ESP 
0x00000041 
0x00000000 
0x00000000 
0x00000000 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 16
Enough theory 
 Noticed something juicy in the stack process? 
 If an attacker controls saved EIP, he controls the program flow 
 Buffer overflow = saved EIP control. That’s it. 
 Go play! 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 17
When I get to rest 
 Compile the following program: 
cisco@kali:~/src/seccon$ pygmentize -g ch2.c 
#include <stdio.h> 
int callee(int a, int b, int c) { 
char local_buf[0x20] = {0x01}; 
unsigned int local_int = 0xffffffff; 
return 0x12345678; 
} 
int main(int argc, char **argv) { 
int ret = callee(0x1, 0x2, 0x3); 
return 0; 
} 
 Disassemble it 
 Understand the objdump output 
 Draw out the stack movement on paper 
 Fire up gdb and set a breakpoint on callee 
entry and exit. Inspect the stack. Follow ebp, 
esp. 
 Make sure you understand the output from 
“info frame”. Get the output manually 
 Overwrite callee’s saved EIP. What happens 
when callee exits? 
 Add a function called by callee. Follow the 
stack 
cisco@kali:~/src/seccon$ objdump -d -j .text -M intel 
ch2 | grep 'callee>:' -A 40 
© 2013-2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential 18