330 likes | 496 Views
A Phrack Double Feature ~ Smashing the Stack for Fun and Profit and Once Upon a Free()…. By Aleph One and Anonymous ~ Joe Tucek. Phrack. Hacker e-magazine published since 1985 First on BBSes, now on the internet Articles accepted from anyone Generally high level of technical content
E N D
A Phrack Double Feature~Smashing the Stack for Fun and ProfitandOnce Upon a Free()… By Aleph One and Anonymous ~ Joe Tucek
Phrack • Hacker e-magazine published since 1985 • First on BBSes, now on the internet • Articles accepted from anyone • Generally high level of technical content • Compared to other hacker magazines • Also, not academic technical content • Most famous articles include • “The Hacker Manifesto” by The Mentor • “Smashing the Stack for Fun and Profit” by Aleph1
Smashing the Stack for Fun… • Walks through the basics of stack-based buffer overruns • From November 1996 • Despite being almost 9 years old, still the basis for many attacks • Defenses exist • Can be expensive • Poorly deployed
Buggy Program void buggy(char * in){ int i; char buffer[4]; for(i=0; in[i]!=0; i++) buffer[i] = in[i]; } What happens if in is “Aleph One”?
Buggy Code’s Stack A l e p h _ O n e \0 41 6C 65 70 68 20 4F 6E 65 00 • Program will start copying…
Buggy Code’s Stack A l e p h _ O n e \0 41 6C 65 70 68 20 4F 6E 65 00 • Program will start copying…
Buggy Code’s Stack A l e p h _ O n e \0 41 6C 65 70 68 20 4F 6E 65 00 • Program will start copying…
Buggy Code’s Stack A l e p h _ O n e \0 41 6C 65 70 68 20 4F 6E 65 00 • Program will start copying…
Buggy Code’s Stack A l e p h _ O n e \0 41 6C 65 70 68 20 4F 6E 65 00 • Program will start copying… and continue.
Buggy Code’s Stack A l e p h _ O n e \0 41 6C 65 70 68 20 4F 6E 65 00 • C isn’t bounds checked…
Buggy Code’s Stack A l e p h _ O n e \0 41 6C 65 70 68 20 4F 6E 65 00 • What happens next?
Buggy Code’s Stack A l e p h _ O n e \0 41 6C 65 70 68 20 4F 6E 65 00 • We’ve overwritten the return address!
Buggy Code’s Stack A l e p h _ O n e \0 41 6C 65 70 68 20 4F 6E 65 00 • Notice anything unusual about this particular return address?
So what? • OK, so we can make programs crash. • Actually, we can make them do anything we want… • Computers are Von Neumann architecture • “a computer design model that uses a single storage structure to hold both programs and data” – Wikipedia • Instructions and data aren’t differentiated…
##execve(“/bin/sh”); pushl %ebp movl %esp, %ebp pushl %ebx movl $0xb, %eax movl 0x8(%ebp), %ebx movl 0cx(%ebp), %exc movl 0x10(%ebp), %edx int $0x80 movl %eax, %edx testl %edx, %edx ... An introduction to shellcode • execve() runs the command it is passed • The assembly is two parts • Function call prelude • The actual work
##execve(“/bin/sh”, 0, 0); pushl %ebp movl %esp, %ebp pushl %ebx movl $0xb, %eax movl 0x8(%ebp), %ebx movl 0cx(%ebp), %exc movl 0x10(%ebp), %edx int $0x80 movl %eax, %edx testl %edx, %edx ... An introduction to shellcode • First we set up some arguments • Which system call (0xb into EAX) • Argument to system call (pointer into EBX) • Misc arguments (ECX and EDX) • Then call interrupt 0x80
So how is this shellcode? • We can write a version which is self contained • Contains the necessary strings, does the setup, everything… \xeb\x2a\x5e\x89\x76\x08\xc6\x46\x07\x00\xc7\x46\x0c\x00\x00\x00\x00\xb8\x0b\x00\x00\x00\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xb8\x01\x00\x00\x00\xbb\x00\x00\x00\x00\xcd\x80\xe8\xd1\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68\x00\x89\xec\x5d\xc3
So how is this shellcode? • We can write a version which is self contained • Contains the necessary strings, does the setup, everything… \xeb\x2a\x5e\x89\x76\x08\xc6\x46\x07\x00\xc7\x46\x0c\x00\x00\x00\x00\xb8\x0b\x00\x00\x00\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xb8\x01\x00\x00\x00\xbb\x00\x00\x00\x00\xcd\x80\xe8\xd1\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68\x00\x89\xec\x5d\xc3 • But it also has a few null bytes… • for(i=0; in[i]!=0; i++)
So how is this shellcode? • We can write a version which is self contained • Contains the necessary strings, does the setup, everything… \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 • A total of 46 bytes • It will even call exit(0) when it’s done… • Just imagine what one could do with a few thousand bytes…
Recap • We find a buffer that we can write past the end of • We put some of our own attack code in it • We also put the address of our code in the return address slot of the stack • When the current function returns, we’ll be transferred to our code, and then we grab control
Anatomy of a stack overflow • We have a region of NOPs to help us jump • We have some exploit code • We have a block of possible addresses to jump to • Does it work? • YES
Advanced Tricks • We can • Put code AFTER the return address • Put code in an environment variable • Try over and over and over again • Given the binary, calculate (sometimes) exact offsets • Have our exploit code simply “bootstrap” to bigger & better things
Once Upon a free()… • Rather than overflowing the stack, overflow the heap • But the return address is nowhere near the heap! • It is still quite possible • Demonstrated by Solar Designer with a bug in Netscape’s JPEG handling routine
Once upon a (GNU) malloc()… • Malloc must manage both allocated and free chunks of memory
More malloc() • In practice, they’re laid out one after another • Never two free blocks in a row though • GCC will consolidate them, so as to have large chunks of contiguous free space • The consolidation code is what we’ll attack.
Consolidation in brief • Use the size field to find the next block • Check the bits in its size to see if it’s free • If not, stop • (Boring) • Extract the “next” block from the linked list • Ahh, pointers that we blindly trust
Exploit in short #define unlink(P, BK, FD) { BK = P->bk; FD = P->fd; FD->bk = BK; BK->fd = FD; }
Summary • Stack overflows are “easy” to do • So people look for the now • Heap overflows are “hard” • Require precise addresses • Must wait for a “free” • BUT – still quite doable, and not as guarded agaist
Guarding against exploits • Stack • StackGuard, MemGuard • High overhead, poorly deployed • Stack Randomization • Just try over and over and over • Or (if local), one can try attaching a debugger… • Heap (& stack too) • Heap & Library Randomization • See “Stack Randomization” • Requires “PIC” code—breaks some things • W^X (non-executable areas) • Breaks some code (JIT compilers, Photoshop) • Poor support on x86 (x86 extensions support it)