From 30acdbf50c1710ba5ccc84014b906d0c36fbe658 Mon Sep 17 00:00:00 2001 From: pancake Date: Fri, 5 Sep 2014 16:03:40 +0200 Subject: [PATCH] Refactor debruijn code and make it accessible from ragg2 -P --- binr/ragg2/ragg2.c | 14 ++- libr/core/cmd_write.c | 6 +- libr/egg/egg.c | 6 ++ libr/include/r_egg.h | 1 + libr/include/r_util.h | 4 + libr/util/debruijn.c | 197 +++++++++++++++++++++--------------------- man/ragg2.1 | 3 + 7 files changed, 126 insertions(+), 105 deletions(-) diff --git a/binr/ragg2/ragg2.c b/binr/ragg2/ragg2.c index 67199cde01..9913043c1e 100644 --- a/binr/ragg2/ragg2.c +++ b/binr/ragg2/ragg2.c @@ -1,4 +1,4 @@ -/* radare - LGPL - Copyright 2011-2013 - pancake */ +/* radare - LGPL - Copyright 2011-2014 - pancake */ #include #include @@ -28,6 +28,7 @@ static int usage (int v) { " -p [padding] add padding after compilation (padding=n10s32)\n" " ntas : begin nop, trap, 'a', sequence\n" " NTAS : same as above, but at the end\n" + " -P [size] prepend debrujn pattern\n" " -s show assembler\n" " -r show raw bytes instead of hexpairs\n" " -x execute\n" @@ -87,6 +88,7 @@ static int openfile (const char *f, int x) { int main(int argc, char **argv) { const char *file = NULL; const char *padding = NULL; + const char *pattern = NULL; char *bytes = NULL; const char *contents = NULL; const char *arch = R_SYS_ARCH; @@ -106,7 +108,7 @@ int main(int argc, char **argv) { int c, i; REgg *egg = r_egg_new (); - while ((c = getopt (argc, argv, "he:a:b:f:o:sxrk:FOI:Li:c:p:B:C:vd:D:w:")) != -1) { + while ((c = getopt (argc, argv, "he:a:b:f:o:sxrk:FOI:Li:c:p:P:B:C:vd:D:w:")) != -1) { switch (c) { case 'a': arch = optarg; @@ -181,6 +183,9 @@ int main(int argc, char **argv) { case 'p': padding = optarg; break; + case 'P': + pattern = optarg; + break; case 'c': { char *p = strchr (optarg, '='); @@ -231,7 +236,7 @@ int main(int argc, char **argv) { } } - if (optind == argc && !shellcode && !bytes && !contents && !encoder && !padding) { + if (optind == argc && !shellcode && !bytes && !contents && !encoder && !padding && !pattern) { return usage (0); } else file = argv[optind]; @@ -333,6 +338,9 @@ int main(int argc, char **argv) { if (padding) r_egg_padding (egg, padding); + if (pattern) + r_egg_pattern (egg, r_num_math (NULL, pattern)); + if (!(b = r_egg_get_bin (egg))) { eprintf ("r_egg_get_bin: invalid egg :(\n"); goto fail; diff --git a/libr/core/cmd_write.c b/libr/core/cmd_write.c index 35326c03fd..cc11d9acea 100644 --- a/libr/core/cmd_write.c +++ b/libr/core/cmd_write.c @@ -1,7 +1,5 @@ /* radare - LGPL - Copyright 2009-2014 - pancake */ -#include "../util/debruijn.c" - static void cmd_write_bits(RCore *core, int set, ut64 val) { ut64 ret, orig; // used to set/unset bit in current address @@ -700,7 +698,7 @@ static int cmd_write(void *data, const char *input) { len = (int)(input[2]==' ')? r_num_math (core->num, input + 2): core->blocksize; if (len > 0) { - buf = cyclic_pattern(len, 0, debruijn_charset); + buf = (ut8*)r_debruijn_pattern (len, 0, NULL); //debruijn_charset); if (buf) { r_core_write_at (core, core->offset, buf, len); free (buf); @@ -712,7 +710,7 @@ static int cmd_write(void *data, const char *input) { case 'O': len = (int)(input[2]==' ')? r_num_math (core->num, input + 2): core->blocksize; - core->num->value = cyclic_pattern_offset (len, !core->assembler->big_endian); + core->num->value = r_debruijn_offset (len, !core->assembler->big_endian); r_cons_printf ("%d\n", core->num->value); break; case '\0': diff --git a/libr/egg/egg.c b/libr/egg/egg.c index b3394cf910..b7482b6506 100644 --- a/libr/egg/egg.c +++ b/libr/egg/egg.c @@ -420,3 +420,9 @@ R_API void r_egg_finalize(REgg *egg) { memcpy (egg->bin->buf + b->cur, b->buf, b->length); } } + +R_API void r_egg_pattern(REgg *egg, int size) { + char *ret = r_debruijn_pattern ((int)size, 0, NULL); + r_buf_prepend_bytes (egg->bin, ret, strlen (ret)); + free (ret); +} diff --git a/libr/include/r_egg.h b/libr/include/r_egg.h index 9e538050a7..8359faecd8 100644 --- a/libr/include/r_egg.h +++ b/libr/include/r_egg.h @@ -141,6 +141,7 @@ R_API void r_egg_printf(REgg *egg, const char *fmt, ...); R_API int r_egg_compile(REgg *egg); R_API int r_egg_padding (REgg *egg, const char *pad); R_API int r_egg_assemble(REgg *egg); +R_API void r_egg_pattern(REgg *egg, int size); R_API RBuffer *r_egg_get_bin(REgg *egg); //R_API int r_egg_dump (REgg *egg, const char *file) { } R_API char *r_egg_get_source(REgg *egg); diff --git a/libr/include/r_util.h b/libr/include/r_util.h index b77cc667ce..6e203c0c72 100644 --- a/libr/include/r_util.h +++ b/libr/include/r_util.h @@ -611,6 +611,10 @@ R_API int r_sandbox_chdir (const char *path); R_API int r_sandbox_check_path (const char *path); R_API int r_sandbox_kill(int pid, int sig); +/* derbuijn.c */ +R_API char* r_debruijn_pattern(int size, int start, const char* charset); +R_API int r_debruijn_offset(ut64 value, int guest_endian); + /* strpool */ #define R_STRPOOL_INC 1024 diff --git a/libr/util/debruijn.c b/libr/util/debruijn.c index 682ff16ce1..80b7a5d1fc 100644 --- a/libr/util/debruijn.c +++ b/libr/util/debruijn.c @@ -1,7 +1,6 @@ /* radare - LGPL - Copyright 2014 - crowell */ -#include -#include +#include // For information about the algorithm, see Joe Sawada and Frank Ruskey, "An // Efficient Algorithm for Generating Necklaces with Fixed Density" @@ -12,126 +11,128 @@ // "A%sB$nC-(D;)Ea0Fb1Gc2Hd3Ie4Jf5Kg6Lh7Mi8Nj9OkPlQmRnSoTpUqVrWsXtYuZvwxyz"; //TODO(crowell): Make charset configurable, to allow banning characters. -char* debruijn_charset = - "ABCDEFGHIJKLMNOPQRSTUVWZYZabcdefghijklmnopqrstuvwxyz1234567890"; +static const char* debruijn_charset = "ABCDEFGHIJKLMNOPQRSTUVWZYZabcdefghijklmnopqrstuvwxyz1234567890"; // Generate a De Bruijn sequence. -void de_bruijn_seq(int prenecklace_len_t, int lyndon_prefix_len_p, int order, - int maxlen, int size, int* prenecklace_a, char* sequence, - char* charset) { - if (strlen(sequence) == maxlen) { - return; - } - int j; - if (prenecklace_len_t > order) { - if (order % lyndon_prefix_len_p == 0) { - for (j = 1; j <= lyndon_prefix_len_p; ++j) { - sequence[strlen(sequence)] = charset[prenecklace_a[j]]; - if (strlen(sequence) == maxlen) { - return; - } - } - } - } else { - prenecklace_a[prenecklace_len_t] = - prenecklace_a[prenecklace_len_t - lyndon_prefix_len_p]; - de_bruijn_seq(prenecklace_len_t + 1, lyndon_prefix_len_p, order, maxlen, - size, prenecklace_a, sequence, charset); - for (j = prenecklace_a[prenecklace_len_t - lyndon_prefix_len_p] + 1; - j < size; ++j) { - prenecklace_a[prenecklace_len_t] = j; - de_bruijn_seq(prenecklace_len_t + 1, prenecklace_len_t, order, maxlen, - size, prenecklace_a, sequence, charset); - } - } +static void de_bruijn_seq(int prenecklace_len_t, int lyndon_prefix_len_p, int order, + int maxlen, int size, int* prenecklace_a, char* sequence, + const char* charset) { + int j; + if (strlen(sequence) == maxlen) { + return; + } + if (prenecklace_len_t > order) { + if (order % lyndon_prefix_len_p == 0) { + for (j = 1; j <= lyndon_prefix_len_p; ++j) { + sequence[strlen(sequence)] = charset[prenecklace_a[j]]; + if (strlen(sequence) == maxlen) { + return; + } + } + } + } else { + prenecklace_a[prenecklace_len_t] = + prenecklace_a[prenecklace_len_t - lyndon_prefix_len_p]; + de_bruijn_seq(prenecklace_len_t + 1, lyndon_prefix_len_p, order, maxlen, + size, prenecklace_a, sequence, charset); + for (j = prenecklace_a[prenecklace_len_t - lyndon_prefix_len_p] + 1; + j < size; ++j) { + prenecklace_a[prenecklace_len_t] = j; + de_bruijn_seq(prenecklace_len_t + 1, prenecklace_len_t, order, maxlen, + size, prenecklace_a, sequence, charset); + } + } } // Generate a De Bruijn sequence. // The returned string is malloced, and it is the responsibility of the caller // to free the memory. -char* de_bruijn(char* charset, int order, int maxlen) { - int size = strlen(charset); - int* prenecklace_a = calloc(size * order, sizeof(int)); - char* sequence = calloc(maxlen + 1, sizeof(char)); - de_bruijn_seq(1, 1, order, maxlen, size, prenecklace_a, sequence, charset); - free(prenecklace_a); - return sequence; +static char* de_bruijn(const char* charset, int order, int maxlen) { + int size = strlen (charset); + int* prenecklace_a = calloc(size * order, sizeof(int)); + char* sequence = calloc(maxlen + 1, sizeof(char)); + de_bruijn_seq(1, 1, order, maxlen, size, prenecklace_a, sequence, charset); + free(prenecklace_a); + return sequence; } // Generate a cyclic pattern of desired size, and charset, return with starting // offset of start. // The returned string is malloced, and it is the responsibility of the caller // to free the memory. -char* cyclic_pattern(int size, int start, char* charset) { - if (start >= size) { - return (char*)NULL; - } - char* pattern = de_bruijn(charset, 3 /*subsequence length*/, size); - if (start == 0) { - return pattern; - } else { - char* returned_pattern = calloc((size - start) + 1, sizeof(char)); - strncpy(returned_pattern, pattern + start, size - start); - free(pattern); - return returned_pattern; - } +R_API char* r_debruijn_pattern(int size, int start, const char* charset) { + char *pat, *pat2; + if (!charset) + charset = debruijn_charset; + if (start >= size) { + return (char*)NULL; + } + pat = de_bruijn(charset, 3 /*subsequence length*/, size); + if (start == 0) + return pat; + pat2 = calloc ((size - start) + 1, sizeof(char)); + strncpy (pat2, pat + start, size - start); + pat2[size-start] = 0; + free (pat); + return pat2; } // In-place reverse a string. -void reverse_string(char* str) { - // Skip null and empty strings. - if (str == 0 || str[0] == 0) { - return; - } - char* start = str; - char* end = start + strlen(str) - 1; - char temp; - while (end > start) { - temp = *start; - *start = *end; - *end = temp; - ++start; - --end; - } +static void reverse_string(char* str) { + char *start = str, *end, temp; + // Skip null and empty strings. + if (!str || !*str) + return; + end = start + strlen (str) - 1; + while (end > start) { + temp = *start; + *start = *end; + *end = temp; + ++start; + --end; + } } // Generate a cyclic pattern of 0x10000 long. // The returned string is malloced, and it is the responsibility of the caller // to free the memory. -char* cyclic_pattern_long() { - // 0x10000 should be long enough. This is how peda works, and nobody - // complains. - return cyclic_pattern(0x10000, 0, debruijn_charset); +static char* cyclic_pattern_long() { + // 0x10000 should be long enough. This is how peda works, and nobody + // complains. + return r_debruijn_pattern (0x10000, 0, debruijn_charset); } // Finds the offset of a given value in a cyclic pattern of an integer. // Guest endian = 1 if little, 0 if big. // Host endian = 1 if little, 0 if big. -int cyclic_pattern_offset(unsigned long long value, int guest_endian) { - if (value == 0) { - return -1; - } - char* pattern = cyclic_pattern_long(); - unsigned long long needle_l[2]; // Hold the value as a string. - needle_l[0] = value; - needle_l[1] = 0; - char* needle = (char*)&needle_l; - // On little-endian systems with more bits than the binary being analyzed, we - // may need to find the begin of this. - while (needle[0] == 0) { - ++needle; - } - int n = 1; - // little endian if true - int host_endian = (*(char*)&n == 1) ? 1 : 0; - if (host_endian != guest_endian) { - reverse_string(needle); - } - char* pch = strstr(pattern, needle); - int retval = -1; - if (pch != NULL) { - retval = (int)(pch - pattern); - } - free(pattern); - return retval; +R_API int r_debruijn_offset(ut64 value, int guest_endian) { + ut64 needle_l[2]; // Hold the value as a string. + char* needle, *pattern; + + if (value == 0) + return -1; + pattern = cyclic_pattern_long(); + + needle_l[0] = value; + needle_l[1] = 0; + needle = (char*)&needle_l; + // On little-endian systems with more bits than the binary being analyzed, we + // may need to find the begin of this. + while (!needle[0]) + needle++; + + // we should not guess the endian. its already handled by other functions + // and configure by the user in cfg.bigendian + int n = 1; + // little endian if true + int host_endian = (*(char*)&n == 1) ? 1 : 0; + if (host_endian != guest_endian) + reverse_string (needle); + + char* pch = strstr (pattern, needle); + int retval = -1; + if (pch != NULL) + retval = (int)(pch - pattern); + free (pattern); + return retval; } diff --git a/man/ragg2.1 b/man/ragg2.1 index 3b5514e0ee..6ee0990871 100644 --- a/man/ragg2.1 +++ b/man/ragg2.1 @@ -19,6 +19,7 @@ ragg2 \- radare2 utility to run programs in exotic environments .Op Fl D Ar off:qword .Op Fl w Ar off:hexpair .Op Fl p Ar padding +.Op Fl P Ar pattern .Op Fl FOLsrxvh .Sh DESCRIPTION ragg2 is a frontend for r_egg, compile programs into tiny binaries for x86-32/64 and arm. @@ -62,6 +63,8 @@ Patch final buffer with given qword at specified offset Patch final buffer with given hexpairs at specified offset .It Fl p Ar padding Specify generic paddings with a format string. +.It Fl P Ar size +Prepend debruijn sequence of given length. .It Fl F autodetect native file format (osx=mach0, linux=elf, ..) .It Fl O