from etl.parsers.etw.core import Etw, build_etw, Guid as EtwGuid from etl.utils import Guid WinTraceHeader = Struct( "size" / Int16ul, "marker" / Const(0x9000, Int16ul), "event_id" / Int16ul, "flags" / Int16ul, "provider_id" / Guid, "thread_id" / Int32ul, "process_id" / Int32ul ) WinTraceRecord = AlignedStruct(8, "mark1" / Computed(lambda this: this._io.tell()), "event_header" / WinTraceHeader, "mark2" / Computed(lambda this: this._io.tell()), "user_data" / Bytes(lambda this: this.event_header.size - (this.mark2 - this.mark1)) ) class WinTrace: """ This is a python wrapper around construct struct to access interesting fields """ def __init__(self, source: Container): """ :param source Container: The EventTraceRecord Container once it's parsed """ self.source = source
"flags" / EventHeaderFlag, "event_property" / EventHeaderPropertyFlag, "thread_id" / Int32ul, "process_id" / Int32ul, "timestamp" / Int64ul, "provider_id" / Guid, "event_descriptor" / EventDescriptor, "processor_time" / Int64ul, "activity_id" / Guid) EventHeaderExtendedDataItem = Struct( "reserved1" / Int16ul, "ext_type" / Int16ul, "reserved2" / Int16ul, "data_size" / Int16ul, "data_item" / Bytes(lambda this: this.data_size)) EventRecord = AlignedStruct( 8, "mark1" / Computed(lambda this: this._io.tell()), "event_header" / EventHeader, "extended_data" / If( lambda this: this.event_header.flags.EVENT_HEADER_FLAG_EXTENDED_INFO, RepeatUntil(lambda el, lst, this: not lst[-1].reserved2 & 0x1, Aligned(8, EventHeaderExtendedDataItem))), "mark2" / Computed(lambda this: this._io.tell()), "user_data" / Bytes(lambda this: this.event_header.marker.version - (this.mark2 - this.mark1))) class Event: """ This is a python wrapper around construct struct to access interesting fields """ def __init__(self, source): self.source = source def get_process_id(self): """
'p_flags' / Int32ul, 'p_align' / Int32ul, ) ElfHeaderTables = Struct( 'elf_header' / ElfHeader, 'program_headers' / Pointer(this.elf_header.e_phoff, ProgramHeader[this.elf_header.e_phnum]), 'section_headers' / Pointer(this.elf_header.e_shoff, SectionHeader[this.elf_header.e_shnum]), ) NoteSection = AlignedStruct( 4, 'namesz' / Int32ul, 'descsz' / Int32ul, 'type' / Int32ul, 'name' / Bytes(this.namesz), 'desc' / Bytes(this.descsz), ) NoteSections = GreedyRange(NoteSection) class ElfFile(object): """ Elf class to a single elf file """ SHN_UNDEF = 0x00 SHT_PROGBITS = 0x01 SHT_STRTAB = 0x03
def _extract_bin_corefile(self): """ Creates core dump ELF file """ tcbsz_aligned = self._get_aligned_size(self.header.tcbsz) coredump_data_struct = Struct( 'tasks' / GreedyRange( AlignedStruct( 4, 'task_header' / TaskHeader, 'tcb' / Bytes(self.header.tcbsz), 'stack' / Bytes( abs_(this.task_header.stack_top - this.task_header.stack_end)), )), 'mem_seg_headers' / MemSegmentHeader[self.core_src.header.segs_num]) core_elf = ESPCoreDumpElfFile() notes = b'' core_dump_info_notes = b'' task_info_notes = b'' coredump_data = coredump_data_struct.parse(self.core_src.data) for i, task in enumerate(coredump_data.tasks): stack_len_aligned = self._get_aligned_size( abs(task.task_header.stack_top - task.task_header.stack_end)) task_status_kwargs = { 'task_index': i, 'task_flags': TASK_STATUS_CORRECT, 'task_tcb_addr': task.task_header.tcb_addr, 'task_stack_start': min(task.task_header.stack_top, task.task_header.stack_end), 'task_stack_len': stack_len_aligned, 'task_name': Padding(16).build( {} ) # currently we don't have task_name, keep it as padding } # Write TCB try: if self.target_method_cls.tcb_is_sane( task.task_header.tcb_addr, tcbsz_aligned): core_elf.add_segment(task.task_header.tcb_addr, task.tcb, ElfFile.PT_LOAD, ElfSegment.PF_R | ElfSegment.PF_W) elif task.task_header.tcb_addr and self.target_method_cls.addr_is_fake( task.task_header.tcb_addr): task_status_kwargs[ 'task_flags'] |= TASK_STATUS_TCB_CORRUPTED except ESPCoreDumpLoaderError as e: logging.warning( 'Skip TCB {} bytes @ 0x{:x}. (Reason: {})'.format( tcbsz_aligned, task.task_header.tcb_addr, e)) # Write stack try: if self.target_method_cls.stack_is_sane( task_status_kwargs['task_stack_start']): core_elf.add_segment( task_status_kwargs['task_stack_start'], task.stack, ElfFile.PT_LOAD, ElfSegment.PF_R | ElfSegment.PF_W) elif task_status_kwargs['task_stack_start'] \ and self.target_method_cls.addr_is_fake(task_status_kwargs['task_stack_start']): task_status_kwargs[ 'task_flags'] |= TASK_STATUS_TCB_CORRUPTED core_elf.add_segment( task_status_kwargs['task_stack_start'], task.stack, ElfFile.PT_LOAD, ElfSegment.PF_R | ElfSegment.PF_W) except ESPCoreDumpLoaderError as e: logging.warning( 'Skip task\'s ({:x}) stack {} bytes @ 0x{:x}. (Reason: {})' .format(task_status_kwargs['tcb_addr'], task_status_kwargs['stack_len_aligned'], task_status_kwargs['stack_base'], e)) try: logging.debug('Stack start_end: 0x{:x} @ 0x{:x}'.format( task.task_header.stack_top, task.task_header.stack_end)) task_regs, extra_regs = self.arch_method_cls.get_registers_from_stack( task.stack, task.task_header.stack_end > task.task_header.stack_top) except Exception as e: raise ESPCoreDumpLoaderError(str(e)) task_info_notes += self._build_note_section( 'TASK_INFO', ESPCoreDumpElfFile.PT_TASK_INFO, EspTaskStatus.build(task_status_kwargs)) notes += self._build_note_section( 'CORE', ElfFile.PT_LOAD, self.arch_method_cls.build_prstatus_data( task.task_header.tcb_addr, task_regs)) if extra_regs and len(core_dump_info_notes) == 0: # actually there will be only one such note - for crashed task core_dump_info_notes += self._build_note_section( 'ESP_CORE_DUMP_INFO', ESPCoreDumpElfFile.PT_INFO, Int32ul.build(self.header.ver)) exc_regs = [] for reg_id in extra_regs: exc_regs.extend([reg_id, extra_regs[reg_id]]) _regs = [task.task_header.tcb_addr] + exc_regs core_dump_info_notes += self._build_note_section( 'EXTRA_INFO', ESPCoreDumpElfFile.PT_EXTRA_INFO, Int32ul[1 + len(exc_regs)].build(_regs)) if self.dump_ver == self.BIN_V2: for header in coredump_data.mem_seg_headers: logging.debug('Read memory segment {} bytes @ 0x{:x}'.format( header.mem_sz, header.mem_start)) core_elf.add_segment(header.mem_start, header.data, ElfFile.PT_LOAD, ElfSegment.PF_R | ElfSegment.PF_W) # add notes try: core_elf.add_segment(0, notes, ElfFile.PT_NOTE, 0) except ESPCoreDumpLoaderError as e: logging.warning( 'Skip NOTES segment {:d} bytes @ 0x{:x}. (Reason: {})'.format( len(notes), 0, e)) # add core dump info notes try: core_elf.add_segment(0, core_dump_info_notes, ElfFile.PT_NOTE, 0) except ESPCoreDumpLoaderError as e: logging.warning( 'Skip core dump info NOTES segment {:d} bytes @ 0x{:x}. (Reason: {})' .format(len(core_dump_info_notes), 0, e)) try: core_elf.add_segment(0, task_info_notes, ElfFile.PT_NOTE, 0) except ESPCoreDumpLoaderError as e: logging.warning( 'Skip failed tasks info NOTES segment {:d} bytes @ 0x{:x}. (Reason: {})' .format(len(task_info_notes), 0, e)) # dump core ELF core_elf.e_type = ElfFile.ET_CORE core_elf.e_machine = ESPCoreDumpElfFile.EM_XTENSA core_elf.dump(self.core_elf_file.name)