Rizin
unix-like reverse engineering framework and cli tools
bin_mach064.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2009-2019 nibble <nibble.ds@gmail.com>
2 // SPDX-FileCopyrightText: 2009-2019 pancake <pancake@nopcode.org>
3 // SPDX-FileCopyrightText: 2009-2019 alvaro_fe <alvaro.felipe91@gmail.com>
4 // SPDX-License-Identifier: LGPL-3.0-only
5 
6 #define RZ_BIN_MACH064 1
7 #include "bin_mach0.c"
8 
9 #include "objc/mach064_classes.h"
10 #include "../format/mach0/kernelcache.h"
11 
12 static bool check_buffer(RzBuffer *b) {
13  ut8 buf[4] = { 0 };
14  if (rz_buf_size(b) > 4) {
15  rz_buf_read_at(b, 0, buf, sizeof(buf));
16  if (!memcmp(buf, "\xfe\xed\xfa\xcf", 4)) {
17  return true;
18  }
19  if (!memcmp(buf, "\xcf\xfa\xed\xfe", 4)) {
21  }
22  }
23  return false;
24 }
25 
26 static RzBuffer *create(RzBin *bin, const ut8 *code, int codelen, const ut8 *data, int datalen, RzBinArchOptions *opt) {
27  const bool use_pagezero = true;
28  const bool use_main = true;
29  const bool use_dylinker = true;
30  const bool use_libsystem = true;
31  const bool use_linkedit = true;
32  ut64 filesize, codeva, datava;
33  ut32 ncmds, magiclen, headerlen;
34  ut64 p_codefsz = 0, p_codeva = 0, p_codesz = 0, p_codepa = 0;
35  ut64 p_datafsz = 0, p_datava = 0, p_datasz = 0, p_datapa = 0;
36  ut64 p_cmdsize = 0, p_entry = 0, p_tmp = 0;
37  ut64 baddr = 0x100001000LL;
38  // TODO: baddr must be overriden with -b
40 
41 #define B(x, y) rz_buf_append_bytes(buf, (const ut8 *)(x), y)
42 #define D(x) rz_buf_append_ut32(buf, x)
43 #define Q(x) rz_buf_append_ut64(buf, x)
44 #define Z(x) rz_buf_append_nbytes(buf, x)
45 #define W(x, y, z) rz_buf_write_at(buf, x, (const ut8 *)(y), z)
46 #define WZ(x, y) \
47  p_tmp = rz_buf_size(buf); \
48  Z(x); \
49  W(p_tmp, y, strlen(y))
50 
51  /* MACH0 HEADER */
52  // 32bit B ("\xce\xfa\xed\xfe", 4); // header
53  B("\xcf\xfa\xed\xfe", 4); // header
54  D(7 | 0x01000000); // cpu type (x86) | ABI64
55  // D (3); // subtype (i386-all)
56  D(0x80000003); // x86-64 subtype
57  D(2); // filetype (executable)
58 
59  ncmds = (data && datalen > 0) ? 3 : 2;
60  if (use_pagezero) {
61  ncmds++;
62  }
63  if (use_dylinker) {
64  ncmds++;
65  if (use_linkedit) {
66  ncmds += 3;
67  }
68  if (use_libsystem) {
69  ncmds++;
70  }
71  }
72 
73  /* COMMANDS */
74  D(ncmds); // ncmds
75  p_cmdsize = rz_buf_size(buf);
76  D(-1); // headsize // cmdsize?
77  D(0); // 0x85); // flags
78  D(0); // reserved -- only found in x86-64
79 
80  magiclen = rz_buf_size(buf);
81 
82  if (use_pagezero) {
83  /* PAGEZERO */
84  D(0x19); // cmd.LC_SEGMENT
85  D(72); // sizeof (cmd)
86  WZ(16, "__PAGEZERO");
87  Q(0); // vmaddr
88  Q(0x1000); // vmsize XXX
89  Q(0); // fileoff
90  Q(0); // filesize
91  D(0); // maxprot
92  D(0); // initprot
93  D(0); // nsects
94  D(0); // flags
95  }
96 
97  /* TEXT SEGMENT */
98  D(0x19); // cmd.LC_SEGMENT_64
99  // D (124+16+8); // sizeof (cmd)
100  D(124 + 28); // sizeof (cmd)
101  WZ(16, "__TEXT");
102  Q(baddr); // vmaddr
103  Q(0x1000); // vmsize XXX
104 
105  Q(0); // fileoff
106  p_codefsz = rz_buf_size(buf);
107  Q(-1); // filesize
108  D(7); // maxprot
109  D(5); // initprot
110  D(1); // nsects
111  D(0); // flags
112  // define section
113  WZ(16, "__text");
114  WZ(16, "__TEXT");
115  p_codeva = rz_buf_size(buf); // virtual address
116  Q(-1);
117  p_codesz = rz_buf_size(buf); // size of code (end-start)
118  Q(-1);
119  p_codepa = rz_buf_size(buf); // code - baddr
120  D(-1); // offset, _start-0x1000);
121  D(2); // align
122  D(0); // reloff
123  D(0); // nrelocs
124  D(0); // flags
125  D(0); // reserved1
126  D(0); // reserved2
127  D(0); // reserved3
128 
129  if (data && datalen > 0) {
130  /* DATA SEGMENT */
131  D(0x19); // cmd.LC_SEGMENT_64
132  D(124 + 28); // sizeof (cmd)
133  p_tmp = rz_buf_size(buf);
134  Z(16);
135  W(p_tmp, "__TEXT", 6); // segment name
136  // XXX must be vmaddr+baddr
137  Q(0x2000); // vmaddr
138  // XXX must be vmaddr+baddr
139  Q(0x1000); // vmsize
140  Q(0); // fileoff
141  p_datafsz = rz_buf_size(buf);
142  Q(-1); // filesize
143  D(6); // maxprot
144  D(6); // initprot
145  D(1); // nsects
146  D(0); // flags
147 
148  WZ(16, "__data");
149  WZ(16, "__DATA");
150 
151  p_datava = rz_buf_size(buf);
152  Q(-1);
153  p_datasz = rz_buf_size(buf);
154  Q(-1);
155  p_datapa = rz_buf_size(buf);
156  D(-1); //_start-0x1000);
157  D(2); // align
158  D(0); // reloff
159  D(0); // nrelocs
160  D(0); // flags
161  D(0); // reserved1
162  D(0); // reserved2
163  D(0); // reserved3
164  }
165 
166  if (use_dylinker) {
167  if (use_linkedit) {
168  /* LINKEDIT */
169  D(0x19); // cmd.LC_SEGMENT
170  D(72); // sizeof (cmd)
171  WZ(16, "__LINKEDIT");
172  Q(0x3000); // vmaddr
173  Q(0x00001000); // vmsize XXX
174  Q(0x1000); // fileoff
175  Q(0); // filesize
176  D(7); // maxprot
177  D(3); // initprot
178  D(0); // nsects
179  D(0); // flags
180 
181  /* LC_SYMTAB */
182  D(2); // cmd.LC_SYMTAB
183  D(24); // sizeof (cmd)
184  D(0x1000); // symtab offset
185  D(0); // symtab size
186  D(0x1000); // strtab offset
187  D(0); // strtab size
188 
189  /* LC_DYSYMTAB */
190  D(0xb); // cmd.LC_DYSYMTAB
191  D(80); // sizeof (cmd)
192  Z(18 * sizeof(ut32)); // empty
193  }
194 
195  const char *dyld = "/usr/lib/dyld";
196  const int dyld_len = strlen(dyld) + 1;
197  D(0xe); /* LC_DYLINKER */
198  D((4 * 3) + dyld_len);
199  D(dyld_len - 2);
200  WZ(dyld_len, dyld); // path
201 
202  if (use_libsystem) {
203  /* add libSystem at least ... */
204  const char *lib = "/usr/lib/libSystem.B.dylib";
205  const int lib_len = strlen(lib) + 1;
206  D(0xc); /* LC_LOAD_DYLIB */
207  D(24 + lib_len); // cmdsize
208  D(24); // offset where the lib string start
209  D(0x2);
210  D(0x1);
211  D(0x1);
212  WZ(lib_len, lib);
213  }
214  }
215  if (use_main) {
216  /* LC_MAIN */
217  D(0x80000028); // cmd.LC_MAIN
218  D(24); // sizeof (cmd)
219  D(baddr); // entryoff
220  D(0); // stacksize
221  D(0); // ???
222  D(0); // ???
223  } else {
224 #define STATESIZE (21 * sizeof(ut64))
225  /* THREAD STATE */
226  D(5); // LC_UNIXTHREAD
227  D(184); // sizeof (cmd)
228  D(4); // 1=i386, 4=x86_64
229  D(42); // thread-state-count
230  p_entry = rz_buf_size(buf) + (16 * sizeof(ut64));
231  Z(STATESIZE);
232  }
233 
234  WZ(4096 - rz_buf_size(buf), "");
235  headerlen = rz_buf_size(buf) - magiclen;
236 
237  codeva = rz_buf_size(buf) + baddr;
238  datava = rz_buf_size(buf) + codelen + baddr;
239 
240  if (p_entry != 0) {
241  W(p_entry, &codeva, 8); // set PC
242  }
243 
244  /* fill header variables */
245  W(p_cmdsize, &headerlen, 4);
246  filesize = magiclen + headerlen + codelen + datalen;
247  // TEXT SEGMENT //
248  W(p_codefsz, &filesize, 8);
249  W(p_codefsz - 16, &filesize, 8); // vmsize = filesize
250  W(p_codeva, &codeva, 8);
251  {
252  ut64 clen = codelen;
253  W(p_codesz, &clen, 8);
254  }
255  p_tmp = codeva - baddr;
256  W(p_codepa, &p_tmp, 8);
257 
258  B(code, codelen);
259 
260  if (data && datalen > 0) {
261  /* append data */
262  W(p_datafsz, &filesize, 8);
263  W(p_datava, &datava, 8);
264  W(p_datasz, &datalen, 8);
265  p_tmp = datava - baddr;
266  W(p_datapa, &p_tmp, 8);
267  B(data, datalen);
268  }
269 
270  return buf;
271 }
272 
274  ut64 addr;
275  RzBinAddr *ret = NULL;
276  switch (sym) {
278  addr = MACH0_(get_main)(bf->o->bin_obj);
279  if (!addr || !(ret = RZ_NEW0(RzBinAddr))) {
280  return NULL;
281  }
282  ret->paddr = ret->vaddr = addr;
283  break;
284  default:
285  break;
286  }
287  return ret;
288 }
289 
290 static RzList *strings(RzBinFile *bf) {
291  return rz_bin_file_strings(bf, 4, false);
292 }
293 
295  .name = "mach064",
296  .desc = "mach064 bin plugin",
297  .license = "LGPL3",
298  .get_sdb = &get_sdb,
299  .load_buffer = &load_buffer,
300  .destroy = &destroy,
301  .check_buffer = &check_buffer,
302  .baddr = &baddr,
303  .binsym = binsym,
304  .entries = &entries,
305  .virtual_files = &virtual_files,
306  .maps = &maps,
307  .sections = &sections,
308  .signature = &entitlements,
309  .symbols = &symbols,
310  .imports = &imports,
311  .strings = &strings,
312  .info = &info,
313  .libs = &libs,
314  .header = &MACH0_(mach_headerfields),
315  .relocs = &relocs,
316  .fields = &MACH0_(mach_fields),
317  .create = &create,
318  .classes = &classes,
319  .section_type_to_string = &MACH0_(section_type_to_string),
320  .section_flag_to_rzlist = &MACH0_(section_flag_to_rzlist),
321 };
322 
323 #ifndef RZ_PLUGIN_INCORE
326  .data = &rz_bin_plugin_mach064,
328 };
329 #endif
RZ_API RZ_OWN RzList * rz_bin_file_strings(RZ_NONNULL RzBinFile *bf, size_t min_length, bool raw_strings)
Generates a RzList struct containing RzBinString from a given RzBinFile.
Definition: bfile_string.c:325
static bool load_buffer(RzBinFile *bf, RzBinObject *obj, RzBuffer *buf, Sdb *sdb)
Definition: bin_any.c:50
static void destroy(RzBinFile *bf)
Definition: bin_any.c:54
static ut64 baddr(RzBinFile *bf)
Definition: bin_any.c:58
static Sdb * get_sdb(RzBinFile *bf)
Definition: bin_art.c:60
static RzList * maps(RzBinFile *bf)
Definition: bin_bf.c:116
static RzList * virtual_files(RzBinFile *bf)
Definition: bin_bflt.c:167
static RzList * libs(RzBinFile *bf)
Definition: bin_coff.c:379
static RzList * classes(RzBinFile *bf)
Definition: bin_dex.c:71
static RzBinAddr * binsym(RzBinFile *bf, RzBinSpecialSymbol sym)
Definition: bin_mach064.c:273
static RzBuffer * create(RzBin *bin, const ut8 *code, int codelen, const ut8 *data, int datalen, RzBinArchOptions *opt)
Definition: bin_mach064.c:26
#define W(x, y, z)
#define Q(x)
#define WZ(x, y)
static RzList * strings(RzBinFile *bf)
Definition: bin_mach064.c:290
#define Z(x)
RZ_API RzLibStruct rizin_plugin
Definition: bin_mach064.c:324
static bool check_buffer(RzBuffer *b)
Definition: bin_mach064.c:12
#define B(x, y)
#define STATESIZE
RzBinPlugin rz_bin_plugin_mach064
Definition: bin_mach064.c:294
#define D(x)
static char * entitlements(RzBinFile *bf, bool json)
Definition: bin_mach0.c:27
RzList * entries(RzBinFile *bf)
Definition: bin_ne.c:98
RzBinInfo * info(RzBinFile *bf)
Definition: bin_ne.c:86
RzList * symbols(RzBinFile *bf)
Definition: bin_ne.c:102
RzList * imports(RzBinFile *bf)
Definition: bin_ne.c:106
RzList * sections(RzBinFile *bf)
Definition: bin_ne.c:110
RzList * relocs(RzBinFile *bf)
Definition: bin_ne.c:114
#define RZ_API
#define NULL
Definition: cris-opc.c:27
uint32_t ut32
voidpf void * buf
Definition: ioapi.h:138
RZ_API bool rz_xnu_kernelcache_buf_is_kernelcache(RzBuffer *b)
Definition: kernelcache.c:13
uint8_t ut8
Definition: lh5801.h:11
RzList *MACH0_() mach_fields(RzBinFile *bf)
Definition: mach0.c:3969
char *MACH0_() section_type_to_string(ut64 type)
Definition: mach0.c:2347
RzList *MACH0_() section_flag_to_rzlist(ut64 flag)
Definition: mach0.c:2378
void MACH0_() mach_headerfields(RzBinFile *bf)
Definition: mach0.c:3633
ut64 MACH0_() get_main(struct MACH0_(obj_t) *bin)
Definition: mach0.c:3582
#define MACH0_(name)
Definition: mach0_specs.h:20
RzBinSpecialSymbol
Definition: rz_bin.h:136
@ RZ_BIN_SPECIAL_SYMBOL_MAIN
Definition: rz_bin.h:139
RZ_API st64 rz_buf_read_at(RZ_NONNULL RzBuffer *b, ut64 addr, RZ_NONNULL RZ_OUT ut8 *buf, ut64 len)
Read len bytes of the buffer at the specified address.
Definition: buf.c:1136
RZ_API RZ_OWN RzBuffer * rz_buf_new_with_bytes(RZ_NULLABLE RZ_BORROW const ut8 *bytes, ut64 len)
Creates a new buffer with a bytes array.
Definition: buf.c:465
RZ_API ut64 rz_buf_size(RZ_NONNULL RzBuffer *b)
Return the size of the buffer.
Definition: buf.c:1225
@ RZ_LIB_TYPE_BIN
Definition: rz_lib.h:75
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_VERSION
Definition: rz_version.h:8
#define b(i)
Definition: sha256.c:42
Definition: malloc.c:26
Definition: inftree9.h:24
ut64 vaddr
Definition: rz_bin.h:186
ut64 paddr
Definition: rz_bin.h:187
XX curplugin == o->plugin.
Definition: rz_bin.h:298
RzBinObject * o
Definition: rz_bin.h:305
void * bin_obj
Definition: rz_bin.h:293
char * name
Definition: rz_bin.h:509
char * version
Definition: rz_bin.h:512
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static int addr
Definition: z80asm.c:58