36
36
37
37
logger = get_logger ()
38
38
39
+ QNX_PADDING_SIZE = 4096
40
+ QNX_SECTION_NAME_PREFIX_BYTES = b"QNX_"
41
+
39
42
KERNEL_MODULE_SIGNATURE_INFO_LEN = 12
40
43
KERNEL_MODULE_SIGNATURE_FOOTER = b"~Module signature appended~\n "
41
44
@@ -371,6 +374,55 @@ def get_upx_end_offset(self, file: File, start_offset: int, end_offset: int) ->
371
374
# no matching UPX footer found
372
375
return end_offset
373
376
377
+ def get_end_offset_with_qnx_null_padding (
378
+ self , file : File , current_end_offset : int
379
+ ) -> int :
380
+ # Check for exactly one 4KB (4096 bytes) page of null bytes, QNX
381
+ # binaries are often padded this way.
382
+ if (
383
+ file [current_end_offset : current_end_offset + QNX_PADDING_SIZE ]
384
+ == b"\x00 " * QNX_PADDING_SIZE
385
+ ):
386
+ return current_end_offset + QNX_PADDING_SIZE
387
+ return current_end_offset
388
+
389
+ def is_qnx_elf (self , file : File , start_offset : int , header , endian ) -> bool :
390
+ # Preliminary checks for section header table validity
391
+ if (
392
+ header .e_shoff == 0
393
+ or header .e_shnum == 0
394
+ or header .e_shstrndx >= header .e_shnum
395
+ ):
396
+ return False
397
+
398
+ # Get the section header string table section
399
+ file .seek (
400
+ start_offset + header .e_shoff + header .e_shstrndx * header .e_shentsize ,
401
+ io .SEEK_SET ,
402
+ )
403
+ shstrtab_shdr = self ._struct_parser .parse (
404
+ self .SECTION_HEADER_STRUCT , file , endian
405
+ )
406
+
407
+ # Read the section header string table content
408
+ file .seek (start_offset + shstrtab_shdr .sh_offset , io .SEEK_SET )
409
+ shstrtab_content = file .read (shstrtab_shdr .sh_size )
410
+
411
+ # Iterate through all section headers
412
+ file .seek (start_offset + header .e_shoff , io .SEEK_SET )
413
+ for _ in range (header .e_shnum ):
414
+ section_header = self ._struct_parser .parse (
415
+ self .SECTION_HEADER_STRUCT , file , endian
416
+ )
417
+ # Get the section name from the string table
418
+ name_offset = section_header .sh_name
419
+ maybe_section_name_prefix = shstrtab_content [
420
+ name_offset : name_offset + len (QNX_SECTION_NAME_PREFIX_BYTES )
421
+ ]
422
+ if maybe_section_name_prefix == QNX_SECTION_NAME_PREFIX_BYTES :
423
+ return True
424
+ return False
425
+
374
426
def calculate_chunk (self , file : File , start_offset : int ) -> Optional [ElfChunk ]:
375
427
endian = self .get_endianness (file , start_offset )
376
428
file .seek (start_offset , io .SEEK_SET )
@@ -386,6 +438,9 @@ def calculate_chunk(self, file: File, start_offset: int) -> Optional[ElfChunk]:
386
438
if self .is_upx (file = file , start_offset = start_offset , end_offset = end_offset ):
387
439
end_offset = self .get_upx_end_offset (file , start_offset , end_offset )
388
440
441
+ if self .is_qnx_elf (file , start_offset , header , endian ):
442
+ end_offset = self .get_end_offset_with_qnx_null_padding (file , end_offset )
443
+
389
444
# do a special extraction of ELF files with ElfChunk
390
445
return ElfChunk (
391
446
start_offset = start_offset ,
0 commit comments