1 /* radare - LGPL - Copyright 2011-2018 - pancake */
2 
3 #include <r_egg.h>
4 #include <config.h>
5 
6 R_LIB_VERSION (r_egg);
7 
8 // TODO: must be plugins
9 extern REggEmit emit_x86;
10 extern REggEmit emit_x64;
11 extern REggEmit emit_arm;
12 extern REggEmit emit_trace;
13 
14 static REggPlugin *egg_static_plugins[] =
15 	{ R_EGG_STATIC_PLUGINS };
16 
17 struct egg_patch_t {
18 	RBuffer *b;
19 	int off;
20 };
21 
egg_patch_free(void * p)22 void egg_patch_free (void *p) {
23 	struct egg_patch_t *ep = (struct egg_patch_t *)p;
24 	r_buf_free (ep->b);
25 	free (ep);
26 }
27 
r_egg_new(void)28 R_API REgg *r_egg_new(void) {
29 	int i;
30 	REgg *egg = R_NEW0 (REgg);
31 	if (!egg) {
32 		return NULL;
33 	}
34 	egg->src = r_buf_new ();
35 	if (!egg->src) {
36 		goto beach;
37 	}
38 	egg->buf = r_buf_new ();
39 	if (!egg->buf) {
40 		goto beach;
41 	}
42 	egg->bin = r_buf_new ();
43 	if (!egg->bin) {
44 		goto beach;
45 	}
46 	egg->remit = &emit_x86;
47 	egg->syscall = r_syscall_new ();
48 	if (!egg->syscall) {
49 		goto beach;
50 	}
51 	egg->rasm = r_asm_new ();
52 	if (!egg->rasm) {
53 		goto beach;
54 	}
55 	egg->bits = 0;
56 	egg->endian = 0;
57 	egg->db = sdb_new (NULL, NULL, 0);
58 	if (!egg->db) {
59 		goto beach;
60 	}
61 	egg->patches = r_list_newf (egg_patch_free);
62 	if (!egg->patches) {
63 		goto beach;
64 	}
65 	egg->plugins = r_list_new ();
66 	for (i=0; egg_static_plugins[i]; i++) {
67 		r_egg_add (egg, egg_static_plugins[i]);
68 	}
69 	return egg;
70 
71 beach:
72 	r_egg_free (egg);
73 	return NULL;
74 }
75 
r_egg_add(REgg * a,REggPlugin * foo)76 R_API int r_egg_add(REgg *a, REggPlugin *foo) {
77 	RListIter *iter;
78 	RAsmPlugin *h;
79 	// TODO: cache foo->name length and use memcmp instead of strcmp
80 	if (!foo->name) {
81 		return false;
82 	}
83 	r_list_foreach (a->plugins, iter, h) {
84 		if (!strcmp (h->name, foo->name)) {
85 			return false;
86 		}
87 	}
88 	r_list_append (a->plugins, foo);
89 	return true;
90 }
91 
r_egg_to_string(REgg * egg)92 R_API char *r_egg_to_string(REgg *egg) {
93 	return r_buf_to_string (egg->buf);
94 }
95 
r_egg_free(REgg * egg)96 R_API void r_egg_free(REgg *egg) {
97 	if (egg) {
98 		r_buf_free (egg->src);
99 		r_buf_free (egg->buf);
100 		r_buf_free (egg->bin);
101 		r_list_free (egg->list);
102 		r_asm_free (egg->rasm);
103 		r_syscall_free (egg->syscall);
104 		sdb_free (egg->db);
105 		r_list_free (egg->plugins);
106 		r_list_free (egg->patches);
107 		r_egg_lang_free (egg);
108 		free (egg);
109 	}
110 }
111 
r_egg_reset(REgg * egg)112 R_API void r_egg_reset(REgg *egg) {
113 	r_egg_lang_include_init (egg);
114 	// TODO: use r_list_purge instead of free/new here
115 	r_buf_free (egg->src);
116 	r_buf_free (egg->buf);
117 	r_buf_free (egg->bin);
118 	egg->src = r_buf_new ();
119 	egg->buf = r_buf_new ();
120 	egg->bin = r_buf_new ();
121 	r_list_purge (egg->patches);
122 }
123 
r_egg_setup(REgg * egg,const char * arch,int bits,int endian,const char * os)124 R_API int r_egg_setup(REgg *egg, const char *arch, int bits, int endian, const char *os) {
125 	const char *asmcpu = NULL; // TODO
126 	egg->remit = NULL;
127 
128 	egg->os = os? r_str_hash (os): R_EGG_OS_DEFAULT;
129 	//eprintf ("%s -> %x (linux=%x) (darwin=%x)\n", os, egg->os, R_EGG_OS_LINUX, R_EGG_OS_DARWIN);
130 	// TODO: setup egg->arch for all archs
131 	if (!strcmp (arch, "x86")) {
132 		egg->arch = R_SYS_ARCH_X86;
133 		switch (bits) {
134 		case 32:
135 			r_syscall_setup (egg->syscall, arch, bits, asmcpu, os);
136 			egg->remit = &emit_x86;
137 			egg->bits = bits;
138 			break;
139 		case 64:
140 			r_syscall_setup (egg->syscall, arch, bits, asmcpu, os);
141 			egg->remit = &emit_x64;
142 			egg->bits = bits;
143 			break;
144 		}
145 	} else if (!strcmp (arch, "arm")) {
146 		egg->arch = R_SYS_ARCH_ARM;
147 		switch (bits) {
148 		case 16:
149 		case 32:
150 		case 64:
151 			r_syscall_setup (egg->syscall, arch, bits, asmcpu, os);
152 			egg->remit = &emit_arm;
153 			egg->bits = bits;
154 			egg->endian = endian;
155 			break;
156 		}
157 	} else if (!strcmp (arch, "trace")) {
158 		//r_syscall_setup (egg->syscall, arch, os, bits);
159 		egg->remit = &emit_trace;
160 		egg->bits = bits;
161 		egg->endian = endian;
162 	}
163 	return 0;
164 }
165 
r_egg_include(REgg * egg,const char * file,int format)166 R_API int r_egg_include(REgg *egg, const char *file, int format) {
167 	size_t sz;
168 	const ut8 *foo = (const ut8 *)r_file_slurp (file, &sz);
169 	if (!foo) {
170 		return 0;
171 	}
172 	// XXX: format breaks compiler layers
173 	switch (format) {
174 	case 'r': // raw
175 		r_egg_raw (egg, foo, (int)sz);
176 		break;
177 	case 'a': // assembly
178 		r_buf_append_bytes (egg->buf, foo, (ut64)sz);
179 		break;
180 	default:
181 		r_buf_append_bytes (egg->src, foo, (ut64)sz);
182 	}
183 	free ((void *)foo);
184 	return 1;
185 }
186 
r_egg_load(REgg * egg,const char * code,int format)187 R_API void r_egg_load(REgg *egg, const char *code, int format) {
188 	switch (format) {
189 	case 'a': // assembly
190 		r_buf_append_bytes (egg->buf, (const ut8 *)code, strlen (code));
191 		break;
192 	default:
193 		r_buf_append_bytes (egg->src, (const ut8 *)code, strlen (code));
194 		break;
195 	}
196 }
197 
r_egg_syscall(REgg * egg,const char * arg,...)198 R_API void r_egg_syscall(REgg *egg, const char *arg, ...) {
199 	RSyscallItem *item = r_syscall_get (egg->syscall,
200 		r_syscall_get_num (egg->syscall, arg), -1);
201 	if (!strcmp (arg, "close")) {
202 		//egg->remit->syscall_args ();
203 	}
204 	if (!item) {
205 		return;
206 	}
207 	egg->remit->syscall (egg, item->num);
208 }
209 
r_egg_alloc(REgg * egg,int n)210 R_API void r_egg_alloc(REgg *egg, int n) {
211 	// add esp, n
212 }
213 
r_egg_label(REgg * egg,const char * name)214 R_API void r_egg_label(REgg *egg, const char *name) {
215 	r_egg_printf (egg, "%s:\n", name);
216 }
217 
r_egg_math(REgg * egg)218 R_API void r_egg_math(REgg *egg) { //, char eq, const char *vs, char type, const char *sr
219 	// TODO
220 	//e->mathop (egg, op, type, eq, p);
221 }
222 
r_egg_raw(REgg * egg,const ut8 * b,int len)223 R_API int r_egg_raw(REgg *egg, const ut8 *b, int len) {
224 	int outlen = len * 2; // two hexadecimal digits per byte
225 	char *out = malloc (outlen + 1);
226 	if (!out) {
227 		return false;
228 	}
229 	(void)r_hex_bin2str (b, len, out);
230 	r_buf_append_bytes (egg->buf, (const ut8 *)".hex ", 5);
231 	r_buf_append_bytes (egg->buf, (const ut8 *)out, outlen);
232 	r_buf_append_bytes (egg->buf, (const ut8 *)"\n", 1);
233 	free (out);
234 	return true;
235 }
236 
r_egg_raw_prepend(REgg * egg,const ut8 * b,int len)237 static int r_egg_raw_prepend(REgg *egg, const ut8 *b, int len) {
238 	int outlen = len * 2; // two hexadecimal digits per byte
239 	char *out = malloc (outlen + 1);
240 	if (!out) {
241 		return false;
242 	}
243 	r_hex_bin2str (b, len, out);
244 	r_buf_prepend_bytes (egg->buf, (const ut8 *)"\n", 1);
245 	r_buf_prepend_bytes (egg->buf, (const ut8 *)out, outlen);
246 	r_buf_prepend_bytes (egg->buf, (const ut8 *)".hex ", 5);
247 	free (out);
248 	return true;
249 }
250 
r_egg_prepend_bytes(REgg * egg,const ut8 * b,int len)251 static int r_egg_prepend_bytes(REgg *egg, const ut8 *b, int len) {
252 	if (!r_egg_raw_prepend (egg, b, len)) {
253 		return false;
254 	}
255 	if (!r_buf_prepend_bytes (egg->bin, b, len)) {
256 		return false;
257 	}
258 	return true;
259 }
260 
r_egg_append_bytes(REgg * egg,const ut8 * b,int len)261 static int r_egg_append_bytes(REgg *egg, const ut8 *b, int len) {
262 	if (!r_egg_raw (egg, b, len)) {
263 		return false;
264 	}
265 
266 	if (!r_buf_append_bytes (egg->bin, b, len)) {
267 		return false;
268 	}
269 
270 	return true;
271 }
272 
273 // r_egg_block (egg, FRAME | IF | ELSE | ENDIF | FOR | WHILE, sz)
r_egg_if(REgg * egg,const char * reg,char cmp,int v)274 R_API void r_egg_if(REgg *egg, const char *reg, char cmp, int v) {
275 	//	egg->depth++;
276 }
277 
r_egg_printf(REgg * egg,const char * fmt,...)278 R_API void r_egg_printf(REgg *egg, const char *fmt, ...) {
279 	va_list ap;
280 	int len;
281 	char buf[1024];
282 	va_start (ap, fmt);
283 	len = vsnprintf (buf, sizeof (buf), fmt, ap);
284 	r_buf_append_bytes (egg->buf, (const ut8 *)buf, len);
285 	va_end (ap);
286 }
287 
r_egg_assemble_asm(REgg * egg,char ** asm_list)288 R_API bool r_egg_assemble_asm(REgg *egg, char **asm_list) {
289 	RAsmCode *asmcode = NULL;
290 	char *code = NULL;
291 	char *asm_name = NULL;
292 
293 	if (asm_list) {
294 		char **asm_;
295 
296 		for (asm_ = asm_list; *asm_; asm_ += 2) {
297 			if (!strcmp (egg->remit->arch, asm_[0])) {
298 				asm_name = asm_[1];
299 				break;
300 			}
301 		}
302 	}
303 	if (!asm_name) {
304 		if (egg->remit == &emit_x86 || egg->remit == &emit_x64) {
305 			asm_name = "x86.nz";
306 		} else if (egg->remit == &emit_arm) {
307 			asm_name = "arm";
308 		}
309 	}
310 	if (asm_name) {
311 		r_asm_use (egg->rasm, asm_name);
312 		r_asm_set_bits (egg->rasm, egg->bits);
313 		r_asm_set_big_endian (egg->rasm, egg->endian);
314 		r_asm_set_syntax (egg->rasm, R_ASM_SYNTAX_INTEL);
315 		code = r_buf_to_string (egg->buf);
316 		asmcode = r_asm_massemble (egg->rasm, code);
317 		if (asmcode) {
318 			if (asmcode->len > 0) {
319 				r_buf_append_bytes (egg->bin, asmcode->bytes, asmcode->len);
320 			}
321 			// LEAK r_asm_code_free (asmcode);
322 		} else {
323 			eprintf ("fail assembling\n");
324 		}
325 	}
326 	free (code);
327 	bool ret = (asmcode != NULL);
328 	r_asm_code_free (asmcode);
329 	return ret;
330 }
331 
r_egg_assemble(REgg * egg)332 R_API bool r_egg_assemble(REgg *egg) {
333 	return r_egg_assemble_asm (egg, NULL);
334 }
335 
r_egg_compile(REgg * egg)336 R_API int r_egg_compile(REgg *egg) {
337 	r_buf_seek (egg->src, 0, R_BUF_SET);
338 	char b;
339 	int r = r_buf_read (egg->src, (ut8 *)&b, sizeof (b));
340 	if (r != sizeof (b) || !egg->remit) {
341 		return true;
342 	}
343 	// only emit begin if code is found
344 	r_egg_lang_init (egg);
345 	for (; b; ) {
346 		r_egg_lang_parsechar (egg, b);
347 		if (egg->lang.elem_n >= sizeof (egg->lang.elem)) {
348 			eprintf ("ERROR: elem too large.\n");
349 			break;
350 		}
351 		int r = r_buf_read (egg->src, (ut8 *)&b, sizeof (b));
352 		if (r != sizeof (b)) {
353 			break;
354 		}
355 		// XXX: some parse fail errors are false positives :(
356 	}
357 	if (egg->context>0) {
358 		eprintf ("ERROR: expected '}' at the end of the file. %d left\n", egg->context);
359 		return false;
360 	}
361 	// TODO: handle errors here
362 	return true;
363 }
364 
r_egg_get_bin(REgg * egg)365 R_API RBuffer *r_egg_get_bin(REgg *egg) {
366 	// TODO increment reference
367 	return egg->bin;
368 }
369 
370 //R_API int r_egg_dump (REgg *egg, const char *file) { }
371 
r_egg_get_source(REgg * egg)372 R_API char *r_egg_get_source(REgg *egg) {
373 	return r_buf_to_string (egg->src);
374 }
375 
r_egg_get_assembly(REgg * egg)376 R_API char *r_egg_get_assembly(REgg *egg) {
377 	return r_buf_to_string (egg->buf);
378 }
379 
r_egg_append(REgg * egg,const char * src)380 R_API void r_egg_append(REgg *egg, const char *src) {
381 	r_buf_append_bytes (egg->src, (const ut8*)src, strlen (src));
382 }
383 
384 /* JIT : TODO: accept arguments here */
r_egg_run(REgg * egg)385 R_API int r_egg_run(REgg *egg) {
386 	ut64 tmpsz;
387 	const ut8 *tmp = r_buf_data (egg->bin, &tmpsz);
388 	bool res = r_sys_run (tmp, tmpsz);
389 	return res;
390 }
391 
r_egg_run_rop(REgg * egg)392 R_API int r_egg_run_rop(REgg *egg) {
393 	ut64 sz;
394 	const ut8 *tmp = r_buf_data (egg->bin, &sz);
395 	return r_sys_run_rop (tmp, sz);
396 }
397 
398 #define R_EGG_FILL_TYPE_TRAP
399 #define R_EGG_FILL_TYPE_NOP
400 #define R_EGG_FILL_TYPE_CHAR
401 #define R_EGG_FILL_TYPE_SEQ
402 #define R_EGG_FILL_TYPE_SEQ
403 
eon(char * n)404 static inline char *eon(char *n) {
405 	while (*n && (*n >= '0' && *n <= '9')) {
406 		n++;
407 	}
408 	return n;
409 }
410 
411 /* padding looks like:
412   ([snatSNAT][0-9]+)*
413 */
r_egg_padding(REgg * egg,const char * pad)414 R_API int r_egg_padding(REgg *egg, const char *pad) {
415 	int number;
416 	ut8 *buf, padding_byte;
417 	char *p, *o = strdup (pad);
418 
419 	for (p = o; *p;) { // parse pad string
420 		const char f = *p++;
421 		number = strtol (p, NULL, 10);
422 
423 		if (number < 1) {
424 			eprintf ("Invalid padding length at %d\n", number);
425 			free (o);
426 			return false;
427 		}
428 		p = eon(p);
429 
430 		switch (f) {
431 		case 's': case 'S': padding_byte = 0; break;
432 		case 'n': case 'N': padding_byte = 0x90; break;
433 		case 'a':
434 		case 'A': padding_byte = 'A'; break;
435 		case 't':
436 		case 'T': padding_byte = 0xcc; break;
437 		default:
438 			eprintf ("Invalid padding format (%c)\n", *p);
439 			eprintf ("Valid ones are:\n");
440 			eprintf ("	s S : NULL byte");
441 			eprintf ("	n N : nop");
442 			eprintf ("	a A : 0x41");
443 			eprintf ("	t T : trap (0xcc)");
444 			free (o);
445 			return false;
446 		}
447 
448 		buf = malloc (number);
449 		if (!buf) {
450 			free (o);
451 			return false;
452 		}
453 
454 		memset (buf, padding_byte, number);
455 		if (f >= 'a' && f <= 'z') {
456 			r_egg_prepend_bytes(egg, buf, number);
457 		} else {
458 			r_egg_append_bytes(egg, buf, number);
459 		}
460 		free (buf);
461 	}
462 	free (o);
463 	return true;
464 }
465 
r_egg_fill(REgg * egg,int pos,int type,int argc,int length)466 R_API void r_egg_fill(REgg *egg, int pos, int type, int argc, int length) {
467 	// TODO
468 }
469 
r_egg_option_set(REgg * egg,const char * key,const char * val)470 R_API void r_egg_option_set(REgg *egg, const char *key, const char *val) {
471 	sdb_set (egg->db, key, val, 0);
472 }
473 
r_egg_option_get(REgg * egg,const char * key)474 R_API char *r_egg_option_get(REgg *egg, const char *key) {
475 	return sdb_get (egg->db, key, NULL);
476 }
477 
r_egg_shellcode(REgg * egg,const char * name)478 R_API int r_egg_shellcode(REgg *egg, const char *name) {
479 	REggPlugin *p;
480 	RListIter *iter;
481 	RBuffer *b;
482 	r_list_foreach (egg->plugins, iter, p) {
483 		if (p->type == R_EGG_PLUGIN_SHELLCODE && !strcmp (name, p->name)) {
484 			b = p->build (egg);
485 			if (!b) {
486 				eprintf ("%s Shellcode has failed\n", p->name);
487 				return false;
488 			}
489 			ut64 tmpsz;
490 			const ut8 *tmp = r_buf_data (b, &tmpsz);
491 			r_egg_raw (egg, tmp, tmpsz);
492 			return true;
493 		}
494 	}
495 	return false;
496 }
497 
r_egg_encode(REgg * egg,const char * name)498 R_API int r_egg_encode(REgg *egg, const char *name) {
499 	REggPlugin *p;
500 	RListIter *iter;
501 	RBuffer *b;
502 	r_list_foreach (egg->plugins, iter, p) {
503 		if (p->type == R_EGG_PLUGIN_ENCODER && !strcmp (name, p->name)) {
504 			b = p->build (egg);
505 			if (!b) {
506 				return false;
507 			}
508 			r_buf_free (egg->bin);
509 			egg->bin = b;
510 			return true;
511 		}
512 	}
513 	return false;
514 }
515 
r_egg_patch(REgg * egg,int off,const ut8 * buf,int len)516 R_API int r_egg_patch(REgg *egg, int off, const ut8 *buf, int len) {
517 	struct egg_patch_t *ep = R_NEW (struct egg_patch_t);
518 	if (!ep) {
519 		return false;
520 	}
521 	ep->b = r_buf_new_with_bytes (buf, len);
522 	if (!ep->b) {
523 		egg_patch_free (ep);
524 		return false;
525 	}
526 	ep->off = off;
527 	r_list_append (egg->patches, ep);
528 	return true;
529 }
530 
r_egg_finalize(REgg * egg)531 R_API void r_egg_finalize(REgg *egg) {
532 	struct egg_patch_t *ep;
533 	RListIter *iter;
534 	if (!egg->bin) {
535 		r_buf_free (egg->bin);
536 		egg->bin = r_buf_new ();
537 	}
538 	r_list_foreach (egg->patches, iter, ep) {
539 		if (ep->off < 0) {
540 			ut64 sz;
541 			const ut8 *buf = r_buf_data (ep->b, &sz);
542 			r_egg_append_bytes (egg, buf, sz);
543 		} else if (ep->off < r_buf_size (egg->bin)) {
544 			ut64 sz;
545 			const ut8 *buf = r_buf_data (ep->b, &sz);
546 			int r = r_buf_write_at (egg->bin, ep->off, buf, sz);
547 			if (r < sz) {
548 				eprintf ("Error during patch\n");
549 				return;
550 			}
551 		} else {
552 			eprintf ("Cannot patch outside\n");
553 			return;
554 		}
555 	}
556 }
557 
r_egg_pattern(REgg * egg,int size)558 R_API void r_egg_pattern(REgg *egg, int size) {
559 	char *ret = r_debruijn_pattern ((int)size, 0, NULL);
560 	if (ret) {
561 		r_egg_prepend_bytes (egg, (const ut8*)ret, strlen(ret));
562 		free (ret);
563 	} else {
564 		eprintf ("Invalid debruijn pattern length.\n");
565 	}
566 }
567