Blob


1 /*-
2 * Copyright (c) 2006 Matthias Schmidt <xhr @ giessen.ccc.de>
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS'
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
18 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24 * THE POSSIBILITY OF SUCH DAMAGE.
25 */
27 /* $Id: dermob.c,v 1.28 2006/08/15 12:29:02 matthias Exp $ */
29 #include "dermob.h"
30 #include "mach.h"
31 #include "defs.h"
32 #include "list.h"
34 /*
35 * Analyse a possible fat header or return silently
36 */
37 int
38 analyse_fat_header(char *buffer, int *offset, struct fat_header *rfh)
39 {
40 struct fat_header *fh;
41 char *ptr;
43 fh = malloc(sizeof(*fh));
44 ptr = buffer;
46 memcpy(fh, ptr, sizeof(*fh));
48 /* No universal binary */
49 if (fh->magic != FAT_CIGAM && fh->magic != FAT_MAGIC) {
50 free(fh);
51 rfh = NULL;
52 return(-1);
53 }
55 if (fh->magic == FAT_MAGIC)
56 bo_b = LE;
57 else if (fh->magic == FAT_CIGAM)
58 bo_b = BE;
60 *offset += sizeof(*fh);
61 memcpy(rfh, fh, sizeof(*fh));
63 free(fh);
64 return(1);
65 }
67 int
68 analyse_fat_arch(char *buffer, int *offset, struct fat_arch *rfa)
69 {
70 char *ptr;
71 ptr = buffer;
72 ptr += *offset;
74 memcpy(rfa, ptr, sizeof(*rfa));
75 *offset += sizeof(*rfa);
77 return(0);
78 }
80 int
81 determine_mo_arch(char *buffer)
82 {
83 struct mach_header_magic mhh;
84 char *ptr = buffer;
85 int ret = -1;
87 memcpy(&mhh, ptr, sizeof(mhh));
89 if (mhh.magic == MH_MAGIC_64)
90 ret = 0;
91 else if (mhh.magic == MH_CIGAM_64)
92 ret = 1;
93 else if (mhh.magic == MH_MAGIC)
94 ret = 2;
95 else if (mhh.magic == MH_CIGAM)
96 ret = 3;
98 return ret;
99 }
101 /*
102 * Parse the mach-o header, set the correct byte order ot the binary and
103 * determine the number of load commands.
104 */
105 int
106 analyse_mo_header(char *buffer, int *offset, struct mach_header *rmh)
108 struct mach_header *mh;
109 char *ptr;
110 int moa;
112 ptr = buffer;
113 if (offset > 0)
114 ptr += *offset;
116 moa = determine_mo_arch(buffer);
117 if (moa != 0 && moa != 1 && moa != 2 && moa != 3) {
118 printf("Cannot determine mach-o architecture\n");
119 return(1);
122 /*
123 * There is no need to differentiate between 32 and 64bit here, as the
124 * headers are identical (I ignore the reserved field).
125 */
126 mh = malloc(sizeof(*mh));
127 if (mh == NULL) {
128 printf("Cannot allocate memory\n");
129 return(1);
131 memcpy(mh, ptr, sizeof(*mh));
133 /* Determine the correct byte order */
134 if ((mh->magic == MH_MAGIC && bo_a == LE) ||
135 (mh->magic == MH_MAGIC_64 && bo_a == LE))
136 bo_b = LE;
137 else if ((mh->magic == MH_CIGAM && bo_a == LE) ||
138 (mh->magic == MH_CIGAM_64 && bo_a == LE))
139 bo_b = BE;
140 else if ((mh->magic == MH_MAGIC && bo_a != LE) ||
141 (mh->magic == MH_MAGIC_64 && bo_a != LE))
142 bo_b = BE;
143 else if ((mh->magic == MH_CIGAM && bo_a != LE) ||
144 (mh->magic == MH_CIGAM_64 && bo_a != LE))
145 bo_b = LE;
147 offset_moh = *offset;
148 *offset += sizeof(*mh);
150 memcpy(rmh, mh, sizeof(*rmh));
151 free(mh);
153 return(0);
156 /*
157 * Analyse all load commands
158 */
159 void
160 analyse_load_command(char *buffer, int *offset, struct load_command *rld)
162 char *ptr;
164 ptr = buffer;
165 ptr += *offset;
167 memcpy(rld, ptr, sizeof(*rld));
170 /*
171 * Examine the different sections and display various information.
172 */
173 void
174 examine_section(char *buffer, int *offset, struct section *rsec)
176 char *ptr;
178 ptr = buffer;
179 ptr += *offset;
181 memcpy(rsec, ptr, sizeof(*rsec));
182 *offset += sizeof(*rsec);
185 /*
186 * Examine the different segments and display various information.
187 */
188 int
189 examine_segmet(char *buffer, int *offset, int cmd, int cmdsize, int *nofx)
191 struct segment_command *sc;
192 struct symtab_command *symc;
193 struct dylib_command *dly;
194 struct dylinker_command *dlnk;
195 struct dysymtab_command *dsym;
196 struct twolevel_hints_command *two;
197 int ret = 0;
198 char *ptr;
200 ptr = buffer;
201 ptr += *offset;
203 switch(cmd) {
204 case LC_SEGMENT:
205 sc = malloc(sizeof(*sc));
206 memcpy(sc, ptr, sizeof(*sc));
207 list_insert_node(lst, sc, 0x6);
208 *nofx = swapi(sc->nsects);
209 //*offset += sizeof(*sc);
210 ret = sizeof(*sc);
211 break;
212 case LC_SYMTAB:
213 symc = malloc(sizeof(*symc));
214 memcpy(symc, ptr, sizeof(*symc));
215 list_insert_node(lst, symc, 0x7);
216 //*offset += sizeof(*symc);
217 ret = sizeof(*symc);
218 break;
219 case LC_LOAD_DYLIB:
220 dynamic = 1;
221 dly = malloc(sizeof(*dly));
222 memcpy(dly, ptr, sizeof(*dly));
223 list_insert_node(lst, dly, 0x8);
224 //*offset += sizeof(*dly);
225 ret = sizeof(*dly);
226 break;
227 case LC_LOAD_DYLINKER:
228 dlnk = malloc(sizeof(*dlnk));
229 memcpy(dlnk, ptr, sizeof(*dlnk));
230 //mprintf(" Name: %s\n", ptr+swapi(dlnk->name.offset));
231 //*offset += sizeof(*dlnk);
232 ret = sizeof(*dlnk);
233 break;
234 case LC_DYSYMTAB:
235 dsym = malloc(sizeof(*dsym));
236 memcpy(dsym, ptr, sizeof(*dsym));
237 list_insert_node(lst, dsym, 0x9);
238 //*offset += sizeof(*dsym);
239 ret = sizeof(*dsym);
240 break;
241 case LC_TWOLEVEL_HINTS:
242 two = malloc(sizeof(*two));
243 memcpy(two, ptr, sizeof(*two));
244 list_insert_node(lst, two, 0xa);
245 //*offset += sizeof(*two);
246 ret = sizeof(*two);
247 break;
248 case LC_THREAD:
249 case LC_UNIXTHREAD:
250 break;
251 case LC_ROUTINES:
252 mprintf("routines\n");
253 break;
254 case LC_ID_DYLIB:
255 mprintf("id dylib\n");
256 break;
257 default:
258 break;
261 return (ret);
264 /*
265 * Display the __TEXT,__text section (the actual machine code) as hexadecimal
266 * values on screen.
267 */
268 void
269 display_buffer(char *buffer, int addr, int offset, int size)
271 char *ptr;
272 char line[17];
273 int i, j=0;
275 if (offset < 0)
276 return;
278 printf("Starting at address 0x%x offset %d size %d\n", addr, offset, size);
280 ptr = buffer;
281 ptr += offset;
282 // Skip the fat header, if necessarry
283 ptr += offset_moh;
284 offset += offset_moh;
286 memset(line, 0, sizeof(line));
288 for (i = 0; i < size; i++) {
289 if (j == 0)
290 printf("%.08x ", offset+i);
291 printf("%.02x ", (*ptr & 0xFF));
293 if (isprint(*ptr & 0xFF))
294 line[j] = (*ptr & 0xFF);
295 else
296 line[j] = '.';
297 j++;
298 if (j == 16) {
299 printf(" %s\n", line);
300 j = 0;
301 } else if (j == 8)
302 printf(" ");
303 ptr += 1;
305 printf("\n");