-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy patharchitect.c
More file actions
130 lines (112 loc) · 3.54 KB
/
Copy patharchitect.c
File metadata and controls
130 lines (112 loc) · 3.54 KB
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
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <elf.h>
#include <sys/syscall.h>
#include <linux/memfd.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#if ARCH == 32
typedef Elf32_Ehdr Elf_Ehdr;
typedef Elf32_Shdr Elf_Shdr;
typedef Elf32_Xword Elf_Xword;
#else
typedef Elf64_Ehdr Elf_Ehdr;
typedef Elf64_Shdr Elf_Shdr;
typedef Elf64_Xword Elf_Xword;
#endif
int main(int argc, char* argv[], char *envp[])
{
if (argc == 0)
{
fprintf(stderr, "ERROR: Called improperly.\n");
return 1;
}
// Open this file for reading
FILE* self = fopen("/proc/self/exe", "rb");
Elf_Ehdr elfHeader;
fread(&elfHeader, sizeof(elfHeader), 1, self);
if (elfHeader.e_shoff == 0 || elfHeader.e_shnum == 0)
{
fprintf(stderr, "No ELF sections found\n");
}
Elf_Shdr* section_headers = malloc(elfHeader.e_shnum * elfHeader.e_shentsize);
fseek(self, elfHeader.e_shoff, SEEK_SET);
fread(section_headers, elfHeader.e_shentsize, elfHeader.e_shnum, self);
char* string_table = malloc(section_headers[elfHeader.e_shstrndx].sh_size);
fseek(self, section_headers[elfHeader.e_shstrndx].sh_offset, SEEK_SET);
fread(string_table, section_headers[elfHeader.e_shstrndx].sh_size, 1, self);
int sf_payload_section = -1;
int hf_payload_section = -1;
for (int i = 0; i < elfHeader.e_shnum; i++)
{
char* section_name = string_table + section_headers[i].sh_name;
if (strcmp(section_name, ".sf_payload") == 0)
{
sf_payload_section = i;
}
if (strcmp(section_name, ".hf_payload") == 0)
{
hf_payload_section = i;
}
}
if (sf_payload_section == -1)
{
fprintf(stderr, "No sf_payload section found\n");
return 1;
}
// Check our architecture
int payload_section = sf_payload_section;
char* interpreter = "/lib/ld-linux.so.3";
if (access("/lib/ld-linux-armhf.so.3", R_OK) == 0)
{
interpreter = "/lib/ld-linux-armhf.so.3";
if (hf_payload_section != -1)
{
payload_section = hf_payload_section;
}
}
char* filepath = strdup("/tmp/architect_XXXXXX");
int fd = mkostemp(filepath, O_EXCL);
FILE* payload_file = fdopen(fd, "wb");
fchmod(fd, S_IRUSR|S_IWUSR|S_IXUSR|S_IXGRP|S_IXOTH);
fseek(self, section_headers[payload_section].sh_offset, SEEK_SET);
for (Elf_Xword i=0; i < section_headers[payload_section].sh_size; i++)
{
fputc(fgetc(self), payload_file);
}
free(section_headers);
free(string_table);
fclose(self);
fclose(payload_file);
char** final_argv = malloc(sizeof(char*) * (argc - 1 + 4 + 1)); // argv[0] is handled separetely, add the 4 args we need for that, and also we need to NULL-terminate the char* array
final_argv[0] = interpreter;
final_argv[1] = "--argv0";
final_argv[2] = argv[0];
final_argv[3] = filepath;
memcpy(&final_argv[4], &argv[1], sizeof(char*) * (argc-1)); // We copy from the 1st element to the last
final_argv[argc - 1 + 4] = NULL;
pid_t pid = fork();
int status;
switch (pid)
{
case -1:
fprintf(stderr, "Fork error! (%i)", errno);
break;
case 0:
execve(interpreter, final_argv, envp);
break;
default:
waitpid(pid, &status, 0);
remove(filepath);
free(filepath);
return status;
break;
}
return 1;
}