1 /* radare - LGPL - Copyright 2009-2019 nibble, pancake */
2
3 #include <r_types.h>
4 #include <r_util.h>
5 #include <r_lib.h>
6 #include <r_bin.h>
7 #include "mach0/dyldcache.h"
8 #include "mach0/mach0.h"
9
10 static RBinXtrData * extract(RBin *bin, int idx);
11 static RList * extractall(RBin *bin);
12 static RBinXtrData * oneshot(RBin *bin, const ut8 *buf, ut64 size, int idx);
13 static RList * oneshotall(RBin *bin, const ut8 *buf, ut64 size);
14
check_buffer(RBuffer * buf)15 static bool check_buffer(RBuffer *buf) {
16 ut8 b[4] = {0};
17 r_buf_read_at (buf, 0, b, sizeof (b));
18 return !memcmp (buf, "dyld", 4);
19 }
20
free_xtr(void * xtr_obj)21 static void free_xtr(void *xtr_obj) {
22 r_bin_dyldcache_free ((struct r_bin_dyldcache_obj_t*)xtr_obj);
23 }
24
destroy(RBin * bin)25 static void destroy(RBin *bin) {
26 free_xtr (bin->cur->xtr_obj);
27 }
28
load(RBin * bin)29 static bool load(RBin *bin) {
30 if (!bin || !bin->cur) {
31 return false;
32 }
33 if (!bin->cur->xtr_obj) {
34 bin->cur->xtr_obj = r_bin_dyldcache_new (bin->cur->file);
35 }
36 if (!bin->file) {
37 bin->file = bin->cur->file;
38 }
39 return bin->cur->xtr_obj? true : false;
40 }
41
extractall(RBin * bin)42 static RList * extractall(RBin *bin) {
43 RList *result = NULL;
44 int nlib, i = 0;
45 RBinXtrData *data = extract (bin, i);
46 if (!data) {
47 return result;
48 }
49 // XXX - how do we validate a valid nlib?
50 nlib = data->file_count;
51 result = r_list_newf (r_bin_xtrdata_free);
52 if (!result) {
53 r_bin_xtrdata_free (data);
54 return NULL;
55 }
56 r_list_append (result, data);
57 for (i = 1; data && i < nlib; i++) {
58 data = extract (bin, i);
59 r_list_append (result, data);
60 }
61 return result;
62 }
63
fill_metadata_info_from_hdr(RBinXtrMetadata * meta,struct MACH0_ (mach_header)* hdr)64 static inline void fill_metadata_info_from_hdr(RBinXtrMetadata *meta, struct MACH0_ (mach_header) *hdr) {
65 meta->arch = strdup (MACH0_(get_cputype_from_hdr) (hdr));
66 meta->bits = MACH0_(get_bits_from_hdr) (hdr);
67 meta->machine = MACH0_(get_cpusubtype_from_hdr) (hdr);
68 meta->type = MACH0_(get_filetype_from_hdr) (hdr);
69 }
70
extract(RBin * bin,int idx)71 static RBinXtrData *extract(RBin *bin, int idx) {
72 int nlib = 0;
73 RBinXtrData *res = NULL;
74 char *libname;
75 struct MACH0_(mach_header) *hdr;
76 struct r_bin_dyldcache_lib_t *lib = r_bin_dyldcache_extract (
77 (struct r_bin_dyldcache_obj_t*)bin->cur->xtr_obj, idx, &nlib);
78
79 if (lib) {
80 RBinXtrMetadata *metadata = R_NEW0(RBinXtrMetadata);
81 if (!metadata) {
82 free (lib);
83 return NULL;
84 }
85 hdr = MACH0_(get_hdr) (lib->b);
86 if (!hdr) {
87 free (lib);
88 R_FREE (metadata);
89 free (hdr);
90 return NULL;
91 }
92 fill_metadata_info_from_hdr (metadata, hdr);
93 r_bin_dydlcache_get_libname (lib, &libname);
94 metadata->libname = strdup (libname);
95
96 res = r_bin_xtrdata_new (lib->b, lib->offset, lib->size, nlib, metadata);
97 r_buf_free (lib->b);
98 free (lib);
99 free (hdr);
100 }
101 return res;
102 }
103
oneshot(RBin * bin,const ut8 * buf,ut64 size,int idx)104 static RBinXtrData *oneshot(RBin *bin, const ut8* buf, ut64 size, int idx) {
105 RBinXtrData *res = NULL;
106 struct r_bin_dyldcache_obj_t *xtr_obj;
107 struct r_bin_dyldcache_lib_t *lib;
108 int nlib = 0;
109 char *libname;
110 struct MACH0_(mach_header) *hdr;
111
112 if (!load (bin)) {
113 return NULL;
114 }
115
116 xtr_obj = bin->cur->xtr_obj;
117 lib = r_bin_dyldcache_extract (xtr_obj, idx, &nlib);
118 if (!lib) {
119 free_xtr (xtr_obj);
120 bin->cur->xtr_obj = NULL;
121 return NULL;
122 }
123 RBinXtrMetadata *metadata = R_NEW0 (RBinXtrMetadata);
124 if (!metadata) {
125 free (lib);
126 return NULL;
127 }
128 hdr = MACH0_(get_hdr) (lib->b);
129 if (!hdr) {
130 free (lib);
131 free (metadata);
132 return NULL;
133 }
134 fill_metadata_info_from_hdr (metadata, hdr);
135 r_bin_dydlcache_get_libname (lib, &libname);
136 metadata->libname = strdup (libname);
137
138 res = r_bin_xtrdata_new (lib->b, lib->offset, r_buf_size (lib->b), nlib, metadata);
139 r_buf_free (lib->b);
140 free (hdr);
141 free (lib);
142 return res;
143 }
144
oneshotall(RBin * bin,const ut8 * buf,ut64 size)145 static RList * oneshotall(RBin *bin, const ut8* buf, ut64 size) {
146 RBinXtrData *data = NULL;
147 RList *res = NULL;
148 int nlib, i = 0;
149 if (!bin->file) {
150 if (!load (bin)) {
151 return NULL;
152 }
153 }
154 data = oneshot (bin, buf, size, i);
155 if (!data) {
156 return res;
157 }
158 // XXX - how do we validate a valid nlib?
159 nlib = data->file_count;
160 res = r_list_newf (r_bin_xtrdata_free);
161 if (!res) {
162 r_bin_xtrdata_free (data);
163 return NULL;
164 }
165 r_list_append (res, data);
166 for (i = 1; data && i < nlib; i++) {
167 data = oneshot (bin, buf, size, i);
168 r_list_append (res, data);
169 }
170 return res;
171 }
172
173 RBinXtrPlugin r_bin_xtr_plugin_xtr_dyldcache = {
174 .name = "xtr.dyldcache",
175 .desc = "dyld cache bin extractor plugin",
176 .license = "LGPL3",
177 .load = &load,
178 .extract = &extract,
179 .extractall = &extractall,
180 .destroy = &destroy,
181 .extract_from_bytes = &oneshot,
182 .extractall_from_bytes = &oneshotall,
183 .free_xtr = &free_xtr,
184 .check_buffer = &check_buffer,
185 };
186
187 #ifndef R2_PLUGIN_INCORE
188 R_API RLibStruct radare_plugin = {
189 .type = R_LIB_TYPE_BIN_XTR,
190 .data = &r_bin_xtr_plugin_dyldcache,
191 .version = R2_VERSION
192 };
193 #endif
194