Rizin
unix-like reverse engineering framework and cli tools
bin_xtr_sep64.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-License-Identifier: LGPL-3.0-only
4 
5 #include <rz_types.h>
6 #include <rz_util.h>
7 #include <rz_lib.h>
8 #include <rz_bin.h>
9 
10 #define RZ_BIN_MACH064 1
11 #include "../format/mach0/mach0.h"
12 #include "../format/mach0/mach0_defines.h"
13 
14 /* at offset 0x10f8 (pointer to it stored right after "legion2") */
15 typedef struct _RSepHdr64 {
22  ut64 paddr_max; /* size of SEP firmware image */
33  char init_name[16];
39 
40 /* right after the above, from offset 0x11c0 */
41 typedef struct _RSepApp64 {
53  char app_name[16];
57 
58 typedef struct _RSepMachoInfo {
59  struct MACH0_(mach_header) * hdr;
60  ut64 total_size;
61  ut64 text_size;
62  ut64 data_offset;
63  ut64 data_size;
64  ut64 text_offset_in_whole;
65  ut64 data_offset_in_whole;
67 
68 typedef struct _RSepSlice64 {
74 
75 typedef struct _RSepXtr64Ctx {
79 
81 static void sep64_xtr_ctx_free(void *p);
83 
84 static RSepMachoInfo *mach0_info_new(RzBuffer *buf, ut64 at, ut64 max_size);
85 static void mach0_info_free(RSepMachoInfo *info);
86 
87 static bool read_arm64_ins(RzBuffer *b, int idx, ut64 *result);
88 static char *get_proper_name(const char *app_name);
90 static inline void fill_metadata_info_from_hdr(RzBinXtrMetadata *meta, struct MACH0_(mach_header) * hdr);
91 
92 #define BTW(val, min, max) ((val) > min && (val) < max)
93 
94 static bool check_buffer(RzBuffer *b) {
95  rz_return_val_if_fail(b, false);
96 
97  const ut64 sz = rz_buf_size(b);
98  if (sz < 0x11c0) {
99  return false;
100  }
101 
102  ut64 msr_vbar_el1;
103  if (!read_arm64_ins(b, 2, &msr_vbar_el1)) {
104  return false;
105  }
106 
107  if (msr_vbar_el1 != 0xd518c002) {
108  return false;
109  }
110 
111  ut64 adr;
112  if (!read_arm64_ins(b, 1, &adr)) {
113  return false;
114  }
115 
116  if (adr != 0x10003fe2) {
117  return false;
118  }
119 
120  ut64 tmp;
121  if (!read_arm64_ins(b, 512, &tmp)) {
122  return false;
123  }
124 
125  /* check exception vector */
126  if (tmp != 0x14000000) {
127  return false;
128  }
129 
130  if (!read_arm64_ins(b, 1023, &tmp)) {
131  return false;
132  }
133 
134  if (tmp != 0x14000000) {
135  return false;
136  }
137 
138  if (!read_arm64_ins(b, 1028, &tmp)) {
139  return false;
140  }
141 
142  /* legion2 */
143  if (tmp != 0x326e6f69) {
144  return false;
145  }
146 
147  /* data header start */
148  ut64 hdr_offset;
149  if (!read_arm64_ins(b, 1029, &hdr_offset)) {
150  return false;
151  };
152 
153  if (hdr_offset >= sz) {
154  return false;
155  }
156 
157  ut64 size;
158  if (!rz_buf_read_le64_at(b, hdr_offset + 56, &size)) {
159  return false;
160  }
161 
162  /* check size */
163  if (size != sz) {
164  return false;
165  }
166 
167  return true;
168 }
169 
170 static bool load(RzBin *bin) {
171  return ((bin->cur->xtr_obj = sep64_xtr_ctx_new(bin->cur->buf)) != NULL);
172 }
173 
174 static void destroy(RzBin *bin) {
175  sep64_xtr_ctx_free(bin->cur->xtr_obj);
176 }
177 
178 static int size(RzBin *bin) {
179  // TODO
180  return 0;
181 }
182 
184  rz_return_val_if_fail(bin && bin->cur, NULL);
185 
186  if (!bin->cur->xtr_obj) {
187  bin->cur->xtr_obj = sep64_xtr_ctx_new(b);
188  }
189  RSepXtr64Ctx *ctx = bin->cur->xtr_obj;
190 
192  RzBinXtrData *res = rz_bin_xtrdata_new(slice->buf, slice->nominal_offset, slice->total_size, 3 + ctx->hdr->n_apps, slice->meta);
193 
194  rz_buf_free(slice->buf);
195  free(slice);
196  return res;
197 }
198 
200  RzBinXtrData *data = oneshot_buffer(bin, b, 0);
201  if (data) {
202  int narch = data->file_count;
204  if (!res) {
205  rz_bin_xtrdata_free(data);
206  return NULL;
207  }
208  rz_list_append(res, data);
209  int i;
210  for (i = 1; data && i < narch; i++) {
211  data = oneshot_buffer(bin, b, i);
212  rz_list_append(res, data);
213  }
214  return res;
215  }
216  return NULL;
217 }
218 
220  RSepHdr64 *hdr = NULL;
221  RSepApp64 *apps = NULL;
222  RSepXtr64Ctx *ctx = NULL;
223 
224  ut64 hdr_offset;
225  if (!rz_buf_read_le64_at(buf, 0x1014, &hdr_offset)) {
226  goto beach;
227  }
228 
229  if (hdr_offset == UT64_MAX) {
230  goto beach;
231  }
232 
233  hdr = RZ_NEW0(RSepHdr64);
234  if (!hdr) {
235  goto beach;
236  }
237  if (rz_buf_fread_at(buf, hdr_offset, (ut8 *)hdr, "16c16l16c16c3l", 1) != sizeof(RSepHdr64)) {
238  goto beach;
239  }
240 
241  if (!hdr->n_apps) {
242  goto beach;
243  }
244 
245  ut64 apps_at = hdr_offset + sizeof(RSepHdr64);
246  apps = RZ_NEWS0(RSepApp64, hdr->n_apps);
247  if (!apps) {
248  goto beach;
249  }
250  if (rz_buf_fread_at(buf, apps_at, (ut8 *)apps, "9l2i16c16cl", hdr->n_apps) != (sizeof(RSepApp64) * hdr->n_apps)) {
251  goto beach;
252  }
253 
255  if (!ctx) {
256  goto beach;
257  }
258 
259  ctx->hdr = hdr;
260  ctx->apps = apps;
261 
262  return ctx;
263 beach:
264  free(hdr);
265  free(apps);
266  free(ctx);
267 
268  return NULL;
269 }
270 
271 static void sep64_xtr_ctx_free(void *p) {
272  if (!p) {
273  return;
274  }
275 
276  RSepXtr64Ctx *ctx = p;
277 
278  RZ_FREE(ctx->hdr);
279  RZ_FREE(ctx->apps);
280 
281  free(ctx);
282 }
283 
285  if (idx >= ctx->hdr->n_apps + 3) {
286  return NULL;
287  }
288 
289  ut64 whole_size = rz_buf_size(whole);
290  RzBuffer *slice_buf = NULL;
291  char *name = NULL;
292  RSepSlice64 *slice = NULL;
294  RzBinXtrMetadata *meta = NULL;
295  ut64 nominal_offset = 0;
296  ut64 total_size = 0;
297 
298  if (idx == 0) {
299  name = strdup("boot");
300  slice_buf = rz_buf_new_slice(whole, 0, ctx->hdr->kernel_base_paddr);
301  total_size = ctx->hdr->kernel_base_paddr;
302  } else if (idx == 1) {
303  name = strdup("kernel");
304  info = mach0_info_new(whole, ctx->hdr->kernel_base_paddr, whole_size - ctx->hdr->kernel_base_paddr);
305  if (!info) {
306  goto beach;
307  }
308  slice_buf = rz_buf_new_slice(whole, ctx->hdr->kernel_base_paddr, info->total_size);
309  nominal_offset = ctx->hdr->kernel_base_paddr;
310  total_size = info->total_size;
311  } else if (idx == 2) {
312  name = get_proper_name(ctx->hdr->init_name);
313  info = mach0_info_new(whole, ctx->hdr->init_base_paddr, whole_size - ctx->hdr->init_base_paddr);
314  if (!info) {
315  goto beach;
316  }
317  slice_buf = extract_slice(whole, info);
318  nominal_offset = ctx->hdr->init_base_paddr;
319  total_size = info->total_size;
320  } else {
321  int app_idx = idx - 3;
322  name = get_proper_name(ctx->apps[app_idx].app_name);
323  info = mach0_info_new(whole, ctx->apps[app_idx].phys_text, whole_size - ctx->apps[app_idx].phys_text);
324  if (!info) {
325  goto beach;
326  }
327  info->data_offset_in_whole = ctx->apps[app_idx].phys_data;
328  slice_buf = extract_slice(whole, info);
329  nominal_offset = ctx->apps[app_idx].phys_text;
330  total_size = info->total_size;
331  }
332 
333  if (!name || !slice_buf) {
334  goto beach;
335  }
336 
337  meta = RZ_NEW0(RzBinXtrMetadata);
338  if (!meta) {
339  goto beach;
340  }
341 
342  if (info) {
343  fill_metadata_info_from_hdr(meta, info->hdr);
344  } else {
345  meta->arch = strdup("arm");
346  meta->bits = 64;
347  meta->machine = strdup("arm64e");
348  meta->type = strdup("Executable file");
349  }
350 
351  meta->xtr_type = "SEP";
352  meta->libname = name;
353 
354  slice = RZ_NEW0(RSepSlice64);
355  if (!slice) {
356  goto beach;
357  }
358 
359  slice->buf = slice_buf;
360  slice->nominal_offset = nominal_offset;
361  slice->total_size = total_size;
362  slice->meta = meta;
363 
365 
366  return slice;
367 beach:
368  rz_buf_free(slice_buf);
369  free(name);
370  free(slice);
371  free(meta);
373  return NULL;
374 }
375 
377  rz_return_val_if_fail(max_size >= 1024, NULL);
378 
379  RSepMachoInfo *result = NULL;
380  struct MACH0_(mach_header) *hdr = NULL;
381  ut8 *commands = NULL;
382  ut64 total_size = 0, text_size = 0, data_offset = 0, data_size = 0;
383 
384  ut32 hdr_size = sizeof(struct MACH0_(mach_header));
385  hdr = malloc(hdr_size);
386  if (!hdr) {
387  goto beach;
388  }
389  if (rz_buf_read_at(buf, at, (ut8 *)hdr, hdr_size) != hdr_size) {
390  goto beach;
391  }
392  if (hdr->magic != MH_MAGIC_64 || !BTW(hdr->sizeofcmds, 0, max_size)) {
393  goto beach;
394  }
395 
396  commands = malloc(hdr->sizeofcmds);
397  if (!commands) {
398  goto beach;
399  }
400  if (rz_buf_read_at(buf, at + hdr_size, commands, hdr->sizeofcmds) != hdr->sizeofcmds) {
401  goto beach;
402  }
403 
404  ut32 i;
405  ut8 *cursor = commands;
406  for (i = 0; i < hdr->ncmds; i++) {
407  const struct load_command *cmd = (struct load_command *)cursor;
408  if (cmd->cmd == LC_SEGMENT_64) {
409  const struct MACH0_(segment_command) *seg = (struct MACH0_(segment_command) *)cursor;
410  ut64 end = seg->fileoff + seg->filesize;
411  if (total_size < end) {
412  total_size = end;
413  }
414  if (!strcmp(seg->segname, "__TEXT")) {
415  text_size = seg->filesize;
416  } else if (!strcmp(seg->segname, "__DATA")) {
417  data_offset = seg->fileoff;
418  data_size = seg->filesize;
419  }
420  }
421  cursor = cursor + cmd->cmdsize;
422  }
423 
424  if (total_size == 0 || text_size == 0 || data_offset == 0 || data_size == 0) {
425  goto beach;
426  }
427 
428  result = RZ_NEW0(RSepMachoInfo);
429  if (!result) {
430  goto beach;
431  }
432 
433  result->hdr = hdr;
434  result->total_size = total_size;
435  result->text_size = text_size;
436  result->data_offset = data_offset;
437  result->data_size = data_size;
438  result->text_offset_in_whole = at;
439 
440  free(commands);
441 
442  return result;
443 beach:
444 
445  free(result);
446  free(hdr);
447  free(commands);
448 
449  return NULL;
450 }
451 
453  if (!info) {
454  return;
455  }
456 
457  free(info->hdr);
458  free(info);
459 }
460 
462  ut8 *content = NULL;
463 
464  content = (ut8 *)malloc(info->total_size);
465  if (!content) {
466  goto beach;
467  }
468  if (rz_buf_read_at(whole, info->text_offset_in_whole, content, info->text_size) != info->text_size) {
469  goto beach;
470  }
471  ut64 data_offset = info->data_offset_in_whole ? info->data_offset_in_whole : info->text_offset_in_whole + info->data_offset;
472  if (rz_buf_read_at(whole, data_offset, content + info->data_offset, info->data_size) != info->data_size) {
473  goto beach;
474  }
475 
476  return rz_buf_new_with_pointers(content, info->total_size, true);
477 beach:
478  free(content);
479 
480  return NULL;
481 }
482 
483 static inline void fill_metadata_info_from_hdr(RzBinXtrMetadata *meta, struct MACH0_(mach_header) * hdr) {
484  meta->arch = strdup(MACH0_(get_cputype_from_hdr)(hdr));
485  meta->bits = MACH0_(get_bits_from_hdr)(hdr);
486  meta->machine = MACH0_(get_cpusubtype_from_hdr)(hdr);
487  meta->type = MACH0_(get_filetype_from_hdr)(hdr);
488 }
489 
490 static char *get_proper_name(const char *app_name) {
491  char *proper_name = calloc(13, 1);
492  if (!proper_name) {
493  return NULL;
494  }
495  int i;
496 
497  for (i = 12; i != -1; i--) {
498  if (app_name[i] == ' ') {
499  proper_name[i] = 0;
500  } else {
501  proper_name[i] = app_name[i];
502  }
503  }
504 
505  return proper_name;
506 }
507 
508 static bool read_arm64_ins(RzBuffer *b, int idx, ut64 *result) {
509  ut32 tmp;
510 
511  bool res = rz_buf_read_le32_at(b, idx * 4, &tmp);
512  if (!res) {
513  return false;
514  }
515 
516  *result = tmp;
517  return res;
518 }
519 
521  .name = "xtr.sep64",
522  .desc = "64-bit SEP bin extractor plugin",
523  .license = "LGPL3",
524  .check_buffer = check_buffer,
525  .load = &load,
526  .destroy = &destroy,
527  .size = &size,
528  .extract_from_buffer = &oneshot_buffer,
529  .extractall_from_buffer = &oneshotall_buffer,
530  .free_xtr = &sep64_xtr_ctx_free,
531 };
532 
533 #ifndef RZ_PLUGIN_INCORE
537  .version = RZ_VERSION
538 };
539 #endif
lzma_index ** i
Definition: index.h:629
static RzILOpEffect * adr(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:449
RZ_API void rz_bin_xtrdata_free(void *data_)
Definition: bin.c:61
RZ_API RzBinXtrData * rz_bin_xtrdata_new(RzBuffer *buf, ut64 offset, ut64 size, ut32 file_count, RzBinXtrMetadata *metadata)
Definition: bin.c:47
RzBinInfo * info(RzBinFile *bf)
Definition: bin_ne.c:86
static RSepMachoInfo * mach0_info_new(RzBuffer *buf, ut64 at, ut64 max_size)
struct _RSepMachoInfo RSepMachoInfo
struct _RSepApp64 RSepApp64
static RzList * oneshotall_buffer(RzBin *bin, RzBuffer *b)
static void destroy(RzBin *bin)
static int size(RzBin *bin)
RZ_API RzLibStruct rizin_plugin
struct _RSepSlice64 RSepSlice64
static bool check_buffer(RzBuffer *b)
Definition: bin_xtr_sep64.c:94
static bool load(RzBin *bin)
struct _RSepHdr64 RSepHdr64
static void fill_metadata_info_from_hdr(RzBinXtrMetadata *meta, struct MACH0_(mach_header) *hdr)
static RSepSlice64 * sep64_xtr_ctx_get_slice(RSepXtr64Ctx *ctx, RzBuffer *whole, int idx)
static char * get_proper_name(const char *app_name)
static bool read_arm64_ins(RzBuffer *b, int idx, ut64 *result)
struct _RSepXtr64Ctx RSepXtr64Ctx
static RzBuffer * extract_slice(RzBuffer *whole, RSepMachoInfo *info)
RzBinXtrPlugin rz_bin_xtr_plugin_xtr_sep64
static RSepXtr64Ctx * sep64_xtr_ctx_new(RzBuffer *buf)
#define BTW(val, min, max)
Definition: bin_xtr_sep64.c:92
static void mach0_info_free(RSepMachoInfo *info)
static void sep64_xtr_ctx_free(void *p)
static RzBinXtrData * oneshot_buffer(RzBin *bin, RzBuffer *b, int idx)
#define RZ_API
#define NULL
Definition: cris-opc.c:27
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags cmd
Definition: sflib.h:79
uint32_t ut32
static const char * commands[]
Definition: h8300_disas.c:21
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void uLong size
Definition: ioapi.h:138
voidpf void * buf
Definition: ioapi.h:138
uint8_t ut8
Definition: lh5801.h:11
void * p
Definition: libc.cpp:67
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
Definition: list.c:248
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
void * malloc(size_t size)
Definition: malloc.c:123
void * calloc(size_t number, size_t size)
Definition: malloc.c:102
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
char *MACH0_() get_filetype_from_hdr(struct MACH0_(mach_header) *hdr)
Definition: mach0.c:3559
int MACH0_() get_bits_from_hdr(struct MACH0_(mach_header) *hdr)
Definition: mach0.c:3299
const char *MACH0_() get_cputype_from_hdr(struct MACH0_(mach_header) *hdr)
Definition: mach0.c:3336
char *MACH0_() get_cpusubtype_from_hdr(struct MACH0_(mach_header) *hdr)
Definition: mach0.c:3541
@ LC_SEGMENT_64
@ MH_MAGIC_64
Definition: mach0_defines.h:63
#define MACH0_(name)
Definition: mach0_specs.h:20
int idx
Definition: setup.py:197
const char * name
Definition: op.c:541
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
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_pointers(const ut8 *bytes, ut64 len, bool steal)
Creates a new buffer with a bytes array.
Definition: buf.c:552
RZ_API st64 rz_buf_fread_at(RZ_NONNULL RzBuffer *b, ut64 addr, RZ_NONNULL ut8 *buf, RZ_NONNULL const char *fmt, int n)
...
Definition: buf.c:1001
#define rz_buf_read_le32_at(b, addr, result)
Definition: rz_buf.h:271
RZ_API void rz_buf_free(RzBuffer *b)
Free all internal data hold by the buffer and the buffer.
Definition: buf.c:1253
RZ_API RZ_OWN RzBuffer * rz_buf_new_slice(RzBuffer *b, ut64 offset, ut64 size)
Creates a new buffer from a slice of another buffer.
Definition: buf.c:364
RZ_API ut64 rz_buf_size(RZ_NONNULL RzBuffer *b)
Return the size of the buffer.
Definition: buf.c:1225
#define rz_buf_read_le64_at(b, addr, result)
Definition: rz_buf.h:272
@ RZ_LIB_TYPE_BIN_XTR
Definition: rz_lib.h:76
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_NEWS0(x, y)
Definition: rz_types.h:282
#define RZ_FREE(x)
Definition: rz_types.h:369
#define UT64_MAX
Definition: rz_types_base.h:86
#define RZ_VERSION
Definition: rz_version.h:8
#define b(i)
Definition: sha256.c:42
ut64 size_data
Definition: bin_xtr_sep64.c:45
ut64 phys_text
Definition: bin_xtr_sep64.c:42
char app_name[16]
Definition: bin_xtr_sep64.c:53
ut8 app_uuid[16]
Definition: bin_xtr_sep64.c:54
ut32 minus_one
Definition: bin_xtr_sep64.c:51
ut64 size_text
Definition: bin_xtr_sep64.c:43
ut64 phys_data
Definition: bin_xtr_sep64.c:44
ut64 init_base_paddr
Definition: bin_xtr_sep64.c:26
ut64 unknown11
Definition: bin_xtr_sep64.c:36
ut64 unknown10
Definition: bin_xtr_sep64.c:35
ut64 kernel_base_paddr
Definition: bin_xtr_sep64.c:18
ut64 app_images_max_paddr
Definition: bin_xtr_sep64.c:21
ut64 paddr_max
Definition: bin_xtr_sep64.c:22
ut8 kernel_uuid[16]
Definition: bin_xtr_sep64.c:16
ut64 app_images_base_paddr
Definition: bin_xtr_sep64.c:20
char init_name[16]
Definition: bin_xtr_sep64.c:33
ut8 init_uuid[16]
Definition: bin_xtr_sep64.c:34
ut64 kernel_max_paddr
Definition: bin_xtr_sep64.c:19
ut64 nominal_offset
Definition: bin_xtr_sep64.c:71
RzBuffer * buf
Definition: bin_xtr_sep64.c:69
RzBinXtrMetadata * meta
Definition: bin_xtr_sep64.c:70
RSepApp64 * apps
Definition: bin_xtr_sep64.c:77
RSepHdr64 * hdr
Definition: bin_xtr_sep64.c:76
Definition: malloc.c:26
unsigned char * buf
Definition: gzjoin.c:83
Definition: z80asm.h:102
const char * xtr_type
Definition: rz_bin.h:374
ut64(WINAPI *w32_GetEnabledXStateFeatures)()