diff options
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | binsearch.c | 84 | ||||
-rw-r--r-- | bintrim.c | 44 | ||||
-rwxr-xr-x | contrib/brute-map.bash | 16 | ||||
-rwxr-xr-x | contrib/winedbg-map | 10 | ||||
-rwxr-xr-x | contrib/winedbg-pid | 4 | ||||
-rwxr-xr-x | contrib/winedbg-procmap | 18 | ||||
-rwxr-xr-x | contrib/winedbg-share | 10 |
8 files changed, 189 insertions, 1 deletions
@@ -9,13 +9,15 @@ WARNINGS := -Wall -Wextra -Wpedantic -Wformat=2 -Wstrict-aliasing=3 -Wstrict-ove override CFLAGS ?= -g override CFLAGS += -std=c99 -D_DEFAULT_SOURCE $(WARNINGS) -bins = proc-region-rw +bins = proc-region-rw binsearch bintrim all: $(bins) $(bins): %: $(LINK.c) $^ $(LDLIBS) -o $@ proc-region-rw: proc-region-rw.c +binsearch: binsearch.c +bintrim: bintrim.c install-bin: $(bins) install -Dm755 $^ -t "$(DESTDIR)$(PREFIX)$(bindir)" diff --git a/binsearch.c b/binsearch.c new file mode 100644 index 0000000..a4195ba --- /dev/null +++ b/binsearch.c @@ -0,0 +1,84 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdbool.h> +#include <err.h> + +static void +usage(const char *argv0) +{ + fprintf(stderr, "usage: %s needle [window-size] < haystack\n", argv0); + exit(EXIT_FAILURE); +} + +static const char* +search(const char *haystack, const char *needle, const size_t window_size) +{ + for (const char *s = haystack; s < haystack + window_size; ++s) { + if (memcmp(s, needle, window_size)) + continue; + return s; + } + return NULL; +} + +static void +search_and_exit_if_match(const char *haystack, const char *needle, const size_t window_size, const size_t offset) +{ + const char *match; + if ((match = search(haystack, needle, window_size))) { + printf("%zu\n", offset + match - haystack); + free((void*)needle); + free((void*)haystack); + exit(EXIT_SUCCESS); + } +} + +int +main(int argc, const char *argv[]) +{ + // default incase failure, or cant get size of file + size_t window_size = 4096 * 1024; + bool has_window_size = false; + + if (argc < 2) + usage(argv[0]); + else if (argc > 2) { + window_size = strtoull(argv[2], NULL, 10); + has_window_size = true; + } + + FILE *f; + if (!(f = fopen(argv[1], "rb"))) + err(EXIT_FAILURE, "fopen(%s)", argv[1]); + + if (!has_window_size) { + fseek(f, 0, SEEK_END); + const long tell = ftell(f); + window_size = (tell > 0 ? (size_t)tell : window_size); + fseek(f, 0, SEEK_SET); + } + + char *needle; + if (!(needle = malloc(window_size))) + err(EXIT_FAILURE, "malloc"); + + window_size = fread(needle, 1, window_size, f); + fclose(f); + + char *haystack; + if (!(haystack = calloc(2, window_size))) + 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); + offset += window_size; + memmove(haystack, haystack + window_size, window_size); + } + + search_and_exit_if_match(haystack, needle, (rd >= window_size ? window_size : 0), offset); + free(needle); + free(haystack); + return EXIT_FAILURE; +} diff --git a/bintrim.c b/bintrim.c new file mode 100644 index 0000000..2a2018e --- /dev/null +++ b/bintrim.c @@ -0,0 +1,44 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stdbool.h> +#include <string.h> +#include <err.h> + +int +main(int argc, const char *argv[]) +{ + unsigned char trim = 0; + + if (argc > 1) + trim = strtoul(argv[1], NULL, 10); + + bool leading = true; + size_t rd, out_sz = 0, out_allocated = 0; + char buf[4096], *out = NULL; + while ((rd = fread(buf, 1, sizeof(buf), stdin))) { + for (const char *s = buf; s < buf + rd; ++s) { + if (*s == trim && leading) + continue; + + if (out_sz >= out_allocated) { + if (!(out = realloc(out, out_allocated += sizeof(buf)))) + err(EXIT_FAILURE, "realloc"); + } + + out[out_sz++] = *s; + leading = false; + } + + const char *s; + for (s = out + (out_sz ? out_sz - 1 : 0); s > out && *s == trim; --s); + + const size_t to_write = (size_t)(s - out); + if (fwrite(out, 1, to_write, stdout) != to_write) + err(EXIT_FAILURE, "fwrite"); + + memmove(out, s, (out_sz = out_sz - to_write)); + } + + free(out); + return EXIT_SUCCESS; +} diff --git a/contrib/brute-map.bash b/contrib/brute-map.bash new file mode 100755 index 0000000..a7a735c --- /dev/null +++ b/contrib/brute-map.bash @@ -0,0 +1,16 @@ +#!/bin/bash +# usage: ./brute-map.bash pid file [window-size] +# 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 <(proc-region-rw "$1" read <<<"$region" 2>/dev/null | bintrim) $3 < "$2") + fi + if ((offset != 0)); then + hex=$(printf '%.8x' "$offset") + awk '{printf "%s %s %s %s %s %s\n", $1, $2, "'"$hex"'", $4, $5, $6, $7}' <<<"$region" + else + printf '%s\n' "$region" + fi +done diff --git a/contrib/winedbg-map b/contrib/winedbg-map new file mode 100755 index 0000000..d257c64 --- /dev/null +++ b/contrib/winedbg-map @@ -0,0 +1,10 @@ +#!/bin/sh +# usage: winedbg-map wpid +# Get windows process map information + +# --file doesn't work for some reason +winedbg << EOF | sed 's/Wine-dbg>//g' | tail -n +3 +attach $1 +info map +detach +EOF diff --git a/contrib/winedbg-pid b/contrib/winedbg-pid new file mode 100755 index 0000000..0c04115 --- /dev/null +++ b/contrib/winedbg-pid @@ -0,0 +1,4 @@ +#!/bin/sh +# usage: winedbg-pid process-name +# Get windows process id with process name +winedbg --command 'info process' | awk '/'"${@:-0xdeadbeef}"'/ { print strtonum("0x"$1) }' diff --git a/contrib/winedbg-procmap b/contrib/winedbg-procmap new file mode 100755 index 0000000..3922150 --- /dev/null +++ b/contrib/winedbg-procmap @@ -0,0 +1,18 @@ +#!/bin/sh +# usage: winedbg-procmap wpid +# Convert winedbg's share and map information into /proc/<pid>/maps compatible format +# NOTE: since there's no map offsets you may need to use the brute-map.bash tool as well + +tmpdir="$(mktemp -d)" +trap 'rm -rf "$tmpdir"' EXIT +winedbg-share "$1" > "$tmpdir/share" +winedbg-map "$1" > "$tmpdir/map" + +awk '{print substr($2, 1, length($2)-1); print $3; print $5}' < "$tmpdir/share" |\ +while { + read -r start + read -r end + read -r name +}; do + awk '(strtonum(0x'"$start"') <= strtonum("0x"$1) && strtonum(0x'"$end"') >= strtonum("0x"$2)) { printf "%s-%s rwxp 00000000 00:00 0 %s\n", $1, $2, "'"$name"'" }' < "$tmpdir/map" +done diff --git a/contrib/winedbg-share b/contrib/winedbg-share new file mode 100755 index 0000000..66dc8ff --- /dev/null +++ b/contrib/winedbg-share @@ -0,0 +1,10 @@ +#!/bin/sh +# usage: winedbg-share wpid +# Get windows process share information + +# --file doesn't work for some reason +winedbg << EOF | sed 's/Wine-dbg>//g' | tail -n +3 +attach $1 +info share +detach +EOF |