-
Notifications
You must be signed in to change notification settings - Fork 57
/
amfi_utils.m
159 lines (136 loc) · 4.51 KB
/
amfi_utils.m
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
// Comes from Electra, adapted for FAT binary support by me
//
// amfi_utils.c
// electra
//
// Created by Jamie on 27/01/2018.
// Copyright © 2018 Electra Team. All rights reserved.
//
#include "amfi_utils.h"
#include "kernel_utils.h"
#include "patchfinder64.h"
#include <stdlib.h>
#include <mach-o/loader.h>
#include <mach-o/fat.h>
#include <CommonCrypto/CommonDigest.h>
#include <Foundation/Foundation.h>
uint32_t swap_uint32( uint32_t val ) {
val = ((val << 8) & 0xFF00FF00 ) | ((val >> 8) & 0xFF00FF );
return (val << 16) | (val >> 16);
}
uint32_t read_magic(FILE* file, off_t offset) {
uint32_t magic;
fseek(file, offset, SEEK_SET);
fread(&magic, sizeof(uint32_t), 1, file);
return magic;
}
void *load_bytes(FILE *file, off_t offset, size_t size) {
void *buf = calloc(1, size);
fseek(file, offset, SEEK_SET);
fread(buf, size, 1, file);
return buf;
}
void getSHA256inplace(const uint8_t* code_dir, uint8_t *out) {
if (code_dir == NULL) {
printf("NULL passed to getSHA256inplace!\n");
return;
}
uint32_t* code_dir_int = (uint32_t*)code_dir;
uint32_t realsize = 0;
for (int j = 0; j < 10; j++) {
if (swap_uint32(code_dir_int[j]) == 0xfade0c02) {
realsize = swap_uint32(code_dir_int[j+1]);
code_dir += 4*j;
}
}
CC_SHA256(code_dir, realsize, out);
}
uint8_t *getSHA256(const uint8_t* code_dir) {
uint8_t *out = malloc(CC_SHA256_DIGEST_LENGTH);
getSHA256inplace(code_dir, out);
return out;
}
uint8_t *getCodeDirectory(const char* name) {
FILE* fd = fopen(name, "r");
uint32_t magic;
fread(&magic, sizeof(magic), 1, fd);
fseek(fd, 0, SEEK_SET);
long off = 0, file_off = 0;
int ncmds = 0;
BOOL foundarm64 = false;
if (magic == MH_MAGIC_64) { // 0xFEEDFACF
struct mach_header_64 mh64;
fread(&mh64, sizeof(mh64), 1, fd);
off = sizeof(mh64);
ncmds = mh64.ncmds;
}
else if (magic == MH_MAGIC) {
printf("[-] %s is 32bit. What are you doing here?\n", name);
fclose(fd);
return NULL;
}
else if (magic == 0xBEBAFECA) { //FAT binary magic
size_t header_size = sizeof(struct fat_header);
size_t arch_size = sizeof(struct fat_arch);
size_t arch_off = header_size;
struct fat_header *fat = (struct fat_header*)load_bytes(fd, 0, header_size);
struct fat_arch *arch = (struct fat_arch *)load_bytes(fd, arch_off, arch_size);
int n = swap_uint32(fat->nfat_arch);
printf("[*] Binary is FAT with %d architectures\n", n);
while (n-- > 0) {
magic = read_magic(fd, swap_uint32(arch->offset));
if (magic == 0xFEEDFACF) {
printf("[*] Found arm64\n");
foundarm64 = true;
struct mach_header_64* mh64 = (struct mach_header_64*)load_bytes(fd, swap_uint32(arch->offset), sizeof(struct mach_header_64));
file_off = swap_uint32(arch->offset);
off = swap_uint32(arch->offset) + sizeof(struct mach_header_64);
ncmds = mh64->ncmds;
break;
}
arch_off += arch_size;
arch = load_bytes(fd, arch_off, arch_size);
}
if (!foundarm64) { // by the end of the day there's no arm64 found
printf("[-] No arm64? RIP\n");
fclose(fd);
return NULL;
}
}
else {
printf("[-] %s is not a macho! (or has foreign endianness?) (magic: %x)\n", name, magic);
fclose(fd);
return NULL;
}
for (int i = 0; i < ncmds; i++) {
struct load_command cmd;
fseek(fd, off, SEEK_SET);
fread(&cmd, sizeof(struct load_command), 1, fd);
if (cmd.cmd == LC_CODE_SIGNATURE) {
uint32_t off_cs;
fread(&off_cs, sizeof(uint32_t), 1, fd);
uint32_t size_cs;
fread(&size_cs, sizeof(uint32_t), 1, fd);
uint8_t *cd = malloc(size_cs);
fseek(fd, off_cs + file_off, SEEK_SET);
fread(cd, size_cs, 1, fd);
fclose(fd);
return cd;
} else {
off += cmd.cmdsize;
}
}
fclose(fd);
return NULL;
}
//from xerub
int strtail(const char *str, const char *tail)
{
size_t lstr = strlen(str);
size_t ltail = strlen(tail);
if (ltail > lstr) {
return -1;
}
str += lstr - ltail;
return memcmp(str, tail, ltail);
}