From 840d92358e311b405475ba7488ec55cc3f4f5fae Mon Sep 17 00:00:00 2001 From: Jari Vetoniemi Date: Sun, 21 Oct 2018 19:48:24 +0300 Subject: Give binsearch ability to find all matches --- contrib/brute-map.bash | 4 ++-- src/binsearch.c | 51 +++++++++++++++++++++++++++++++++++++------------- 2 files changed, 40 insertions(+), 15 deletions(-) diff --git a/contrib/brute-map.bash b/contrib/brute-map.bash index 4a5a811..a05e915 100755 --- a/contrib/brute-map.bash +++ b/contrib/brute-map.bash @@ -1,11 +1,11 @@ #!/bin/bash -# usage: ./brute-map.bash pid file [window-size] +# usage: ./brute-map.bash pid file [window-size] < regions # Sometimes region offsets aren't available, but we know that some regions map a file # Fix the region offsets by bruteforcing the offsets from a known file while read -r region; do offset=$(printf '%d' "0x$(awk '{print $3}' <<<"$region")") if ((offset == 0)); then - offset=$(binsearch <(ptrace-region-rw "$1" read <<<"$region" 2>/dev/null | bintrim) $3 < "$2") + offset=$(binsearch <(ptrace-region-rw "$1" read <(printf '%s\n' "$region") | bintrim) first $3 < "$2" 2>/dev/null) if [[ -n "$offset" ]]; then hex=$(printf '%.8x' "$offset") awk '{printf "%s %s %s %s %s %s\n", $1, $2, "'"$hex"'", $4, $5, $6, $7}' <<<"$region" diff --git a/src/binsearch.c b/src/binsearch.c index a4195ba..d382c5a 100644 --- a/src/binsearch.c +++ b/src/binsearch.c @@ -2,12 +2,16 @@ #include #include #include +#include #include +static bool FOUND = false; + static void usage(const char *argv0) { - fprintf(stderr, "usage: %s needle [window-size] < haystack\n", argv0); + fprintf(stderr, "usage: %s needle first [window-size] < haystack\n" + " %s needle all [window-size] < haystack\n", argv0, argv0); exit(EXIT_FAILURE); } @@ -23,14 +27,17 @@ search(const char *haystack, const char *needle, const size_t window_size) } static void -search_and_exit_if_match(const char *haystack, const char *needle, const size_t window_size, const size_t offset) +search_and_print_if_match(const char *haystack, const char *needle, const size_t window_size, const size_t offset, const bool exit_on_match) { const char *match; if ((match = search(haystack, needle, window_size))) { + FOUND = true; printf("%zu\n", offset + match - haystack); - free((void*)needle); - free((void*)haystack); - exit(EXIT_SUCCESS); + if (exit_on_match) { + free((void*)needle); + free((void*)haystack); + exit(EXIT_SUCCESS); + } } } @@ -41,10 +48,23 @@ main(int argc, const char *argv[]) size_t window_size = 4096 * 1024; bool has_window_size = false; - if (argc < 2) + if (argc < 3) usage(argv[0]); - else if (argc > 2) { - window_size = strtoull(argv[2], NULL, 10); + + enum { + FIRST, + ALL + } mode; + + if (!strcmp(argv[2], "first")) + mode = FIRST; + else if (!strcmp(argv[2], "all")) + mode = ALL; + else + errx(EXIT_FAILURE, "mode must be first or all"); + + if (argc > 3) { + window_size = hexdecstrtoull(argv[3], NULL); has_window_size = true; } @@ -55,7 +75,12 @@ main(int argc, const char *argv[]) if (!has_window_size) { fseek(f, 0, SEEK_END); const long tell = ftell(f); - window_size = (tell > 0 ? (size_t)tell : window_size); + + if (tell < 0) + warnx("can't figure out the size of a needle, not a normal file? fallbacking to a window size of %zu bytes", window_size); + else + window_size = tell; + fseek(f, 0, SEEK_SET); } @@ -71,14 +96,14 @@ main(int argc, const char *argv[]) err(EXIT_FAILURE, "calloc"); size_t rd = 0, offset = 0; - while ((rd = fread(haystack + window_size * !!offset, 1 + !offset, window_size, stdin))) { - search_and_exit_if_match(haystack, needle, (rd >= window_size ? window_size : 0), offset); + while ((rd = fread(haystack + window_size * !!offset, 1, window_size * (1 + !offset), stdin))) { + search_and_print_if_match(haystack, needle, (rd >= window_size ? window_size : 0), offset, (mode == FIRST)); offset += window_size; memmove(haystack, haystack + window_size, window_size); } - search_and_exit_if_match(haystack, needle, (rd >= window_size ? window_size : 0), offset); + search_and_print_if_match(haystack, needle, (rd >= window_size ? window_size : 0), offset, (mode == FIRST)); free(needle); free(haystack); - return EXIT_FAILURE; + return (FOUND ? EXIT_SUCCESS : EXIT_FAILURE); } -- cgit v1.2.3