[PATCH rebase] rebase: Add -c, --checksum option

Christian Franke Christian.Franke@t-online.de
Tue Aug 8 10:10:50 GMT 2023


Last patch for now.

Left for later: ReBaseImage64() unconditionally updates the timestamp in 
the file header.

-- 
Regards,
Christian

-------------- next part --------------
From 3973a92cf11056521552d9d3f87efe8e721e8c31 Mon Sep 17 00:00:00 2001
From: Christian Franke <christian.franke@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.franke@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



More information about the Cygwin-apps mailing list