예제 #1
0
class DescriptorField(construct.Subconstruct):
    """
    Construct field definition that automatically adds fields of the proper
    size to Descriptor definitions.
    """

    #
    # The C++-wonk operator overloading is Construct, not me, I swear.
    #

    # FIXME: these are really primitive views of these types;
    # we should extend these to get implicit parsing wherever possible
    USB_TYPES = {
        'b'   : construct.Optional(construct.Int8ul),
        'bcd' : construct.Optional(construct.Int16ul),  # Create a BCD parser for this
        'i'   : construct.Optional(construct.Int8ul),
        'id'  : construct.Optional(construct.Int16ul),
        'bm'  : construct.Optional(construct.Int8ul),
        'w'   : construct.Optional(construct.Int16ul),
    }

    @staticmethod
    def _get_prefix(name):
        """ Returns the lower-case prefix on a USB descriptor name. """
        prefix = []

        # Silly loop that continues until we find an uppercase letter.
        # You'd be aghast at how the 'pythonic' answers look.
        for c in name:

            # Ignore leading underscores.
            if c == '_':
                continue

            if c.isupper():
                break
            prefix.append(c)

        return ''.join(prefix)


    @classmethod
    def _get_type_for_name(cls, name):
        """ Returns the type that's appropriate for a given descriptor field name. """

        try:
            return cls.USB_TYPES[cls._get_prefix(name)]
        except KeyError:
            raise ValueError("field names must be formatted per the USB standard!")


    def __init__(self, description=""):
        self.description = description


    def __rtruediv__(self, field_name):
        field_type = self._get_type_for_name(field_name)

        # wew does construct make this look weird
        return (field_name / field_type) * self.description
예제 #2
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")))
예제 #3
0
        def _apply_optional(subcon):

            subcon_type = cls._get_subcon_field_type(subcon)

            #
            # If it's already Optional then we don't need to apply it again.
            #
            if isinstance(subcon_type, construct.Select):
                # construct uses a weird singleton to define Pass. `construct.core.Pass` would normally be
                # the type's name, but then they create a singleton of that same name, replacing that name and
                # making the type technically unnamable and only accessable via `type()`.
                if isinstance(subcon_type.subcons[1], type(construct.Pass)):
                    return subcon

            return (subcon.name /
                    construct.Optional(subcon_type)) * subcon.docs
예제 #4
0
        construct.Embed(
            construct.Struct('encrypted',
                             construct.Bytes('data',
                                             lambda ctx: ctx.size - 1)))))

VAULT_ATTRIBUTE = construct.Struct(
    'VAULT_ATTRIBUTE',
    construct.ULInt32('id'),
    construct.ULInt32('attr_unknown_1'),
    construct.ULInt32('attr_unknown_2'),
    construct.ULInt32('attr_unknown_3'),
    # Ok, this is bad, but till now I have not understood how to distinguish
    # the different structs used. Actually the last ATTRIBUTE is different.
    # Usually we have 6 more bytes zeroed, not always aligned: otherwise,
    # if id >= 100, we have 4 more bytes: weird.
    construct.Optional(
        construct.Const(construct.Bytes('padding', 6), '\x00' * 6)),
    construct.If(lambda ctx: not ctx.padding and ctx.id >= 0x64,
                 construct.ULInt32('attr_unknown_4')),
    construct.ULInt32('size'),
    construct.If(lambda ctx: ctx.size > 0,
                 construct.Embed(VAULT_ATTRIBUTE_ENCRYPTED)),
    construct.Anchor('stream_end'))

VAULT_ATTRIBUTE_EXTRA = construct.Struct('VAULT_ATTRIBUTE_EXTRA',
                                         construct.ULInt32('id'),
                                         construct.ULInt32('attr_unknown_1'),
                                         construct.ULInt32('attr_unknown_2'),
                                         construct.Embed(SIZED_DATA))

VAULT_ATTRIBUTE_MAP_ENTRY = construct.Struct(
    'VAULT_ATTRIBUTE_MAP_ENTRY', construct.ULInt32('id'),
예제 #5
0
    c.Terminated,
)

FirmwareOne = c.Struct(
    "magic" / c.Const(b"TRZR"),
    "code_length" / c.Rebuild(c.Int32ul, c.len_(c.this.code)),
    "key_indexes" / c.Int8ul[V1_SIGNATURE_SLOTS],  # pylint: disable=E1136
    "flags" / c.BitStruct(
        c.Padding(7),
        "restore_storage" / c.Flag,
    ),
    "reserved" / c.Padding(52),
    "signatures" / c.Bytes(64)[V1_SIGNATURE_SLOTS],
    "code" / c.Bytes(c.this.code_length),
    c.Terminated,
    "embedded_onev2" / c.RestreamData(c.this.code, c.Optional(FirmwareOneV2)),
)

# fmt: on


class FirmwareFormat(Enum):
    TREZOR_ONE = 1
    TREZOR_T = 2
    TREZOR_ONE_V2 = 3


FirmwareType = NewType("FirmwareType", c.Container)
ParsedFirmware = Tuple[FirmwareFormat, FirmwareType]

예제 #6
0
    "DATA" / c.Array(c.this.NUM_SAMPLES, c.Int16ub))

SpeechCMODE = c.Struct("FIELD_ID" / c.Const(b'\x02'), "CMODE_IN" / ECMODE_IN)

SpeechDCMODE = c.Struct("FIELD_ID" / c.Const(b'\x02'),
                        "DCMODE_OUT" / DCMODE_OUT)

SpeechTONE = c.Struct(
    "FIELD_ID" / c.Const(b'\x08'),
    "TONE_IDX" / c.Byte,
    "TONE_AMPLITUDE" / c.Byte,
)

SpeechPCMPacket = c.Struct(
    "FIELD_ID" / c.Const(b'\x40'),
    "SPEECHD" / c.Optional(SpeechPCM),
    "CMODE" / c.Optional(SpeechCMODE),
    "TONE" / c.Optional(SpeechTONE),
)

SpeechPCMResp = c.Struct(
    "FIELD_ID" / c.Const(b'\x00'),
    "NUM_SAMPLES" / c.Byte,  # 156 - 164
    "DATA" / c.Array(c.this.NUM_SAMPLES, c.Int16ub),
    "BYTES" /
    c.Computed(lambda this: struct.pack('H' * this.NUM_SAMPLES, *this.DATA)),
    "CMODE" / c.Optional(SpeechDCMODE))

###############################################################################
# Channel Messages
예제 #7
0
class Status(Enum):
    VALID = click.style("VALID", fg="green", bold=True)
    INVALID = click.style("INVALID", fg="red", bold=True)
    MISSING = click.style("MISSING", fg="blue", bold=True)
    DEVEL = click.style("DEVEL", fg="red", bold=True)

    def is_ok(self):
        return self is Status.VALID or self is Status.DEVEL


VHASH_DEVEL = bytes.fromhex(
    "c5b4d40cb76911392122c8d1c277937e49c69b2aaf818001ec5c7663fcce258f")

AnyFirmware = c.Struct(
    "vendor_header" / c.Optional(firmware.VendorHeader),
    "image" / c.Optional(firmware.FirmwareImage),
)


class ImageType(Enum):
    VENDOR_HEADER = 0
    BOOTLOADER = 1
    FIRMWARE = 2


def _make_dev_keys(*key_bytes: bytes) -> List[bytes]:
    return [k * 32 for k in key_bytes]


def compute_vhash(vendor_header):
예제 #8
0
 def __init__(self, const):
     self.const = const
     super().__init__(c.Optional(c.Const(const)))
예제 #9
0
CONTROL_TYPE_TUNNEL = 0x04
CONTROL_TYPE_KEEPALIVE = 0x05
CONTROL_TYPE_PMTUD = 0x06
CONTROL_TYPE_PMTUD_ACK = 0x07
CONTROL_TYPE_REL_ACK = 0x08

# Reliable messages (0x80 - 0xFF)
MASK_CONTROL_TYPE_RELIABLE = 0x80
CONTROL_TYPE_LIMIT = 0x80

# Prepare message
PrepareMessage = cs.Struct(
    "prepare",
    cs.String("cookie", 8),
    cs.PascalString("uuid"),
    cs.Optional(cs.UBInt16("tunnel_id")),
)

# Limit message
LimitMessage = cs.Struct(
    "limit",
    # Limit type
    cs.UBInt8("type"),
    # Limit configuration
    cs.PascalString("data"))

LIMIT_TYPE_BANDWIDTH_DOWN = 0x01

# Overhead of IP and UDP headers for measuring PMTU
IPV4_HDR_OVERHEAD = 28
예제 #10
0
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
"""
ImageSectionHeader = construct.Struct(
    "name" / construct.PaddedString(8, 'ascii'),
    "virtual_size" / construct.Int32ul, "virtual_address" / construct.Int32ul,
    "raw_data_size" / construct.Int32ul, "raw_data_ptr" / construct.Int32ul,
    "relocations_ptr" / construct.Int32ul,
    "linenumbers_ptr" / construct.Int32ul,
    "relocation_count" / construct.Int16ul,
    "linenumbers_count" / construct.Int16ul,
    "characteristics" / construct.Int32ul)

ImageNtHeader = construct.Struct(
    "pe_magic" / construct.Const("PE\x00\x00"),
    "file_header" / ImageFileHeader,
    "optional_header" / construct.Optional(ImageOptionalHeader),
)


def dos_stub(lfanew):
    return construct.Bytes(lfanew - ImageDosHeader.sizeof())


PeFile = construct.Struct(
    "dos_header" / ImageDosHeader,
    "dos_stub_program" / dos_stub(construct.this.dos_header.e_lfanew),
    "nt_header" / ImageNtHeader, "section_table" /
    construct.Array(construct.this.nt_header.file_header.section_count,
                    ImageSectionHeader))

예제 #11
0
# 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.Optional(cs.Padding(lambda ctx: max(0, 6 - len(ctx["data"])))),
)

# Unreliable messages (0x00 - 0x7F)
CONTROL_TYPE_COOKIE    = 0x01
CONTROL_TYPE_PREPARE   = 0x02
CONTROL_TYPE_ERROR     = 0x03
CONTROL_TYPE_TUNNEL    = 0x04
CONTROL_TYPE_KEEPALIVE = 0x05
CONTROL_TYPE_PMTUD     = 0x06
CONTROL_TYPE_PMTUD_ACK = 0x07
CONTROL_TYPE_REL_ACK   = 0x08
CONTROL_TYPE_PMTU_NTFY = 0x09
CONTROL_TYPE_USAGE     = 0x0A

# Error Reason Byte
예제 #12
0
    C.IfThenElse(C.this.frameCount != 0,
                 C.Pointer(C.this.dataOffset, C.Int32sl[4]), C.Int32sl[0]),
)


def defaultMapIndices(l):
    return l + [0] * (4 - len(l))


StringHead = C.Struct("blank" / C.Int64sl, "stringOffset" / C.Int64sl,
                      "type" / C.Int32sl)
StringBody = C.Struct("string" / C.CString("utf-8"), )
StringData = C.Struct(
    "blank" / C.Int64sl, "stringOffset" / C.Int64sl, "type" / C.Int32sl,
    "string" / C.Pointer(C.this.stringOffset, C.CString("utf-8")),
    "padding" / C.Optional(C.Const(0, C.Int32sl)))

UVSFile = C.Struct(
    "Header" / Header, "Groups" /
    C.Pointer(C.this.Header.groupOffset, Group[C.this.Header.groupCount]),
    "Strings" / C.Pointer(C.this.Header.stringOffset,
                          StringData[C.this.Header.stringCount]))


def pad(size, offset):
    cursor = offset
    return (-cursor) % size + offset


def bpad(size, data):
    return data + b"\x00" * ((-len(data)) % size)
예제 #13
0
 def __init__(self, const: bytes) -> None:
     self.const = const
     super().__init__(c.Optional(c.Const(const)))
예제 #14
0
    "bEndpointAddress" / DescriptorField("Endpoint Address"),
    "bmAttributes" / DescriptorField("Attributes", default=2),
    "wMaxPacketSize" / DescriptorField("Maximum Packet Size", default=64),
    "bInterval" / DescriptorField("Polling interval", default=255),
)

DeviceQualifierDescriptor = DescriptorFormat(
    "bLength" / construct.Const(9, construct.Int8ul), "bDescriptorType" /
    DescriptorNumber(StandardDescriptorNumbers.DEVICE_QUALIFIER),
    "bcdUSB" / DescriptorField("USB Version"),
    "bDeviceClass" / DescriptorField("Class"),
    "bDeviceSubclass" / DescriptorField("Subclass"),
    "bDeviceProtocol" / DescriptorField("Protocol"),
    "bMaxPacketSize0" / DescriptorField("EP0 Max Pkt Size"),
    "bNumConfigurations" / DescriptorField("Configuration Count"),
    "_bReserved" / construct.Optional(construct.Const(b"\0")))


class DescriptorParserCases(unittest.TestCase):

    STRING_DESCRIPTOR = bytes([
        40,  # Length
        3,  # Type
        ord('G'),
        0x00,
        ord('r'),
        0x00,
        ord('e'),
        0x00,
        ord('a'),
        0x00,
예제 #15
0
EndpointDescriptor = DescriptorFormat(

    # [USB2.0: 9.6; USB Audio Device Class Definition 1.0: 4.6.1.1, 4.6.2.1]
    # Interfaces of the Audio 1.0 class extend their subordinate endpoint descriptors with
    # 2 additional bytes (extending it from 7 to 9 bytes). Thankfully, this is the only extension that
    # changes the length of a standard descriptor type, but we do have to handle this case in Construct.
    "bLength" /
    construct.Default(construct.OneOf(construct.Int8ul, [7, 9]), 7),
    "bDescriptorType" / DescriptorNumber(StandardDescriptorNumbers.ENDPOINT),
    "bEndpointAddress" / DescriptorField("Endpoint Address"),
    "bmAttributes" / DescriptorField("Attributes", default=2),
    "wMaxPacketSize" / DescriptorField("Maximum Packet Size", default=64),
    "bInterval" / DescriptorField("Polling interval", default=255),

    # 2 bytes that are only present on endpoint descriptors for Audio 1.0 class interfaces.
    ("bRefresh" / construct.Optional(construct.Int8ul)) * "Refresh Rate",
    ("bSynchAddress" / construct.Optional(construct.Int8ul)) *
    "Synch Endpoint Address",
)

DeviceQualifierDescriptor = DescriptorFormat(
    "bLength" / construct.Const(9, construct.Int8ul), "bDescriptorType" /
    DescriptorNumber(StandardDescriptorNumbers.DEVICE_QUALIFIER),
    "bcdUSB" / DescriptorField("USB Version"),
    "bDeviceClass" / DescriptorField("Class"),
    "bDeviceSubclass" / DescriptorField("Subclass"),
    "bDeviceProtocol" / DescriptorField("Protocol"),
    "bMaxPacketSize0" / DescriptorField("EP0 Max Pkt Size"),
    "bNumConfigurations" / DescriptorField("Configuration Count"),
    "_bReserved" / construct.Optional(construct.Const(b"\0")))
예제 #16
0
        construct.Embed(
            construct.Struct(
                'encrypted', construct.ULInt32('iv_size'),
                construct.Bytes('iv', lambda ctx: ctx.iv_size),
                construct.Bytes('data',
                                lambda ctx: ctx.size - 1 - 4 - ctx.iv_size))),
        construct.Embed(
            construct.Struct('encrypted',
                             construct.Bytes('data',
                                             lambda ctx: ctx.size - 1)))))

VAULT_ATTRIBUTE = construct.Struct(
    'VAULT_ATTRIBUTE', construct.ULInt32('id'),
    construct.ULInt32('attr_unknown_1'), construct.ULInt32('attr_unknown_2'),
    construct.ULInt32('attr_unknown_3'),
    construct.Optional(
        construct.Const(construct.Bytes('padding', 6), '\x00' * 6)),
    construct.ULInt32('size'),
    construct.If(lambda ctx: ctx.size > 0,
                 construct.Embed(VAULT_ATTRIBUTE_ENCRYPTED)))
'''
VAULT_ATTRIBUTE_EX = construct.Struct(
    'VAULT_ATTRIBUTE_EX',
    construct.ULInt32('id'),
    construct.ULInt32('attr_unknown_1'),
    construct.ULInt32('attr_unknown_2'),
    construct.ULInt32('attr_unknown_3'),
    construct.ULInt32('attr_unknown_4'),
    construct.Anchor('attr_stream_pos'),
    construct.If(
        lambda ctx: ctx.attr_stream_pos % 8,
        construct.Bytes('padding',