Last patch for now.
Left for later: ReBaseImage64() unconditionally updates the timestamp in
the file header.
--
Regards,
Christian
From 3973a92cf11056521552d9d3f87efe8e721e8c31 Mon Sep 17 00:00:00 2001
From: Christian Franke <christian.fra...@t-online.de>
Date: Tue, 8 Aug 2023 12:04:25 +0200
Subject: [PATCH] rebase: Add -c, --checksum option
If specified, the file checksum in the PE header is updated after
rebasing.
Signed-off-by: Christian Franke <christian.fra...@t-online.de>
---
Makefile.in | 4 ++--
rebase.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++----
2 files changed, 48 insertions(+), 6 deletions(-)
diff --git a/Makefile.in b/Makefile.in
index adb7972..2f061ca 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -74,7 +74,7 @@ override CXX_LDFLAGS+=@EXTRA_CXX_LDFLAG_OVERRIDES@
LIBIMAGEHELPER = imagehelper/libimagehelper.a
-REBASE_OBJS = rebase.$(O) rebase-db.$(O) $(LIBOBJS)
+REBASE_OBJS = rebase.$(O) rebase-db.$(O) pechecksum.$(O) $(LIBOBJS)
REBASE_LIBS = $(LIBIMAGEHELPER)
REBASE_DUMP_OBJS = rebase-dump.$(O) rebase-db.$(O) $(LIBOBJS)
@@ -100,7 +100,7 @@ $(LIBIMAGEHELPER):
rebase$(EXEEXT): $(REBASE_LIBS) $(REBASE_OBJS)
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(CXX_LDFLAGS) -o $@ $(REBASE_OBJS)
$(REBASE_LIBS)
-rebase.$(O):: rebase.c rebase-db.h Makefile
+rebase.$(O):: rebase.c pechecksum.h rebase-db.h Makefile
rebase-db.$(O):: rebase-db.c rebase-db.h Makefile
diff --git a/rebase.c b/rebase.c
index 7417d4d..50cc79f 100644
--- a/rebase.c
+++ b/rebase.c
@@ -39,6 +39,7 @@
#include <errno.h>
#include <io.h>
#include "imagehelper.h"
+#include "pechecksum.h"
#include "rebase-db.h"
#include <versionhelpers.h> /* requires <windows.h> */
@@ -74,6 +75,7 @@ WORD machine = IMAGE_FILE_MACHINE_I386;
ULONG64 image_base = 0;
ULONG64 low_addr;
BOOL down_flag = FALSE;
+BOOL checksum_flag = FALSE;
BOOL image_info_flag = FALSE;
BOOL image_storage_flag = FALSE;
BOOL image_oblivious_flag = FALSE;
@@ -1188,6 +1190,32 @@ print_overlapped ()
}
}
+static BOOL
+update_checksum (const char *pathname)
+{
+ int fd, err;
+ unsigned old_checksum, new_checksum;
+
+ if ((fd = open (pathname, O_RDWR | O_BINARY)) == -1)
+ {
+ fprintf (stderr, "%s: failed to reopen for checksum update: %s\n",
+ pathname, strerror (errno));
+ return FALSE;
+ }
+ new_checksum = pe32_checksum (fd, 1, &old_checksum);
+ err = errno;
+ close(fd);
+ if (!new_checksum)
+ {
+ fprintf (stderr, "%s: checksum update failed: %s\n", pathname,
+ strerror (err));
+ /* Assume file is unchanged. */
+ return FALSE;
+ }
+
+ return (new_checksum != old_checksum);
+}
+
BOOL
rebase (const char *pathname, ULONG64 *new_image_base, BOOL down_flag)
{
@@ -1279,13 +1307,18 @@ retry:
}
#endif
+ /* Update checksum, if requested. */
+ status = (checksum_flag ? update_checksum (pathname) : FALSE);
+
/* Display rebase results, if verbose. */
if (verbose)
{
- printf ("%s: new base = %" PRIx64 ", new size = %x\n",
+ printf ("%s: new base = %" PRIx64 ", new size = %x%s\n",
pathname,
(uint64_t) ((down_flag) ? *new_image_base : prev_new_image_base),
- (uint32_t) (new_image_size + offset));
+ (uint32_t) (new_image_size + offset),
+ (checksum_flag ? (status ? ", checksum updated" :
+ ", checksum unchanged") : ""));
}
/* Calculate next base address, if rebasing up. */
@@ -1299,6 +1332,7 @@ static struct option long_options[] = {
{"32", no_argument, NULL, '4'},
{"64", no_argument, NULL, '8'},
{"base", required_argument, NULL, 'b'},
+ {"checksum", no_argument, NULL, 'c'},
{"down", no_argument, NULL, 'd'},
{"help", no_argument, NULL, 'h'},
{"usage", no_argument, NULL, 'h'},
@@ -1316,7 +1350,7 @@ static struct option long_options[] = {
{NULL, no_argument, NULL, 0 }
};
-static const char *short_options = "48b:dhiMno:OqstT:vV";
+static const char *short_options = "48b:cdhiMno:OqstT:vV";
void
parse_args (int argc, char *argv[])
@@ -1341,6 +1375,9 @@ parse_args (int argc, char *argv[])
image_base = string_to_ulonglong (optarg);
force_rebase_flag = TRUE;
break;
+ case 'c':
+ checksum_flag = TRUE;
+ break;
case 'd':
down_flag = TRUE;
break;
@@ -1625,6 +1662,10 @@ Rebase PE files, usually DLLs, to a specified address or
address range.\n\
One of the options -b, -s or -i is mandatory. If no rebase database
exists\n\
yet, -b is required together with -s.\n\
\n\
+ -c, --checksum Update the file's checksum in the PE header if the\n\
+ file has been successfully rebased. This also
bumps\n\
+ the file's modification time (like -t) if the\n\
+ checksum has been changed.\n\
-d, --down Treat the BaseAddress as upper ceiling and rebase\n\
files top-down from there. Without this option
the\n\
files are rebased from BaseAddress bottom-up.\n\
@@ -1634,7 +1675,8 @@ Rebase PE files, usually DLLs, to a specified address or
address range.\n\
when rebasing. Default is no offset.\n\
-t, --touch Use this option to make sure the file's
modification\n\
time is bumped if it has been successfully
rebased.\n\
- Usually rebase does not change the file's time.\n\
+ Usually rebase does not change the file's time
unless\n\
+ the -c flag is also specified.\n\
-T, --filelist=FILE Also rebase the files specified in FILE. The
format\n\
of FILE is one DLL per line.\n\
-q, --quiet Be quiet about non-critical issues.\n\
--
2.39.0