36
36
37
37
logger = get_logger ()
38
38
39
+ QNX_PADDING_SIZE = 4096
40
+ QNX_SECTION_NAME_PREFIX = "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,59 @@ 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
+ name_end_offset = shstrtab_content .find (b"\x00 " , name_offset )
420
+ if name_end_offset == - 1 :
421
+ name_end_offset = len (shstrtab_content )
422
+ section_name = shstrtab_content [name_offset :name_end_offset ].decode (
423
+ "utf-8" , errors = "ignore"
424
+ )
425
+
426
+ if section_name .startswith (QNX_SECTION_NAME_PREFIX ):
427
+ return True
428
+ return False
429
+
374
430
def calculate_chunk (self , file : File , start_offset : int ) -> Optional [ElfChunk ]:
375
431
endian = self .get_endianness (file , start_offset )
376
432
file .seek (start_offset , io .SEEK_SET )
@@ -386,6 +442,9 @@ def calculate_chunk(self, file: File, start_offset: int) -> Optional[ElfChunk]:
386
442
if self .is_upx (file = file , start_offset = start_offset , end_offset = end_offset ):
387
443
end_offset = self .get_upx_end_offset (file , start_offset , end_offset )
388
444
445
+ if self .is_qnx_elf (file , start_offset , header , endian ):
446
+ end_offset = self .get_end_offset_with_qnx_null_padding (file , end_offset )
447
+
389
448
# do a special extraction of ELF files with ElfChunk
390
449
return ElfChunk (
391
450
start_offset = start_offset ,
0 commit comments