Пример #1
0
class Request(object):
    """Parse the Socks4 request from the client.
    """
    SOCKS_4_REQUEST_STRUCT = Struct(
        "cd" / Byte,
        "dstport" / Int16ub,
        "dstip" / Int32ub,
        "userid" / RepeatUntil(lambda b, _1, _2: b == 0, Byte),
    )

    def __init__(self, cd, dstport, dstip, userid):
        self.vn = VERSION
        self.cd = cd
        self.dstport = dstport
        self.dstip = dstip
        self.userid = userid

    @classmethod
    def parse_stream(cls, stream):
        try:
            req = cls.SOCKS_4_REQUEST_STRUCT.parse_stream(stream)
            return cls(cd=req.cd,
                       dstport=req.dstport,
                       dstip=ipaddress.ip_address(req.dstip),
                       userid=req.userid[:-1])
        except StreamError as ex:
            raise ex
            raise SocksError("Error parsing socks 4 request")

    def __repr__(self):
        return repr(self.__dict__)
Пример #2
0
def _gen_fmh3_struct(int_type, pointer_type, codepoint_type, addr_mode='rel'):
    return Struct(
        "pointer_offset" / (Computed(0) if addr_mode == 'abs' else Tell),
        "signature" / Const(b'FMH3'),
        Padding(4),
        "fonts_count" / Padded(pointer_type.sizeof(), int_type),
        "fonts_pointers_offset" / pointer_type,
        "fonts" / Pointer(
            lambda this: this.fonts_pointers_offset + this.pointer_offset,
            RepeatUntil(
                lambda obj, lst, ctx: ctx._index >= ctx.fonts_count - 1,
                Struct(
                    "pointer" / pointer_type,
                    "data" / Pointer(
                        lambda this: this.pointer + this._.pointer_offset,
                        Struct(
                            "id" / int_type,
                            "advance_width" / Byte,
                            "line_height" / Byte,
                            "box_width" / Byte,
                            "box_height" / Byte,
                            "layout_param_1" / Byte,
                            "layout_param_2_numerator" / Byte,
                            "layout_param_2_denominator" / Byte,
                            Padding(1),
                            "other_params?" / int_type,
                            "tex_size_chars" / int_type,
                            "chars_count" / int_type,
                            "chars_pointer" / pointer_type,
                            "chars" / Pointer(
                                lambda this: this.chars_pointer + this._._.
                                pointer_offset,
                                RepeatUntil(
                                    lambda obj, lst, ctx: ctx._index >= ctx.
                                    chars_count - 1,
                                    Struct(
                                        "codepoint" / codepoint_type,
                                        "halfwidth" / Flag,
                                        Padding(1),
                                        "tex_col" / Byte,
                                        "tex_row" / Byte,
                                        "glyph_x" / Byte,
                                        "glyph_width" / Byte,
                                    ))),
                        )),
                ))),
    )
Пример #3
0
def DelimitedField(stop):

    return _StripDelimiter(
        Sequence(
            RepeatUntil(
                lambda x, lst, ctx: lst[-len(stop):] == [int(c) for c in stop],
                Byte), Computed(this[0][:-len(stop)]),
            Seek(-len(stop), whence=1)))
Пример #4
0
 def __init__(self, idx_field, subcon):
     super().__init__(RepeatUntil(
         lambda obj, values, ctx: obj["idx"] < 0,
         Struct(
             "idx" / idx_field,
             Check(lambda this: abs(this.idx) == this._index + 1),
             "data" / subcon,
         ),
     ))
Пример #5
0
def Label(name):
    '''
    return a construct to parse/build a DNS label.

    Example:
    >> Label('qname').parse('\x05hello\x00')
    >> ['hello', '']

    :param name: the name of the field
    :type name: string
    :returns: a construct to parse/build a DNS label
    :rtype: construct.core.RepeatUntil
    '''
    return RepeatUntil(
        lambda obj, ctx: obj == '',
        PascalString(name),
    )
Пример #6
0
         Bytes(10),
     )),
 "fog_of_war" / Flag,
 "cheat_notifications" / Flag,
 "colored_chat" / Flag,
 Bytes(4),
 "ranked" / Flag,
 "allow_specs" / Flag,
 Bytes(3),
 separator,
 Bytes(12),
 "strings" / Array(
     23,
     Struct(
         "string" / de_string,
         RepeatUntil(lambda x, lst, ctx: lst[-1] not in [3, 21, 42],
                     Int32ul))),
 "strategic_numbers" / Array(59, Int32sl),
 "num_ai_files" / Int32ul,
 Const(b"\x00\x00\x00\x00"),
 "ai_files" / Array(lambda ctx: ctx.num_ai_files,
                    Struct(
                        Bytes(4),
                        "name" / de_string,
                        Bytes(4),
                    )),
 "guid" / Bytes(16),
 "lobby_name" / de_string,
 de_string,
 Bytes(19),
 de_string,
 Bytes(5),
Пример #7
0
from crypto.aeswrap import AESUnwrap
from zipfile import crc32
import struct

Dkey = 0x446B6579
EMF = 0x454D4621
BAG1 = 0x42414731
DONE = 0x444f4e45  #locker sentinel
#**** = 0x2A2A2A2A   #wildcard for erase

#MAGIC (kL) | LEN (2bytes) | TAG (4) | DATA (LEN)
Locker = Struct("Locker", String("magic", 2), ULInt16("length"),
                Union("tag", ULInt32("int"), String("tag", 4)),
                String("data", lambda ctx: ctx["length"]))

Lockers = RepeatUntil(lambda obj, ctx: obj.tag.int == DONE, Locker)


def xor_strings(s, key):
    res = ""
    for i in xrange(len(s)):
        res += chr(ord(s[i]) ^ ord(key[i % len(key)]))
    return res


def check_effaceable_header(plog):
    z = xor_strings(plog[:16], plog[16:32])
    if z[:4] != "ecaF":
        return False
    plog_generation = struct.unpack("<L", plog[0x38:0x3C])[0]
    print "Effaceable generation", plog_generation
Пример #8
0
class DurationAdapter(Adapter):
    def _decode(self, obj, context, path):
        secs = obj // (10**7)
        nanosecs = (obj - secs * (10**7)) * 100
        return timedelta64(secs, 's') + timedelta64(nanosecs, 'ns')

    def _encode(self, obj, context, path):
        return int(uint64(obj.astype('O')))


Duration = DurationAdapter(Int64ul)
PVoid = IfThenElse(lambda ctx: ctx.is_64bit, Int64ul, Int32ul)

UTF16MultiSz = ExprAdapter(
    RepeatUntil(lambda x, lst, ctx: not x, CString("UTF_16_le")),
    lambda obj, ctx: list(obj[:-1]),  # last element is the null
    lambda obj, ctx: obj + [''])


def SizedUTF16MultiSz(size_func):
    return ExprAdapter(
        FixedSized(size_func, GreedyRange(CString("UTF_16_le"))),
        lambda obj, ctx: list(obj[:-1]),  # last element is the null
        lambda obj, ctx: obj + [''])


class CheckCustom(Check):
    def __init__(self, func, exc_type, msg):
        super(CheckCustom, self).__init__(func)
        self.exc_type = exc_type
Пример #9
0
SurfaceResult = Struct("type" / Const(1, Int8ul), "status" / Int32ul)

DecodingResult = Struct("type" / Const(2, Int8ul), "status" / Int32ul)

RectResult = Struct("type" / Const(3, Int8ul), "status" / Int32ul)
"""
This struct encompass all calista stream
"""
Bitmap = Struct("type" / Const(4, Int8ul), "index" / Int32ul,
                "length" / Int32ul, "data" / Bytes(lambda this: this.length),
                "info" / RdpBitmapinfo, "have_point" / Int8ul,
                "point" / If(lambda this: this.have_point != 0, Int64ul))

CacdecDump = Struct(
    "magic" / Const(b"CacDec01"), "objects" / RepeatUntil(
        lambda x, lst, ctx: len(x._io.getbuffer()) == x._io.tell(),
        Select(SurfaceContext, SurfaceResult, DecodingResult, RectResult,
               Bitmap)))


def write_bmp(file_path, width, height, data):
    """
    Write a BMP file a output
    :param file_path: path of file
    :param width: with of image
    :param height: height of image
    :param data: raw image data
    """
    with open(file_path, "wb") as f:
        f.write(b"BM" + pack("<L",
                             len(data) + 0x36) +
                b"\x00\x00\x00\x00\x32\x00\x00\x00\x28\x00\x00\x00" +
Пример #10
0
    "object_type" / Int16ul, "sprite" / Int16ul, "garrisoned_in_id" / Int32sl,
    "hitpoints" / Float32l, "object_state" / Byte, "sleep" / Flag,
    "doppleganger" / Flag, "go_to_sleep" / Flag, "object_id" / Int32ul,
    "facet" / Byte, "x" / Float32l, "y" / Float32l, "z" / Float32l,
    "screen_offset_x" / Int16ul, "screen_offset_y" / Int16ul,
    "shadow_offset_x" / Int16ul, "shadow_offset_y" / Int16ul,
    "selected_group" / If(lambda ctx: find_version(ctx) == Version.AOK, Byte),
    ResourceEnum("resource_type" / Int16sl), "amount" / Float32l,
    "worker_count" / Byte, "current_damage" / Byte, "damaged_lately_timer" /
    Byte, "under_attack" / Byte, "pathing_group_len" / Int32ul, "pathing_group"
    / Array(lambda ctx: ctx.pathing_group_len, "object_id" / Int32ul),
    "group_id" / Int32sl, "roo_already_called" / Byte, "de_static_unk1" /
    If(lambda ctx: find_version(ctx) == Version.DE, Bytes(19)),
    "has_sprite_list" / Byte, "sprite_list" /
    If(lambda ctx: ctx.has_sprite_list != 0,
       RepeatUntil(lambda x, lst, ctx: lst[-1].type == 0, sprite_list)),
    "de_effect_block" / If(
        lambda ctx: find_version(ctx) == Version.DE,
        Struct(
            Padding(4), "has_effect" / Byte, "effect" / If(
                lambda ctx: ctx.has_effect == 1,
                Struct(Padding(3), "length" / Int16ul,
                       "name" / Bytes(lambda ctx: ctx.length),
                       If(lambda ctx: ctx.length > 0, Padding(33)))),
            If(
                lambda ctx: ctx.effect is None or
                (ctx.effect and ctx.effect.length > 0), Byte), Padding(4))))

animated = "animated" / Struct(Embedded(static), "turn_speed" / Float32l)

path_data = "path_data" / Struct(
Пример #11
0
    "items",
    SBInt16("primary"),
    If(
        lambda context: context["primary"] >= 0,
        Embed(
            Struct(
                "item_information",
                UBInt8("count"),
                UBInt16("secondary"),
            )),
    ),
)

# Metadata subconstruct.
metadata = StringAdapter(
    RepeatUntil(lambda obj, ctx: obj == "\x7f", Field("metadata", 1)))

# Build faces, used during dig and build.
faces = {
    "noop": -1,
    "-y": 0,
    "+y": 1,
    "-z": 2,
    "+z": 3,
    "-x": 4,
    "+x": 5,
}
face = Enum(SBInt8("face"), **faces)

packets = {
    0:
Пример #12
0
WIPTag = Struct(
    'WIPTag',
    'name' / WIPString,
    'type' / WIPTagType,
    'data_start' / Int64sl,
    'data_end' / Int64sl,
    # 'start'/Tell,
    # OneOf(Computed(this.start == this.data_start), [True]),
    'data_size' / Computed(this.data_end - this.data_start),
    'data' / If(
        this.data_end > this.data_start,
        Switch(
            this.type,
            dict(
                WIP_TAG_LIST=RepeatUntil(
                    lambda obj, ctx: obj.data_end >= ctx.data_end,
                    LazyBound(lambda: WIPTag)),
                WIP_TAG_EXTENDED=Bytes(10),
                WIP_TAG_DOUBLE=Float64l,
                WIP_TAG_FLOAT=Float32l,
                WIP_TAG_INT64=Int64sl,
                WIP_TAG_INT32=Array(this.data_size // 4, Int32sl),
                WIP_TAG_UINT32=Array(this.data_size // 4, Int32ul),
                WIP_TAG_CHAR=Array(this.data_size, Int8ul),
                WIP_TAG_BOOL=Int8ul,
                WIP_TAG_STRING=WIPString,
            ))),
    'end' / Tell,
    # pad to get to data_end
    Padding(this.data_end - this.end),
)
Пример #13
0
 def __init__(self):
     super(VariableLengthIDAdapter, self).__init__(RepeatUntil(lambda obj, lst, ctx: obj & 0xF0 == 0x00, Byte))
Пример #14
0
)
orientation = Struct("orientation", BFloat32("rotation"), BFloat32("pitch"))

# Notchian item packing
items = Struct("items",
    SBInt16("primary"),
    If(lambda context: context["primary"] >= 0,
        Embed(Struct("item_information",
            UBInt8("count"),
            UBInt16("secondary"),
        )),
    ),
)

# Metadata subconstruct.
metadata = StringAdapter(RepeatUntil(lambda obj, ctx: obj == "\x7f",
    Field("metadata", 1)))

# Build faces, used during dig and build.
faces = {
    "noop": -1,
    "-y": 0,
    "+y": 1,
    "-z": 2,
    "+z": 3,
    "-x": 4,
    "+x": 5,
}
face = Enum(SBInt8("face"), **faces)

packets = {
    0: Struct("ping"),
Пример #15
0
    "ObjectId" / Int32ul,
    "MetadataId" / Int32ul,
    "Values" / MemberValues(True))

ObjectNull = Struct(
    "RecordTypeEnum" / RecordTypeEnum)


Record = Struct(
    "RecordTypeEnum" / Peek(RecordTypeEnum),
    "Obj" / Switch(this.RecordTypeEnum, {
        RecordTypeEnum.SerializedStreamHeader: SerializationHeaderRecord,
        RecordTypeEnum.BinaryObjectString: BinaryObjectString,
        RecordTypeEnum.BinaryLibrary: BinaryLibrary,
        RecordTypeEnum.ClassWithMembersAndTypes: ClassWithMembersAndTypes,
        RecordTypeEnum.MemberReference: MemberReference,
        RecordTypeEnum.SystemClassWithMembers: SystemClassWithMembers,
        RecordTypeEnum.ArraySinglePrimitive: ArraySinglePrimitive,
        RecordTypeEnum.ClassWithId: ClassWithId,
        RecordTypeEnum.ObjectNull: ObjectNull,
        RecordTypeEnum.BinaryArray: BinaryArray,
        RecordTypeEnum.MemberPrimitiveTyped: MemberPrimitiveTyped
        }
    ))

AllRecords = RepeatUntil(lambda obj,lst,ctx: obj.RecordTypeEnum == RecordTypeEnum.MessageEnd, Record)

def parse(data):
    MemberValues._allClses = {}
    return AllRecords.parse(data)
Пример #16
0
        SBInt32("y"),
        SBInt32("z"),
    ),
}

# Metadata subconstruct.
entity_metadata = MetadataAdapter(
    Struct(
        "metadata",
        RepeatUntil(
            lambda obj, context: obj["peeked"] == 0x7f,
            Struct(
                "data",
                BitStruct(
                    "id",
                    BitField("data_type", 3),  # first
                    BitField("identifier", 5),  # second
                ),
                Switch("value", lambda context: context["id"]["data_type"],
                       metadata_switch),
                Peek(SBInt8("peeked")),
            ),
        ),
        Const(UBInt8("terminator"), 0x7f),
    ), )

# The actual packet list.
packets = {
    0:
    Struct(
        "keep alive",
        SBInt32("pid"),
Пример #17
0
"""
TimeZone Information definition in Windows Internal
"""
TimeZoneInformation = Struct("bias" / Int32sl, "standard_name" / Byte[64],
                             "standard_date" / SystemTime,
                             "standard_bias" / Int32sl,
                             "delight_name" / Byte[64],
                             "delight_date" / SystemTime,
                             "delight_bias" / Int32sl)

PerfinfoGroupMask = Struct("masks" / Int32ul[8])
"""
Wide string windows style
"""
WString = Struct(
    "type" / Computed("WString"), "string" / RepeatUntil(
        lambda x, lst, ctx: len(lst) % 2 == 0 and lst[-2:] == [0, 0], Byte))
"""
C string style
"""
CString = Struct(
    "type" / Computed("CString"),
    "string" / RepeatUntil(lambda x, lst, ctx: lst[-1:] == [0], Byte))


def check_enum(enum: Enum) -> Struct:
    """
    Enforce an enum value to be in enum range
    :param enum: source enum
    :return: Struct
    :raise: construct.core.CheckError
    """
Пример #18
0
 "damaged_lately_timer"/Byte,
 "under_attack"/Byte,
 "pathing_group_len"/Int32ul,
 "pathing_group"/Array(lambda ctx: ctx.pathing_group_len, "object_id"/Int32ul),
 "group_id"/Int32sl,
 "roo_already_called"/Byte,
 "de_static_unk1"/If(lambda ctx: find_version(ctx) == Version.DE, Bytes(17)),
 If(lambda ctx: find_save_version(ctx) >= 26.16, Byte),
 "de_has_object_props"/If(lambda ctx: find_version(ctx) == Version.DE, Int16ul),
 "de_object_props"/IfThenElse(lambda ctx: ctx.de_has_object_props == 1, Struct(
     Bytes(162),
     Find(b'`\n\x00\x00`\n\x00\x00', 1000), # Skip a large unparseable block that (likely) contains RMS-modified object data
     Bytes(2)
 ), Struct(
     "has_sprite_list"/Byte,
     "sprite_list"/If(lambda ctx: ctx.has_sprite_list != 0, RepeatUntil(lambda x,lst,ctx: lst[-1].type == 0, sprite_list)),
     "de_extension"/If(lambda ctx: find_version(ctx) == Version.DE, Struct(
         "particles"/Array(5, particle),
         If(lambda ctx: find_save_version(ctx) >= 13.15, Bytes(5)),
         If(lambda ctx: find_save_version(ctx) >= 13.17, Bytes(2)),
         If(lambda ctx: find_save_version(ctx) >= 13.34, Struct(
             Bytes(2),
             de_string,
             de_string,
             Bytes(2)
         ))
     ))
 )),
 "de_extension_p2"/If(lambda ctx: find_version(ctx) == Version.DE, Struct(
     # not the right way to do this, needs improvement
     If(lambda ctx: find_save_version(ctx) >= 20.16, Struct(
Пример #19
0
        UBInt32("y"),
        UBInt32("z"),
    ),
}

# Metadata subconstruct.
metadata = MetadataAdapter(
    Struct(
        "metadata",
        RepeatUntil(
            lambda obj, context: obj["peeked"] == 0x7f,
            Struct(
                "data",
                BitStruct(
                    "id",
                    BitField("first", 3),
                    BitField("second", 5),
                ),
                Switch("value", lambda context: context["id"]["first"],
                       metadata_switch),
                Peek(UBInt8("peeked")),
            ),
        ),
        Const(UBInt8("terminator"), 0x7f),
    ), )

# Build faces, used during dig and build.
faces = {
    "noop": -1,
    "-y": 0,
    "+y": 1,
    "-z": 2,
Пример #20
0
            Int32ul, Const(b"\x00\x00\x00\x00"), "player_number" / Int32sl,
            "hd_rm_elo" / Int32ul, "hd_dm_elo" / Int32ul,
            "animated_destruction_enabled" / Flag, "custom_ai" / Flag)),
 "fog_of_war" / Flag,
 "cheat_notifications" / Flag,
 "colored_chat" / Flag,
 Bytes(9),
 separator,
 Bytes(12),
 If(lambda ctx: ctx._.save_version >= 13.13, Bytes(5)),
 "strings" / Array(
     23,
     Struct(
         "string" / de_string,
         RepeatUntil(
             lambda x, lst, ctx: lst[-1] not in [3, 21, 23, 42, 44, 45],
             Int32ul))),
 "strategic_numbers" / Array(59, Int32sl),
 "num_ai_files" / Int64ul,
 "ai_files" / Array(lambda ctx: ctx.num_ai_files,
                    Struct(
                        Bytes(4),
                        "name" / de_string,
                        Bytes(4),
                    )),
 "guid" / Bytes(16),
 "lobby_name" / de_string,
 "modded_dataset" / de_string,
 Bytes(19),
 If(lambda ctx: ctx._.save_version >= 13.13, Bytes(5)),
 If(lambda ctx: ctx._.save_version >= 13.17, Bytes(9)),
Пример #21
0
    'ReservedSpace' / Int16ul,
    # Only look for a Value if this isn't the END pseudo-parameter.
    'Value' / If(
        this.Name != 'END',
        Switch(this.Type, {
            'INT32': Int32ul,
            'REAL64': Float64l
        },
               default=FixedSizeCString(this.ReservedSpace * 2))))


def is_ParameterList(block):
    return block.BlockType.param != 0


ParameterList = RepeatUntil(obj_.Name == 'END', Parameter)
FloatData = Array(this.BlockLength, Float32l)
StringData = String(this.BlockLength * 4)

DirectoryEntry = Struct(
    'BlockType' / BlockType, 'BlockLength' / Int32ul, 'DataPtr' / Int32ul,
    'Block' / Pointer(
        this.DataPtr,
        FunctionSwitch(
            [(is_ParameterList, ParameterList),
             (lambda ctx: ctx.BlockType.extend != 0, OnDemand(StringData)),
             (lambda ctx: ctx.BlockType.data not in
              (0, 13), OnDemand(FloatData))])))

# The entire file.
OpusFile = Struct(
Пример #22
0
 "fog_of_war"/Flag,
 "cheat_notifications"/Flag,
 "colored_chat"/Flag,
 separator,
 "ranked"/Flag,
 "allow_specs"/Flag,
 "lobby_visibility"/Int32ul,
 "hidden_civs"/Flag,
 "matchmaking"/Flag,
 "spec_delay"/Int32ul,
 "scenario_civ"/If(lambda ctx: find_save_version(ctx) >= 13.13, Byte),
 "rms_crc"/If(lambda ctx: find_save_version(ctx) >= 13.13, Bytes(4)),
 "strings"/Array(23,
     Struct(
         "string"/de_string,
         "nums"/RepeatUntil(lambda x, lst, ctx: lst[-1] not in [3, 21, 23, 42, 44, 45, 46, 47], Int32ul)
     )
 ),
 # There's probably a right way to do this, but this is not it.
 "num_sn"/Computed(lambda ctx: ctx.strings[22].nums[1]),
 "strategic_numbers"/Array(lambda ctx: ctx.num_sn if find_save_version(ctx) >= 25.22 else 59, Int32sl),
 "num_ai_files"/Int64ul,
 "ai_files"/Array(lambda ctx: ctx.num_ai_files, Struct(
     Bytes(4),
     "name"/de_string,
     Bytes(4),
 )),
 If(lambda ctx: find_save_version(ctx) >= 25.02, Bytes(8)),
 "guid"/Bytes(16),
 "lobby_name"/de_string,
 If(lambda ctx: find_save_version(ctx) >= 25.22, Bytes(8)),
Пример #23
0
            'stream_start_bytes': 9,
            'protected_stream_id': 10,
        }),
    "data" / Prefixed(
        Int16ul,
        Switch(this.id, {
            'compression_flags': CompressionFlags,
            'cipher_id': CipherId,
            'transform_rounds': Int32ul,
            'protected_stream_id': ProtectedStreamId
        },
               default=GreedyBytes)),
)

DynamicHeader = DynamicDict(
    'id', RepeatUntil(lambda item, a, b: item.id == 'end', DynamicHeaderItem))

# -------------------- Payload Verification --------------------

# encrypted payload is split into multiple data blocks with hashes
PayloadBlock = Struct(
    "block_index" / Checksum(Int32ul, lambda this: this._index, this),
    "block_hash_offset" / Tell,
    Padding(32),
    "block_data" / Prefixed(Int32ul, GreedyBytes),
    # block_hash has to be at the end with a pointer because it needs to
    # come after other fields
    "block_hash" / Pointer(
        this.block_hash_offset,
        IfThenElse(
            len_(this.block_data) == 0,
Пример #24
0
                     "flags" / EventHeaderFlag,
                     "event_property" / EventHeaderPropertyFlag,
                     "thread_id" / Int32ul, "process_id" / Int32ul,
                     "timestamp" / Int64ul, "provider_id" / Guid,
                     "event_descriptor" / EventDescriptor,
                     "processor_time" / Int64ul, "activity_id" / Guid)

EventHeaderExtendedDataItem = Struct(
    "reserved1" / Int16ul, "ext_type" / Int16ul, "reserved2" / Int16ul,
    "data_size" / Int16ul, "data_item" / Bytes(lambda this: this.data_size))

EventRecord = AlignedStruct(
    8, "mark1" / Computed(lambda this: this._io.tell()),
    "event_header" / EventHeader, "extended_data" / If(
        lambda this: this.event_header.flags.EVENT_HEADER_FLAG_EXTENDED_INFO,
        RepeatUntil(lambda el, lst, this: not lst[-1].reserved2 & 0x1,
                    Aligned(8, EventHeaderExtendedDataItem))),
    "mark2" / Computed(lambda this: this._io.tell()),
    "user_data" / Bytes(lambda this: this.event_header.marker.version -
                        (this.mark2 - this.mark1)))


class Event:
    """
    This is a python wrapper around construct struct to access interesting fields
    """
    def __init__(self, source):
        self.source = source

    def get_process_id(self):
        """
        Return the process id of issuer
Пример #25
0
from construct import Computed, ExprAdapter, FocusedSeq, Int8ul, Int24ul, Pointer, RepeatUntil, String, Switch, this

#PioString = Struct(
PioString = FocusedSeq(
    1,
    "padded_length" / RepeatUntil(lambda x, lst, ctx: x != 0, Int8ul),
    "data" / Switch(
        this.padded_length[-1],
        {
            # string longer than 127 bytes, prefixed with 3 bytes length
            0x40:
            FocusedSeq(
                1, "actual_length" /
                ExprAdapter(Int24ul, lambda o, c: o + 4, lambda o, c: o - 4),
                "text" / String(this.actual_length, encoding="ascii")),
            # iso-8859 text with \x00 between every character (like utf-16, but its iso-8859)
            0x90:
            FocusedSeq(
                1, "actual_length" /
                ExprAdapter(Int24ul, lambda o, c: o + 4, lambda o, c: o - 4),
                "text" / ExprAdapter(
                    String(this.actual_length, encoding="iso-8859-1"),
                    lambda o, c: "".join(x + "\x00"
                                         for x in o), lambda o, c: o[::2])),
        },
        default=  # just ascii text
        FocusedSeq(
            1,
            "actual_length" / Computed((this.padded_length[-1] - 1) // 2 - 1),
            "text" / String(this.actual_length, encoding="ascii"))))
Пример #26
0
EtlLogFile = GreedyRange(EtlChunk)

# This is a common way to select any type of chunks
# We add name selecting as computed to handle typing during parsing
Chunk = Aligned(
    8,
    Select(
        Struct("type" / Computed("PerfInfoTraceRecord"),
               "value" / PerfInfoTraceRecord),
        Struct("type" / Computed("EventRecord"), "value" / EventRecord),
        Struct("type" / Computed("TraceRecord"), "value" / TraceRecord),
        Struct("type" / Computed("SystemTraceRecord"),
               "value" / SystemTraceRecord),
        Struct("type" / Computed("WinTraceRecord"), "value" / WinTraceRecord)))

ChunkParser = RepeatUntil(
    lambda x, lst, ctx: len(x._io.getbuffer()) == x._io.tell(), Chunk)


class IEtlFileObserver(metaclass=ABCMeta):
    """
    This is etl file observer
    Parse sequentially an etl file and commit event when found a particular event
    """
    @abstractmethod
    def on_event_record(self, event: Event):
        """
        Raise when an event record is parsed
        Mostly use by ETW and tracelogging
        If you search classic provider you are at the correct place
        :param event: the event record
        """
Пример #27
0
        Switch(
            this.type, {
                0x04: Int32ul,
                0x05: Int64ul,
                0x08: Flag,
                0x0C: Int32sl,
                0x0D: Int64sl,
                0x42: GreedyBytes,
                0x18: GreedyString('utf-8')
            })), "next_byte" / Peek(Byte))

# new dynamic dictionary structure added in KDBX4
VariantDictionary = Struct(
    "version" / Bytes(2), "dict" / DynamicDict(
        'key',
        RepeatUntil(lambda item, a, b: item.next_byte == 0x00,
                    VariantDictionaryItem)),
    Padding(1) * "null padding")

# -------------------- Dynamic Header --------------------

# https://github.com/dlech/KeePass2.x/blob/dbb9d60095ef39e6abc95d708fb7d03ce5ae865e/KeePassLib/Serialization/KdbxFile.cs#L234-L246

DynamicHeaderItem = Struct(
    "id" / Mapping(
        Byte, {
            'end': 0,
            'comment': 1,
            'cipher_id': 2,
            'compression_flags': 3,
            'master_seed': 4,
            'encryption_iv': 7,
Пример #28
0
    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,
            ))
        ))
Пример #29
0
if _construct_version:
    if (_construct_version[0] < 2) or ((_construct_version[0] == 2) and
                                       (_construct_version[1] < 9)):
        raise Exception(
            'Construct version too low, please install version 2.9+')

from construct import Struct, Const, Int32ub, Int32sb, RepeatUntil, CString, Pointer, Bytes, Padding, BitStruct, Flag, IfThenElse, Seek, Tell

_FArc_format = Struct(
    "signature" / Const(b'FArc'),
    "header_size" / Int32ub,  # doesn't include signature or header_size
    "alignment" / Int32sb,
    "files" / RepeatUntil(
        lambda obj, lst, ctx: ctx._io.tell() - 7 > ctx.header_size,
        Struct(
            "name" / CString("utf8"), "pointer" / Int32ub, "size" / Int32ub,
            "data" / Pointer(lambda this: this.pointer,
                             Bytes(lambda this: this.size)))),
    #Padding(lambda this: this.alignment - (this._io.tell() % this.alignment) if this._io.tell() % this.alignment else 0)
)

_FArC_format = Struct(
    "signature" / Const(b'FArC'),
    "header_size" / Int32ub,  # doesn't include signature or header_size
    "alignment" / Int32sb,
    "files" / RepeatUntil(
        lambda obj, lst, ctx: ctx._io.tell() - 7 > ctx.header_size,
        Struct(
            "name" / CString("utf8"), "pointer" / Int32ub,
            "compressed_size" / Int32ub, "uncompressed_size" / Int32ub,
            "data" / Pointer(lambda this: this.pointer,
Пример #30
0
# unfortunately, the entry_enabled field contains unexistant entries for the last entry
# entry_enabled[:-1] matches revidx[:-1],
# but len(entry_enabled)==16 while len(revidx)<=16

ReverseIndexArray = Struct(
    "entry_count" /
    Computed(lambda ctx: min([16, ctx._.entry_count - 16 * ctx._._index])),
    Seek(-4 - 2 * this.entry_count, 1),  # jump back the size of this struct
    "entries" / Array(this.entry_count, ReverseIndexedEntry),
    "entry_enabled" / ByteSwapped(Bitwise(Array(16, Flag))),
    "entry_enabled_override" / ByteSwapped(Bitwise(Array(16, Flag))),
    Seek(-36 if this.entry_count == 16 else 0,
         1)  # jump back once again for the next read or 0 if finished
)

PageFooter = RepeatUntil(lambda x, lst, ctx: len(lst) * 16 > ctx.entry_count,
                         ReverseIndexArray)

PageHeader = Struct(  # 40 bytes
    Padding(4),  # always 0
    "index" / Int32ul,  # in units of 4096 bytes
    "page_type" / PageTypeEnum,
    "next_index" /
    Int32ul,  # in units of 4096 bytes, finally points to empty page, even outside of file
    "u1" / Int32ul,  # sequence number (0->1: 8->13, 1->2: 22, 2->3: 27)
    Padding(4),
    "entry_count_small" / Int8ul,
    "u3" / Int8ul,  # a bitmask (1st track: 32)
    "u4" /
    Int8ul,  # often 0, sometimes larger, esp. for pages with high entry_count_small (e.g. 12 for 101 entries)
    "u5" / Int8ul,  # strange pages: 0x44, 0x64; otherwise seen: 0x24, 0x34
    "free_size" / Int16ul,  # excluding data at page end