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