aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore11
-rw-r--r--CMakeLists.txt7
-rw-r--r--LICENSE25
-rw-r--r--README.md84
-rw-r--r--main.c154
-rw-r--r--reloc.h47
6 files changed, 328 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5a63b1b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,11 @@
+CMakeCache.txt
+CMakeFiles
+CMakeScripts
+Testing
+Makefile
+cmake_install.cmake
+install_manifest.txt
+compile_commands.json
+CTestTestfile.cmake
+reloc
+
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..1c8055f
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 2.8.11)
+project(reloc C)
+
+set(CMAKE_C_STANDARD 99)
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -Wall -Wextra")
+
+add_executable(reloc main.c reloc.h)
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..a284304
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,25 @@
+BSD 2-Clause License
+
+Copyright (c) 2019, Joseph Hunkeler
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..551118b
--- /dev/null
+++ b/README.md
@@ -0,0 +1,84 @@
+# Reloc
+
+Replace strings in binary executables and data files.
+
+## System Requirements
+
+* `gcc`
+* `>=cmake-2.18.11`
+
+## Installing
+
+```bash
+$ git clone https://github.com/jhunkeler/reloc
+$ mkdir build
+$ cd build
+$ cmake -DCMAKE_INSTALL_PREFIX=/some/place ..
+$ make install
+```
+
+## Usage
+```
+$ reloc <str1> <str2> <input_file> <output_file>
+
+Arguments:
+str1 - Pattern to search for
+str2 - Replace str1 with contents of str2
+input_file - Path to input file
+output_file - Path to output file
+
+Example:
+reloc /original/path /new/path input.bin output.bin
+```
+
+## Showcase
+
+### Before
+
+```
+$ xxd -u -g1 test.dat
+00000000: DE AD BE EF 2F 5F 30 31 32 33 34 35 36 37 38 39 ..../_0123456789
+00000010: 5F 30 31 32 33 34 35 36 37 38 39 5F 30 31 32 33 _0123456789_0123
+00000020: 34 35 36 37 38 39 5F 30 31 32 33 34 35 36 37 38 456789_012345678
+00000030: 39 5F 30 31 32 33 34 35 36 37 38 39 5F 30 31 32 9_0123456789_012
+00000040: 33 34 35 36 37 38 39 5F 30 31 32 33 34 35 36 37 3456789_01234567
+00000050: 38 39 5F 2F 74 65 73 74 00 52 41 4E 44 4F 4D 20 89_/test.RANDOM
+00000060: 44 41 54 41 20 54 48 41 54 20 43 41 4E 4E 4F 54 DATA THAT CANNOT
+00000070: 20 42 45 20 4D 4F 56 45 44 00 FE CE FA CE 2F 5F BE MOVED...../_
+00000080: 30 31 32 33 34 35 36 37 38 39 5F 30 31 32 33 34 0123456789_01234
+00000090: 35 36 37 38 39 5F 30 31 32 33 34 35 36 37 38 39 56789_0123456789
+000000a0: 5F 30 31 32 33 34 35 36 37 38 39 5F 30 31 32 33 _0123456789_0123
+000000b0: 34 35 36 37 38 39 5F 30 31 32 33 34 35 36 37 38 456789_012345678
+000000c0: 39 5F 30 31 32 33 34 35 36 37 38 39 5F 2F 73 75 9_0123456789_/su
+000000d0: 66 66 69 78 00 FF FF FF FF FF FF FF FF FF ffix..........
+```
+
+### During
+
+```bash
+$ reloc \
+ /_0123456789_0123456789_0123456789_0123456789_0123456789_0123456789_0123456789_ \
+ /tmp/_installed \
+ test.dat \
+ output.dat
+```
+
+### After
+
+```
+xxd -u -g1 output.dat
+00000000: DE AD BE EF 2F 74 6D 70 2F 5F 69 6E 73 74 61 6C ..../tmp/_instal
+00000010: 6C 65 64 2F 74 65 73 74 00 00 00 00 00 00 00 00 led/test........
+00000020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+00000030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+00000040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+00000050: 00 00 00 00 00 00 00 00 00 52 41 4E 44 4F 4D 20 .........RANDOM
+00000060: 44 41 54 41 20 54 48 41 54 20 43 41 4E 4E 4F 54 DATA THAT CANNOT
+00000070: 20 42 45 20 4D 4F 56 45 44 00 FE CE FA CE 2F 74 BE MOVED...../t
+00000080: 6D 70 2F 5F 69 6E 73 74 61 6C 6C 65 64 2F 73 75 mp/_installed/su
+00000090: 66 66 69 78 00 00 00 00 00 00 00 00 00 00 00 00 ffix............
+000000a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+000000b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+000000c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+000000d0: 00 00 00 00 00 FF FF FF FF FF FF FF FF FF ..............
+```
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..535b277
--- /dev/null
+++ b/main.c
@@ -0,0 +1,154 @@
+#include "reloc.h"
+
+
+RelocMatch *reloc_match(char *haystack, const char *needle) {
+ char *data = haystack;
+ size_t needle_size = strlen(needle);
+ RelocMatch *match = NULL;
+
+ // Search the needle in the data
+ if (!(memcmp(data, needle, needle_size))) {
+ if (!(match = calloc(1, sizeof(RelocMatch)))) {
+ fprintf(stderr,"Failed to allocate FindStat structure: %s\n", strerror(errno));
+ exit(1);
+ }
+ size_t data_end = strlen(data);
+ match->begin = data;
+ match->end = match->begin + needle_size;
+ match->length = match->end - match->begin;
+ match->post = match->end;
+ match->post_length = strlen(match->post);
+ match->total_length = data_end;
+ }
+ return match;
+}
+
+
+RelocData *reloc_read(const char *filename) {
+ char *data = NULL;
+ FILE *fp = NULL;
+ size_t size = 0;
+
+ // Open file for reading in binary mode
+ if (!(fp = fopen(filename, "rb"))) {
+ fprintf(stderr, "Cannot open %s: %s\n", filename, strerror(errno));
+ exit(1);
+ }
+
+ // Determine file size
+ fseek(fp, 0, SEEK_END);
+ size = ftell(fp);
+ rewind(fp);
+
+ if (!(data = calloc(sizeof(char), size + 1))) {
+ fprintf(stderr, "Cannot allocate data array: %s\n", strerror(errno));
+ exit(1);
+ }
+
+ // Read data into array
+ fread(data, sizeof(char), size, fp);
+ RelocData *result = (RelocData *) malloc(sizeof(RelocData));
+ result->size = size;
+ result->data = data;
+ result->path = strdup(filename);
+ return result;
+}
+
+
+size_t reloc_write(RelocData *finfo, const char *filename) {
+ FILE *fp;
+
+ // Open file for writing in binary mode
+ if (!(fp = fopen(filename, "w+b"))) {
+ fprintf(stderr,"Cannot open %s for writing: %s\n", filename, strerror(errno));
+ exit(1);
+ }
+
+ // Write data
+ return fwrite(finfo->data, sizeof(char), finfo->size, fp);
+}
+
+
+void reloc_deinit_data(RelocData *finfo) {
+ if (finfo) {
+ if (finfo->path) {
+ free(finfo->path);
+ }
+ free(finfo);
+ }
+}
+
+
+void reloc_replace(RelocMatch *match, const char *rstr) {
+ size_t rstr_length = strlen(rstr);
+ if (rstr_length > match->length) {
+ fprintf(stderr, "Replacement value is too long (%lu > %lu)\n", match->length, rstr_length);
+ return;
+ }
+ char *data = match->begin;
+ size_t i = 0;
+
+ // Overwrite data with replacement string
+ while (i < rstr_length) {
+ *data = *rstr;
+ data++;
+ rstr++;
+ i++;
+ }
+
+ i = 0;
+ // Append remaining bytes not part of the original match to the replaced string
+ char *post = match->post;
+ while (i < match->post_length) {
+ *data = *post;
+ data++;
+ post++;
+ i++;
+ }
+
+ // Destroy bytes between the end of the original data and the end of the replaced string
+ memset(data, '\0', post - data);
+}
+
+
+int main(int argc, char *argv[]) {
+ const char *program = strrchr(argv[0], DIRSEP) + 1;
+ if (argc < 5) {
+ printf("%s <str1> <str2> <input_file> <output_file>\n"
+ "\n"
+ "Arguments:\n"
+ "str1 - Pattern to search for\n"
+ "str2 - Replace str1 with contents of str2\n"
+ "input_file - Path to input file\n"
+ "output_file - Path to output file\n"
+ "\n"
+ "Example:\n"
+ "%s /original/path /new/path input.bin output.bin\n"
+ "\n", program, program);
+ exit(1);
+ }
+ char *needle = argv[1];
+ char *replacement = argv[2];
+ char *input_file = strdup(argv[3]);
+ char *output_file = strdup(argv[4]);
+ RelocData *info = reloc_read(input_file);
+ size_t records = 0;
+
+ for (size_t i = 0; i < info->size; i++) {
+ RelocMatch *match = NULL;
+ if (!(match = reloc_match(&info->data[i], needle))) {
+ // No match found
+ continue;
+ }
+ // Replace string
+ reloc_replace(match, replacement);
+ free(match);
+ records++;
+ }
+
+ reloc_write(info, output_file);
+ printf("%lu\n", records);
+
+ reloc_deinit_data(info);
+ return 0;
+}
diff --git a/reloc.h b/reloc.h
new file mode 100644
index 0000000..bebd8bb
--- /dev/null
+++ b/reloc.h
@@ -0,0 +1,47 @@
+//
+// Created by jhunk on 11/7/2019.
+//
+
+#ifndef RELOC_RELOC_H
+#define RELOC_RELOC_H
+
+#define _GNU_SOURCE 1
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if defined(_WIN32) || defined(_WIN64)
+#define DIRSEP '\\'
+#elif defined(__linux__) || defined(__unix__) || defined(__APPLE__) || defined(__MACH__)
+#define DIRSEP '/'
+#endif
+
+
+typedef struct {
+ size_t size;
+ char *path;
+ char *data;
+} RelocData;
+
+
+typedef struct {
+ char *begin;
+ char *end;
+ char *post;
+ size_t length;
+ size_t post_length;
+ size_t total_length;
+} RelocMatch;
+
+
+RelocMatch *reloc_match(char *haystack, const char *needle);
+char *reloc_find_null(char *s);
+RelocData *reloc_read(const char *filename);
+size_t reloc_write(RelocData *finfo, const char *filename);
+void reloc_deinit_data(RelocData *finfo);
+void reloc_replace(RelocMatch *match, const char *rstr);
+
+
+#endif //RELOC_RELOC_H