Exemple #1
0
    def test_overwrite(self):
        s = Struct("s",
            Byte("a"),
            Byte("a"),
            allow_overwrite = True
        )
        self.assertEqual(s.parse(b"\x01\x02").a, 2)

        s = Struct("s",
            Byte("a"),
            Embedded(Struct("b",
                Byte("a"),
                allow_overwrite = True
            )),
        )
        self.assertEqual(s.parse(b"\x01\x02").a, 2)

        s = Struct("s",
            Embedded(Struct("b",
                Byte("a"),
            )),
            Byte("a"),
            allow_overwrite = True
        )
        self.assertEqual(s.parse(b"\x01\x02").a, 2)
    def test_overwrite(self):
        s = Struct("s",
            Byte("a"),
            Byte("a"),
            allow_overwrite = True
        )
        self.assertEqual(s.parse(six.b("\x01\x02")).a, 2)

        s = Struct("s",
            Byte("a"),
            Embedded(Struct("b",
                Byte("a"),
                allow_overwrite = True
            )),
        )
        self.assertEqual(s.parse(six.b("\x01\x02")).a, 2)

        s = Struct("s",
            Embedded(Struct("b",
                Byte("a"),
            )),
            Byte("a"),
            allow_overwrite = True
        )
        self.assertEqual(s.parse(six.b("\x01\x02")).a, 2)
Exemple #3
0
def parse(buffer, byteorder = "<"):
    """
    Parameters
    ----------
    buffer: bytes-like

    byteorder: char
        "<": Little-endian
        ">": Big-endian

    Returns
    -------
    dict
        key: Vendor name
        values: list of attributes
    """
    Integer = Int32ul if byteorder == "<" else Int32ub
    Section = Struct(
        "len" / Integer,
        "vendor" / CString(encoding = "ascii"),
        "_pos" / Tell,
        "data" / Bytes(this.len - this._pos),
    )
    SubSectionHeader = Struct(
        "tag" / Byte,
        "len" / Integer,
        "_pos" / Tell,
        "data" / Bytes(this.len - this._pos),
    )

    RawAttribute = Struct(
        "tag" / ULEB,
        "parameterType" / Computed(lambda ctx: ATTRIBUTES[ctx.tag].parameterType),
        "name" / Computed(lambda ctx: ATTRIBUTES[ctx.tag].tag),
        "_conv" / Computed(lambda ctx: ATTRIBUTES[ctx.tag].conv),
        "value" / Switch(this.parameterType, { Reader.INT32: Integer, Reader.ULEB: ULEB, Reader.CSTRING: CString(encoding = "ascii") }),
        "pos" / Tell,
    )
    format_version = buffer[0]
    i = 1
    length = len(buffer)
    result = {}
    while True:
        section = Section.parse(buffer[i : ])
        if not section.vendor in result:
            result[section.vendor] = []
        i += section.len
        res = SubSectionHeader.parse(section.data)
        j = 0
        while j < len(res.data):
            attr = RawAttribute.parse(res.data[j : ])
            r = Attribute(attr.tag, attr.name, attr.value)
            if attr._conv != Ident:
                r.description = attr._conv[attr.value]
            result[section.vendor].append(r)
            j += attr.pos
        if i >= length:
            break
    return result
Exemple #4
0
    def do_abbrevs(self):
        section = self.sections['.debug_abbrev']
        image = section.image
        length = len(section.image)
        Abbrevation = Struct(
            "start" / Tell,
            "code" / ULEB,
            "details" / If(lambda ctx: ctx.code != 0,
                           Struct(
                               "tag" / ULEB,
                               "children" / self.u8,
                           )),
            "stop" / Tell,
        )
        Attribute = Struct(
            "start" / Tell,
            "attrValue" / ULEB,
            "formValue" / ULEB,
            "stop" / Tell,
            "next" / Computed((this.attrValue != 0) and (this.formValue != 0)),
        )
        offset = 0
        result = OrderedDict()
        kOffs = offset
        while True:
            print("Offset: {}".format(offset))
            abbrev = Abbrevation.parse(image[offset:])
            if abbrev.code != 0:
                print("{} {} {}".format(abbrev.code,
                                        constants.Tag(abbrev.details.tag),
                                        abbrev.details.children == 1))
            key = (
                kOffs,
                abbrev.code,
            )
            offset += abbrev.stop - abbrev.start
            if offset >= length:
                break
            if abbrev.code == 0:
                kOffs = offset
                result[key] = Abbreviation(0, False, [])
                continue
            result[key] = Abbreviation(constants.Tag(abbrev.details.tag),
                                       (abbrev.details.children == 1), [])
            while True:
                attr = Attribute.parse(image[offset:])

                if attr.attrValue != 0 and attr.formValue != 0:
                    result[key].attrs.append(
                        (constants.AttributeEncoding(attr.attrValue),
                         constants.AttributeForm(attr.formValue)))
                    print("   {} {}".format(
                        constants.AttributeEncoding(attr.attrValue),
                        constants.AttributeForm(attr.formValue)))
                offset += (attr.stop - attr.start)
                if not attr.next:
                    break
        self.abbreviations = result
Exemple #5
0
def test_list_invalid():
    s = Struct(
        'hash' / ChecksumValue(hashlib.sha1, this.data, True),  # note: True instead of default False
        'data' / ChecksumSourceData(Struct(
            'x' / Bytes(4)
        )),
        VerifyOrWriteChecksums
    )

    with pytest.raises(ChecksumCalcError):
        s.parse(test_data)
Exemple #6
0
def test_no_sourcedata():
    s = Struct(
        'hash' / ChecksumValue(hashlib.sha1, this.data),
        'data' / Struct(
            'x' / Bytes(4)
        ),
        VerifyOrWriteChecksums
    )

    with pytest.raises(ChecksumCalcError):
        s.parse(test_data)
Exemple #7
0
def test_main():
    s = Struct('a' / Byte)

    # original behavior
    _global_struct_io_patch.unpatch()
    try:
        value = s.parse(b'\x01')
        assert '_io' in value
    finally:
        _global_struct_io_patch.patch()

    # patched
    value = s.parse(b'\x01')
    assert '_io' not in value
Exemple #8
0
    def __init__(self, data):
        frame = Struct(
            "Frame", Bytes("destination", 6), Bytes("source", 6),
            Enum(UBInt16("type"),
                 IPv4=0x0800,
                 ARP=0x0806,
                 RARP=0x8035,
                 X25=0x0805,
                 IPX=0x8137,
                 IPv6=0x86DD,
                 VLAN=0x8100))

        try:
            ethernet = frame.parse(data[:14])
        except MappingError:
            self.frame = None
            log.msg("Broken ethernet header %s" % repr(data))
            return
        data = data[14:]

        self.src_mac = ethernet.destination
        self.dst_mac = ethernet.source

        if ethernet.type == 'VLAN':
            d = ord(data[0])
            self.vlan = d & 0x0fff
            self.vlan_priority = d >> 13

        elif ethernet.type == 'IPv4':
            ipv4 = IPv4Header(data)
            self.ip = ipv4.ip
            self.ip_sport = ipv4.ip_sport
            self.ip_dport = ipv4.ip_dport
        else:
            print(ethernet.type, repr(data))
    def read_messages(self):
        """Read messages."""
        from construct import Struct, PascalString, Int16ul, Tell, this, Bytes

        frmt = Struct(
            "instructions_length" / Int16ul,
            "instructions" / Bytes(this.instructions_length),
            "hints" / PascalString(Int16ul, "utf8"),
            "victory" / PascalString(Int16ul, "utf8"),
            "defeat" / PascalString(Int16ul, "utf8"),
            "history" / PascalString(Int16ul, "utf8"),
            "scouts" / PascalString(Int16ul, "utf8"),
            "offset" / Tell,
        )

        parsing = frmt.parse(self.header[self.position:])
        self.position += parsing.offset

        parsing.instructions = parsing.instructions.rstrip(b'\x00')
        parsing.hints = parsing.hints.rstrip('\x00')
        parsing.victory = parsing.victory.rstrip('\x00')
        parsing.defeat = parsing.defeat.rstrip('\x00')
        parsing.history = parsing.history.rstrip('\x00')
        parsing.scouts = parsing.scouts.rstrip('\x00')

        return dict(parsing)
Exemple #10
0
class MessageParse(object):
    def __init__(self):
        self.constructFrame = Struct(
            "parser",
            OptionalGreedyRange(
                Struct(
                    "packets",
                    UBInt8("header"),
                    UBInt16("plen"),
                    UBInt8("dir"),
                    ULInt64("nodeid"),
                    UBInt16("funcid"),
                    Array(
                        lambda ctx: (ctx.plen - 1 - 8 - 2) / 8,
                        Struct(
                            "datas",
                            ULInt16("type"),
                            ULInt16("unit"),
                            LFloat32("value"),
                        )),
                    UBInt8("sum"),
                    # UBInt8("simulation")
                ), ),
            OptionalGreedyRange(UBInt8("leftovers"), ),
        )

    def construct_parse(self, bytestream):
        return self.constructFrame.parse(bytestream)

    def parse_pkgs(self, bytestream):
        container = self.construct_parse(bytestream)
        return container.packets, container.leftovers
Exemple #11
0
    def _extract_elf_corefile(self, exe_name=None):
        """
        Reads the ELF formatted core dump image and parse it
        """
        self.core_elf_file.write(self.core_src.data)
        # Need to be closed before read. Otherwise the result will be wrong
        self.core_elf_file.close()

        core_elf = ESPCoreDumpElfFile(self.core_elf_file.name)

        # Read note segments from core file which are belong to tasks (TCB or stack)
        for seg in core_elf.note_segments:
            for note_sec in seg.note_secs:
                # Check for version info note
                if note_sec.name == 'ESP_CORE_DUMP_INFO' \
                        and note_sec.type == ESPCoreDumpElfFile.PT_INFO \
                        and exe_name:
                    exe_elf = ElfFile(exe_name)
                    app_sha256 = binascii.hexlify(exe_elf.sha256)
                    coredump_sha256_struct = Struct(
                        'ver' / Int32ul,
                        'sha256' / Bytes(64)  # SHA256 as hex string
                    )
                    coredump_sha256 = coredump_sha256_struct.parse(
                        note_sec.desc[:coredump_sha256_struct.sizeof()])
                    if coredump_sha256.sha256 != app_sha256:
                        raise ESPCoreDumpLoaderError(
                            'Invalid application image for coredump: coredump SHA256({}) != app SHA256({}).'
                            .format(coredump_sha256, app_sha256))
                    if coredump_sha256.ver != self.version:
                        raise ESPCoreDumpLoaderError(
                            'Invalid application image for coredump: coredump SHA256 version({}) != app SHA256 version({}).'
                            .format(coredump_sha256.ver, self.version))
Exemple #12
0
def decode_data(payload):
    from construct import Struct, Int8ub, Int16ub, Float32l

    pytrack = Struct(
        "lat" / Float32l,
        "lng" / Float32l,
        "roll" / Int8ub,
        "pitch" / Int8ub,
        "volt" / Int8ub,
        "wake" / Int8ub,
    )
    s = pytrack.parse(bytearray.fromhex(payload))
    p = {}
    if 'lat' in s.keys():
        p['lat'] = s['lat']
    if 'lng' in s.keys():
        p['lng'] = s['lng']
    if 'roll' in s.keys():
        p['roll'] = (s['roll'] - 128.0) / (256.0 / 360.0)
    if 'pitch' in s.keys():
        p['pitch'] = (s['pitch'] - 128.0) / (256.0 / 180.0)
    if 'volt' in s.keys():
        p['volt'] = s['volt'] / 256.0 * 5.0
    if 'wake' in s.keys():
        p['wake'] = s['wake']
    return p
Exemple #13
0
def test_nested():
    s = Struct(
        'a' / Byte, 'b' / DeferredValue(Byte), 'c' / Byte, 'struct' /
        Struct('new_value' / Tell,
               WriteDeferredValue(this.new_value + 7, this._.b), 'x' / Byte))

    # parsing
    assert s.parse(b'\x01\x02\x03\x04') == {
        'a': 1,
        'b': 2,
        'c': 3,
        'struct': {
            'new_value': 3,
            'x': 4
        }
    }

    # building
    assert s.build({
        'a': 0xff,
        'c': 0xfe,
        'struct': {
            'x': 0x42
        }
    }) == b'\xff\x0a\xfe\x42'
def decode_data(data):
    print("Pytrack sensor data:")
    pytrack = Struct(
        "lat" / Float32l,
        "lng" / Float32l,
        "roll" / Int8ub,
        "pitch" / Int8ub,
        "volt" / Int8ub,
        "wake" / Int8ub,
    )
    s = pytrack.parse(bytearray.fromhex(data))
    print(s)
    d = {}
    if 'lat' in s.keys():
        d['lat'] = s['lat']
    if 'lng' in s.keys():
        d['lng'] = s['lng']
    if 'roll' in s.keys():
        d['roll'] = (s['roll'] - 128.0) / (256.0 / 360.0)
    if 'pitch' in s.keys():
        d['pitch'] = (s['pitch'] - 128.0) / (256.0 / 180.0)
    if 'volt' in s.keys():
        d['volt'] = s['volt'] / 256.0 * 5.0
    if 'wake' in s.keys():
        d['wake'] = s['wake']
    return d
Exemple #15
0
    def _parse(self, struct: Struct, encoded: HexStr_, crc=True) -> dict:
        """
        Parses struct, and returns a serializable Python object.
        """
        if encoded is None:
            return None

        def normalize(val):
            """
            Recursively converts construct Container values to serializable Python objects.
            Private items (key starts with '_') are filtered.
            """
            if isinstance(val, Container):
                return {
                    k: normalize(v)
                    for k, v in dict(val).items() if not k.startswith('_')
                }
            else:
                return val

        byte_val = unhexlify(encoded)

        if crc:
            if CRC8.calculate(byte_val) == b'\x00':
                byte_val = byte_val[:-1]
            else:
                raise exceptions.CRCFailed(f'{self} failed CRC check')

        return normalize(struct.parse(byte_val))
Exemple #16
0
 def _parse_program_headers(self):
     ProgramHeaders = Struct("segments" / Array(
         lambda ctx: self.e_phnum,
         "segment" / IfThenElse(
             lambda ctx: self.b64,
             Struct(
                 "p_type" / self.Word,
                 "p_flags" / self.Word,
                 "p_offset" / self.Off,
                 "p_vaddr" / self.Addr,
                 "p_paddr" / self.Addr,
                 "p_filesz" / self.Xword,
                 "p_memsz" / self.Xword,
                 "p_align" / self.Xword,
             ),
             Struct(
                 "p_type" / self.Word,
                 "p_offset" / self.Off,
                 "p_vaddr" / self.Addr,
                 "p_paddr" / self.Addr,
                 "p_filesz" / self.Word,
                 "p_memsz" / self.Word,
                 "p_flags" / self.Word,
                 "p_align" / self.Word,
             )),
     ))
     if hasattr(self, 'e_shnum'):
         #if self.e_shnum:
         #    print("PG_size: {}".format(ProgramHeaders.sizeof() / self.e_phnum))
         self._program_headers = ProgramHeaders.parse(
             self.fp[self.e_phoff:])
Exemple #17
0
    def __init__(self, filename, encoding=None, password=None, cached=True, check=False,
                 current_tablename=None, date_fieldname=None,
                 time_fieldname=None, decryptor_class=TpsDecryptor):
        self.filename = filename
        self.encoding = encoding
        self.password = password
        self.cached = cached
        self.check = check
        self.current_table_number = None
        # Name part before .tps
        self.name = os.path.basename(filename)
        self.name = text_type(os.path.splitext(self.name)[0]).lower()
        if date_fieldname is not None:
            self.date_fieldname = date_fieldname
        else:
            self.date_fieldname = []
        if time_fieldname is not None:
            self.time_fieldname = time_fieldname
        else:
            self.time_fieldname = []
        self.cache_pages = {}

        if not os.path.isfile(self.filename):
            raise FileNotFoundError(self.filename)

        self.file_size = os.path.getsize(self.filename)

        # Check file size
        if check:
            if self.file_size & 0x3F != 0:
                # TODO check translate
                warn('File size is not a multiple of 64 bytes.', RuntimeWarning)

        with open(self.filename, mode='r+b') as tpsfile:
            self.tps_file = mmap.mmap(tpsfile.fileno(), 0)

            self.decryptor = decryptor_class(self.tps_file, self.password)

            try:
                # TPS file header
                header = Struct('header',
                                ULInt32('offset'),
                                ULInt16('size'),
                                ULInt32('file_size'),
                                ULInt32('allocated_file_size'),
                                Const(Bytes('top_speed_mark', 6), b'tOpS\x00\x00'),
                                UBInt32('last_issued_row'),
                                ULInt32('change_count'),
                                ULInt32('page_root_ref'),
                                Array(lambda ctx: (ctx['size'] - 0x20) / 2 / 4, ULInt32('block_start_ref')),
                                Array(lambda ctx: (ctx['size'] - 0x20) / 2 / 4, ULInt32('block_end_ref')), )

                self.header = header.parse(self.read(0x200))
                self.pages = TpsPagesList(self, self.header.page_root_ref, check=self.check)
                self.tables = TpsTablesList(self, encoding=self.encoding, check=self.check)
                self.set_current_table(current_tablename)
            except adapters.ConstError:
                print('Bad cryptographic keys.')
Exemple #18
0
def test_single():
    s = Struct('a' / Byte, 'b' / DeferredValue(Byte), 'c' / Byte,
               'new_value' / Tell, WriteDeferredValue(this.new_value, this.b))

    # parsing
    assert s.parse(b'\x01\x02\x03') == {'a': 1, 'b': 2, 'c': 3, 'new_value': 3}

    # building
    assert s.build({'a': 0xff, 'c': 0xfe}) == b'\xff\x03\xfe'
Exemple #19
0
def test_group_adapter():
    s = Struct('groups' / commands.GroupListAdapter())

    for left, right in [([], b'\x00'), ([0, 1], b'\x03'),
                        ([i for i in range(8)], b'\xFF')]:
        assert s.build({'groups': left}) == right
        assert s.parse(right) == {'groups': left}

    with pytest.raises(ValueError):
        s.build({'groups': [8]})
Exemple #20
0
def test_list():
    s = Struct(
        ChecksumValue(hashlib.sha1, lambda this: this.data[0:2], True),
        'data' / Array(3, ChecksumSourceData(Struct(
            'a' / Byte
        ))),
        VerifyOrWriteChecksums
    )

    values = b'\x01\x02\x03'

    # same range
    hashval = hashlib.sha1(values[0:2]).digest()
    assert s.parse(hashval + values) == {'data': [{'a': 1}, {'a': 2}, {'a': 3}]}

    # different range
    hashval = hashlib.sha1(values[0:1]).digest()
    with pytest.raises(ChecksumVerifyError):
        s.parse(hashval + values)
Exemple #21
0
 def _parse_note(self, data):
     Note = Struct("namesz" / self.Word, "descsz" / self.Word,
                   "type" / self.Word, "name" / Bytes(this.namesz),
                   "desc" / Bytes(this.descsz))
     if not data:
         return None
     result = Note.parse(data)
     result.desc = binascii.b2a_hex(result.desc).decode()
     result.name = self.asciiCString.parse(result.name)
     return result
Exemple #22
0
def test_enumconvert():
    class TestEnum(Enum):
        A = 0x42

        @property
        def prop(self):
            return 1337

    s = Struct('e' / EnumConvert(Byte, TestEnum),
               'v' / Computed(lambda this: this.e.prop))

    # valid
    assert s.parse(b'\x42') == {'e': TestEnum.A, 'v': 1337}
    assert s.build({'e': TestEnum.A}) == b'\x42'

    # invalid
    with pytest.raises(MappingError):
        s.parse(b'\x00')
    with pytest.raises(MappingError):
        s.build({'e': 0})
Exemple #23
0
    def _parse_symbol_section(self, section):
        sh_link = section.sh_link
        if self.b64:
            pass
        else:
            pass
        Symbol = Struct(
            "st_name" / self.Word,
            "st_value" / self.Addr,
            "st_size" / self.Word,
            "st_info" / BitStruct(
                "st_bind" / BitsInteger(4),
                "st_type" / BitsInteger(4),
            ),
            "st_other" / Int8ul,
            "symbol_name" / Computed(lambda ctx: self.get_string(sh_link, ctx.st_name)),
            "st_shndx" / self.Half,
            "section_name" / Computed(lambda ctx: defs.section_name(ctx.st_shndx)),
             "hidden" / Computed(lambda ctx: ctx.st_other in
                 (defs.SymbolVisibility.STV_HIDDEN, defs.SymbolVisibility.STV_INTERNAL)),
        )
        """
        typedef struct {
            Elf32_Word  st_name;
            Elf32_Addr  st_value;
            Elf32_Word  st_size;
            unsigned char   st_info;
            unsigned char   st_other;
            Elf32_Half  st_shndx;
        } Elf32_Sym;

        typedef struct {
            Elf64_Word  st_name;
            unsigned char   st_info;
            unsigned char   st_other;
            Elf64_Half  st_shndx;
            Elf64_Addr  st_value;
            Elf64_Xword st_size;
        } Elf64_Sym;
        """
        num_symbols = len(section.image) // Symbol.sizeof()
        for offset in range(0, len(section.image), Symbol.sizeof()):
            sym = Symbol.parse(section.image[offset : offset + Symbol.sizeof()])
            db_sym = Elf_Symbol(st_name = sym.st_name, st_value = sym.st_value, st_size = sym.st_size,
                st_bind = sym.st_info.st_bind, st_type = sym.st_info.st_type, st_other = sym.st_other,
                st_shndx = sym.st_shndx, symbol_name = sym.symbol_name, section_name = sym.section_name,
                hidden = sym.hidden)
            self.session.add(db_sym)
        #print(db_sym)
        self.session.commit()
        query = self.session.query(Elf_Symbol)
        aaa = query.filter(Elf_Symbol.section_name == "SHN_ABS").all()
        print("SECTIONS",  [a.symbol_name for a in aaa])
Exemple #24
0
    def _recv_hello_request(self):
        fmt = Struct(
            'length' / Int32ul,
            'type' / Int32ul,
            'version' / Int32ul,
            'dummy' / Bytes(8),
            'seed' / Bytes(16),
        )

        msg = self._recv_msg()
        data = fmt.parse(msg)
        return data
Exemple #25
0
 def test(self):
     pstring = Struct("pstring", 
         UBInt8("length"),
         Struct("inner",
             UBInt8("inner_length"),
             Bytes("data", foo),
         )
     )
     obj = pstring.parse(six.b("\x03\x02helloXXX"))
     print(repr(obj))
     self.assertEqual(obj, Container(length = 3, inner = Container(inner_length = 2, data = six.b("hello"))))
     size = pstring._sizeof(Container(inner_length = 2, _ = Container(length = 3)))
     self.assertEqual(size, 7)
Exemple #26
0
def parse_header(data):
    """
    split up header information (using construct)
    """
    mavlink_header = Struct('header',
        Const(Byte('magic'), MAVLINK_MAGIC),
        Byte('plength'),
        Byte('sequence'),
        Byte('sysid'),
        Byte('compid'),
        Byte('msgid'),
    )
    return mavlink_header.parse(data[0:6])
Exemple #27
0
 def _parse_note(self, data):
     Note = Struct(
         "namesz" / self.Word,
         "descsz" / self.Word,
         "type" / self.Word,
         "name" / Bytes(this.namesz),
         "desc" / Bytes(this.descsz)
     )
     print(len(data), data.tobytes())
     result = Note.parse(data)
     result.desc = binascii.b2a_hex(result.desc).decode()
     print(result.desc)
     print(result)
Exemple #28
0
def test_parse():
    rawcopy = AttributeRawCopy(Array(3, Byte))

    # test default and custom name
    for name in [None, 'newname']:
        subcon = (name @ rawcopy) if name is not None else rawcopy
        s = Struct('num' / Byte, 'array' / subcon)

        value = s.parse(b'\xff\x01\x02\x03')
        assert value.num == 0xff
        assert value.array == [1, 2, 3]
        assert getattr(value.array,
                       '__raw__' if name is None else name) == b'\x01\x02\x03'
Exemple #29
0
def parse_header(data):
    """
    split up header information (using construct)
    """
    mavlink_header = Struct('header',
        Const(Byte('magic'), MAVLINK_MAGIC),
        Byte('plength'),
        Byte('sequence'),
        Byte('sysid'),
        Byte('compid'),
        Byte('msgid'),
    )
    return mavlink_header.parse(data[0:6])
Exemple #30
0
class TestMetaFieldStruct(unittest.TestCase):
    def setUp(self):
        self.mf = MetaField("data", lambda context: context["length"])
        self.s = Struct("foo", Byte("length"), self.mf)

    def test_trivial(self):
        pass

    def test_parse(self):
        c = self.s.parse(b"\x03ABC")
        self.assertEqual(c.length, 3)
        self.assertEqual(c.data, b"ABC")

        c = self.s.parse(b"\x04ABCD")
        self.assertEqual(c.length, 4)
        self.assertEqual(c.data, b"ABCD")

    def test_sizeof_default(self):
        self.assertRaises(SizeofError, self.mf.sizeof)

    def test_sizeof(self):
        context = Container(length=4)
        self.assertEqual(self.mf.sizeof(context), 4)
Exemple #31
0
class TestMetaFieldStruct(unittest.TestCase):
    def setUp(self):
        self.mf = MetaField("data", lambda context: context["length"])
        self.s = Struct("foo", Byte("length"), self.mf)

    def test_trivial(self):
        pass

    def test_parse(self):
        c = self.s.parse("\x03ABC")
        self.assertEqual(c.length, 3)
        self.assertEqual(c.data, "ABC")

        c = self.s.parse("\x04ABCD")
        self.assertEqual(c.length, 4)
        self.assertEqual(c.data, "ABCD")

    def test_sizeof_default(self):
        self.assertRaises(SizeofError, self.mf.sizeof)

    def test_sizeof(self):
        context = Container(length=4)
        self.assertEqual(self.mf.sizeof(context), 4)
Exemple #32
0
    def f(client: LedgerClient) -> DeviceResponse:
        response = client.apdu_exchange(INS, data, P1, P2)

        response_template = Struct(
            public_key=Prefixed(Int8ub, GreedyBytes),
            address=PascalString(Int8ub, "ascii"),
            chain_code=Bytes(32),
        )

        parsed_response = response_template.parse(response)
        return DeviceResponse(
            public_key=parsed_response.public_key,
            address=parsed_response.address,
            chain_code=parsed_response.chain_code,
        )
Exemple #33
0
    def _send_request(
        self,
        request_format: construct.struct,
        request_obj: Optional[Dict[str, Any]],
        response_format: construct.Struct,
    ) -> construct.Container:
        try:
            request = request_format.build(request_obj)
            self._send_packet(request)

            response_pkt = self._read_packet()

            return response_format.parse(response_pkt.message)
        except construct.ConstructError as e:
            raise lifescan.MalformedCommand(str(e))
    def _send_request(
        self,
        lba: int,
        request_format: construct.Struct,
        request_obj: Optional[Dict[str, Any]],
        response_format: construct.Struct,
    ) -> construct.Container:
        """Send a request to the meter, and read its response.

        Args:
          lba: the address of the block register to use, known
            valid addresses are 3, 4 and 5.
          request_format: a construct format identifier of the request to send
          request_obj: the object to format with the provided identifier
          response_format: a construct format identifier to parse the returned
            message with.

        Returns:
          The Container object parsed from the response received by the meter.

        Raises:
          lifescan.MalformedCommand if Construct fails to build the request or
            parse the response.

        """
        try:
            request = request_format.build(request_obj)
            request_raw = _PACKET.build(
                {"data": {
                    "value": {
                        "message": request
                    }
                }})
            logging.debug("Request sent: %s", binascii.hexlify(request_raw))
            self.scsi_.write10(lba, 1, request_raw)

            response_raw = self.scsi_.read10(lba, 1)
            logging.debug("Response received: %s",
                          binascii.hexlify(response_raw.datain))
            response_pkt = _PACKET.parse(response_raw.datain).data
            logging.debug("Response packet: %r", response_pkt)

            response = response_format.parse(response_pkt.value.message)
            logging.debug("Response parsed: %r", response)

            return response
        except construct.ConstructError as e:
            raise lifescan.MalformedCommand(str(e))
Exemple #35
0
 def _parse_comment(self, data):
     Line = Struct("line" / CString("ascii"), "pos" / Tell)
     if not data:
         return ""
     length = len(data)
     result = []
     i = 0
     if data.find(b"\x00") == -1:
         return str(data, "ascii")
     while i < length:
         #print("*** LINE", data[i : ])
         line = Line.parse(data[i:])
         if line.line:
             result.append(line.line)
         i += line.pos
     return '\n'.join(result)
Exemple #36
0
class TestEmbedingBranch(TestCase):

    def setUp(self):

        self.cons = Struct('foo',
            Enum(Byte("a_enum"),
                ALFA=1,
                BETA=2
                ),
                Switch('switch', lambda ctx: ctx.a_enum, {
                    'ALFA': Embed(Struct('struct_alfa', Byte('byte_alfa'))),
                    'BETA': Embed(Struct('struct_beta', Byte('byte_beta'))),
                })
            )

    def test_construct(self):
        contents = self.cons.parse('\x01\x03\xee\x33')
        self.assertIn('a_enum', contents)
        self.assertEqual(contents['a_enum'], 'ALFA')
        self.assertIn('byte_alfa', contents)
Exemple #37
0
def get_data(binary_data):
    """Get data from binary string."""

    raw_header, raw_body = binary_data[:HEADER_LENTH], binary_data[HEADER_LENTH+1:]

    # TODO !!! Uncomment when will take valid data !!!
    #header = HEADER_FORMAT.parse(raw_header)
    # if binascii.crc_hqx(raw_body, 0xffff) != header.checksum:
    #     logger.exception('Checksums is not match')
    #     raise InputError(binascii.crc_hqx(raw_body, 0xffff), 'Checksums is not match')

    result = {}

    while True:
        current_type = raw_body[:1]
        if not current_type:
            return result
        type_of_struct = "0x{}".format(binascii.hexlify(current_type))

        data = STRUCT_TYPES.get(type_of_struct, None)
        if not data:
            logger.exception('Data type is not exist')
            raise AttributeError

        data_size = data[1] if not isinstance(data[1], int) else Byte[data[1]]
        body_format = Struct(
            "type" / Int8ul,
            "data" / data_size,
        )

        # TODO !!! Remove that exception when will take valid data
        try:
            current = body_format.parse(raw_body[:data_size.sizeof()+1])
        except :
            return result

        result[data[0]] =  current.data

        raw_body = raw_body[body_format.sizeof():]
Exemple #38
0
            SERVER_INVITE_OPTION = 0x12
        ),
        Switch("OptionData", lambda ctx: ctx["OptionID"],
            {
                "CLIENT_NICK_OPTION" : CString('Nickname'),
                "CLIENT_MEMBERSHIP_OPTION" : ClientMemberShipOption,
                "SERVER_OPTION" : Struct("ServerOption", ULInt16('Port')),
                "SERVER_CHANNELS_OPTION" : PrefixedArray(CString('Channels'), ULInt8("NumChannels")),
                "SERVER_INVITE_OPTION" : ServerInviteOption
            }
        )
)


peerPDU = Struct(
          'peerPDU',
          CString('ClientID'),
          OptionalGreedyRepeater(Option)
)


if __name__ == '__main__':
    data = peerPDU.build(Container(ClientID="Bob", Option=[
                                                    Container(OptionID="SERVER_INVITE_OPTION", OptionData=Container(ChannelID="TM2011", ClientID=["Alice", "Billy"])),
                                                    Container(OptionID="CLIENT_NICK_OPTION", OptionData="Susan")]
                                  )
    )

    print repr(data)
    packet = peerPDU.parse(data)
    print packet
Exemple #39
0
class IpAddressAdapter(Adapter):
	def _encode(self,obj,context):
		return "".join(chr(int(b)) for b in obj.split())
	def _decode(self,obj,context):
		return ".".join(str(ord(b)) for b in obj)

#IpAddressAdapter(Bytes("foo",4)).parse("\x01\x02\x03\x04")



class PrintContext(Construct):
	def _parse(self, stream, context):
		print context
		print "hello"

foo = Struct("foo",
			 Byte("a"),
			 Byte("b"),
			 PrintContext("c"),
			 Struct("bar",
					Byte("a"),
					Byte("b"),
					PrintContext("c"),
					),
			 PrintContext("d"),
			 )

foo.parse("\x01\x02\x03\x04")


class RfidFrame(object):
    def __init__(self):
        # 接收数据的数据格式定义
        self.rfidFrame = Struct("frame",
                                OptionalGreedyRange(
                                    Struct("packets",
                                           UBInt16("header"),
                                           Enum(UBInt8("cmdcode"),
                                                F1=0xF1,
                                                F2=0xF2,
                                                F3=0xF3,
                                                F4=0xF4,
                                                ),
                                           Switch("datas", lambda ctx: ctx.cmdcode, {
                                               "F1": Struct("sub",
                                                            UBInt8("readerID"),
                                                            UBInt8("packet_len"),
                                                            UBInt8("status"),
                                                            Array(lambda ctx: (
                                                                                  ctx.packet_len - 2 - 1 - 1 - 1 - 1 - 2) / 6,
                                                                  Struct("blocks",
                                                                         # UBInt8('elec'),
                                                                         Array(3, UBInt8('cardID')),
                                                                         UBInt8('triggerID'),
                                                                         UBInt16('relativeTime')
                                                                         )
                                                                  )
                                                            ),
                                               "F2": Struct("sub", UBInt8("packet_len"), UBInt8("readerID")),
                                               "F3": Struct("sub", UBInt8("packet_len"), UBInt8("result")),
                                               "F4": Struct("sub", UBInt8("packet_len"), UBInt8("rssl")),
                                           }
                                                  ),
                                           UBInt16("crc"),
                                           )
                                ),
                                OptionalGreedyRange(
                                    UBInt8("leftovers"),
                                ),
                                )
        self.readerID = None
        self.rssl = 1
        self.triggerID = None

    def rfidFrameParse(self, bytestream):
        return self.rfidFrame.parse(bytestream)

    def handle_data(self, pkgs):
        cmdcode = pkgs[0].cmdcode
        # datas = pkgs.packets.datas[0]
        # 对指令码判断工作模式
        if cmdcode == "F1":
            # 存储温度,湿度,以及其他数据
            print self.data_p(pkgs)
            # #rfidDb.saveID( self.cardID,self.triggerID,) #存储触发器id和卡号到数据库
            #
            # print 'the trigger ID is :', self.triggerID
            # print 'the card ID is :', self.cardID

        elif cmdcode == "F2":
            # 得到阅读器id
            self.readerID = self.getReaderID(pkgs)
            print self.readerID

        elif cmdcode == 'F3':  # 此处还不能写小写的f3,是字符串匹配,要和系统返回的一样.否则无法进入循环
            # 获得设置门限值的结果
            result = self.getResult(pkgs)
            result = hex(result)  # 此处result的值是2进制数要转换成16进制数来进行门限值的设置结果判断

            if result == '0xaa':
                print 'setted success'
            else:
                print 'setted falure'

        elif cmdcode == "F4":
            # 得到门限值
            self.rssl = self.getRSSI(pkgs)
            print self.rssl

    def getReaderID(self, pkgs):
        return pkgs[0].datas.readerID

    def getCardID(self, pkgs):
        return pkgs[0].datas.blocks[0].cardID

    def getTriggerID(self, pkgs):
        return pkgs[0].datas.blocks[0].triggerID

    def getResult(self, pkgs):
        return pkgs[0].datas.result

    def getRSSI(self, pkgs):
        return pkgs[0].datas.rssl

    def data_p(self, pkgs):

        data = ""  # 处理卡号和触发器id
        important_data = ""
        for pkg in pkgs[0].datas.blocks:
            cardID = pkg.cardID
            if cardID[0] == 1:
                print cardID
                print dec_to_hex(cardID[1]) + dec_to_hex(cardID[2]), "电量异常"

            data += dec_to_hex(cardID[1])
            data += dec_to_hex(cardID[2])

            triggerID = pkg.triggerID
            if triggerID != 0:
                important_data += hex_to_dec(data) + ":" + str(triggerID) + ","
            data = ""

        important_data = important_data[0:-1] + "\n"
        return important_data
Exemple #41
0
class IPTransport(object):
    '''Implement IP transport.'''
    def __init__(self, device=None):
        '''Instantiate the first available PTP device over IP'''
        self.__setup_constructors()
        logger.debug('Init IP')

        self.__dev = device
        if device is None:
            raise NotImplementedError(
                'IP discovery not implemented. Please provide a device.'
            )
        self.__device = device

        # Signal usable implicit session
        self.__implicit_session_open = Event()
        # Signal implicit session is shutting down
        self.__implicit_session_shutdown = Event()

        self.__check_session_lock = Lock()
        self.__transaction_lock = Lock()

        self.__event_queue = Queue()

        atexit.register(self._shutdown)

    def _shutdown(self):
        try:
            self.__close_implicit_session()
        except Exception as e:
            logger.error(e)

    @contextmanager
    def __implicit_session(self):
        '''Manage implicit sessions with responder'''
        # There is now an implicit session
        self.__check_session_lock.acquire()
        if not self.__implicit_session_open.is_set():
            try:
                self.__open_implicit_session()
                self.__check_session_lock.release()
                yield
            except Exception as e:
                logger.error(e)
                raise PTPError('Failed to open PTP/IP implicit session')
            finally:
                if self.__implicit_session_open.is_set():
                    self.__close_implicit_session()
                if self.__check_session_lock.locked():
                    self.__check_session_lock.release()
        else:
            self.__check_session_lock.release()
            yield

    def __open_implicit_session(self):
        '''Establish implicit session with responder'''

        self.__implicit_session_shutdown.clear()

        # Establish Command and Event connections
        if type(self.__device) is tuple:
            host, port = self.__device
            self.__setup_connection(host, port)
        else:
            self.__setup_connection(self.__device)

        self.__implicit_session_open.set()

        # Prepare Event and Probe threads
        self.__event_proc = Thread(
            name='EvtPolling',
            target=self.__poll_events
        )
        self.__event_proc.daemon = False

        self.__ping_pong_proc = Thread(
            name='PingPong',
            target=self.__ping_pong
        )
        self.__ping_pong_proc.daemon = False

        # Launch Event and Probe threads
        self.__event_proc.start()
        self.__ping_pong_proc.start()

    def __close_implicit_session(self):
        '''Terminate implicit session with responder'''
        self.__implicit_session_shutdown.set()

        if not self.__implicit_session_open.is_set():
            return

        # Only join running threads.
        if self.__event_proc.is_alive():
            self.__event_proc.join(2)
        if self.__ping_pong_proc.is_alive():
            self.__ping_pong_proc.join(2)

        logger.debug('Close connections for {}'.format(repr(self.__dev)))
        try:
            self.__evtcon.shutdown(socket.SHUT_RDWR)
        except socket.error as e:
            if e.errno == 107:
                pass
            else:
                raise e
        try:
            self.__cmdcon.shutdown(socket.SHUT_RDWR)
        except socket.error as e:
            if e.errno == 107:
                pass
            else:
                raise e
        self.__evtcon.close()
        self.__cmdcon.close()

        self.__implicit_session_open.clear()

    def __setup_connection(self, host=None, port=15740):
        '''Establish a PTP/IP session for a given host'''
        logger.debug(
            'Establishing PTP/IP connection with {}:{}'
            .format(host, port)
        )
        socket.setdefaulttimeout(5)
        hdrlen = self.__Header.sizeof()
        # Command Connection Establishment
        self.__cmdcon = create_connection((host, port))
        # Send InitCommand
        # TODO: Allow users to identify as an arbitrary initiator.
        init_cmd_req_payload = self.__InitCommand.build(
            Container(
                InitiatorGUID=16*[0xFF],
                InitiatorFriendlyName='PTPy',
                InitiatorProtocolVersion=Container(
                    Major=100,
                    Minor=000,
                ),
            ))
        init_cmd_req = self.__Packet.build(
            Container(
                Type='InitCommand',
                Payload=init_cmd_req_payload,
            )
        )
        actual_socket(self.__cmdcon).sendall(init_cmd_req)
        # Get ACK/NACK
        init_cmd_req_rsp = actual_socket(self.__cmdcon).recv(72)
        init_cmd_rsp_hdr = self.__Header.parse(
            init_cmd_req_rsp[0:hdrlen]
        )

        if init_cmd_rsp_hdr.Type == 'InitCommandAck':
            cmd_ack = self.__InitCommandACK.parse(init_cmd_req_rsp[hdrlen:])
            logger.debug(
                'Command connection ({}) established'
                .format(cmd_ack.ConnectionNumber)
            )
        elif init_cmd_rsp_hdr.Type == 'InitFail':
            cmd_nack = self.__InitFail.parse(init_cmd_req_rsp[hdrlen:])
            msg = 'InitCommand failed, Reason: {}'.format(
                cmd_nack
            )
            logger.error(msg)
            raise PTPError(msg)
        else:
            msg = 'Unexpected response Type to InitCommand : {}'.format(
                init_cmd_rsp_hdr.Type
            )
            logger.error(msg)
            raise PTPError(msg)

        # Event Connection Establishment
        self.__evtcon = create_connection((host, port))
        self.__evtcon.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
        self.__evtcon.setsockopt(socket.IPPROTO_TCP, socket.SO_KEEPALIVE, 1)

        # Send InitEvent
        payload = self.__InitEvent.build(Container(
            ConnectionNumber=cmd_ack.ConnectionNumber,
        ))
        evt_req = self.__Packet.build(
            Container(
                Type='InitEvent',
                Payload=payload,
            )
        )
        actual_socket(self.__evtcon).sendall(evt_req)
        # Get ACK/NACK
        init_evt_req_rsp = actual_socket(self.__evtcon).recv(
            hdrlen + self.__InitFail.sizeof()
        )
        init_evt_rsp_hdr = self.__Header.parse(
            init_evt_req_rsp[0:hdrlen]
        )

        if init_evt_rsp_hdr.Type == 'InitEventAck':
            logger.debug(
                'Event connection ({}) established'
                .format(cmd_ack.ConnectionNumber)
            )
        elif init_evt_rsp_hdr.Type == 'InitFail':
            evt_nack = self.__InitFail.parse(init_evt_req_rsp[hdrlen:])
            msg = 'InitEvent failed, Reason: {}'.format(
                evt_nack
            )
            logger.error(msg)
            raise PTPError(msg)
        else:
            msg = 'Unexpected response Type to InitEvent : {}'.format(
                init_evt_rsp_hdr.Type
            )
            logger.error(msg)
            raise PTPError(msg)

    # Helper methods.
    # ---------------------
    def __setup_constructors(self):
        '''Set endianness and create transport-specific constructors.'''
        # Set endianness of constructors before using them.
        self._set_endian('little')

        self.__Length = Int32ul
        self.__Type = Enum(
            Int32ul,
            Undefined=0x00000000,
            InitCommand=0x00000001,
            InitCommandAck=0x00000002,
            InitEvent=0x00000003,
            InitEventAck=0x00000004,
            InitFail=0x00000005,
            Command=0x00000006,
            Response=0x00000007,
            Event=0x00000008,
            StartData=0x00000009,
            Data=0x0000000A,
            Cancel=0x0000000B,
            EndData=0x0000000C,
            Ping=0x0000000D,
            Pong=0x0000000E,
        )
        self.__Header = Struct(
            'Length' / self.__Length,
            'Type' / self.__Type,
        )
        self.__Param = Range(0, 5, self._Parameter)
        self.__EventParam = Range(0, 3, self._Parameter)
        self.__PacketBase = Struct(
            Embedded(self.__Header),
            'Payload' / Bytes(
                lambda ctx, h=self.__Header: ctx.Length - h.sizeof()),
        )
        self.__Packet = ExprAdapter(
            self.__PacketBase,
            encoder=lambda obj, ctx, h=self.__Header: Container(
                Length=len(obj.Payload) + h.sizeof(),
                **obj
            ),
            decoder=lambda obj, ctx: obj,
        )
        # Yet another arbitrary string type. Max-length CString utf8-encoded
        self.__PTPIPString = ExprAdapter(
            RepeatUntil(
                lambda obj, ctx, lst:
                six.unichr(obj) in '\x00' or len(lst) == 40, Int16ul
            ),
            encoder=lambda obj, ctx:
            [] if len(obj) == 0 else[ord(c) for c in six.text_type(obj)]+[0],
            decoder=lambda obj, ctx:
            u''.join(
                [six.unichr(o) for o in obj]
            ).split('\x00')[0],
        )
        # PTP/IP packets
        # Command
        self.__ProtocolVersion = Struct(
            'Major' / Int16ul,
            'Minor' / Int16ul,
        )
        self.__InitCommand = Embedded(Struct(
            'InitiatorGUID' / Array(16, Int8ul),
            'InitiatorFriendlyName' / self.__PTPIPString,
            'InitiatorProtocolVersion' / self.__ProtocolVersion,
        ))
        self.__InitCommandACK = Embedded(Struct(
            'ConnectionNumber' / Int32ul,
            'ResponderGUID' / Array(16, Int8ul),
            'ResponderFriendlyName' / self.__PTPIPString,
            'ResponderProtocolVersion' / self.__ProtocolVersion,
        ))
        # Event
        self.__InitEvent = Embedded(Struct(
            'ConnectionNumber' / Int32ul,
        ))
        # Common to Events and Command requests
        self.__Reason = Enum(
            # TODO: Verify these codes...
            Int32ul,
            Undefined=0x0000,
            RejectedInitiator=0x0001,
            Busy=0x0002,
            Unspecified=0x0003,
        )
        self.__InitFail = Embedded(Struct(
            'Reason' / self.__Reason,
        ))

        self.__DataphaseInfo = Enum(
            Int32ul,
            Undefined=0x00000000,
            In=0x00000001,
            Out=0x00000002,
        )
        self.__Command = Embedded(Struct(
            'DataphaseInfo' / self.__DataphaseInfo,
            'OperationCode' / self._OperationCode,
            'TransactionID' / self._TransactionID,
            'Parameter' / self.__Param,
        ))
        self.__Response = Embedded(Struct(
            'ResponseCode' / self._ResponseCode,
            'TransactionID' / self._TransactionID,
            'Parameter' / self.__Param,
        ))
        self.__Event = Embedded(Struct(
            'EventCode' / self._EventCode,
            'TransactionID' / self._TransactionID,
            'Parameter' / self.__EventParam,
        ))
        self.__StartData = Embedded(Struct(
            'TransactionID' / self._TransactionID,
            'TotalDataLength' / Int64ul,
        ))
        # TODO: Fix packing and unpacking dataphase data
        self.__Data = Embedded(Struct(
            'TransactionID' / self._TransactionID,
            'Data' / Bytes(
                lambda ctx:
                ctx._.Length -
                self.__Header.sizeof() -
                self._TransactionID.sizeof()
            ),
        ))
        self.__EndData = Embedded(Struct(
            'TransactionID' / self._TransactionID,
            'Data' / Bytes(
                lambda ctx:
                ctx._.Length -
                self.__Header.sizeof() -
                self._TransactionID.sizeof()
            ),
        ))
        self.__Cancel = Embedded(Struct(
            'TransactionID' / self._TransactionID,
        ))
        # Convenience construct for parsing packets

        self.__PacketPayload = Debugger(Struct(
            'Header' / Embedded(self.__Header),
            'Payload' / Embedded(Switch(
                lambda ctx: ctx.Type,
                {
                    'InitCommand': self.__InitCommand,
                    'InitCommandAck': self.__InitCommandACK,
                    'InitEvent': self.__InitEvent,
                    'InitFail': self.__InitFail,
                    'Command': self.__Command,
                    'Response': self.__Response,
                    'Event': self.__Event,
                    'StartData': self.__StartData,
                    'Data': self.__Data,
                    'EndData': self.__EndData,
                },
                default=Pass,
            ))
        ))

    def __parse_response(self, ipdata):
        '''Helper method for parsing data.'''
        # Build up container with all PTP info.
        response = self.__PacketPayload.parse(ipdata)
        # Sneak in an implicit Session ID
        response['SessionID'] = self.session_id
        return response

    def __recv(self, event=False, wait=False, raw=False):
        '''Helper method for receiving packets.'''
        hdrlen = self.__Header.sizeof()
        with self.__implicit_session():
            ip = (
                actual_socket(self.__evtcon)
                if event
                else actual_socket(self.__cmdcon)
            )
            data = bytes()
            while True:
                try:
                    ipdata = ip.recv(hdrlen)
                except socket.timeout:
                    if event:
                        return None
                    else:
                        ipdata = ip.recv(hdrlen)

                if len(ipdata) == 0 and not event:
                    raise PTPError('Command connection dropped')
                elif event:
                    return None

                # Read a single entire header
                while len(ipdata) < hdrlen:
                    ipdata += ip.recv(hdrlen - len(ipdata))
                header = self.__Header.parse(
                    ipdata[0:hdrlen]
                )
                # Read a single entire packet
                while len(ipdata) < header.Length:
                    ipdata += ip.recv(header.Length - len(ipdata))
                # Run sanity checks.
                if header.Type not in [
                        'Cancel',
                        'Data',
                        'Event',
                        'Response',
                        'StartData',
                        'EndData',
                ]:
                    raise PTPError(
                        'Unexpected PTP/IP packet type {}'
                        .format(header.Type)
                    )
                if header.Type not in ['StartData', 'Data', 'EndData']:
                    break
                else:
                    response = self.__parse_response(ipdata)

                if header.Type == 'StartData':
                    expected = response.TotalDataLength
                    current_transaction = response.TransactionID
                elif (
                        header.Type == 'Data' and
                        response.TransactionID == current_transaction
                ):
                    data += response.Data
                elif (
                        header.Type == 'EndData' and
                        response.TransactionID == current_transaction
                ):
                    data += response.Data
                    datalen = len(data)
                    if datalen != expected:
                        logger.warning(
                            '{} data than expected {}/{}'
                            .format(
                                'More' if datalen > expected else 'Less',
                                datalen,
                                expected
                            )
                        )
                    response['Data'] = data
                    response['Type'] = 'Data'
                    return response

        if raw:
            # TODO: Deal with raw Data packets??
            return ipdata
        else:
            return self.__parse_response(ipdata)

    def __send(self, ptp_container, event=False):
        '''Helper method for sending packets.'''
        packet = self.__Packet.build(ptp_container)
        ip = (
            actual_socket(self.__evtcon)
            if event
            else actual_socket(self.__cmdcon)
        )
        while ip.sendall(packet) is not None:
            logger.debug('Failed to send {} packet'.format(ptp_container.Type))

    def __send_request(self, ptp_container):
        '''Send PTP request without checking answer.'''
        # Don't modify original container to keep abstraction barrier.
        ptp = Container(**ptp_container)

        # Send unused parameters always
        ptp['Parameter'] += [0] * (5 - len(ptp.Parameter))

        # Send request
        ptp['Type'] = 'Command'
        ptp['DataphaseInfo'] = 'In'
        ptp['Payload'] = self.__Command.build(ptp)
        self.__send(ptp)

    def __send_data(self, ptp_container, data):
        '''Send data without checking answer.'''
        # Don't modify original container to keep abstraction barrier.
        ptp = Container(**ptp_container)
        # Send data
        ptp['Type'] = 'Data'
        ptp['DataphaseInfo'] = 'Out'
        ptp['Payload'] = data
        self.__send(ptp)

    # Actual implementation
    # ---------------------
    def send(self, ptp_container, data):
        '''Transfer operation with dataphase from initiator to responder'''
        logger.debug('SEND {}{}'.format(
            ptp_container.OperationCode,
            ' ' + str(list(map(hex, ptp_container.Parameter)))
            if ptp_container.Parameter else '',
        ))
        with self.__implicit_session():
            with self.__transaction_lock:
                self.__send_request(ptp_container)
                self.__send_data(ptp_container, data)
                # Get response and sneak in implicit SessionID and missing
                # parameters.
                return self.__recv()

    def recv(self, ptp_container):
        '''Transfer operation with dataphase from responder to initiator.'''
        logger.debug('RECV {}{}'.format(
            ptp_container.OperationCode,
            ' ' + str(list(map(hex, ptp_container.Parameter)))
            if ptp_container.Parameter else '',
        ))
        with self.__implicit_session():
            with self.__transaction_lock:
                self.__send_request(ptp_container)
                dataphase = self.__recv()
                if hasattr(dataphase, 'Data'):
                    response = self.__recv()
                    if (
                            (ptp_container.TransactionID != dataphase.TransactionID) or
                            (ptp_container.SessionID != dataphase.SessionID) or
                            (dataphase.TransactionID != response.TransactionID) or
                            (dataphase.SessionID != response.SessionID)
                    ):
                        raise PTPError(
                            'Dataphase does not match with requested operation'
                        )
                    response['Data'] = dataphase.Data
                    return response
                else:
                    return dataphase

    def mesg(self, ptp_container):
        '''Transfer operation without dataphase.'''
        op = ptp_container['OperationCode']
        if op == 'OpenSession':
            self.__open_implicit_session()

        with self.__implicit_session():
            with self.__transaction_lock:
                self.__send_request(ptp_container)
                # Get response and sneak in implicit SessionID and missing
                # parameters for FullResponse.
                response = self.__recv()

        rc = response['ResponseCode']
        if op == 'OpenSession':
            if rc != 'OK':
                self.__close_implicit_session()
        elif op == 'CloseSession':
            if rc == 'OK':
                self.__close_implicit_session()

        return response

    def event(self, wait=False):
        '''Check event.

        If `wait` this function is blocking. Otherwise it may return None.
        '''
        evt = None
        ipdata = None
        timeout = None if wait else 0.001
        if not self.__event_queue.empty():
            ipdata = self.__event_queue.get(block=not wait, timeout=timeout)
        if ipdata is not None:
            evt = self.__parse_response(ipdata)

        return evt

    def __poll_events(self):
        '''Poll events, adding them to a queue.'''
        logger.debug('Start')
        while (
                not self.__implicit_session_shutdown.is_set() and
                self.__implicit_session_open.is_set() and
                _main_thread_alive()
        ):
            try:
                evt = self.__recv(event=True, wait=False, raw=True)
            except OSError as e:
                if e.errno == 9 and not self.__implicit_session_open.is_set():
                    break
                else:
                    raise e
            if evt is not None:
                logger.debug('Event queued')
                self.__event_queue.put(evt)
            sleep(5e-3)
        logger.debug('Stop')

    def __ping_pong(self):
        '''Poll events, adding them to a queue.'''
        logger.debug('Start')
        last = time()
        while (
                not self.__implicit_session_shutdown.is_set() and
                self.__implicit_session_open.is_set() and
                _main_thread_alive()
        ):
            if time() - last > 10:
                logger.debug('PING')
                # TODO: implement Ping Pong
                last = time()
            sleep(0.10)
        logger.debug('Stop')
Exemple #42
0
class USBTransport(object):
    '''Implement USB transport.'''
    def __init__(self, *args, **kwargs):
        device = kwargs.get('device', None)
        '''Instantiate the first available PTP device over USB'''
        logger.debug('Init USB')
        self.__setup_constructors()
        # If no device is specified, find all devices claiming to be Cameras
        # and get the USB endpoints for the first one that works.
        if device is None:
            logger.debug('No device provided, probing all USB devices.')
        if isinstance(device, six.string_types):
            name = device
            logger.debug(
                'Device name provided, probing all USB devices for {}.'
                .format(name)
            )
            device = None
        else:
            name = None
        devs = (
            [device] if (device is not None)
            else find_usb_cameras(name=name)
        )
        self.__claimed = False
        self.__acquire_camera(devs)

        self.__event_queue = Queue()
        self.__event_shutdown = Event()
        # Locks for different end points.
        self.__inep_lock = RLock()
        self.__intep_lock = RLock()
        self.__outep_lock = RLock()
        # Slightly redundant transaction lock to avoid catching other request's
        # response
        self.__transaction_lock = RLock()

        self.__event_proc = Thread(
            name='EvtPolling',
            target=self.__poll_events
        )
        self.__event_proc.daemon = False
        atexit.register(self._shutdown)
        self.__event_proc.start()

    def __available_cameras(self, devs):
        for dev in devs:
            if self.__setup_device(dev):
                logger.debug('Found USB PTP device {}'.format(dev))
                yield
        else:
            message = 'No USB PTP device found.'
            logger.error(message)
            raise PTPError(message)

    def __acquire_camera(self, devs):
        '''From the cameras given, get the first one that does not fail'''

        for _ in self.__available_cameras(devs):
            # Stop system drivers
            try:
                if self.__dev.is_kernel_driver_active(
                        self.__intf.bInterfaceNumber):
                    try:
                        self.__dev.detach_kernel_driver(
                            self.__intf.bInterfaceNumber)
                    except usb.core.USBError:
                        message = (
                            'Could not detach kernel driver. '
                            'Maybe the camera is mounted?'
                        )
                        logger.error(message)
            except NotImplementedError as e:
                logger.debug('Ignoring unimplemented function: {}'.format(e))
            # Claim camera
            try:
                logger.debug('Claiming {}'.format(repr(self.__dev)))
                usb.util.claim_interface(self.__dev, self.__intf)
                self.__claimed = True
            except Exception as e:
                logger.warn('Failed to claim PTP device: {}'.format(e))
                continue
            self.__dev.reset()
            break
        else:
            message = (
                'Could not acquire any camera.'
            )
            logger.error(message)
            raise PTPError(message)

    def _shutdown(self):
        logger.debug('Shutdown request')
        self.__event_shutdown.set()
        # Free USB resource on shutdown.

        # Only join a running thread.
        if self.__event_proc.is_alive():
            self.__event_proc.join(2)

        try:
            if self.__claimed:
                logger.debug('Release {}'.format(repr(self.__dev)))
                usb.util.release_interface(self.__dev, self.__intf)
        except Exception as e:
            logger.warn(e)

    # Helper methods.
    # ---------------------
    def __setup_device(self, dev):
        '''Get endpoints for a device. True on success.'''
        self.__inep = None
        self.__outep = None
        self.__intep = None
        self.__cfg = None
        self.__dev = None
        self.__intf = None
        # Attempt to find the USB in, out and interrupt endpoints for a PTP
        # interface.
        for cfg in dev:
            for intf in cfg:
                if intf.bInterfaceClass == PTP_USB_CLASS:
                    for ep in intf:
                        ep_type = endpoint_type(ep.bmAttributes)
                        ep_dir = endpoint_direction(ep.bEndpointAddress)
                        if ep_type == ENDPOINT_TYPE_BULK:
                            if ep_dir == ENDPOINT_IN:
                                self.__inep = ep
                            elif ep_dir == ENDPOINT_OUT:
                                self.__outep = ep
                        elif ((ep_type == ENDPOINT_TYPE_INTR) and
                                (ep_dir == ENDPOINT_IN)):
                            self.__intep = ep
                if not (self.__inep and self.__outep and self.__intep):
                    self.__inep = None
                    self.__outep = None
                    self.__intep = None
                else:
                    logger.debug('Found {}'.format(repr(self.__inep)))
                    logger.debug('Found {}'.format(repr(self.__outep)))
                    logger.debug('Found {}'.format(repr(self.__intep)))
                    self.__cfg = cfg
                    self.__dev = dev
                    self.__intf = intf
                    return True
        return False

    def __setup_constructors(self):
        '''Set endianness and create transport-specific constructors.'''
        # Set endianness of constructors before using them.
        self._set_endian('little')

        self.__Length = Int32ul
        self.__Type = Enum(
                Int16ul,
                default=Pass,
                Undefined=0x0000,
                Command=0x0001,
                Data=0x0002,
                Response=0x0003,
                Event=0x0004,
                )
        # This is just a convenience constructor to get the size of a header.
        self.__Code = Int16ul
        self.__Header = Struct(
                'Length' / self.__Length,
                'Type' / self.__Type,
                'Code' / self.__Code,
                'TransactionID' / self._TransactionID,
                )
        # These are the actual constructors for parsing and building.
        self.__CommandHeader = Struct(
                'Length' / self.__Length,
                'Type' / self.__Type,
                'OperationCode' / self._OperationCode,
                'TransactionID' / self._TransactionID,
                )
        self.__ResponseHeader = Struct(
                'Length' / self.__Length,
                'Type' / self.__Type,
                'ResponseCode' / self._ResponseCode,
                'TransactionID' / self._TransactionID,
                )
        self.__EventHeader = Struct(
                'Length' / self.__Length,
                'Type' / self.__Type,
                'EventCode' / self._EventCode,
                'TransactionID' / self._TransactionID,
                )
        # Apparently nobody uses the SessionID field. Even though it is
        # specified in ISO15740:2013(E), no device respects it and the session
        # number is implicit over USB.
        self.__Param = Range(0, 5, self._Parameter)
        self.__CommandTransactionBase = Struct(
                Embedded(self.__CommandHeader),
                'Payload' / Bytes(
                    lambda ctx, h=self.__Header: ctx.Length - h.sizeof()
                )
        )
        self.__CommandTransaction = ExprAdapter(
                self.__CommandTransactionBase,
                encoder=lambda obj, ctx, h=self.__Header: Container(
                    Length=len(obj.Payload) + h.sizeof(),
                    **obj
                    ),
                decoder=lambda obj, ctx: obj,
                )
        self.__ResponseTransactionBase = Struct(
                Embedded(self.__ResponseHeader),
                'Payload' / Bytes(
                    lambda ctx, h=self.__Header: ctx.Length - h.sizeof())
                )
        self.__ResponseTransaction = ExprAdapter(
                self.__ResponseTransactionBase,
                encoder=lambda obj, ctx, h=self.__Header: Container(
                    Length=len(obj.Payload) + h.sizeof(),
                    **obj
                    ),
                decoder=lambda obj, ctx: obj,
                )

    def __parse_response(self, usbdata):
        '''Helper method for parsing USB data.'''
        # Build up container with all PTP info.
        logger.debug('Transaction:')
        usbdata = bytearray(usbdata)
        if logger.isEnabledFor(logging.DEBUG):
            for l in hexdump(
                    six.binary_type(usbdata[:512]),
                    result='generator'
            ):
                logger.debug(l)
        transaction = self.__ResponseTransaction.parse(usbdata)
        response = Container(
            SessionID=self.session_id,
            TransactionID=transaction.TransactionID,
        )
        logger.debug('Interpreting {} transaction'.format(transaction.Type))
        if transaction.Type == 'Response':
            response['ResponseCode'] = transaction.ResponseCode
            response['Parameter'] = self.__Param.parse(transaction.Payload)
        elif transaction.Type == 'Event':
            event = self.__EventHeader.parse(
                usbdata[0:self.__Header.sizeof()]
            )
            response['EventCode'] = event.EventCode
            response['Parameter'] = self.__Param.parse(transaction.Payload)
        else:
            command = self.__CommandHeader.parse(
                usbdata[0:self.__Header.sizeof()]
            )
            response['OperationCode'] = command.OperationCode
            response['Data'] = transaction.Payload
        return response

    def __recv(self, event=False, wait=False, raw=False):
        '''Helper method for receiving data.'''
        # TODO: clear stalls automatically
        ep = self.__intep if event else self.__inep
        lock = self.__intep_lock if event else self.__inep_lock
        usbdata = array.array('B', [])
        with lock:
            tries = 0
            # Attempt to read a header
            while len(usbdata) < self.__Header.sizeof() and tries < 5:
                if tries > 0:
                    logger.debug('Data smaller than a header')
                    logger.debug(
                        'Requesting {} bytes of data'
                        .format(ep.wMaxPacketSize)
                    )
                try:
                    usbdata += ep.read(
                        ep.wMaxPacketSize
                    )
                except usb.core.USBError as e:
                    # Return None on timeout or busy for events
                    if (
                            (e.errno is None and
                             ('timeout' in e.strerror.decode() or
                              'busy' in e.strerror.decode())) or
                            (e.errno == 110 or e.errno == 16 or e.errno == 5)
                    ):
                        if event:
                            return None
                        else:
                            logger.warning('Ignored exception: {}'.format(e))
                    else:
                        logger.error(e)
                        raise e
                tries += 1
            logger.debug('Read {} bytes of data'.format(len(usbdata)))

            if len(usbdata) == 0:
                if event:
                    return None
                else:
                    raise PTPError('Empty USB read')

            if (
                    logger.isEnabledFor(logging.DEBUG) and
                    len(usbdata) < self.__Header.sizeof()
            ):
                logger.debug('Incomplete header')
                for l in hexdump(
                        six.binary_type(bytearray(usbdata)),
                        result='generator'
                ):
                    logger.debug(l)

            header = self.__ResponseHeader.parse(
                bytearray(usbdata[0:self.__Header.sizeof()])
            )
            if header.Type not in ['Response', 'Data', 'Event']:
                raise PTPError(
                    'Unexpected USB transfer type. '
                    'Expected Response, Event or Data but received {}'
                    .format(header.Type)
                )
            while len(usbdata) < header.Length:
                usbdata += ep.read(
                    min(
                        header.Length - len(usbdata),
                        # Up to 64kB
                        64 * 2**10
                    )
                )
        if raw:
            return usbdata
        else:
            return self.__parse_response(usbdata)

    def __send(self, ptp_container, event=False):
        '''Helper method for sending data.'''
        ep = self.__intep if event else self.__outep
        lock = self.__intep_lock if event else self.__outep_lock
        transaction = self.__CommandTransaction.build(ptp_container)
        with lock:
            try:
                sent = 0
                while sent < len(transaction):
                    sent = ep.write(
                        # Up to 64kB
                        transaction[sent:(sent + 64*2**10)]
                    )
            except usb.core.USBError as e:
                # Ignore timeout or busy device once.
                if (
                        (e.errno is None and
                         ('timeout' in e.strerror.decode() or
                          'busy' in e.strerror.decode())) or
                        (e.errno == 110 or e.errno == 16 or e.errno == 5)
                ):
                    logger.warning('Ignored USBError {}'.format(e.errno))
                    ep.write(transaction)

    def __send_request(self, ptp_container):
        '''Send PTP request without checking answer.'''
        # Don't modify original container to keep abstraction barrier.
        ptp = Container(**ptp_container)
        # Don't send unused parameters
        try:
            while not ptp.Parameter[-1]:
                ptp.Parameter.pop()
                if len(ptp.Parameter) == 0:
                    break
        except IndexError:
            # The Parameter list is already empty.
            pass

        # Send request
        ptp['Type'] = 'Command'
        ptp['Payload'] = self.__Param.build(ptp.Parameter)
        self.__send(ptp)

    def __send_data(self, ptp_container, data):
        '''Send data without checking answer.'''
        # Don't modify original container to keep abstraction barrier.
        ptp = Container(**ptp_container)
        # Send data
        ptp['Type'] = 'Data'
        ptp['Payload'] = data
        self.__send(ptp)

    @property
    def _dev(self):
        return None if self.__event_shutdown.is_set() else self.__dev

    @_dev.setter
    def _dev(self, value):
        raise ValueError('Read-only property')

    # Actual implementation
    # ---------------------
    def send(self, ptp_container, data):
        '''Transfer operation with dataphase from initiator to responder'''
        datalen = len(data)
        logger.debug('SEND {} {} bytes{}'.format(
            ptp_container.OperationCode,
            datalen,
            ' ' + str(list(map(hex, ptp_container.Parameter)))
            if ptp_container.Parameter else '',
        ))
        with self.__transaction_lock:
            self.__send_request(ptp_container)
            self.__send_data(ptp_container, data)
            # Get response and sneak in implicit SessionID and missing
            # parameters.
            response = self.__recv()
        logger.debug('SEND {} {} bytes {}{}'.format(
            ptp_container.OperationCode,
            datalen,
            response.ResponseCode,
            ' ' + str(list(map(hex, response.Parameter)))
            if ptp_container.Parameter else '',
        ))
        return response

    def recv(self, ptp_container):
        '''Transfer operation with dataphase from responder to initiator.'''
        logger.debug('RECV {}{}'.format(
            ptp_container.OperationCode,
            ' ' + str(list(map(hex, ptp_container.Parameter)))
            if ptp_container.Parameter else '',
        ))
        with self.__transaction_lock:
            self.__send_request(ptp_container)
            dataphase = self.__recv()
            if hasattr(dataphase, 'Data'):
                response = self.__recv()
                if not (ptp_container.SessionID ==
                        dataphase.SessionID ==
                        response.SessionID):
                    self.__dev.reset()
                    raise PTPError(
                        'Dataphase session ID missmatch: {}, {}, {}.'
                        .format(
                            ptp_container.SessionID,
                            dataphase.SessionID,
                            response.SessionID
                        )
                    )
                if not (ptp_container.TransactionID ==
                        dataphase.TransactionID ==
                        response.TransactionID):
                    self.__dev.reset()
                    raise PTPError(
                        'Dataphase transaction ID missmatch: {}, {}, {}.'
                        .format(
                            ptp_container.TransactionID,
                            dataphase.TransactionID,
                            response.TransactionID
                        )
                    )
                if not (ptp_container.OperationCode ==
                        dataphase.OperationCode):
                    self.__dev.reset()
                    raise PTPError(
                        'Dataphase operation code missmatch: {}, {}.'.
                        format(
                            ptp_container.OperationCode,
                            dataphase.OperationCode
                        )
                    )

                response['Data'] = dataphase.Data
            else:
                response = dataphase

        logger.debug('RECV {} {}{}{}'.format(
            ptp_container.OperationCode,
            response.ResponseCode,
            ' {} bytes'.format(len(response.Data))
            if hasattr(response, 'Data') else '',
            ' ' + str(list(map(hex, response.Parameter)))
            if response.Parameter else '',
        ))
        return response

    def mesg(self, ptp_container):
        '''Transfer operation without dataphase.'''
        logger.debug('MESG {}{}'.format(
            ptp_container.OperationCode,
            ' ' + str(list(map(hex, ptp_container.Parameter)))
            if ptp_container.Parameter else '',
        ))
        with self.__transaction_lock:
            self.__send_request(ptp_container)
            # Get response and sneak in implicit SessionID and missing
            # parameters for FullResponse.
            response = self.__recv()
        logger.debug('MESG {} {}{}'.format(
            ptp_container.OperationCode,
            response.ResponseCode,
            ' ' + str(list(map(hex, response.Parameter)))
            if response.Parameter else '',
        ))
        return response

    def event(self, wait=False):
        '''Check event.

        If `wait` this function is blocking. Otherwise it may return None.
        '''
        evt = None
        usbdata = None
        if wait:
            usbdata = self.__event_queue.get(block=True)
        elif not self.__event_queue.empty():
            usbdata = self.__event_queue.get(block=False)

        if usbdata is not None:
            evt = self.__parse_response(usbdata)

        return evt

    def __poll_events(self):
        '''Poll events, adding them to a queue.'''
        while not self.__event_shutdown.is_set() and _main_thread_alive():
            try:
                evt = self.__recv(event=True, wait=False, raw=True)
                if evt is not None:
                    logger.debug('Event queued')
                    self.__event_queue.put(evt)
            except usb.core.USBError as e:
                logger.error(
                    '{} polling exception: {}'.format(repr(self.__dev), e)
                )
                # check if disconnected
                if e.errno == 19:
                    break
            except Exception as e:
                logger.error(
                    '{} polling exception: {}'.format(repr(self.__dev), e)
                )
Exemple #43
0
"""
What : Internet Group Management Protocol, Version 2
 How : http://www.ietf.org/rfc/rfc2236.txt
 Who : jesse @ housejunkie . ca
"""

from construct import Byte, Enum,Struct, UBInt16
from construct.protocols.layer3.ipv4 import IpAddress
from binascii import unhexlify
import six


igmp_type = Enum(Byte("igmp_type"), 
    MEMBERSHIP_QUERY = 0x11,
    MEMBERSHIP_REPORT_V1 = 0x12,
    MEMBERSHIP_REPORT_V2 = 0x16,
    LEAVE_GROUP = 0x17,
)

igmpv2_header = Struct("igmpv2_header",
    igmp_type,
    Byte("max_resp_time"),
    UBInt16("checksum"),
    IpAddress("group_address"),
)

if __name__ == '__main__':
    capture = unhexlify(six.b("1600FA01EFFFFFFD"))
    print (igmpv2_header.parse(capture))
Exemple #44
0
 Who : jesse @ housejunkie . ca
"""

from construct import (
    Byte,
    Enum,
    Struct,
    UBInt16,
    UBInt32,
)
from construct.protocols.layer3.ipv4 import IpAddress

igmp_type = Enum(Byte("igmp_type"), 
    MEMBERSHIP_QUERY = 0x11,
    MEMBERSHIP_REPORT_V1 = 0x12,
    MEMBERSHIP_REPORT_V2 = 0x16,
    LEAVE_GROUP = 0x17,
)

igmpv2_header = Struct("igmpv2_header",
    igmp_type,
    Byte("max_resp_time"),
    UBInt16("checksum"),
    IpAddress("group_address"),
)

if __name__ == '__main__':
    
    capture = "1600FA01EFFFFFFD".decode("hex")
    print igmpv2_header.parse(capture)
Exemple #45
0
def ssexy_linux(fname, *eips):
    import elf32
    from construct import Struct, ULInt32, ULInt16, ULInt8, Array, CString
    from construct import OptionalGreedyRange

    # assume low-endian binary
    elf32_rel = Struct('elf32_rel', ULInt32('r_offset'), ULInt32('r_info'))
    ELF32_R_SYM = lambda x: x.r_info >> 8
    ELF32_R_TYPE = lambda x: x.r_info & 0xff
    R_386_PC32 = 2

    elf32_sym = Struct('elf32_sym', ULInt32('st_name'), ULInt32('st_value'),
        ULInt32('st_size'), ULInt8('st_info'), ULInt8('st_other'),
        ULInt16('st_shndx'))

    elf = elf32.elf32_file.parse_stream(file(fname, 'rb'))

    # retrieve section by name
    elf32_section = lambda elf, name: [x for x in elf.sections
        if x.name == name][0]

    # for now we assume that all code is in the .text section
    code_section = [x for x in elf.sections if x.name == '.text']
    if not len(code_section):
        raise Exception('your binary doesn\'t have a .text section..')

    relocs = [x.data.value for x in elf.sections if x.name == '.rel.dyn']
    if not len(relocs):
        raise Exception('no relocs available, compile with -pie')

    # read all relocations
    relocs = Array(len(relocs[0]) / elf32_rel.sizeof(),
        elf32_rel).parse(relocs[0])
    # now get the offsets of the relocations
    relocs = set([x.r_offset for x in relocs])

    imports = {}

    # a list of addresses that were used.
    addresses = []

    # a list of all m128 values we use
    m128s = []

    # a list of all dword values we use
    m32s = []

    instructions = pyasm2.block()

    # get string at offset
    dynstr = lambda x: CString(None).parse(
        elf32_section(elf, '.dynstr').data.value[x:])

    # read the symbol table
    imports = OptionalGreedyRange(elf32_sym).parse(elf32_section(elf,
        '.dynsym').data.value)

    # resolve relocations
    section = elf32_section(elf, '.rel.dyn')
    relocates = {}
    for x in xrange(0, section.size, elf32_rel.sizeof()):
        x = elf32_rel.parse(section.data.value[x:x+elf32_rel.sizeof()])
        # relocation to fixup addresses to imports
        if ELF32_R_TYPE(x) == R_386_PC32:
            relocates[x.r_offset] = dynstr(imports[ELF32_R_SYM(x)].st_name)

    # walk each section, find those that are executable and disassemble those
    section = elf32_section(elf, '.text')
    g = distorm3.DecomposeGenerator(section.addr, section.data.value,
            distorm3.Decode32Bits)
    for instr in g:
        # useless instruction?
        if str(instr) in ('NOP', 'ADD [EAX], AL', 'LEA ESI, [ESI]',
                    'INT 3') or str(instr)[:2] == 'DB':
            continue

        # a jump to one of the imports?
        #if instr.mnemonic == 'JMP' and instr.operands[0].type == \
        #        distorm3.OPERAND_ABSOLUTE_ADDRESS and \
        #        instr.operands[0].disp in imports:
        #    iat_label[instr.address] = imports[instr.operands[0].disp]
        #    continue

        # quite hackery, but when the jumps with thunk address have been
        # processed, we can be fairly sure that there will be no (legit)
        # code anymore.
        #if len(iat_label):
        #    break

        #print str(instr)

        #print str(instr)

        # convert the instruction from distorm3 format to pyasm2 format.
        instr = distorm3_to_pyasm2(instr)

        # we create the block already here, otherwise our `labelnr' is
        # not defined.
        #block = pyasm2.block(pyasm2.Label('%08x' % instr.address), instr)
        offset_flat = None
        addr = instr.address

        # now we check if this instruction has a relocation inside it
        # not a very efficient way, but oke.
        reloc = instr.length > 4 and relocs.intersection(range(
            instr.address, instr.address + instr.length - 3))
        if reloc:
            # make an immediate with `addr' set to True
            enable_addr = lambda x: Immediate(int(x), addr=True)

            # TODO support for two relocations in one instruction
            # (displacement *and* immediate)
            reloc = reloc.pop()
            if not hasattr(instr, 'op1'):
                instr.op1, instr.op2 = None, None
            # there is only one operand, that's easy
            if not instr.op2:
                #sys.stderr.write('reloc in op1 %s??\n' % instr.op1)
                if isinstance(instr.op1, pyasm2.MemoryAddress):
                    # special occassion, this memory addres is an import
                    if instr.op1.reg1 is None and \
                            instr.op1.reg2 is None and \
                            int(instr.op1.disp) in imports:
                        instr.op1 = imports[int(instr.op1.disp)]
                    else:
                        addresses.append(int(instr.op1.disp))
                        # change the displacement to a label
                        #instr.op1 = str(instr.op1).replace('0x',
                        #    '__lbl_00')
                        instr.op1 = enable_addr(instr.op1)
                elif isinstance(instr.op1, pyasm2.Immediate):
                    addresses.append(int(instr.op1))
                    offset_flat = int(instr.op1)
                    #instr.op1 = str(instr.op1).replace('0x',
                    #    'offset flat:__lbl_00')
            # if the second operand is an immediate and the relocation is
            # in the last four bytes of the instruction, then this
            # immediate is the reloc. Otherwise, if the second operand is
            # a memory address, then it's the displacement.
            elif isinstance(instr.op2, pyasm2.Immediate) and reloc == \
                    instr.address + instr.length - 4:
                # keep this address
                addresses.append(int(instr.op2))
                # make a label from this address
                # TODO: fix this horrible hack
                offset_flat = int(instr.op2)
                #instr.op2 = pyasm2.Label('offset flat:__lbl_%08x' %
                #    int(instr.op2), prepend=False)
            elif isinstance(instr.op2, pyasm2.MemoryAddress) and \
                    reloc == instr.address + instr.length - 4:
                addresses.append(int(instr.op2.disp))
                # change the displacement to a label
                instr.op2 = enable_addr(instr.op2)
                #instr.op2 = str(instr.op2).replace('0x', '__lbl_00')
                #sys.stderr.write('reloc in op2 memaddr %s\n' %
                #    str(instr.op2))
            # the relocation is not inside the second operand, it must be
            # inside the first operand after all.
            elif isinstance(instr.op1, pyasm2.MemoryAddress):
                addresses.append(int(instr.op1.disp))
                instr.op1 = enable_addr(instr.op1)
                #instr.op1 = str(instr.op1).replace('0x', '__lbl_00')
                #sys.stderr.write('reloc in op1 memaddr %s\n' %
                #    str(instr.op1))
            elif isinstance(instr.op1, pyasm2.Immediate):
                addresses.append(int(instr.op1))
                instr.op1 = enable_addr(instr.op1)
                #instr.op1 = '__lbl_%08x' % int(instr.op1)
                #sys.stderr.write('reloc in op1 imm %s\n' % instr.op1)
            else:
                sys.stderr.write('Invalid Relocation!\n')

        #print instr
        m32len = len(m32s)
        instr = translate.Translater(instr, m128s, m32s).translate()
        if offset_flat:
            encode_offset_flat = lambda x: str(x).replace('0x',
                'offset flat:__lbl_') if isinstance(x, (int, long,
                pyasm2.imm)) and int(x) == offset_flat or isinstance(x,
                pyasm2.mem) and x.disp == offset_flat else x

            if isinstance(instr, pyasm2.block):
                for x in instr.instructions:
                    x.op1 = encode_offset_flat(x.op1)
                    x.op2 = encode_offset_flat(x.op2)
            else:
                x.op1 = encode_offset_flat(x.op1)
                x.op2 = encode_offset_flat(x.op2)

            # update stuff
            m32s = m32s[:m32len] + [x.replace('0x%08x' % offset_flat,
                'offset flat:__lbl_%08x' % offset_flat)
                for x in m32s[m32len:]]

        instructions += pyasm2.block(pyasm2.Label('%08x' % addr), instr)

    # remove any addresses that are from within the current section
    newlist = addresses[:]
    for i in xrange(len(addresses)):
        if addresses[i] >= code_section[0].addr and addresses[i] < \
                code_section[0].addr + code_section[0].size:
            newlist[i] = None
    addresses = filter(lambda x: x is not None, newlist)

    # walk over each instruction, if it has references, we update them
    for instr in instructions.instructions:
        # we can skip labels
        if isinstance(instr, pyasm2.Label):
            continue

        # check for references to imports
        if isinstance(instr, pyasm2.RelativeJump):
            # not very good, but for now (instead of checking relocs) we check
            # if the index is in the iat tabel..
            #if int(instr.lbl.index, 16) in iat_label:
                #instr.lbl.index = iat_label[int(instr.lbl.index, 16)]
                #instr.lbl.prepend = False
            continue

    program = ['.file "ssexy.c"', '.intel_syntax noprefix']

    # we walk over each section, if a reference to this section has been found
    # then we will dump the entire section as bytecode.. with matching labels
    for section in elf.sections:
        base = section.addr
        data = section.data.value
        addr = set(range(base, base + section.size)).intersection(addresses)
        if addr:
            # create a header for this section
            program.append('.section %s' % section.name)

            # for now we do it the easy way.. one line and label per byte, lol
            for addr in xrange(section.size):
                program.append('__lbl_%08x: .byte 0x%02x' % (base + addr,
                    ord(data[addr])))

            # empty line..
            program.append('')

    # now we define all xmm's etc we gathered
    program.append('.align 4')
    program += m32s
    program.append('.align 16')
    program += m128s

    # time to define 'main'
    program.append('.text')
    program.append('.globl Main')
    program.append('.type Main, @function')

    OEP = elf.entry

    # f****d up shit
    relocates = dict(('jmp __lbl_%08x' % k, 'jmp ' + v)
        for k, v in relocates.items())

    eips = ['__lbl_%08x' % x for x in eips]

    # append each instruction
    for instr in instructions.instructions:
        # if this is an label, we want a colon as postfix
        if isinstance(instr, pyasm2.Label):
            program.append(str(instr) + ':')

            # if OEP is at this address, we will also add the `_main' label
            if str(instr) == '__lbl_%08x' % OEP:
                program.append('Main:')

                # we have to initialize the stack register, so..
                # for now we assume esp gpr is stored as first gpr in xmm7
                program.append('movd xmm7, esp')

            # if the label is in the list of addresses to which we have to add
            # an "movd xmm7, esp" instruction, then add it (e.g. callback
            # function for pthread_create)
            if str(instr) in eips:
                program.append('movd xmm7, esp')
        else:
            # TODO: fix this terrible hack as well
            program.append(str(instr).replace('byte', 'byte ptr').replace(
                'word', 'word ptr').replace('retn', 'ret').replace(
                '__lbl_00400000', '0x400000').replace('oword ptr', ''))
            if program[-1] in relocates:
                program[-1] = relocates[program[-1]]

    print '\n'.join(program)
Exemple #46
0
  if(sysstr =="Windows"):
    print ("Call Windows tasks")
  elif(sysstr == "Linux"):
    print ("Call Linux tasks")
  else:
    print ("Other System tasks")

# UsePlatform()


from construct import Struct, OptionalGreedyRange, Embed, Enum, Switch,String
from construct import UBInt8, UBInt16, UBInt32, UBInt64, Byte
from construct.macros import Array
rfid = Struct("frame",
                   UBInt8("flagID"),
                   String("f",1),
                     Array(4, String("nodeID",1)),
                   )
mm = rfid.parse("F1070E0100138E0000F21D65" | hexStr_to_hex)
print mm
print [binascii.b2a_hex(x) for x in mm.nodeID]
# print binascii.b2a_hex(mm.f)
# print mm.flagID
# print '01' | hex_to_dec
# print [binascii.b2a_hex(x) for x in mm.nodeID ]

a = {'or':2}
# print a[::-1]
if not a.get('order'):
    print 12