예제 #1
0
 class ConstDefaultTest(DataclassMixin):
     const_bytes: bytes = csfield(cs.Const(b"BMP"))
     const_int: int = csfield(cs.Const(5, cs.Int8ub))
     default_int: int = csfield(cs.Default(cs.Int8ub, 28))
     default_lambda: bytes = csfield(
         cs.Default(cs.Bytes(cs.this.const_int),
                    lambda ctx: bytes(ctx.const_int)))
예제 #2
0
class JBSQ(ct.TContainerMixin):
    magic: Optional[bytes] = ct.sfield(
        c.Select(c.Const(b"IJBQ"), c.Const(b"IJSQ"), c.Const(b"JBSQ")))
    num_events: int = ct.sfield(c.Int32ul)
    combo: int = ct.sfield(c.Int32ul)
    end_time: int = ct.sfield(c.Int32ul)
    _1: None = ct.sfield(c.Padding(2))
    starting_buttons: int = ct.sfield(c.Int16ul)
    start_time: int = ct.sfield(c.Int32ul)
    _2: None = ct.sfield(c.Padding(12))
    density_graph: List[int] = ct.sfield(c.Byte[60])
    events: List[Event] = ct.sfield(
        c.Array(c.this.num_events, ct.TStruct(Event)))
예제 #3
0
 def __init__(self, const):
     self.const = const
     super().__init__(
         c.IfThenElse(
             c.this._building,
             c.Select(c.Bytes(len(self.const)), c.Pass),
             Optional(c.Const(const)),
         )
     )
def LifeScanPacket(include_link_control: bool, ) -> construct.Struct:  # pylint: disable=invalid-name
    if include_link_control:
        link_control_construct = _LINK_CONTROL
    else:
        link_control_construct = construct.Const(b"\x00")

    return construct.Struct(
        "data" / construct.RawCopy(
            construct.Struct(
                construct.Const(b"\x02"),  # stx
                "length" / construct.Rebuild(
                    construct.Byte, lambda this: len(this.message) + 6),
                "link_control" / link_control_construct,
                "message" / construct.Bytes(lambda this: this.length - 6),
                construct.Const(b"\x03"),  # etx
            ), ),
        "checksum" / construct.Checksum(construct.Int16ul, lifescan.crc_ccitt,
                                        construct.this.data.data),
    )
예제 #5
0
def LifeScanPacket(include_link_control):  # pylint: disable=invalid-name
    # type: (bool) -> construct.Struct
    if include_link_control:
        link_control_construct = _LINK_CONTROL
    else:
        link_control_construct = construct.Const(b'\x00')

    return construct.Struct(
        'data' / construct.RawCopy(
            construct.Struct(
                construct.Const(b'\x02'),  # stx
                'length' / construct.Rebuild(
                    construct.Byte, lambda this: len(this.message) + 6),
                'link_control' / link_control_construct,
                'message' / construct.Bytes(lambda this: this.length - 6),
                construct.Const(b'\x03'),  # etx
            ), ),
        'checksum' / construct.Checksum(construct.Int16ul, lifescan.crc_ccitt,
                                        construct.this.data.data),
    )
예제 #6
0
def LifeScanPacket(command_prefix, include_link_control):
    if include_link_control:
        link_control_construct = _LINK_CONTROL
    else:
        link_control_construct = construct.Const(b'\x00')

    command_prefix_construct = construct.Const(command_prefix, construct.Byte)

    return construct.Struct(
        'data' / construct.RawCopy(
            construct.Struct(
                construct.Const(b'\x02'),  # stx
                'length' / construct.Rebuild(
                    construct.Byte, lambda this: len(this.message) + 7),
                'link_control' / link_control_construct,
                'command_prefix' / command_prefix_construct,
                'message' / construct.Bytes(lambda this: this.length - 7),
                construct.Const(b'\x03'),  # etx
            ), ),
        'checksum' / construct.Checksum(construct.Int16ul, lifescan.crc_ccitt,
                                        construct.this.data.data),
    )
예제 #7
0
class GetDeviceQualifierDescriptorRequest(GetDescriptorRequest):

    DESCRIPTOR_NAME = "device qualifier"
    BINARY_FORMAT = DescriptorFormat(
        "bLength" / DescriptorField("Length"),
        "bDescriptorType" / DescriptorNumber(6),
        "bcdUSB" / DescriptorField("USB Version"),
        "bDeviceClass" / DescriptorField("Class"),
        "bDeviceSubclass" / DescriptorField("Subclass"),
        "bDeviceProtocol" / DescriptorField("Protocol"),
        "bMaxPacketSize0" / DescriptorField("EP0 Max Pkt Size"),
        "bNumConfigurations" / DescriptorField("Configuration Count"),
        "_bReserevd" / construct.Optional(construct.Const(b"\0")))
예제 #8
0
 def _bitmap_header_bytes():
     return construct.Struct(
         "Type" / construct.Const(b'\x42\x4D'),
         "BF_Size" / construct.
         Int32ul,  # File Header (14) + DIB Header (40) + Pixel Array
         "Reserved_1" / construct.Const(b'\x00\x00'),
         "Reserved_2" / construct.Const(b'\x00\x00'),
         "Pixel_Array_Offset" / construct.Const(b'\x36\x00\x00\x00'),
         "Header_Size" / construct.Const(b'\x28\x00\x00\x00'),  # DIB Header
         "Bitmap_Width" / construct.Int32ul,
         "Bitmap_Height" / construct.Int32ul,
         "Colour_Plane_Count" / construct.Const(b'\x01\x00'),
         "Bits_Per_Pixel" / construct.Int16ul,
         "Compression_Method" / construct.Const(b'\x00\x00\x00\x00'),
         "Bitmap_Size_In_Bytes" / construct.Int32ul,  # Pixel Array
         "Horizontal_Resolution_In_Pixels_Per_Meter" / construct.Int32ul,
         "Vertical_Resolution_In_Pixels_Per_Meter" / construct.Int32ul,
         "Color_Used" / construct.Const(b'\x00\x00\x00\x00'),
         "Important_Color" / construct.Const(b'\x00\x00\x00\x00'))
예제 #9
0
import binascii
import datetime
import logging

import construct

from glucometerutils import common
from glucometerutils.support import construct_extras
from glucometerutils.support import lifescan
from glucometerutils.support import lifescan_binary_protocol
from glucometerutils.support import serial

_PACKET = lifescan_binary_protocol.LifeScanPacket(False)

_COMMAND_SUCCESS = construct.Const(b'\x03\x06')

_VERSION_REQUEST = construct.Const(b'\x03\x0d\x01')

_VERSION_RESPONSE = construct.Struct(
    _COMMAND_SUCCESS,
    'version' / construct.PascalString(construct.Byte, encoding='ascii'),
    # NULL-termination is not included in string length.
    construct.Const(b'\x00'),
)

_SERIAL_NUMBER_REQUEST = construct.Const(b'\x03\x0b\x01\x02')

_SERIAL_NUMBER_RESPONSE = construct.Struct(
    _COMMAND_SUCCESS,
    'serial_number' / construct.CString(encoding='ascii'),
예제 #10
0
                            "height" / construct.Int16ul,
                            "data" / construct.GreedyBytes)

# cseg01:0002F528 66 81 7A 0E 57 52                       cmp     word ptr [edx+0Eh], 5257h
# cseg01:0002F52E 0F 85 A3 01 00 00                       jnz     loc_2F6D7
# cseg01:0002F534 66 C7 05 0C 9F 08 00 0D+                mov     error_num, 0Dh
# cseg01:0002F53D 66 83 7A 02 70                          cmp     word ptr [edx+2], 70h ; 'p
raw_file_2 = construct.Struct(
    "unk_word_00" / construct.Int16ul,  # + 0x00
    "version" / construct.Int16ul,  # + 0x02
    "ns_offset_00" / construct.Int16ul,  # + 0x04
    "ns_offset_01" / construct.Int16ul,  # + 0x06
    "ns_offset_02" / construct.Int16ul,  # + 0x08
    "field_A" / construct.Int16ul,
    "field_C" / construct.Int16ul,
    "signature" / construct.Const("\x57\x52"),
    "field_10" / construct.Int16ul,
    "field_12" / construct.Int16ul,
    "field_14" / construct.Int16ul,  # // length
    "field_16" / construct.Int16ul,
    "field_18" / construct.Int16ul,
    "field_1A" / construct.Int16ul)

obj_00 = construct.Struct(
    "unk_field_00" / construct.Int16ul,  # + 0x00
    "unk_field_02" / construct.Int16ul,  # + 0x02
    "unk_field_04" / construct.Int16ul,  # + 0x04
    "index_texture_up" / construct.Int16ul,  # + 0x06
    "index_texture_down" / construct.Int16ul,  # + 0x08
    "unk_field_0A" / construct.Int16ul,  # + 0x0A
    "unk_field_0C" / construct.Int8ul,  # + 0x0C
예제 #11
0
    MAT = (1 << 22)
    DTS_IV = (1 << 23)
    MPEG_4_HE_AAC = (1 << 24)
    MPEG_4_HE_AAC_V2 = (1 << 25)
    MPEG_4_AAC_LC = (1 << 26)
    DRA = (1 << 27)
    MPEG_4_HE_AAC_SURROUND = (1 << 28)
    MPEG_4_AAC_LC_SURROUND = (1 << 29)
    MPEG_H_3D_AUDIO = (1 << 30)
    AC4 = (1 << 31)
    MPEG_4_AAC_ELD = (1 << 32)


# As defined in [Audio30], Table 4-47
AudioControlInterruptEndpointDescriptor = DescriptorFormat(
    "bLength" / construct.Const(7, construct.Int8ul), "bDescriptorType" /
    DescriptorNumber(AudioClassSpecificStandardDescriptorNumbers.CS_ENDPOINT),
    "bEndpointAddress" / DescriptorField(
        description=
        "The address of the endpoint, use USBDirection.*.from_endpoint_address()"
    ), "bmAttributes" / DescriptorField(
        description="D1..0: Transfer type (0b11 = Interrupt)", default=0b11),
    "wMaxPacketSize" / DescriptorField(
        description=
        "Maximum packet size this endpoint is capable of. Used here to pass 6-byte interrupt information.",
        default=6), "bInterval" /
    DescriptorField(description="Interval for polling the Interrupt endpoint"))

# As defined in [Audio30], Table 4-51
AudioStreamingIsochronousEndpointDescriptor = DescriptorFormat(
    "bLength" / construct.Const(7, construct.Int8ul),
예제 #12
0
class SystemdJournalParser(interface.FileObjectParser):
  """Parses Systemd Journal files."""

  NAME = 'systemd_journal'

  DESCRIPTION = 'Parser for Systemd Journal files.'

  _OBJECT_COMPRESSED_FLAG = 0x00000001

  # Unfortunately this doesn't help us knowing about the "dirtiness" or
  # "corrupted" file state.
  # A file can be in any of these states and still be corrupted, for example, by
  # an unexpected shut down. Once journald detects one of these, it will
  # "rotate" the corrupted journal file, an store it away, and change the status
  # to STATE_OFFLINE.
  # STATE_ONLINE means the file wasn't closed, but the journal can still be in a
  # clean state.
  _JOURNAL_STATE = construct.Enum(
      construct.ULInt8('state'),
      STATE_OFFLINE=0,
      STATE_ONLINE=1,
      STATE_ARCHIVED=2
  )

  _OBJECT_HEADER_TYPE = construct.Enum(
      construct.ULInt8('type'),
      UNUSED=0,
      DATA=1,
      FIELD=2,
      ENTRY=3,
      DATA_HASH_TABLE=4,
      FIELD_HASH_TABLE=5,
      ENTRY_ARRAY=6,
      TAG=7
  )

  _ULInt64 = construct.ULInt64('int')

  _OBJECT_HEADER = construct.Struct(
      'object_header',
      _OBJECT_HEADER_TYPE,
      construct.ULInt8('flags'),
      construct.Bytes('reserved', 6),
      construct.ULInt64('size')
  )

  _OBJECT_HEADER_SIZE = _OBJECT_HEADER.sizeof()

  _DATA_OBJECT = construct.Struct(
      'data_object',
      construct.ULInt64('hash'),
      construct.ULInt64('next_hash_offset'),
      construct.ULInt64('next_field_offset'),
      construct.ULInt64('entry_offset'),
      construct.ULInt64('entry_array_offset'),
      construct.ULInt64('n_entries')
  )

  _DATA_OBJECT_SIZE = _DATA_OBJECT.sizeof()

  _ENTRY_ITEM = construct.Struct(
      'entry_item',
      construct.ULInt64('object_offset'),
      construct.ULInt64('hash')
  )

  _ENTRY_OBJECT = construct.Struct(
      'entry_object',
      construct.ULInt64('seqnum'),
      construct.ULInt64('realtime'),
      construct.ULInt64('monotonic'),
      construct.Struct(
          'boot_id',
          construct.Bytes('bytes', 16),
          construct.ULInt64('qword1'),
          construct.ULInt64('qword2')),
      construct.ULInt64('xor_hash'),
      construct.Rename('object_items', construct.GreedyRange(_ENTRY_ITEM))
  )

  _JOURNAL_HEADER = construct.Struct(
      'journal_header',
      construct.Const(construct.String('signature', 8), b'LPKSHHRH'),
      construct.ULInt32('compatible_flags'),
      construct.ULInt32('incompatible_flags'),
      _JOURNAL_STATE,
      construct.Bytes('reserved', 7),
      construct.Bytes('file_id', 16),
      construct.Bytes('machine_id', 16),
      construct.Bytes('boot_id', 16),
      construct.Bytes('seqnum_id', 16),
      construct.ULInt64('header_size'),
      construct.ULInt64('arena_size'),
      construct.ULInt64('data_hash_table_offset'),
      construct.ULInt64('data_hash_table_size'),
      construct.ULInt64('field_hash_table_offset'),
      construct.ULInt64('field_hash_table_size'),
      construct.ULInt64('tail_object_offset'),
      construct.ULInt64('n_objects'),
      construct.ULInt64('n_entries'),
      construct.ULInt64('tail_entry_seqnum'),
      construct.ULInt64('head_entry_seqnum'),
      construct.ULInt64('entry_array_offset'),
      construct.ULInt64('head_entry_realtime'),
      construct.ULInt64('tail_entry_realtime'),
      construct.ULInt64('tail_entry_monotonic'),
      # Added in format version 187
      construct.ULInt64('n_data'),
      construct.ULInt64('n_fields'),
      # Added in format version 189
      construct.ULInt64('n_tags'),
      construct.ULInt64('n_entry_arrays')
  )

  def __init__(self):
    """Initializes a parser object."""
    super(SystemdJournalParser, self).__init__()
    self._max_journal_file_offset = 0

  def _ParseObjectHeader(self, file_object, offset):
    """Parses a Systemd journal object header structure.

    Args:
      file_object (dfvfs.FileIO): a file-like object.
      offset (int): offset to the object header.

    Returns:
      tuple[construct.Struct, int]: parsed object header and size of the
          object payload (data) that follows.
    """
    file_object.seek(offset, os.SEEK_SET)
    object_header_data = file_object.read(self._OBJECT_HEADER_SIZE)
    object_header = self._OBJECT_HEADER.parse(object_header_data)
    payload_size = object_header.size - self._OBJECT_HEADER_SIZE
    return (object_header, payload_size)

  def _ParseItem(self, file_object, offset):
    """Parses a Systemd journal DATA object.

    This method will read, and decompress if needed, the content of a DATA
    object.

    Args:
      file_object (dfvfs.FileIO): a file-like object.
      offset (int): offset to the DATA object.

    Returns:
      tuple[str, str]: key and value of this item.

    Raises:
      ParseError: When an unexpected object type is parsed.
    """
    object_header, payload_size = self._ParseObjectHeader(file_object, offset)
    file_object.read(self._DATA_OBJECT_SIZE)

    if object_header.type != 'DATA':
      raise errors.ParseError(
          'Expected an object of type DATA, but got {0:s}'.format(
              object_header.type))

    event_data = file_object.read(payload_size - self._DATA_OBJECT_SIZE)
    if object_header.flags & self._OBJECT_COMPRESSED_FLAG:
      event_data = lzma.decompress(event_data)

    event_string = event_data.decode('utf-8')
    event_key, event_value = event_string.split('=', 1)
    return (event_key, event_value)

  def _ParseJournalEntry(self, parser_mediator, file_object, offset):
    """Parses a Systemd journal ENTRY object.

    This method will generate an event per ENTRY object.

    Args:
      parser_mediator (ParserMediator): parser mediator.
      file_object (dfvfs.FileIO): a file-like object.
      offset (int): offset of the ENTRY object.

    Raises:
      ParseError: When an unexpected object type is parsed.
    """
    object_header, payload_size = self._ParseObjectHeader(file_object, offset)

    entry_object_data = file_object.read(payload_size)
    entry_object = self._ENTRY_OBJECT.parse(entry_object_data)

    if object_header.type != 'ENTRY':
      raise errors.ParseError(
          'Expected an object of type ENTRY, but got {0:s}'.format(
              object_header.type))

    fields = {}
    for item in entry_object.object_items:
      if item.object_offset < self._max_journal_file_offset:
        raise errors.ParseError(
            'object offset should be after hash tables ({0:d} < {1:d})'.format(
                offset, self._max_journal_file_offset))
      key, value = self._ParseItem(file_object, item.object_offset)
      fields[key] = value

    reporter = fields.get('SYSLOG_IDENTIFIER', None)
    if reporter and reporter != 'kernel':
      pid = fields.get('_PID', fields.get('SYSLOG_PID', None))
    else:
      pid = None

    event_data = SystemdJournalEventData()
    event_data.body = fields['MESSAGE']
    event_data.hostname = fields['_HOSTNAME']
    event_data.pid = pid
    event_data.reporter = reporter

    date_time = dfdatetime_posix_time.PosixTimeInMicroseconds(
        timestamp=entry_object.realtime)
    event = time_events.DateTimeValuesEvent(
        date_time, definitions.TIME_DESCRIPTION_WRITTEN)
    parser_mediator.ProduceEventWithEventData(event, event_data)

  def _ParseEntries(self, file_object, offset):
    """Parses Systemd journal ENTRY_ARRAY objects.

    Args:
      file_object (dfvfs.FileIO): a file-like object.
      offset (int): offset of the ENTRY_ARRAY object.

    Returns:
      list[dict]: every ENTRY objects offsets.

    Raises:
      ParseError: When an unexpected object type is parsed.
    """
    entry_offsets = []
    object_header, payload_size = self._ParseObjectHeader(file_object, offset)

    if object_header.type != 'ENTRY_ARRAY':
      raise errors.ParseError(
          'Expected an object of type ENTRY_ARRAY, but got {0:s}'.format(
              object_header.type))

    next_array_offset = self._ULInt64.parse_stream(file_object)
    entry_offests_numbers, _ = divmod((payload_size - 8), 8)
    for entry_offset in range(entry_offests_numbers):
      entry_offset = self._ULInt64.parse_stream(file_object)
      if entry_offset != 0:
        entry_offsets.append(entry_offset)

    if next_array_offset != 0:
      next_entry_offsets = self._ParseEntries(file_object, next_array_offset)
      entry_offsets.extend(next_entry_offsets)

    return entry_offsets

  def ParseFileObject(self, parser_mediator, file_object, **kwargs):
    """Parses a Systemd journal file-like object.

    Args:
      parser_mediator (ParserMediator): parser mediator.
      file_object (dfvfs.FileIO): a file-like object.

    Raises:
      UnableToParseFile: when the header cannot be parsed.
    """
    try:
      journal_header = self._JOURNAL_HEADER.parse_stream(file_object)
    except construct.ConstructError as exception:
      raise errors.UnableToParseFile(
          'Unable to parse journal header with error: {0!s}'.format(exception))

    max_data_hash_table_offset = (
        journal_header.data_hash_table_offset +
        journal_header.data_hash_table_size)
    max_field_hash_table_offset = (
        journal_header.field_hash_table_offset +
        journal_header.field_hash_table_size)
    self._max_journal_file_offset = max(
        max_data_hash_table_offset, max_field_hash_table_offset)

    entries_offsets = self._ParseEntries(
        file_object, journal_header.entry_array_offset)

    for entry_offset in entries_offsets:
      try:
        self._ParseJournalEntry(parser_mediator, file_object, entry_offset)
      except errors.ParseError as exception:
        parser_mediator.ProduceExtractionError((
            'Unable to complete parsing journal file: {0:s} at offset '
            '0x{1:08x}').format(exception, entry_offset))
        return
      except construct.ConstructError as exception:
        raise errors.UnableToParseFile((
            'Unable to parse journal header at offset: 0x{0:08x} with '
            'error: {1:s}').format(entry_offset, exception))
예제 #13
0
        return (message[0] == message_type
                and (content is None or content == message[1]))

    return _matcher


_is_init_reply = _create_matcher(_INIT_RESPONSE, b'\x01')
_is_keepalive_response = _create_matcher(_KEEPALIVE_RESPONSE, b'\x05')
_is_uknown_message_error = _create_matcher(_UNKNOWN_MESSAGE_RESPONSE, b'\x85')
_is_encryption_missing_error = _create_matcher(_ENCRYPTION_SETUP_RESPONSE,
                                               b'\x15')
_is_encryption_setup_error = _create_matcher(_ENCRYPTION_SETUP_RESPONSE,
                                             b'\x14')

_FREESTYLE_MESSAGE = construct.Struct(
    'hid_report' / construct.Const(0, construct.Byte),
    'message_type' / construct.Byte,
    'command' / construct.Padded(
        63,  # command can only be up to 62 bytes, but one is used for length.
        construct.Prefixed(construct.Byte, construct.GreedyBytes)),
)

_FREESTYLE_ENCRYPTED_MESSAGE = construct.Struct(
    'hid_report' / construct.Const(0, construct.Byte),
    'message_type' / construct.Byte,
    'command' / construct.Padded(
        63,  # command can only be up to 62 bytes, but one is used for length.
        construct.GreedyBytes),
)

_TEXT_COMPLETION_RE = re.compile(b'CMD (?:OK|Fail!)')
예제 #14
0
from glucometerutils.support import serial


class Direction(enum.Enum):
    In = 0xa5
    Out = 0xa3


def byte_checksum(data):
    return functools.reduce(operator.add, data) & 0xFF


_PACKET = construct.Struct(
    'data' / construct.RawCopy(
        construct.Struct(
            construct.Const(b'\x51'),
            'command' / construct.Byte,
            'message' / construct.Bytes(4),
            'direction' /
            construct.Mapping(construct.Byte, {e: e.value
                                               for e in Direction}),
        ), ),
    'checksum' / construct.Checksum(construct.Byte, byte_checksum,
                                    construct.this.data.data),
)

_EMPTY_MESSAGE = 0

_CONNECT_REQUEST = 0x22
_VALID_CONNECT_RESPONSE = {0x22, 0x24, 0x54}
예제 #15
0
            "type" / CompactUint,
            "data" / Optional(c.GreedyBytes),
        )),
    "value" / c.Prefixed(CompactUint, c.GreedyBytes),
)

PsbtProprietaryKey = c.Struct(
    "prefix" / c.CString("utf-8"),
    "subtype" / CompactUint,
    "data" / Optional(c.GreedyBytes),
)

PsbtSequence = c.FocusedSeq(
    "content",
    "content" / c.GreedyRange(PsbtKeyValue),
    c.Const(b"\0"),
)

PsbtEnvelope = c.FocusedSeq(
    "sequences",
    "magic" / c.Const(b"psbt\xff"),
    "sequences" / c.GreedyRange(PsbtSequence),
    c.Terminated,
)

Bip32Field = c.Struct(
    "fingerprint" / c.Bytes(4),
    "address_n" / c.GreedyRange(c.Int32ul),
)
# fmt: on
예제 #16
0
    ETHERNET_NETWORKING_FUNCTIONAL = 0x0f
    ATM_NETWORKING_FUNCTIONAL = 0x10
    WIRELESS_HANDSET_CONTROL_MODEL_FUNCTIONAL = 0x11
    MOBILE_DIRECT_LINE_MODEL_FUNCTIONAL = 0x12
    MDLM_DETAIL_FUNCTIONAL = 0x13
    DEVICE_MANAGEMENT_MODEL_FUNCTIONAL = 0x14
    OBEX_FUNCTIONAL = 0x15
    COMMAND_SET_FUCNTIONAL = 0x16
    COMMAND_SET_DETAIL_FUNCTIONAL = 0x17
    TELEPHONE_CONTROL_MODEL_FUNCTIONAL = 0x18
    OBEX_SERVICE_IDENTIFIER_FUNCTIONAL = 0x19
    NCM_FUNCTIONAL = 0x1A


HeaderDescriptor = DescriptorFormat(
    "bLength" / construct.Const(5, construct.Int8ul),
    "bDescriptorType" / DescriptorNumber(CDCDescriptorNumbers.CS_INTERFACE),
    "bDescriptorSubtype" / DescriptorNumber(CDCDescriptorSubtypes.HEADER),
    "bcdCDC" / DescriptorField(description="CDC Version", default=1.1))

ACMFunctionalDescriptor = DescriptorFormat(
    "bLength" / construct.Const(4, construct.Int8ul),
    "bDescriptorType" / DescriptorNumber(CDCDescriptorNumbers.CS_INTERFACE),
    "bDescriptorSubtype" / DescriptorNumber(
        CDCDescriptorSubtypes.ABSTRACT_CONTROL_MANAGEMENT_FUNCTIONAL),
    "bmCapabilities" /
    DescriptorField(description="ACM Capabilities", default=0b0010))

UnionFunctionalDescriptor = DescriptorFormat(
    "bLength" / construct.Const(5, construct.Int8ul),
    "bDescriptorType" / DescriptorNumber(CDCDescriptorNumbers.CS_INTERFACE),
예제 #17
0
import construct as cst
import time
import sys

con = cst.Container  # alias

HEADER = cst.Struct('pc_header', cst.Magic('\x00'),
                    cst.Const(cst.UBInt8('lines'), 1), cst.UBInt8('address'),
                    cst.Magic('\x03'))

SER_STATUS = cst.BitStruct('serst', cst.Magic('\x01\x01\x00'),
                           cst.Flag('schedule_enabled'),
                           cst.Flag('ack_enabled'), cst.Flag('further_pages'),
                           cst.Flag('interrupt_mode'), cst.Magic('\x00'))

PAGE_IDX = cst.Bytes('page_num', 3)
TEMPO = cst.BitStruct(
    'tempo', cst.Magic('\x01\x01'),
    cst.Enum(cst.BitField('display_ctrl', 2), TIMED=0, FIXED_ON=1,
             FIXED_OFF=2),
    cst.Enum(cst.BitField('persist_time', 4),
             S2=1,
             S5=2,
             S10=3,
             S20=4,
             S30=5,
             S45=6,
             S60=7,
             S90=8,
             S120=9))
예제 #18
0
"""
    Handle packet data
"""
import attr
import construct as cs
from helper import Vector3
from constants import OpCode

packet = cs.Struct(
    "head" / cs.Const(b"\x99\xAA"),
    "len" / cs.Int32sl,
    "opcode" / cs.Int32sl,
    # subsctract the 4 byte (opcode) + len 4 byte + len 4 id
    "rest_data" / cs.Bytes(cs.this.len - 8),
    "end" / cs.Const(b"\xAA\x99"),
)

vector_packet = cs.Struct("X" / cs.Float32l, "Y" / cs.Float32l,
                          "Z" / cs.Float32l)

authentication_packet = cs.Struct(
    # "id" / cs.Int32sl,
    "username" / cs.PascalString(cs.Int32sl, "utf8"), )
"""
    TODO: find a way to re user packet parts
"""
send_vector_packet = cs.Struct(
    "head" / cs.Const(b"\x99\xAA"),
    "len" / cs.Int32sl,
    "opcode" / cs.Int32sl,  # 4
    "id" / cs.Int32sl,  # 4
예제 #19
0
    else:
        op = operator.add
    for b in data:
        yield op(b, rotation) % 256
        rotation = (rotation + per_byte_adjustment) % 256


def create_rotator(inverse: bool):
    return lambda obj, ctx: bytes(
        rotate_bytes(obj, ctx.header.bytes_rotation, ctx.header.bytes_rotation,
                     inverse))


PermalinkBinary = construct.FocusedSeq(
    "fields",
    schema_version=construct.Const(_CURRENT_SCHEMA_VERSION, construct.Byte),
    fields=construct.RawCopy(
        construct.Aligned(
            3,
            construct.Struct(
                header=construct.BitStruct(
                    has_seed_hash=construct.Rebuild(
                        construct.Flag, construct.this._.seed_hash != None),
                    bytes_rotation=construct.Rebuild(
                        construct.BitsInteger(7),
                        lambda ctx: single_byte_hash(ctx._.generator_params) >>
                        1,
                    )),
                seed_hash=construct.If(construct.this.header.has_seed_hash,
                                       construct.Bytes(5)),
                randovania_version=construct.Bytes(4),  # short git hash
예제 #20
0
import os
import repoze.lru
import signal
import struct
import sys
import traceback
import traffic_control

# Control message for our protocol; first few bits are special as we have to
# maintain compatibility with LTPv3 in the kernel (first bit must be 1); also
# the packet must be at least 12 bytes in length, otherwise some firewalls
# may filter it when used over port 53
ControlMessage = cs.Struct(
    "control",
    # Ensure that the first bit is 1 (L2TP control packet)
    cs.Const(cs.UBInt8("magic1"), 0x80),
    # Reduce conflict matching to other protocols as we run on port 53
    cs.Const(cs.UBInt16("magic2"), 0x73A7),
    # Protocol version to allow future upgrades
    cs.UBInt8("version"),
    # Message type
    cs.UBInt8("type"),
    # Message data (with length prefix)
    cs.PascalString("data"),
    # Pad the message so it is at least 12 bytes long
    cs.Padding(lambda ctx: max(0, 6 - len(ctx["data"]))),
)

# Unreliable messages (0x00 - 0x7F)
CONTROL_TYPE_COOKIE = 0x01
CONTROL_TYPE_PREPARE = 0x02
예제 #21
0
                           PKT_READCFG=0x37,
                           PKT_PARITYMODE=0x3F,
                           PKT_WRITE_I2C=0x44,
                           PKT_CLFCODECRESET=0x46,
                           PKT_SETCODECRESET=0x47,
                           PKT_DISCARDCODEC=0x48,
                           PKT_DELAYNUS=0x49,
                           PKT_DELAYNNS=0x4A,
                           PKT_RTSTHRESH=0x4E,
                           PKT_GAIN=0x4B)

ControlPacketField = c.Enum(c.Byte, **ControlPacketFields)

###############################################################################
# Generic Constructs
GeneralPacket = c.Struct("START_BYTE" / c.Const(b'\x61'), "LENGTH" / c.Int16ub,
                         "TYPE" / PacketType, "FIELDS" / c.Byte[c.this.LENGTH])

# Table 12 AMBE-3000R Version 2.2
ECMODE_IN = c.FlagsEnum(
    c.Int16ub,
    NS_ENABLE=(0x1 << 6),
    CP_SELECT=(0x1 << 7),
    CP_ENABLE=(0x1 << 8),
    ES_ENABLE=(0x1 << 9),
    DTX_ENABLE=(0x1 << 11),
    TD_ENABLE=(0x1 << 12),
    EC_ENABLE=(0x1 << 13),
    TS_ENABLE=(0x1 << 14),
)
예제 #22
0
 def __init__(self, const):
     self.const = const
     super().__init__(c.Optional(c.Const(const)))
예제 #23
0
        "data" / c.GreedyBytes,
    )),
    "value" / c.Prefixed(CompactUint, c.GreedyBytes),
    "ofs" / c.Tell,
)

Sequence = c.FocusedSeq("content",
    "content" / c.GreedyRange(
        c.FocusedSeq(
            "keyvalue",
            "terminator" / c.Peek(c.Byte),
            c.StopIf(c.this.terminator == 0),
            "keyvalue" / KeyValue,
        )
    ),
    c.Const(b'\0'),
)

PSBT = c.Struct(
    "magic" / c.Const(b'psbt'),
    "sep" / c.Const(b'\xff'),
    "general" / Sequence,
    "transaction" / c.RestreamData(c.this.general[0].value, Transaction),
    "inputs" / c.Array(c.len_(c.this.transaction.inputs), Sequence),
    "outputs" / c.Array(c.len_(c.this.transaction.outputs), Sequence),
    c.Terminated,
)

# key-less format:

ValueOnly = c.Prefixed(CompactUint, c.Struct(
예제 #24
0
class MasterBootRecord(BootRecord):
    _MBR_STRUCT = construct.Struct(
        "mbr",
        construct.HexDumpAdapter(construct.Bytes("bootloader_code", 440)),
        construct.Field('disk_signature', 4),
        construct.Padding(2),
        construct.Array(
            4,
            construct.Struct(
                "partitions",
                construct.SLInt8("state"),
                construct.BitStruct(
                    "beginning",
                    construct.Octet("head"),
                    construct.Bits("sect", 6),
                    construct.Bits("cyl", 10),
                ),
                construct.Enum(
                    construct.UBInt8("type"),
                    Nothing=0x00,
                    FAT12=0x01,
                    XENIX_ROOT=0x02,
                    XENIX_USR=0x03,
                    FAT16_old=0x04,
                    Extended_DOS=0x05,
                    FAT16=0x06,
                    FAT32=0x0b,
                    FAT32_LBA=0x0c,
                    NTFS=0x07,
                    LINUX_SWAP=0x82,
                    LINUX_NATIVE=0x83,
                    PROTECTIVE_MBR=0xee,
                    _default_=construct.Pass,
                ),
                construct.BitStruct(
                    "ending",
                    construct.Octet("head"),
                    construct.Bits("sect", 6),
                    construct.Bits("cyl", 10),
                ),
                construct.ULInt32(
                    "sector_offset"),  # offset from MBR in sectors
                construct.ULInt32("size"),  # in sectors
            )),
        construct.Const(construct.Bytes("signature", 2), '55aa'.decode('hex')),
    )

    def __init__(self, filePath, size, offset=None, whitelist=()):
        self._type = 'MBR'
        super(MasterBootRecord, self).__init__(filePath, size, offset,
                                               whitelist)

    def _parse(self):
        """
            Main method in charge of parsing the MBR.
            It will try to parse the boot record according to documented known structure and extract the partition table
            disk signature and code section.
            It will then try to narrow down invariant code, hash it and match the hash against a whitelist.
            If no match was found, it will try some simple heuristics to detect malicious behaviours.

        Returns: nothing

        """
        try:
            mbr = self._MBR_STRUCT.parse(self._raw)
        except construct.core.ConstructError as e:
            raise InvalidMBRError('Invalid MBR structure: {0}\n{1}'.format(
                e, hexdump(self._raw)))

        self._parsePartTable(mbr.partitions)

        # Windows stores the disk signature at 0x1B8, other MBRs seem to leave this area alone
        self._diskSignature = mbr.disk_signature

        # If code section is null, check for protective MBR signature (detected in partition table parsing). If found,
        # then the machine is likely using UEFI instead of BIOS to boot. If not, it could mean that the sample being
        # analyzed has been tampered by a bootkit
        if mbr.bootloader_code.encode('hex') == 440 * '00':
            if 'Protective MBR' in self._signature:
                self._signature.append('UEFI (no legacy boot code)')
            else:
                self._suspiciousBehaviour.append('Code section is null')
        else:
            expectedLoader, invariantCode = self._getInvariantCode(
                mbr.bootloader_code)
            codeHash = hashlib.sha256(invariantCode)
            self._matchHash(codeHash, expectedLoader)
            if len(self._signature) == 0:
                # No whitelisted signature matched, try some simple heuristics to flag this MBR as malicious
                # Note that the self._checkCode method is only given the "invariant" code section to help with the
                # disassembling. This will obviously leads to broken offsets, but it doesn't matter since the heuristics
                # don't use them.
                self._checkCode(invariantCode)

    def _parsePartTable(self, partitions):
        """
            Private method that parses the partition table of the MBR. Updates self._partTable list.

        Args:
            partitions: Construct.Container object of the partition table

        Returns: nothing
        """
        partNum = 0
        for part in partitions:
            partNum += 1
            # Assume a partition entry without size (in LBA) or type is invalid, and do not include it in the listing.
            if part.size != 0 and part.type != 'Nothing':
                self._partTable.append((partNum, part.state < 0, part.type,
                                        part.sector_offset, part.size))
            else:
                self._logger.debug('Ignoring invalid partition: %s', part)
            # Early detection of protective MBR so that we don't try to make sense of the MBR partition table
            if part.type == 'PROTECTIVE_MBR' and partNum == 1:
                self._logger.debug(
                    'Protective MBR detected, MBR partition table should not be taken into account. '
                    'GPT partition table parser not implemented yet')
                self._signature.append('Protective MBR')

    def _getInvariantCode(self, rawCode):
        """
            Helper method that tries to narrow down "invariant code" which can be hashed and compared to well known
            signatures. Most MBRs have localized error strings which must be excluded from the hash computation because
            they may vary from a country to another.
            First, this method tries to detect what kind of MBR it is dealing with. Most of the time, it is enough to
            to look for some known hardcoded strings that identify "well known" MBR (such as Truecrypt, GRUB2, etc...).
            Then, this method finds where the strings are and "removes" them (as in "does not include them").
            Finding these strings can be achieved by quickly studying the assembly code and looking for how these
            strings are echoed on screen at boot time (using interrupt 0x10).
            This research only needs to be done once for each type of MBR but requires an analyst to do it by static
            analysis. This script cannot take care of this. This method merely implements the results of such work.

            Currently supported MBR are:
             - Truecrypt
             - McAfee Endpoint Encryption (Safeboot)
             - GRUB2
             - Windows (XP to 10)

        Args:
            rawCode: str of the code section

        Returns: 2-tuple (unicode string of expected loader, concatenated strings of invariant sections of code)

        """
        # By default, assume all the MBR code section will be hashed. It is obviously wrong in most cases, but it allows
        # for a "default case" which will automatically matches no known hash in case something goes wrong with the
        # detection.
        codeStart = 0
        codeEnd = len(rawCode)
        expectedLoader = None
        invariantCode = str()

        # TrueCrypt (detected with the hardcoded string following the first jump: " TrueCrypt Boot Loader")
        if rawCode[0x5:0x1b].encode('hex').upper(
        ) == '2054727565437279707420426F6F74204C6F61646572':
            # TrueCrypt uses hardcoded and not-localized error strings. Therefore every TrueCrypt MBR should have the
            # same code from start to end
            expectedLoader = 'TrueCrypt MBR'

        # MacAfee SafeBoot (detected with the hardcoded string following the first jump: "Safeboot ")
        elif rawCode[0x3:0xc].encode('hex').upper() == '53616665426F6F7420':
            # Two versions have been seen but both start with a jump to the same offset (0x26).
            # There are some strings at the of the code section but localization is unlikely so it will be assumed
            # to be hardcoded (until a localized version is found...).
            # Therefore, Safeboot code can be hashed from 0x26 to the end of code section
            invariantCode += rawCode[:0x3]  # Hash the first JMP
            codeStart = 0x26
            expectedLoader = 'Safeboot MBR'

        # GRUB (detected with the hardcoded string "GRUB " located at 0x188)
        elif rawCode[0x188:0x18d].encode('hex').upper() == '4752554220':
            # GRUB has some error strings but they are hardcoded and not localized so they can be included in the hash
            # computation. However GRUB can be installed on a disk (MBR) as well as on a partition (in a kind of VBR).
            # But in both cases the code used is the same. Since a BPB is needed for the latter case it is also present
            # in the MBR (but not needed). It therefore has to be excluded from the hash computation.
            # GRUB is jumping over the BIOS Parameter Block located between 0x3 and 0x5a.
            # It should be followed by the kernel address (word), kernel sector (dword), kernel sector high (dword) and
            # boot drive (byte). Therefore the code really starts at 0x65.
            # These values are hardcoded in boot.img and have little chance to change anytime soon.
            codeStart = 0x65
            invariantCode += rawCode[:0x3]  # Hash the first JMP
            expectedLoader = 'GRUB2 MBR'

        # Windows MBR cannot be detected with hardcoded strings, so they fall in the default case and further checks
        # are then made based on the hypothesis that this is indeed a Windows MBR.
        else:
            # Starting with NT5.0, the MBR contains localized strings which must be excluded from the hash computation.
            # These strings are located after the code, at 3 different offsets which can be calculated by adding 0x100
            # to the values respectively stored in bytes 0x1b5, 0x1b6 and 0x1b7 (last bytes of the code section).
            # Eg: The first localized string is at : 0x100 + the value saved at offset 0x1B5
            # Even though localized strings can be of different lengths, the offset of the first one does not vary
            # given one Windows version. This can therefore be used to tell Windows versions apart.
            firstStrOffset = construct.UBInt8('FirstStringOffset').parse(
                rawCode[0x1b5])
            # Windows NT5
            if firstStrOffset == 0x2c:
                expectedLoader = 'NT5.1/NT5.2 MBR'
                codeEnd = 0x100 + firstStrOffset
            # Windows NT6.0
            elif firstStrOffset == 0x62:
                expectedLoader = 'NT6.0 MBR'
                codeEnd = 0x100 + firstStrOffset
            # Windows NT6.1+
            elif firstStrOffset == 0x63:
                expectedLoader = 'NT6.1+ MBR'
                codeEnd = 0x100 + firstStrOffset
            else:
                self._suspiciousBehaviour.append(
                    'Invalid string offset: {0:#x}'.format(firstStrOffset))
                self._logger.debug(
                    'First localized string offset is wrong for a windows MBR.'
                    'It should be 0x2c, 0x62 or 0x63) : {0:#x}'.format(
                        firstStrOffset))

        self._logger.debug(
            'Expecting {0}. Code starts at {1:#x} and ends at {2:#x}'.format(
                expectedLoader, codeStart, codeEnd))

        invariantCode += rawCode[codeStart:codeEnd]
        return expectedLoader, invariantCode

    def _checkCode(self, rawCode):
        md = capstone.Cs(capstone.CS_ARCH_X86, capstone.CS_MODE_16)
        md.detail = True

        checkJmp = True
        for i in md.disasm(rawCode, 0):
            # Check for JUMPs and CALLs before the first PUSH/RET.
            if checkJmp and len(i.groups) > 0:
                # Group check if available
                if hasattr(capstone.x86, 'X86_GRP_CALL') and hasattr(
                        capstone.x86, 'X86_GRP_RET'):
                    if capstone.x86.X86_GRP_CALL in i.groups or capstone.x86.X86_GRP_JUMP in i.groups:
                        self._suspiciousBehaviour.append(
                            'JMP or CALL before relocation')
                        checkJmp = False
                    elif capstone.x86.X86_GRP_RET in i.groups:
                        # Stop search after the first PUSH/RET
                        checkJmp = False
                # Manual check in case capstone version doesn't support CALL and RET groups
                else:
                    if i.mnemonic[0] == 'j' or i.mnemonic == 'call':
                        self._suspiciousBehaviour.append(
                            'JMP or CALL before relocation')
                        checkJmp = False
                    elif i.mnemonic[:3] == 'ret':
                        # Stop search after the first PUSH/RET
                        checkJmp = False

            # Check for unknown interrupt
            if i.mnemonic == 'int' and i.bytes[1] not in (0x10, 0x13, 0x18,
                                                          0x1a):
                self._suspiciousBehaviour.append(
                    'Unknown Interrupt : {0:#x}'.format(i.bytes[1]))
예제 #25
0
    command_prefix_construct = construct.Const(command_prefix, construct.Byte)

    return construct.Struct(
        'data' / construct.RawCopy(
            construct.Struct(
                construct.Const(b'\x02'),  # stx
                'length' / construct.Rebuild(
                    construct.Byte, lambda this: len(this.message) + 7),
                'link_control' / link_control_construct,
                'command_prefix' / command_prefix_construct,
                'message' / construct.Bytes(lambda this: this.length - 7),
                construct.Const(b'\x03'),  # etx
            ), ),
        'checksum' / construct.Checksum(construct.Int16ul, lifescan.crc_ccitt,
                                        construct.this.data.data),
    )


COMMAND_SUCCESS = construct.Const(b'\x06')

VERIO_TIMESTAMP = construct_extras.Timestamp(
    construct.Int32ul, epoch=946684800)  # 2000-01-01 (not 2010)

_GLUCOSE_UNIT_MAPPING_TABLE = {
    common.Unit.MG_DL: 0x00,
    common.Unit.MMOL_L: 0x01,
}

GLUCOSE_UNIT = construct.Mapping(construct.Byte, _GLUCOSE_UNIT_MAPPING_TABLE)
예제 #26
0
class VolumeBootRecord(BootRecord):
    _NTFS_VBR_STRUCT = construct.Struct(
        'NTFS-VBR',
        construct.Field('JumpOverBPB', 3),
        construct.String("OemId", 8),
        construct.Struct(
            'BiosParameterBlock',
            construct.ULInt16('SectorSize'),
            construct.ULInt8('SectorsPerCluster'),
            construct.Field('Reserved1', 2),
            construct.Field('MustBeZero1', 3),
            construct.Field('MustBeZero2', 2),
            construct.ULInt8('MediaDescriptor'),
            construct.Field('MustBeZero3', 2),
            construct.ULInt16('SectorsPerTrack'),
            construct.ULInt16('NumberOfHeads'),
            construct.ULInt32('HiddenSectors'),
            construct.Field('NotUsed1', 4),
            construct.Const(construct.Field('DriveNumber', 1),
                            '80'.decode('hex')),
            construct.Field('Reserved2', 3),
            construct.ULInt64('TotalSectors'),
            construct.ULInt64('MFTCluster'),
            construct.ULInt64('MFTMirrCluster'),
            construct.SLInt8('ClustersPerMFTRecord'),
            construct.Field('NotUsed2', 3),
            construct.SLInt8('ClustersPerIdxBuffer'),
            construct.Field('NotUsed3', 3),
            construct.ULInt64('VolumneSN'),
            construct.Field('NotUsed4', 4),
        ),
        construct.HexDumpAdapter(construct.Bytes("Code", 426)),
        construct.Const(construct.Bytes("signature", 2), '55aa'.decode('hex')),
    )

    _BITLOCKER_VBR_STRUCT = construct.Struct(
        'FVE-VBR',
        construct.Field('JumpOverBPB', 3),
        construct.Const(construct.String("OemId", 8),
                        '-FVE-FS-'.encode('utf8')),
        construct.Struct(
            'BiosParameterBlock',
            construct.ULInt16('SectorSize'),
            construct.ULInt8('SectorsPerCluster'),
            construct.Field('Reserved1', 2),
            construct.Field('MustBeZero1', 3),
            construct.Field('MustBeZero2', 2),
            construct.ULInt8('MediaDescriptor'),
            construct.Field('MustBeZero3', 2),
            construct.ULInt16('SectorsPerTrack'),
            construct.ULInt16('NumberOfHeads'),
            construct.ULInt32('HiddenSectors'),
            construct.ULInt32('TotalSectors'),
            construct.ULInt32('SectorsPerFAT'),
            construct.ULInt16('FATFlags'),
            construct.ULInt16('Version'),
            construct.ULInt32('RootDirCluster'),
            construct.ULInt16('FSInfoSector'),
            construct.ULInt16('BackupSector'),
            construct.Field('Reserved2', 12),
            construct.Const(construct.Field('DriveNumber', 1),
                            '80'.decode('hex')),
            construct.Field('Reserved3', 1),
            construct.Field('ExtendedBootSignature', 1),
            construct.ULInt32('VolumneSN'),
            construct.Const(construct.String("VolumeLabel", 11),
                            'NO NAME    '.encode('utf8')),
            construct.Const(construct.String("SystemId", 8),
                            'FAT32   '.encode('utf8')),
        ),
        construct.HexDumpAdapter(construct.Bytes("Code1", 70)),
        construct.Field('BitlockerGUID', 16),
        construct.ULInt64('FVEMetadataBlockOffset1'),
        construct.ULInt64('FVEMetadataBlockOffset2'),
        construct.ULInt64('FVEMetadataBlockOffset3'),
        construct.HexDumpAdapter(construct.Bytes("Code2", 307)),
        construct.ULInt8('FirstStrOffset'),
        construct.ULInt8('SecondStrOffset'),
        construct.ULInt8('ThirdStrOffset'),
        construct.Const(construct.Bytes("signature", 2), '55aa'.decode('hex')),
    )

    def __init__(self, filePath, size, offset=None, whitelist=()):
        self._type = 'VBR'
        super(VolumeBootRecord, self).__init__(filePath, size, offset,
                                               whitelist)

    def _parse(self):
        """
            Main method in charge of parsing the VBR.
            It will try to parse the boot record according to known structures (NTFS and Bitlocker supported).
            It will then try to narrow down invariant code, hash it and match the hash against a whitelist.
            If no match was found, it will try some simple heuristics to detect malicious behaviours.
            Finally it will compare the HiddenSectors value in BPB to that of the record's dump offset.

        Returns: nothing

        """
        try:
            # This will parse both NTFS and Vista bitlocker volumes since they only differ by their OEM ID
            vbr = self._NTFS_VBR_STRUCT.parse(self._raw)
            expectedLoader, invariantCode = self._getInvariantCode('NTFS', vbr)
        except construct.core.ConstructError as e1:
            # Retry with Bitlocker (Win7+) volume header structure
            try:
                vbr = self._BITLOCKER_VBR_STRUCT.parse(self._raw)
                expectedLoader, invariantCode = self._getInvariantCode(
                    'bitlocker', vbr)
            except construct.core.ConstructError as e2:
                raise InvalidVBRError(
                    'Invalid VBR structure: e1={0}, e2={1}\n{2}'.format(
                        e1, e2, hexdump(self._raw)))

        self._oemId = vbr.OemId
        self._bpb = vbr.BiosParameterBlock
        codeHash = hashlib.sha256(invariantCode)
        self._matchHash(codeHash, expectedLoader)

        # If no whitelisted signature matched, try some simple heuristics to flag this VBR as malicious
        # Note that the self._checkCode method is only given the "invariant" code section to help with the
        # disassembling. This will obviously leads to broken offsets, but it doesn't matter since the heuristics don't
        # use them.
        if len(self._signature) == 0:
            self._checkCode(invariantCode)

        # At last, compare the offset at which this VBR was found with the value of the BPB HiddenSectors
        if self._offset is not None \
                and (vbr.BiosParameterBlock.HiddenSectors * vbr.BiosParameterBlock.SectorSize) != self._offset:
            self._suspiciousBehaviour.append(
                'Suspicious HiddenSectors value: {0} ({1} bytes)'.format(
                    vbr.BiosParameterBlock.HiddenSectors,
                    vbr.BiosParameterBlock.HiddenSectors *
                    vbr.BiosParameterBlock.SectorSize))

    def _getInvariantCode(self, vbrType, vbrStruct):
        """
            Helper method that finds all the sections of the boot code that can be hashed and compared to a whitelist.
            This means that localized strings and other variable parameters (BPB, etc...) are excluded.
            Currently, this method only supports NTFS and Bitlocker VBR.

        Args:
            vbrType: unicode string corresponding to the VBR type ('NTFS' or 'bitlocker')
            vbrStruct: construct.container of the VBR

        Returns: 2-tuple (unicode string of expected loader, concatenated strings of invariant sections of code)

        """
        codeStart = 0
        codeEnd = None
        invariantCode = str()
        expectedLoader = None

        if vbrType == 'NTFS':
            # The first three bytes are a jump over the NTFS BPB to where the code really starts (0x54) and a NOP
            invariantCode += vbrStruct.JumpOverBPB
            codeStart = 0x54
            # NTFS VBR contains localized strings which must be excluded from the hash computation.
            # Before Windows 8, these strings are located at 4 different offsets which can be calculated by adding
            # 0x100 to the values respectively stored in bytes 0x1f8, 0x1f9, 0x1fa and 0x1fb.
            # Starting from Windows 8, these strings are located at 3 different offsets which are directly stored in
            # little endian words respectively at 0x1f6, 0x1f8 and 0x1fa
            # Since there is no easy way to tell which version of Windows we are dealing with beforehand, we first
            # assume it is a Windows < 8 by testing 0x1f8 against all the known first offset. If all tests fail, assume
            # it is Windows >= 8 and check 0x1f6 against the only known first offset (to date)
            firstStrOffset = construct.UBInt8('FirstStringOffset').parse(
                self._raw[0x1f8])
            # Windows NT5
            if firstStrOffset == 0x83:
                expectedLoader = 'NT5.1/NT5.2 VBR'
                codeEnd = 0x100 + firstStrOffset
            # Windows NT6.0
            elif firstStrOffset == 0x80:
                expectedLoader = 'NT6.0 VBR'
                codeEnd = 0x100 + firstStrOffset
            # Windows NT6.1
            elif firstStrOffset == 0x8c:
                expectedLoader = 'NT6.1 VBR'
                codeEnd = 0x100 + firstStrOffset
            # Windows NT6.2+
            else:
                firstStrOffset = construct.ULInt16('FirstStringOffset').parse(
                    self._raw[0x1f6:0x1f8])
                if firstStrOffset == 0x18a:
                    expectedLoader = 'NT6.2+ VBR'
                    codeEnd = firstStrOffset

            if codeEnd is None:
                self._suspiciousBehaviour.append(
                    'Invalid string offset: {0:#x}'.format(firstStrOffset))
                self._logger.debug(
                    'First localized string offset is wrong for a NTFS VBR: {0:#x}. '
                    'It should be 0x83, 0x80, 0x8c or 0x18a.'.format(
                        firstStrOffset))
                codeEnd = 0

        elif vbrType == 'bitlocker':
            expectedLoader = 'NT6.1+ Bitlocker VBR'
            # The first three bytes are a jump over the NTFS BPB to where the code really starts (0x5A) and a NOP
            invariantCode += vbrStruct.JumpOverBPB
            # First section of code (_BITLOCKER_VBR_STRUCT.Code1)
            invariantCode += vbrStruct.Code1
            # In the second section of code, there are localized strings which must be excluded from hash computation.
            # Their offsets are stored in the last 3 bytes before the VBR signature (0x55aa).
            # For Windows 8, 8.1 and 10, the first string offset seems to always be 0x100 (ie. FirstStrOffset = 0x00)
            if vbrStruct.FirstStrOffset != 0:
                self._suspiciousBehaviour.append(
                    'Invalid string offset: {0:#x}'.format(
                        vbrStruct.FirstStrOffset))
                self._logger.debug(
                    'First localized string offset is wrong for a Bitlocker VBR. '
                    'It should be 0x00) : {0:#x}'.format(
                        vbrStruct.FirstStrOffset))
            codeStart = 0xc8  # Offset of Code2
            codeEnd = 0x100 + vbrStruct.FirstStrOffset
        else:
            raise NotImplementedError(
                'VBR type "{0}" is not implemented yet'.format(vbrType))

        self._logger.debug(
            'Expecting {0}. Code starts at {1:#x} and ends at {2:#x}'.format(
                expectedLoader, codeStart, codeEnd))

        invariantCode += self._raw[codeStart:codeEnd]
        return expectedLoader, invariantCode

    def _checkCode(self, code):
        md = capstone.Cs(capstone.CS_ARCH_X86, capstone.CS_MODE_16)
        md.detail = True
        for i in md.disasm(code, 0):
            # Check for unknown interrupt
            if i.mnemonic == 'int' and i.bytes[1] not in (0x10, 0x13, 0x18,
                                                          0x1a):
                self._suspiciousBehaviour.append(
                    'Unknown Interrupt : {0:#x}'.format(i.bytes[1]))
예제 #27
0
                construct.Struct(
                    '', GUID('unknown1'), GUID('unknown2'),
                    construct.Rename('blob_store', DPAPI_BLOB_STORE))))))

VAULT_POL = construct.Struct('VAULT_POL', construct.ULInt32('version'),
                             GUID('guid'),
                             construct.Rename('description', UNICODE_STRING),
                             construct.ULInt32('unknown1'),
                             construct.ULInt32('unknown2'),
                             construct.ULInt32('unknown3'),
                             construct.Rename('vpol_store', VAULT_POL_STORE))

# Key Data Blob Magic (KDBM).
BCRYPT_KEY_DATA_BLOB_HEADER = construct.Struct(
    'BCRYPT_KEY_DATA_BLOB_HEADER',
    construct.Const(construct.ULInt32('dwMagic'), 0x4d42444b),
    construct.ULInt32('dwVersion'), construct.ULInt32('cbKeyData'))

BCRYPT_KEY_DATA_BLOB = construct.Struct(
    'BCRYPT_KEY_DATA_BLOB', construct.Embed(BCRYPT_KEY_DATA_BLOB_HEADER),
    construct.Bytes('key', lambda ctx: ctx.cbKeyData))

BCRYPT_KEY_STORE = construct.Struct(
    'BCRYPT_KEY_STORE', construct.ULInt32('size'),
    construct.Embed(
        construct.Union(
            '', construct.Bytes('raw', lambda ctx: ctx.size),
            construct.Embed(
                construct.Struct(
                    '', construct.ULInt32('unknown1'),
                    construct.ULInt32('unknown2'),
예제 #28
0
파일: parser.py 프로젝트: orklann/gifprime
    ),
    construct.If(
        lambda ctx: ctx.image_descriptor.lct_flag,
        construct.Array(
            lambda ctx: pow(2, ctx.image_descriptor.lct_size + 1),
            construct.Array(3, construct.ULInt8('lct')),
        ),
    ),
    construct.ULInt8('lzw_min'),
    _get_data_subblocks('compressed_indices'),
)

_application_extension = construct.Struct(
    'application_extension',
    construct.Value('block_type', lambda ctx: 'application'),
    construct.Const(construct.ULInt8('block_size'), 11),
    construct.String('app_id', 8),
    construct.Bytes('app_auth_code', 3),
    _get_data_subblocks('app_data'),
)

_comment_extension = construct.Struct(
    'comment_extension',
    construct.Value('block_type', lambda ctx: 'comment'),
    _get_data_subblocks('comment'),
)

_gce_extension = construct.Struct(
    'gce_extension',
    construct.Value('block_type', lambda ctx: 'gce'),
    construct.Const(construct.ULInt8('block_size'), 4),
예제 #29
0
def _transform_vendor_trust(data: bytes) -> bytes:
    """Byte-swap and bit-invert the VendorTrust field.

    Vendor trust is interpreted as a bitmask in a 16-bit little-endian integer,
    with the added twist that 0 means set and 1 means unset.
    We feed it to a `BitStruct` that expects a big-endian sequence where bits have
    the traditional meaning. We must therefore do a bitwise negation of each byte,
    and return them in reverse order. This is the same transformation both ways,
    fortunately, so we don't need two separate functions.
    """
    return bytes(~b & 0xFF for b in data)[::-1]


# fmt: off
Toif = c.Struct(
    "magic" / c.Const(b"TOI"),
    "format" / c.Enum(c.Byte, full_color=b"f", grayscale=b"g"),
    "width" / c.Int16ul,
    "height" / c.Int16ul,
    "data" / c.Prefixed(c.Int32ul, c.GreedyBytes),
)

VendorTrust = c.Transformed(
    c.BitStruct(
        "reserved" / c.Default(c.BitsInteger(9), 0),
        "show_vendor_string" / c.Flag,
        "require_user_click" / c.Flag,
        "red_background" / c.Flag,
        "delay" / c.BitsInteger(4),
    ), _transform_vendor_trust, 2, _transform_vendor_trust, 2)
예제 #30
0
from pyscsi.pyscsi.scsi import SCSI
from pyscsi.pyscsi.scsi_device import SCSIDevice

from glucometerutils import common
from glucometerutils import exceptions
from glucometerutils.support import lifescan
from glucometerutils.support import lifescan_binary_protocol

# This device uses SCSI blocks as registers.
_REGISTER_SIZE = 512

_PACKET = construct.Padded(
    _REGISTER_SIZE, lifescan_binary_protocol.LifeScanPacket(0x03, False))

_QUERY_REQUEST = construct.Struct(
    construct.Const(b'\xe6\x02'),
    'selector' /
    construct.Enum(construct.Byte, serial=0x00, model=0x01, software=0x02),
)

_QUERY_RESPONSE = construct.Struct(
    lifescan_binary_protocol.COMMAND_SUCCESS,
    'value' / construct.CString(encoding='utf-16-le'),
)

_READ_PARAMETER_REQUEST = construct.Struct(
    'selector' / construct.Enum(construct.Byte, unit=0x04), )

_READ_UNIT_RESPONSE = construct.Struct(
    lifescan_binary_protocol.COMMAND_SUCCESS,
    'unit' / lifescan_binary_protocol.GLUCOSE_UNIT,