1818
1919#include < cstdint>
2020
21+ #include < unistd.h>
2122#include < sys/mman.h>
23+ #include < sys/syscall.h>
2224
2325#include " e9alloc.h"
2426#include " e9elf.h"
@@ -134,14 +136,24 @@ typedef struct _IMAGE_BASE_RELOCATION
134136/*
135137 * Simple string hash function.
136138 */
137- uint64_t hash (const char *s)
139+ static uint64_t hash (const char *s)
138140{
139141 uint64_t h = 777799777ull ;
140142 while (*s)
141143 h = (3333331ull * h) ^ (0xe9e9ea1bull * (uint64_t )*s++);
142144 return h;
143145}
144146
147+ /*
148+ * Simple random number function.
149+ */
150+ static uint64_t random (const char *s)
151+ {
152+ uint64_t r;
153+ (void )syscall (SYS_getrandom, &r, sizeof (r), 0 );
154+ return r;
155+ }
156+
145157/*
146158 * Parse a Windows PE executable.
147159 */
@@ -196,16 +208,6 @@ void parsePE(Binary *B)
196208 error (" failed to parse PE file \" %s\" ; invalid image base (0x%lx), "
197209 " expected a multiple of virtual allocation granularity (%u)" ,
198210 filename, image_base, WINDOWS_VIRTUAL_ALLOC_SIZE);
199- bool have_relocs =
200- (opt_hdr->DllCharacteristics & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE)
201- != 0 ;
202- uint64_t image_base_min = 0x100000000 ;
203- if ((option_mem_rebase == 0 || !have_relocs) &&
204- image_base < image_base_min)
205- error (" failed to parse PE file \" %s\" ; image base (0x%lx) must be "
206- " (>=0x%lx)%s" , filename, image_base, image_base_min,
207- (have_relocs? " (hint: see the `--mem-rebase' option)" :
208- " , but relocations are stripped" ));
209211 PIMAGE_SECTION_HEADER shdr =
210212 (PIMAGE_SECTION_HEADER)&opt_hdr->DataDirectory [
211213 opt_hdr->NumberOfRvaAndSizes ];
@@ -331,16 +333,17 @@ size_t emitPE(Binary *B, const MappingSet &mappings, size_t mapping_size)
331333 uint32_t addr_of_entry = size_of_image + (uint32_t )(size - config_offset);
332334 PIMAGE_TLS_DIRECTORY64 tls = (PIMAGE_TLS_DIRECTORY64)findPEData (B,
333335 opt_hdr->DataDirectory [IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress );
336+ intptr_t image_base = (intptr_t )opt_hdr->ImageBase ;
334337 intptr_t *callbacks = (tls != nullptr ?
335- (intptr_t *)findPEData (B, tls->AddressOfCallBacks - opt_hdr-> ImageBase ):
338+ (intptr_t *)findPEData (B, tls->AddressOfCallBacks - image_base ):
336339 nullptr );
337340 bool use_tls = (callbacks != nullptr && callbacks[0 ] != 0x0 );
338341 if (use_tls)
339342 {
340343 // This PE file uses TLS callbacks, which are called before the entry
341344 // point. Thus we inject the loader here:
342- config->entry = (intptr_t )callbacks[0 ] - ( intptr_t )opt_hdr-> ImageBase ;
343- callbacks[0 ] = ( intptr_t )opt_hdr-> ImageBase + (intptr_t )addr_of_entry;
345+ config->entry = (intptr_t )callbacks[0 ] - image_base ;
346+ callbacks[0 ] = image_base + (intptr_t )addr_of_entry;
344347 }
345348 else
346349 {
@@ -404,13 +407,15 @@ size_t emitPE(Binary *B, const MappingSet &mappings, size_t mapping_size)
404407 * Windows ASLR depends on text relocations, which is not compatible with
405408 * static binary rewriting. Thus, it must be disabled...
406409 */
407- bool have_relocs =
408- (opt_hdr->DllCharacteristics & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE)
409- != 0 ;
410410 uint32_t relocs =
411411 opt_hdr->DataDirectory [IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress ;
412412 uint32_t relocs_size =
413413 opt_hdr->DataDirectory [IMAGE_DIRECTORY_ENTRY_BASERELOC].Size ;
414+ bool have_relocs =
415+ ((file_hdr->Characteristics & IMAGE_FILE_RELOCS_STRIPPED) == 0 ) &&
416+ ((opt_hdr->DllCharacteristics & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE)
417+ != 0 ) &&
418+ relocs != 0x0 && relocs_size > 0 ;
414419 opt_hdr->DllCharacteristics &= ~IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE;
415420 opt_hdr->DataDirectory [IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0 ;
416421 opt_hdr->DataDirectory [IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0 ;
@@ -419,24 +424,33 @@ size_t emitPE(Binary *B, const MappingSet &mappings, size_t mapping_size)
419424 /*
420425 * Rebase the exectuable (if necessary).
421426 */
427+ intptr_t image_base_min = 0x100000000 ;
428+ if ((option_mem_rebase == 0 || !have_relocs) &&
429+ image_base < image_base_min)
430+ error (" failed to parse PE file \" %s\" ; image base (0x%lx) must be "
431+ " (>=0x%lx)%s" , B->filename , image_base, image_base_min,
432+ (have_relocs? " (hint: see the `--mem-rebase' option)" :
433+ " , but relocations are stripped" ));
422434 const uint8_t *relocs_base = findPEData (B, relocs);
423435 intptr_t rebase_delta = 0 ;
424436 switch (option_mem_rebase)
425437 {
426- case - 1 :
438+ case OPTION_REBASE_AUTO: case OPTION_REBASE_RANDOM :
427439 {
428440 // Auto rebase
429441 uint64_t lo = 0x100000000000ull , hi = 0xB00000000000ull ;
430- uint64_t base = hash (B->filename ) % (hi - lo) + lo;
442+ uint64_t r = (option_mem_rebase == OPTION_REBASE_AUTO?
443+ hash (B->filename ): random (B->filename ));
444+ uint64_t base = r % (hi - lo) + lo;
431445 base -= base % mapping_align;
432- rebase_delta = (intptr_t )base - ( intptr_t )opt_hdr-> ImageBase ;
446+ rebase_delta = (intptr_t )base - image_base ;
433447 break ;
434448 }
435- case 0 :
449+ case OPTION_REBASE_NONE :
436450 // No rebase
437451 break ;
438452 default :
439- rebase_delta = option_mem_rebase - ( intptr_t )opt_hdr-> ImageBase ;
453+ rebase_delta = option_mem_rebase - image_base ;
440454 break ;
441455 }
442456 if (rebase_delta != 0 && !have_relocs)
0 commit comments