class TestGreedyRange(unittest.TestCase): def setUp(self): self.c = GreedyRange(UBInt8("foo")) def test_trivial(self): pass def test_empty_parse(self): self.assertRaises(RangeError, self.c.parse, six.b("")) def test_parse(self): self.assertEqual(self.c.parse(six.b("\x01")), [1]) self.assertEqual(self.c.parse(six.b("\x01\x02\x03")), [1, 2, 3]) self.assertEqual(self.c.parse(six.b("\x01\x02\x03\x04\x05\x06")), [1, 2, 3, 4, 5, 6]) def test_empty_build(self): self.assertRaises(RangeError, self.c.build, []) def test_build(self): self.assertEqual(self.c.build([1, 2]), six.b("\x01\x02"))
def info_corefile(): """ Command to load core dump from file or flash and print it's data in user friendly form """ core_filename, loader = core_prepare() exe_elf = ElfFile(args.prog) core_elf = ESPCoreDumpElfFile(core_filename) if exe_elf.e_machine != core_elf.e_machine: raise ValueError( 'The arch should be the same between core elf and exe elf') if core_elf.e_machine == ESPCoreDumpElfFile.EM_XTENSA: exception_registers_info = xtensa.print_exc_regs_info else: raise NotImplementedError extra_note = None task_info = [] for seg in core_elf.note_segments: for note_sec in seg.note_secs: if note_sec.type == ESPCoreDumpElfFile.PT_EXTRA_INFO and 'EXTRA_INFO' in note_sec.name.decode( 'ascii'): extra_note = note_sec if note_sec.type == ESPCoreDumpElfFile.PT_TASK_INFO and 'TASK_INFO' in note_sec.name.decode( 'ascii'): task_info_struct = EspTaskStatus.parse(note_sec.desc) task_info.append(task_info_struct) print('===============================================================') print('==================== ESP32 CORE DUMP START ====================') rom_elf, rom_sym_cmd = load_aux_elf(args.rom_elf) gdb = EspGDB(args.gdb, [rom_sym_cmd], core_filename, args.prog, timeout_sec=args.gdb_timeout_sec) extra_info = None if extra_note: extra_info = Struct('regs' / GreedyRange(Int32ul)).parse( extra_note.desc).regs marker = extra_info[0] if marker == ESPCoreDumpElfFile.CURR_TASK_MARKER: print('\nCrashed task has been skipped.') else: task_name = gdb.get_freertos_task_name(marker) print( "\nCrashed task handle: 0x%x, name: '%s', GDB name: 'process %d'" % (marker, task_name, marker)) print('\n================== CURRENT THREAD REGISTERS ===================') if extra_note and extra_info: exception_registers_info(extra_info) else: print('Exception registers have not been found!') print(gdb.run_cmd('info registers')) print('\n==================== CURRENT THREAD STACK =====================') print(gdb.run_cmd('bt')) if task_info and task_info[0].task_flags != TASK_STATUS_CORRECT: print('The current crashed task is corrupted.') print('Task #%d info: flags, tcb, stack (%x, %x, %x).' % (task_info[0].task_index, task_info[0].task_flags, task_info[0].task_tcb_addr, task_info[0].task_stack_start)) print('\n======================== THREADS INFO =========================') print(gdb.run_cmd('info threads')) # THREADS STACKS threads, _ = gdb.get_thread_info() for thr in threads: thr_id = int(thr['id']) tcb_addr = gdb.gdb2freertos_thread_id(thr['target-id']) task_index = int(thr_id) - 1 task_name = gdb.get_freertos_task_name(tcb_addr) gdb.switch_thread(thr_id) print( '\n==================== THREAD {} (TCB: 0x{:x}, name: \'{}\') =====================' .format(thr_id, tcb_addr, task_name)) print(gdb.run_cmd('bt')) if task_info and task_info[ task_index].task_flags != TASK_STATUS_CORRECT: print("The task '%s' is corrupted." % thr_id) print('Task #%d info: flags, tcb, stack (%x, %x, %x).' % (task_info[task_index].task_index, task_info[task_index].task_flags, task_info[task_index].task_tcb_addr, task_info[task_index].task_stack_start)) print( '\n\n======================= ALL MEMORY REGIONS ========================' ) print('Name Address Size Attrs') merged_segs = [] core_segs = core_elf.load_segments for sec in exe_elf.sections: merged = False for seg in core_segs: if seg.addr <= sec.addr <= seg.addr + len(seg.data): # sec: |XXXXXXXXXX| # seg: |...XXX.............| seg_addr = seg.addr if seg.addr + len(seg.data) <= sec.addr + len(sec.data): # sec: |XXXXXXXXXX| # seg: |XXXXXXXXXXX...| # merged: |XXXXXXXXXXXXXX| seg_len = len(sec.data) + (sec.addr - seg.addr) else: # sec: |XXXXXXXXXX| # seg: |XXXXXXXXXXXXXXXXX| # merged: |XXXXXXXXXXXXXXXXX| seg_len = len(seg.data) merged_segs.append( (sec.name, seg_addr, seg_len, sec.attr_str(), True)) core_segs.remove(seg) merged = True elif sec.addr <= seg.addr <= sec.addr + len(sec.data): # sec: |XXXXXXXXXX| # seg: |...XXX.............| seg_addr = sec.addr if (seg.addr + len(seg.data)) >= (sec.addr + len(sec.data)): # sec: |XXXXXXXXXX| # seg: |..XXXXXXXXXXX| # merged: |XXXXXXXXXXXXX| seg_len = len(sec.data) + (seg.addr + len(seg.data)) - ( sec.addr + len(sec.data)) else: # sec: |XXXXXXXXXX| # seg: |XXXXXX| # merged: |XXXXXXXXXX| seg_len = len(sec.data) merged_segs.append( (sec.name, seg_addr, seg_len, sec.attr_str(), True)) core_segs.remove(seg) merged = True if not merged: merged_segs.append( (sec.name, sec.addr, len(sec.data), sec.attr_str(), False)) for ms in merged_segs: print('%s 0x%x 0x%x %s' % (ms[0], ms[1], ms[2], ms[3])) for cs in core_segs: # core dump exec segments are from ROM, other are belong to tasks (TCB or stack) if cs.flags & ElfSegment.PF_X: seg_name = 'rom.text' else: seg_name = 'tasks.data' print('.coredump.%s 0x%x 0x%x %s' % (seg_name, cs.addr, len(cs.data), cs.attr_str())) if args.print_mem: print( '\n====================== CORE DUMP MEMORY CONTENTS ========================' ) for cs in core_elf.load_segments: # core dump exec segments are from ROM, other are belong to tasks (TCB or stack) if cs.flags & ElfSegment.PF_X: seg_name = 'rom.text' else: seg_name = 'tasks.data' print('.coredump.%s 0x%x 0x%x %s' % (seg_name, cs.addr, len(cs.data), cs.attr_str())) print(gdb.run_cmd('x/%dx 0x%x' % (len(cs.data) // 4, cs.addr))) print('\n===================== ESP32 CORE DUMP END =====================') print('===============================================================') del gdb print('Done!')
# estimote frames ESTIMOTE_UUID: Switch(lambda ctx: ctx.frame_type & 0xF, { ESTIMOTE_TELEMETRY_FRAME: EstimoteTelemetryFrame, }), }), ) LTV = Struct( "length" / Byte, "type" / Byte, "value" / Switch(lambda ctx: ctx.type, { FLAGS_DATA_TYPE: BitStruct( "reserved" / BitsInteger(3), "le_br_edr_support_host" / Flag, "le_br_edr_support_controller" / Flag, "br_edr_not_supported" / Flag, "le_general_discoverable_mode" / Flag, "le_limited_discoverable_mode" / Flag, ), COMPLETE_SERVICE_UUIDS_DATA_TYPE: OneOf(Bytes(2), [EDDYSTONE_UUID, ESTIMOTE_UUID]), SERVICE_DATA_TYPE: ServiceData }, default=Array(lambda ctx: ctx.length - 1, Byte)), ) LTVFrame = GreedyRange(LTV)
from PyCRC.CRCCCITT import CRCCCITT TIME_FORMAT = '%Y-%m-%d;%H:%M' crc16 = lambda val: '{:04x}'.format(CRCCCITT().calculate(val)).upper() TabTerminated = CString(terminators=b'\x09', encoding='cp1250') PosnetParameter = Struct( 'name' / Select(Const('@'), Const('?'), String(length=2)), 'value' / TabTerminated) PosnetFrame = Struct( Const(b'\x02'), 'summed' / RawCopy( Struct('instruction' / TabTerminated, 'parameters' / GreedyRange(PosnetParameter))), Const('#'), 'crc' / Checksum(Bytes(4), crc16, 'summed'), Const('\x03'), 'instruction' / Computed(this.summed.value.instruction), 'parameters' / Computed(this.summed.value.parameters)) def build_frame(instruction, *params): ''' Helper for building Posnet protocol frames out of instructions and params passed as (name, value) tuples. Can't use **kwargs: Posnet protocol uses reserved chars (such as @ and ?) ''' data = Container(summed=Container( value=Container(instruction=instruction, parameters=[ Container(name=name, value=value)
Array(8, UBInt8("serial_number")), Array(3, UBInt8("build")), UBInt8("watchdog"), \ UBInt32("free_ram"), UBInt32("free_print_mem"), UBInt32("free_page_mem"), UBInt8("machine_type")) struct_led = Struct("led", UBInt8("leds"), UBInt8("color"), UBInt16("period"), UBInt16("timeout")) struct_printer_get_status = Struct("printer_get_status", UBInt8("paper_out_1"), UBInt8("paper_out_2"), \ UBInt8("lever_open")) struct_print_buffer = Struct("print_buffer", UBInt16("size"), Array(lambda c: c.size, UBInt8("stream")), \ UBInt8("do_print"), UBInt8("clear_buffer")) struct_tags_list = Struct("tags_list", UBInt8("number"), Array(lambda c: c.number, Array(8, UBInt8("serial_number"))), \ Array(lambda ctx: ctx.number, Array(1, UBInt8("reception_level")))) struct_rfid_block = Struct("rfid_block", Array(4, UBInt8("bytes"))) struct_rfid_blocks = GreedyRange(struct_rfid_block) struct_read_block = Struct("read_block", Array(8, UBInt8("serial_number")), UBInt8("block")) struct_read_blocks = Struct("read_blocks", Embed(struct_read_block), UBInt8("number")) struct_write_block = Struct("write_block", Embed(struct_read_block), Embed(struct_rfid_block)) struct_write_blocks = Struct("write_blocks", Embed(struct_read_blocks), GreedyRange(struct_rfid_block)) struct_byte = Struct("byte", UBInt8("byte")) struct_security_status = GreedyRange(struct_byte)
), "length" / Int32ub, "padding" / Bytes(2), "device" / Bytes(6), "seq" / Int32ub, "xid" / Int32ub, ) PACKET = Struct( "version" / Int8ub, "flags" / BitStruct("msg_type" / Flag, "padding" / Padding(7)), "tsrc" / BitStruct( "crud_result" / BitsInteger(2), "action" / BitsInteger(14), ), "length" / Int32ub, "padding" / Bytes(2), "device" / Bytes(6), "seq" / Int32ub, "xid" / Int32ub, "tlvs" / GreedyRange(TLVS)) # TLV dicts PT_HELLO_SERVICE_PERIOD = 0x05 PT_CAPABILITIES_SERVICE_CELL = 0x06 PT_UE_REPORTS_SERVICE_IDENTITY = 0x07 HELLO_SERVICE_PERIOD = Struct("period" / Int32ub) HELLO_SERVICE_PERIOD.name = "hello_service_period" CAPABILITIES_SERVICE_CELL = Struct("pci" / Int16ub, "dl_earfcn" / Int32ub, "ul_earfcn" / Int32ub, "n_prbs" / Int8ub) CAPABILITIES_SERVICE_CELL.name = "capabilities_service_cell" UE_REPORTS_SERVICE_IDENTITY = Struct(
UBInt8("length"), # TODO: Reject packets of length 0 Array(lambda ctx: ctx.length, UBInt8("compression_methods")), ) ServerName = Struct( "", UBInt8("type"), PascalString("name", length_field=UBInt16("length")), ) SNIExtension = Struct( "", TunnelAdapter( PascalString("server_names", length_field=UBInt16("length")), TunnelAdapter(PascalString("", length_field=UBInt16("length")), GreedyRange(ServerName)), ), ) ALPNExtension = Struct( "", TunnelAdapter( PascalString("alpn_protocols", length_field=UBInt16("length")), TunnelAdapter(PascalString("", length_field=UBInt16("length")), GreedyRange(PascalString("name"))), ), ) UnknownExtension = Struct( "", PascalString("bytes", length_field=UBInt16("extensions_length")))
CompressionMethods = "compression_methods" / Struct( "length" / Int8ub, # TODO: Reject packets of length 0 Array(lambda ctx: ctx.length, "compression_methods" / Int8ub), ) ServerName = Struct( "type" / Int8ub, "name" / PascalString("length" / Int16ub), ) SNIExtension = Prefixed( Int16ub, Struct( Int16ub, "server_names" / GreedyRange("server_name" / Struct( "name_type" / Int8ub, "host_name" / PascalString("length" / Int16ub), )))) ALPNExtension = Prefixed( Int16ub, Struct( Int16ub, "alpn_protocols" / GreedyRange("name" / PascalString(Int8ub), ), )) UnknownExtension = Struct("bytes" / PascalString("length" / Int16ub)) Extension = "Extension" / Struct( "type" / Int16ub, Embedded( Switch(lambda ctx: ctx.type, {
LOAD_SEGMENT_CHUNK_HEADER_LENGTH = 3 MIN_PADDING_LENGTH = 1 SCP_MAC_LENGTH = 0xE LEDGER_HSM_URL = "https://hsmprod.hardwarewallet.com/hsm/process" LEDGER_HSM_KEY = "perso_11" ApduListAppsResponse = Struct( Const(b"\x01"), # Version apps=GreedyRange( Struct( # Application # Prefixed by the size of the structure, size included. _size=Rebuild(Int8ub, 1 + 4 + 32 + 32 + len_(this.name)), flags=Hex(Int32ub), code_data_hash=Bytes(32), full_hash=Bytes(32), name=PascalString(Int8ub, "utf-8"), )), ) VersionInfo = Struct( target_id=Hex(Int32ub), se_version=PascalString(Int8ub, "utf-8"), _flags_len=Const(b"\x04"), flags=FlagsEnum( Int32ul, recovery_mode=1, signed_mcu=2, is_onboarded=4,
Struct(Const('tag' / Int16ul, 5), 'value' / Float64l), encoder=lambda obj, ctx: Container(tag=obj.tag, value=obj.value), decoder=lambda obj, ctx: obj.value) DataList = Struct( 'size' / Int64ul, OnDemand(Array(lambda ctx: ctx.size, TaggedFloat64)), Const('\xc0\xff\xee\x01') # XXX: probably useful ) # XXX: hacks bad_strings = ('\xc0\xff\xee\x01\x00\x00', '\x01#Eg\x00\x00') Property = Struct( 'peek' / Peek(String(6)), Embedded( IfThenElse(this.peek in bad_strings, Padding(6), Struct('label' / VBString, 'TaggedData' / TaggedData)))) Properties = GreedyRange(Property) LabeledDataList = Struct('label' / VBString, Padding(18), 'DataList' / Embedded(DataList)) DataSet = Struct( 'number' / Int64ul, # XXX: may have more than two. Might use ctx.number to decide? 'LabeledDataList' / Array(2, LabeledDataList), 'Properties' / Properties) if __name__ == '__main__': def main(): ap = ArgumentParser() ap.add_argument('-v', '--verbose', action='store_true') ap.add_argument('--xml', action='store_true',
CLOSE, OPEN, HIGH, LOW, FUT, ] NUM_HEADER_BYTES = 0x4A0 OVERALL_ENTRY_BYTES = 40 TERMINATOR_DOUBLE_WORD_LENGTH = 4 Master = Struct( "Header" / Bytes(0x4A0), "Symbols" / GreedyRange( Struct("Symbol" / PaddedString(5, "ASCII"), "Rest" / Bytes(1172 - 5))), ) SymbolConstruct = Struct("Header" / Bytes(0x4A0), "Entries" / GreedyRange(BitsSwapped(EntryChunk))) class AmiSymbolFacade: def __init__(self, binary): self.data = binary pass def __setitem__(self, key, item): self.__dict__[key] = item def __getitem__(self, key):
) extras_header = "extras_header" / Struct( "count" / Int32ub, "sections" / Array(this.count, Select(productinfo_entry, extra_entry)), ) index_entry = "index_entry" / Struct( "offset" / Int32ub, "size" / Int32ub, "flags" / Int32ub, "name" / CString(encoding='ascii'), ) index_header = "index_header" / Struct( "entries" / Prefixed(Int32ub, GreedyRange(index_entry)), ) # Helper method to determine if a MAR file has signatures or not def _has_sigs(ctx): """Helper method to determine if a MAR file has a signature section or not. It does this by looking at where file data starts in the file. If this starts immediately after the headers (at offset 8), then it's an old style MAR that has no signatures or addiontal information blocks. Args: ctx (context): construct parsing context Returns: True if the MAR file has a signature section
def iter_values(self, as_json=False, max_len=MAX_LEN): """ Get the values of a subkey. Will raise if no values exist :param as_json: Whether to normalize the data as JSON or not :param max_len: Max length of value to return :return: List of values for the subkey """ if not self.values_count: return # Get the offset of the values key. We skip 4 because of Cell Header target_offset = REGF_HEADER_SIZE + 4 + self.header.values_list_offset self._stream.seek(target_offset) for _ in range(self.values_count): is_corrupted = False try: vk_offset = Int32ul.parse_stream(self._stream) except StreamError: logger.info( f'Skipping bad registry VK at {self._stream.tell()}') raise RegistryParsingException( f'Bad registry VK at {self._stream.tell()}') with boomerang_stream(self._stream) as substream: actual_vk_offset = REGF_HEADER_SIZE + 4 + vk_offset substream.seek(actual_vk_offset) try: vk = VALUE_KEY.parse_stream(substream) except (ConstError, StreamError): logger.error( f'Could not parse VK at {substream.tell()}, registry hive is probably corrupted.' ) return value = self.read_value(vk, substream) if vk.name_size == 0: value_name = '(default)' elif vk.flags.VALUE_COMP_NAME: # Compressed (ASCII) value name value_name = vk.name.decode('ascii', errors='replace') else: # Unicode (UTF-16) value name value_name = vk.name.decode('utf-16-le', errors='replace') logger.debug( f'Unicode value name identified: "{value_name}"') # If the value is bigger than this value, it means this is a DEVPROP structure # https://doxygen.reactos.org/d0/dba/devpropdef_8h_source.html # https://sourceforge.net/p/mingw-w64/mingw-w64/ci/668a1d3e85042c409e0c292e621b3dc0aa26177c/tree/ # mingw-w64-headers/include/devpropdef.h?diff=dd86a3b7594dadeef9d6a37c4b6be3ca42ef7e94 # We currently do not support these, but also wouldn't like to yield this as binary data # This int casting will always work because the data_type is construct's EnumIntegerString # TODO: Add actual parsing if int(vk.data_type) > 0xffff0000: data_type = int(vk.data_type) & 0xffff continue # Skip this unknown data type, research pending :) # TODO: Add actual parsing if int(vk.data_type) == 0x200000: continue data_type = str(vk.data_type) if data_type in ['REG_SZ', 'REG_EXPAND', 'REG_EXPAND_SZ']: if vk.data_size >= 0x80000000: # data is contained in the data_offset field value.size -= 0x80000000 actual_value = vk.data_offset elif vk.data_size > 0x3fd8 and value.value[:2] == b'db': data = self._parse_indirect_block(substream, value) actual_value = try_decode_binary(data, as_json=as_json) else: actual_value = try_decode_binary(value.value, as_json=as_json) elif data_type in ['REG_BINARY', 'REG_NONE']: if vk.data_size >= 0x80000000: # data is contained in the data_offset field actual_value = vk.data_offset elif vk.data_size > 0x3fd8 and value.value[:2] == b'db': try: actual_value = self._parse_indirect_block( substream, value) actual_value = try_decode_binary( actual_value, as_json=True) if as_json else actual_value except ConstError: logger.error(f'Bad value at {actual_vk_offset}') continue else: # Return the actual data actual_value = binascii.b2a_hex(value.value).decode( )[:max_len] if as_json else value.value elif data_type == 'REG_SZ': actual_value = try_decode_binary(value.value, as_json=as_json) elif data_type == 'REG_DWORD': # If the data size is bigger than 0x80000000, data is actually stored in the VK data offset. actual_value = vk.data_offset if vk.data_size >= 0x80000000 else Int32ul.parse( value.value) elif data_type == 'REG_QWORD': actual_value = vk.data_offset if vk.data_size >= 0x80000000 else Int64ul.parse( value.value) elif data_type == 'REG_MULTI_SZ': parsed_value = GreedyRange(CString('utf-16-le')).parse( value.value) # Because the ListContainer object returned by Construct cannot be turned into a list, # we do this trick actual_value = [x for x in parsed_value if x] # We currently dumps this as hex string or raw # TODO: Add actual parsing elif data_type in [ 'REG_RESOURCE_REQUIREMENTS_LIST', 'REG_RESOURCE_LIST' ]: actual_value = binascii.b2a_hex(value.value).decode( )[:max_len] if as_json else value.value else: actual_value = try_decode_binary(value.value, as_json=as_json) yield Value(name=value_name, value_type=str(value.value_type), value=actual_value, is_corrupted=is_corrupted)
def scan(self, data, file, options, expire_at): with io.BytesIO(data) as lnk_io: lnk_data = lnk_io.read() UnicodeString = "UnicodeString" / Struct( "Length" / Int32ul, "Characters" / StringEncoded(Bytes(this.Length * 2), "utf16")) LinkTargetIDList = "LinkTargetIDList" / Struct( "IDListSize" / Int16ul, "ItemID" / GreedyRange( Struct( "ItemIDSize" / Int16ul, "Data" / Bytes(this.ItemIDSize - 2), )), "TerminalID" / Int16ul) TypedPropertyValue = "TypedPropertyValue" / Struct( "Type" / Enum(Int16ul, VT_EMPTY=0x0000, VT_NULL=0x0001, VT_I2=0x0002, VT_I4=0x0003, VT_R4=0x0004, VT_R8=0x0005, VT_CY=0x0006, VT_DATE=0x0007, VT_BSTR=0x0008, VT_ERROR=0x000A, VT_BOOL=0x000B, VT_DECIMAL=0x000E, VT_I1=0x0010, VT_UI1=0x0011, VT_UI2=0x0012, VT_UI4=0x0013, VT_I8=0x0014, VT_UI8=0x0015, VT_INT=0x0016, VT_UINT=0x0017, VT_LPSTR=0x001E, VT_LPWSTR=0x001F, VT_FILETIME=0x0040, VT_BLOB=0x0041, VT_STREAM=0x0042, VT_STORAGE=0x0043, VT_STREAMED_Object=0x0044, VT_STORED_Object=0x0045, VT_BLOB_Object=0x0046, VT_CF=0x0047, VT_CLSID=0x0048, VT_VERSIONED_STREAM=0x0049, VT_I2_2=0x1002, VT_I4_2=0x1003, VT_R4_2=0x1004, VT_R8_2=0x1005, VT_CY_2=0x1006, VT_DATE_2=0x1007, VT_BSTR_2=0x1008, VT_ERROR_2=0x100A, VT_BOOL_2=0x100B, VT_VARIANT_2=0x100C, VT_I1_2=0x1010, VT_UI1_2=0x1011, VT_UI2_2=0x1012, VT_UI4_2=0x1013, VT_I8_2=0x1014, VT_UI8_2=0x1015, VT_LPSTR_2=0x101E, VT_LPWSTR_2=0x101F, VT_FILETIME_2=0x1040, VT_CF_2=0x1047, VT_CLSID_2=0x1048, VT_I2_3=0x2002, VT_I4_3=0x2003, VT_R4_3=0x2004, VT_R8_3=0x2005, VT_CY_3=0x2006, VT_DATE_3=0x2007, VT_BSTR_3=0x2008, VT_ERROR_3=0x200A, VT_BOOL_3=0x200B, VT_VARIANT_3=0x200C, VT_DECIMAL_3=0x200E, VT_I1_3=0x2010, VT_UI1_3=0x2011, VT_UI2_3=0x2012, VT_UI4_3=0x2013, VT_INT_3=0x2016, VT_UINT_3=0x2017), "Padding" / Bytes(2), # "Value" / If(this.Type=='VT_LPWSTR', UnicodeString) ) ExtraData = "ExtraData" / Struct( "BlockSize" / Int32ul, "BlockSignature" / Int32ul, "ConsoleDataBlock" / If( this.BlockSignature == 0xA0000002, Struct( "FileAttributes" / Enum(Int16ul, FOREGROUND_BLUE=0x001, FOREGROUND_GREEN=0x002, FOREGROUND_RED=0x004, FOREGROUND_INTENSITY=0x008, BACKGROUND_BLUE=0x010, BACKGROUND_GREEN=0x020, BACKGROUND_RED=0x040, BACKGROUND_INTENSITY=0x0080), "PopupFillAttributes" / Enum(Int16ul, FOREGROUND_BLUE=0x001, FOREGROUND_GREEN=0x002, FOREGROUND_RED=0x004, FOREGROUND_INTENSITY=0x008, BACKGROUND_BLUE=0x010, BACKGROUND_GREEN=0x020, BACKGROUND_RED=0x040, BACKGROUND_INTENSITY=0x0080), "ScreenBufferSizeX" / Int16ul, "ScreenBufferSizeY" / Int16ul, "WindowSizeX" / Int16ul, "WindowSizeY" / Int16ul, "WindowOriginX" / Int16ul, "WindowOriginY" / Int16ul, "Unused1" / Bytes(4), "Unused2" / Bytes(4), "FontSize" / Int32ul, "FontFamily" / Enum(Int32ul, FF_DONTCARE=0x0000, FF_ROMAN=0x0010, FF_SWISS=0x0020, FF_MODERN=0x0030, FF_SCRIPT=0x0040, FF_DECORATIVE=0x0050, TMPF_NONE=0x0000, TMPF_FIXED_PITCH=0x0001, TMPF_VECTOR=0x0002, TMPF_TRUETYPE=0x0004, TMPF_DEVICE=0x0004), "FontWeight" / Int32ul, "FaceName" / Bytes(64), "CursorSize" / Int32ul, "FullScreen" / Int32ul, "QuickEdit" / Int32ul, "InsertMode" / Int32ul, "AutoPosition" / Int32ul, "HistoryBufferSize" / Int32ul, "NumberOfHistoryBuffers" / Int32ul, "HistoryNoDup" / Int32ul, "ColorTable" / Bytes(64))), "ConsoleFEDataBlock" / If(this.BlockSignature == 0xA0000004, Struct("CodePage" / Int32ul)), "DarwinDataBlock" / If( this.BlockSignature == 0xA0000006, Struct("TargetAnsi" / CString("utf8"), "TargetUnicode" / CString("utf16"))), "EnvironmentVariableDataBlock" / If( this.BlockSignature == 0xA0000001, Struct("TargetAnsi" / CString("utf8"), "TargetUnicode" / CString("utf16"))), "IconEnvironmentDataBlock" / If( this.BlockSignature == 0xA0000007, Struct("TargetAnsi" / CString("utf8"), "TargetUnicode" / CString("utf16"))), "KnownFolderDataBlock" / If(this.BlockSignature == 0xA000000B, Struct( "KnownFolderID" / Bytes(16), "Offset" / Int32ul, )), "PropertyStoreDataBlock" / If( this.BlockSignature == 0xA0000009, Struct("PropertyStore" / Struct( # "StoreSize" / Int32ul, "SerializedPropertyStorage" / Struct( "StorageSize" / Int32ul, "Version" / Int32ul, "FormatID" / Bytes(16), "StringName" / IfThenElse( this.FormatID == b'\xd5\xcd\xd5\x05\x2e\x9c\x10\x1b\x93\x97\x08\x00\x2b\x2c\xf9\xae', Struct("ValueSize" / Int32ul, "NameSize" / Int32ul, "Reserved" / Bytes(1), "Name" / CString("utf16"), "TypedPropertyValue" / TypedPropertyValue), Struct("ValueSize" / Int32ul, "Id" / Int32ul, "Reserved" / Bytes(1), "TypedPropertyValue" / TypedPropertyValue)), )))), "ShimDataBlock" / If(this.BlockSignature == 0xA0000008, Struct("LayerName" / CString("utf16"))), "SpecialFolderDataBlock" / If( this.BlockSignature == 0xA0000005, Struct( "SpecialFolderID" / Int32ul, "Offset" / Int32ul, "LinkTargetIDList" / LinkTargetIDList, )), "TrackerDataBlock" / If( this.BlockSignature == 0xA0000003, Struct("Length" / Int32ul, "Version" / Int32ul, "MachineID" / Bytes(16), "Droid" / Bytes(32), "DroidBirth" / Bytes(32))), "VistaAndAboveIDListDataBlock" / If( this.BlockSignature == 0xA000000C, Struct( "ItemIDList" / GreedyRange( Struct( "ItemIDSize" / Int16ul, "Data" / Bytes(this.ItemIDSize - 2), )), "TerminalID" / Int16ul)), ) ShellLinkHeader = "ShellLinkHeader" / Struct( "HeaderSize" / Int32ul, "LinkCLSID" / Bytes(16), "LinkFlags" / BitsSwapped( BitStruct( "HasLinkTargetIDList" / Flag, "HasLinkInfo" / Flag, "HasName" / Flag, "HasRelativePath" / Flag, "HasWorkingDir" / Flag, "HasArguments" / Flag, "HasIconLocation" / Flag, "IsUnicode" / Flag, "ForceNoLinkInfo" / Flag, "HasExpString" / Flag, "RunInSeparateProcess" / Flag, "Unused1" / Flag, "HasDarwinID" / Flag, "RunAsUser" / Flag, "HasExpIcon" / Flag, "NoPidlAlias" / Flag, "Unused2" / Flag, "RunWithShimLayer" / Flag, "ForceNoLinkTrack" / Flag, "EnableTargetMetadata" / Flag, "DisableLinkPathTracking" / Flag, "DisableKnownFolderTracking" / Flag, "DisableKnownFolderAlias" / Flag, "AllowLinkToLink" / Flag, "UnaliasOnSave" / Flag, "PreferEnvironmentPath" / Flag, "KeepLocalIDListForUNCTarget" / Flag, Flag, Flag, Flag, Flag, Flag)), "FileAttributes" / BitsSwapped( BitStruct( "FILE_ATTRIBUTE_READONLY" / Flag, "FILE_ATTRIBUTE_READONLY" / Flag, "FILE_ATTRIBUTE_SYSTEM" / Flag, "Reserved1" / Flag, "FILE_ATTRIBUTE_DIRECTORY" / Flag, "FILE_ATTRIBUTE_ARCHIVE" / Flag, "Reserved2" / Flag, "FILE_ATTRIBUTE_NORMAL" / Flag, "FILE_ATTRIBUTE_TEMPORARY" / Flag, "FILE_ATTRIBUTE_SPARSE_FILE" / Flag, "FILE_ATTRIBUTE_REPARSE_POINT" / Flag, "FILE_ATTRIBUTE_COMPRESSED" / Flag, "FILE_ATTRIBUTE_OFFLINE" / Flag, "FILE_ATTRIBUTE_NOT_CONTENT_INDEXED" / Flag, "FILE_ATTRIBUTE_ENCRYPTED" / Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag)), "CreationTime" / Bytes(8), "AccessTime" / Bytes(8), "WriteTime" / Bytes(8), "FileSize" / Int32ul, "IconIndex" / Int32sl, "ShowCommand" / Enum( Int32ul, SW_HIDE=0x00000000, SW_NORMAL=0x00000001, SW_SHOWMINIMIZED=0x00000002, SW_SHOWMAXIMIZED=0x00000003, SW_SHOWNOACTIVATE=0x00000004, SW_SHOW=0x00000005, SW_MINIMIZE=0x00000006, SW_SHOWMINNOACTIVE=0x00000007, SW_SHOWNA=0x00000008, SW_RESTORE=0x00000009, SW_SHOWDEFAULT=0x0000000a, ), "HotKey" / Struct("LowByte" / Int8ul, "HighByte" / Int8ul), "Reserved1" / Bytes(2), "Reserved2" / Bytes(4), "Reserved3" / Bytes(4)) CommonNetworkRelativeLink = "CommonNetworkRelativeLink" / Struct( "CommonNetworkRelativeLinkSize" / Int32ul, "CommonNetworkRelativeLinkFlags" / BitsSwapped( BitStruct("ValidDevice" / Flag, "ValideNetType" / Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag)), "NetNameOffset" / Int32ul, "DeviceNameOffset" / Int32ul, "NetworkProviderType" / If( this.CommonNetworkRelativeLinkFlags.ValideNetType, Enum(Int32ul, WNNC_NET_AVID=0x001A0000, WNNC_NET_DOCUSPACE=0x001B0000, WNNC_NET_MANGOSOFT=0x001C0000, WNNC_NET_SERNET=0x001D0000, WNNC_NET_RIVERFRONT1=0X001E0000, WNNC_NET_RIVERFRONT2=0x001F0000, WNNC_NET_DECORB=0x0020000, WNNC_NET_PROTSTOR=0x00210000, WNNC_NET_FJ_REDIR=0x00220000, WNNC_NET_DISTINCT=0x00230000, WNNC_NET_TWINS=0x00240000, WNNC_NET_RDR2SAMPLE=0x00250000, WNNC_NET_CSC=0x00260000, WNNC_NET_3IN1=0x00270000, WNNC_NET_EXTENDNET=0x00290000, WNNC_NET_STAC=0x002A0000, WNNC_NET_FOXBAT=0x002B0000, WNNC_NET_YAHOO=0x002C0000, WNNC_NET_EXIFS=0x002D0000, WNNC_NET_DAV=0x002E0000, WNNC_NET_KNOWARE=0x002F0000, WNNC_NET_OBJECT_DIRE=0x00300000, WNNC_NET_MASFAX=0x00310000, WNNC_NET_HOB_NFS=0x00320000, WNNC_NET_SHIVA=0x00330000, WNNC_NET_IBMAL=0x00340000, WNNC_NET_LOCK=0x00350000, WNNC_NET_TERMSRV=0x00360000, WNNC_NET_SRT=0x00370000, WNNC_NET_QUINCY=0x00380000, WNNC_NET_OPENAFS=0x00390000, WNNC_NET_AVID1=0X003A0000, WNNC_NET_DFS=0x003B0000, WNNC_NET_KWNP=0x003C0000, WNNC_NET_ZENWORKS=0x003D0000, WNNC_NET_DRIVEONWEB=0x003E0000, WNNC_NET_VMWARE=0x003F0000, WNNC_NET_RSFX=0x00400000, WNNC_NET_MFILES=0x00410000, WNNC_NET_MS_NFS=0x00420000, WNNC_NET_GOOGLE=0x00430000)), If(this.NetNameOffset > 0x00000014, "NetNameOffsetUnicode" / Int32ul), If(this.NetNameOffset > 0x00000014, "DeviceNameOffsetUnicode" / Int32ul), "NetName" / CString("utf8"), If(this.NetNameOffset > 0x00000014, "DeviceName" / CString("utf8")), If(this.NetNameOffset > 0x00000014, "NetNameUnicode" / CString("utf16")), ) LinkInfo = "LinkInfo" / Struct( "LinkInfoSize" / Int32ul, "LinkInfoHeaderSize" / Int32ul, "LinkInfoFlags" / BitsSwapped( BitStruct("VolumeIDAndLocalBasePath" / Flag, "CommonNetworkRelativeLinkAndPathSuffix" / Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag, Flag)), "VolumeIDOffset" / Int32ul, "LocalBasePathOffset" / Int32ul, "CommonNetworkRelativeLinkOffset" / Int32ul, "CommonPathSuffixOffset" / Int32ul, "LocalBasePathOffsetUnicode" / If(this.LinkInfoHeaderSize >= 0x24, Int32ul), "CommonPathSuffixOffsetUnicode" / If(this.LinkInfoHeaderSize >= 0x24, Int32ul), "VolumeID" / Struct( "VolumeIDSize" / Int32ul, "DriveType" / Enum(Int32ul, DRIVE_UNKNOWN=0x00000000, DRIVE_NO_ROOT_DIR=0x00000001, DRIVE_REMOVABLE=0x00000002, DRIVE_FIXED=0x00000003, DRIVE_REMOTE=0x00000004, DRIVE_CDROM=0x00000005, DRIVE_RAMDISK=0x00000006), "DriveSerialNumber" / Int32ul, "VolumeLabelOffset" / Int32ul, "VolumeLabelOffsetUnicode" / If(this.VolumeLabelOffset == 0x14, Int32ul), "Data" / CString("utf8"), ), "LocalBasePath" / If(this.LinkInfoFlags.VolumeIDAndLocalBasePath, CString("utf8")), "CommonNetworkRelativeLink" / If(this.CommonNetworkRelativeLinkOffset, CommonNetworkRelativeLink), "CommonPathSuffix" / CString("utf8"), "LocalBasePathUnicode" / If(this.LinkInfoHeaderSize == 0x24, If(this.LocalBasePathOffsetUnicode, CString("utf16"))), "CommonPathSuffixUnicode" / If(this.LinkInfoHeaderSize == 0x24, If(this.CommonPathSuffixOffsetUnicode, CString("utf16"))), ) header = ShellLinkHeader.parse(lnk_data) offset = header.HeaderSize try: if header.LinkFlags.HasLinkTargetIDList: linktargetidlist = LinkTargetIDList.parse(data[offset:]) offset += linktargetidlist.IDListSize + 2 except: self.flags.append("Unable to parse LinkTargetIDList") try: if header.LinkFlags.HasLinkInfo: linkinfo = LinkInfo.parse(data[offset:]) if linkinfo.VolumeID.DriveType: self.event['DriveType'] = linkinfo.VolumeID.DriveType if linkinfo.VolumeID.DriveSerialNumber: self.event["DriveSerialNumber"] = '{0:x}'.format( linkinfo.VolumeID.DriveSerialNumber) if linkinfo.VolumeID.Data: self.event["VolumeLabel"] = linkinfo.VolumeID.Data if linkinfo.LocalBasePath: self.event["LocalBasePath"] = linkinfo.LocalBasePath if linkinfo.CommonNetworkRelativeLink: commonnetworkrelativelink = CommonNetworkRelativeLink.parse( data[offset + linkinfo.CommonNetworkRelativeLinkOffset:]) self.event["NetName"] = commonnetworkrelativelink.NetName offset += linkinfo.LinkInfoSize except: self.flags.append("Unable to parse LinkInfo") StringData = "StringData" / Struct( "CountCharacters" / Int16ul, "String" / IfThenElse(header.LinkFlags.IsUnicode, StringEncoded(Bytes(this.CountCharacters * 2), "utf16"), StringEncoded(Bytes(this.CountCharacters), "utf8"))) try: if header.LinkFlags.HasName: NAME_STRING = StringData.parse(data[offset:]) self.event["NAME_STRING"] = NAME_STRING.String if header.LinkFlags.IsUnicode: offset += (len(NAME_STRING.String) * 2 + 2) else: offset += (len(NAME_STRING.String) + 2) except: self.flags.append("Unable to parse NAME_STRING") try: if header.LinkFlags.HasRelativePath: RELATIVE_PATH = StringData.parse(data[offset:]) self.event["RELATIVE_PATH"] = RELATIVE_PATH.String if header.LinkFlags.IsUnicode: offset += (len(RELATIVE_PATH.String) * 2 + 2) else: offset += (len(RELATIVE_PATH.String) + 2) except: self.flags.append("Unable to parse RELATIVE_PATH") try: if header.LinkFlags.HasWorkingDir: WORKING_DIR = StringData.parse(data[offset:]) self.event["WORKING_DIR"] = WORKING_DIR.String if header.LinkFlags.IsUnicode: offset += (len(WORKING_DIR.String) * 2 + 2) else: offset += (len(WORKING_DIR.String) + 2) except: self.flags.append("Unable to parse WORKING_DIR") try: if header.LinkFlags.HasArguments: COMMAND_LINE_ARGUMENTS = StringData.parse(data[offset:]) self.event[ "COMMAND_LINE_ARGUMENTS"] = COMMAND_LINE_ARGUMENTS.String if header.LinkFlags.IsUnicode: offset += (len(COMMAND_LINE_ARGUMENTS.String) * 2 + 2) else: offset += (len(COMMAND_LINE_ARGUMENTS.String) + 2) except: self.flags.append("Unable to parse COMMAND_LINE_ARGUMENTS") try: if header.LinkFlags.HasIconLocation: ICON_LOCATION = StringData.parse(data[offset:]) self.event["ICON_LOCATION"] = ICON_LOCATION.String if header.LinkFlags.IsUnicode: offset += (len(ICON_LOCATION.String) * 2 + 2) else: offset += (len(ICON_LOCATION.String) + 2) except: self.flags.append("Unable to parse ICON_LOCATION") try: blocksize = True while blocksize: try: extradata = ExtraData.parse(data[offset:]) blocksize = extradata.BlockSize except: break try: if extradata.IconEnvironmentDataBlock: self.event[ "IconTarget"] = extradata.IconEnvironmentDataBlock.TargetAnsi except: self.flags.append( "Unable to parse IconEnvironmentDataBlock") if extradata.TrackerDataBlock: self.event[ "MachineID"] = extradata.TrackerDataBlock.MachineID.strip( b'\x00') self.event["MAC"] = str( uuid.UUID(bytes_le=extradata.TrackerDataBlock. Droid[16:])).split('-')[-1] offset += extradata.BlockSize except: self.flags.append("Unable to parse ExtraDataBlock")
"away" / IfThenElse(lambda ctx: ctx.mode.AWAY, AwayDataAdapter( Bytes(4)), Optional(Bytes(4))), "presets" / Optional( Struct( "window_open_temp" / TempAdapter(Int8ub), "window_open_time" / WindowOpenTimeAdapter(Int8ub), "comfort_temp" / TempAdapter(Int8ub), "eco_temp" / TempAdapter(Int8ub), "offset" / TempOffsetAdapter(Int8ub), ))) Schedule = "Schedule" / Struct( "cmd" / Enum(Int8ub, **NAME_TO_CMD), "day" / Enum(Int8ub, **NAME_TO_DAY), "base_temp" / TempAdapter(Int8ub), "next_change_at" / TimeAdapter(Int8ub), "hours" / GreedyRange( Struct( "target_temp" / TempAdapter(Int8ub), "next_change_at" / TimeAdapter(Int8ub), )), ) DeviceId = "DeviceId" / Struct( "cmd" / Const(PROP_ID_RETURN, Int8ub), "version" / Int8ub, Int8ub, Int8ub, "serial" / DeviceSerialAdapter(Bytes(10)), Int8ub, )
def setUp(self): self.c = GreedyRange(UBInt8("foo"))
from construct import Array, Embedded, GreedyRange, Struct, Tell from .fileheader import FileHeader from .page import AlignedPage PDBFile = Struct( Embedded(FileHeader), "pages" / GreedyRange(AlignedPage), "file_size" / Tell )