Bug 1082670: Copy breakpadinjector's image header into the remote process. r=bsmedberg
authorDavid Major <dmajor@mozilla.com>
Wed, 22 Oct 2014 09:01:16 +1300
changeset 211601 ac44aef9c4d46927c98ce9edd4126a1242efe1fb
parent 211600 2cc8826abef2a5de6642ff7b2f7c1ab434954dc5
child 211602 5fbd9586a141a9a511fea4e77dcfd1efc299cfdf
push idunknown
push userunknown
push dateunknown
reviewersbsmedberg
bugs1082670
milestone36.0a1
Bug 1082670: Copy breakpadinjector's image header into the remote process. r=bsmedberg
toolkit/crashreporter/LoadLibraryRemote.cpp
--- a/toolkit/crashreporter/LoadLibraryRemote.cpp
+++ b/toolkit/crashreporter/LoadLibraryRemote.cpp
@@ -90,16 +90,45 @@ CopySections(const unsigned char *data, 
     memset(dest, 0, section->Misc.VirtualSize);
     if (section->SizeOfRawData) {
       memcpy(dest, data + section->PointerToRawData, section->SizeOfRawData);
     }
     //     section->Misc.PhysicalAddress = (POINTER_TYPE) module->remoteCodeBase + section->VirtualAddress;
   }
 }
 
+static bool
+CopyRegion(HANDLE hRemoteProcess, void* remoteAddress, void* localAddress, DWORD size, DWORD protect)
+{
+  if (size > 0) {
+    // Copy the data from local->remote and set the memory protection
+    if (!VirtualAllocEx(hRemoteProcess, remoteAddress, size, MEM_COMMIT, PAGE_READWRITE))
+      return false;
+
+    if (!WriteProcessMemory(hRemoteProcess,
+                            remoteAddress,
+                            localAddress,
+                            size,
+                            nullptr)) {
+#ifdef DEBUG_OUTPUT
+      OutputLastError("Error writing remote memory.\n");
+#endif
+      return false;
+    }
+
+    DWORD oldProtect;
+    if (VirtualProtectEx(hRemoteProcess, remoteAddress, size, protect, &oldProtect) == 0) {
+#ifdef DEBUG_OUTPUT
+      OutputLastError("Error protecting memory page");
+#endif
+      return false;
+    }
+  }
+  return true;
+}
 // Protection flags for memory pages (Executable, Readable, Writeable)
 static int ProtectionFlags[2][2][2] = {
   {
     // not executable
     {PAGE_NOACCESS, PAGE_WRITECOPY},
     {PAGE_READONLY, PAGE_READWRITE},
   }, {
     // executable
@@ -112,64 +141,51 @@ static bool
 FinalizeSections(PMEMORYMODULE module, HANDLE hRemoteProcess)
 {
 #ifdef DEBUG_OUTPUT
   fprintf(stderr, "Finalizing sections: local base %p, remote base %p\n",
           module->localCodeBase, module->remoteCodeBase);
 #endif
 
   int i;
+  int numSections = module->headers->FileHeader.NumberOfSections;
+
+  if (numSections < 1)
+    return false;
+
   PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(module->headers);
-  
+
+  // Copy any data before the first section (i.e. the image header)
+  if (!CopyRegion(hRemoteProcess, module->remoteCodeBase, module->localCodeBase, section->VirtualAddress, PAGE_READONLY))
+    return false;
+
   // loop through all sections and change access flags
-  for (i=0; i<module->headers->FileHeader.NumberOfSections; i++, section++) {
-    DWORD protect, oldProtect, size;
+  for (i=0; i<numSections; i++, section++) {
+    DWORD protect, size;
     int executable = (section->Characteristics & IMAGE_SCN_MEM_EXECUTE) != 0;
     int readable =   (section->Characteristics & IMAGE_SCN_MEM_READ) != 0;
     int writeable =  (section->Characteristics & IMAGE_SCN_MEM_WRITE) != 0;
 
     // determine protection flags based on characteristics
     protect = ProtectionFlags[executable][readable][writeable];
     if (section->Characteristics & IMAGE_SCN_MEM_NOT_CACHED) {
       protect |= PAGE_NOCACHE;
     }
 
+    void* remoteAddress = module->remoteCodeBase + section->VirtualAddress;
+    void* localAddress = module->localCodeBase + section->VirtualAddress;
+
     // determine size of region
     size = section->Misc.VirtualSize;
-    if (size > 0) {
-      void* remoteAddress = module->remoteCodeBase + section->VirtualAddress;
-      void* localAddress = module->localCodeBase + section->VirtualAddress;
-
 #ifdef DEBUG_OUTPUT
       fprintf(stderr, "Copying section %s to %p, size %x, executable %i readable %i writeable %i\n",
               section->Name, remoteAddress, size, executable, readable, writeable);
 #endif
-
-      // Copy the data from local->remote and set the memory protection
-      if (!VirtualAllocEx(hRemoteProcess, remoteAddress, size, MEM_COMMIT, PAGE_READWRITE))
-        return false;
-
-      if (!WriteProcessMemory(hRemoteProcess,
-                              remoteAddress,
-                              localAddress,
-                              size,
-                              nullptr)) {
-#ifdef DEBUG_OUTPUT
-        OutputLastError("Error writing remote memory.\n");
-#endif
-        return false;
-      }
-
-      if (VirtualProtectEx(hRemoteProcess, remoteAddress, size, protect, &oldProtect) == 0) {
-#ifdef DEBUG_OUTPUT
-        OutputLastError("Error protecting memory page");
-#endif
-        return false;
-      }
-    }
+    if (!CopyRegion(hRemoteProcess, remoteAddress, localAddress, size, protect))
+      return false;
   }
   return true;
 }
 
 static void
 PerformBaseRelocation(PMEMORYMODULE module, SIZE_T delta)
 {
   DWORD i;