Пример #1
0
 def __init__(self, name):
     construct.Struct.__init__(
         self, name, construct.Bytes('header', 8),
         construct.Value(
             'total_bytes',
             lambda ctx: self.__total_utf8_bytes__(ctx['header'])),
         construct.MetaRepeater(
             lambda ctx: self.__total_utf8_bytes__(ctx['header']) - 1,
             construct.Bytes('sub_byte', 8)),
         construct.Value('value',
                         lambda ctx: self.__calculate_utf8_value__(ctx)))
Пример #2
0
    construct.Anchor('stream_end'))

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

VAULT_ATTRIBUTE_MAP_ENTRY = construct.Struct(
    'VAULT_ATTRIBUTE_MAP_ENTRY', construct.ULInt32('id'),
    construct.ULInt32('offset'), construct.ULInt32('attr_map_entry_unknown_1'),
    construct.Pointer(lambda ctx: ctx.offset, VAULT_ATTRIBUTE))

VAULT_VCRD = construct.Struct(
    'VAULT_VCRD', GUID('schema_guid'), construct.ULInt32('vcrd_unknown_1'),
    FILETIME('last_update'), construct.ULInt32('vcrd_unknown_2'),
    construct.ULInt32('vcrd_unknown_3'),
    construct.Rename('description', UNICODE_STRING),
    construct.ULInt32('attributes_array_size'),
    construct.Value(
        'attributes_num', lambda ctx:
        (ctx.attributes_array_size / VAULT_ATTRIBUTE_MAP_ENTRY.sizeof())),
    construct.Rename(
        'attributes',
        construct.Array(lambda ctx: ctx.attributes_num,
                        VAULT_ATTRIBUTE_MAP_ENTRY)),
    construct.Pointer(
        lambda ctx:
        (ctx.attributes[ctx.attributes_num - 1].VAULT_ATTRIBUTE.stream_end),
        construct.Rename('extra_entry', VAULT_ATTRIBUTE_EXTRA)))
Пример #3
0
        # from comment string, build Containers
        encoder=lambda obj, ctx: construct.Container(blocks=[
            construct.Container(
                block_size=len(chunk),
                data_values=chunk,
            ) for chunk in [obj[i:i + 255] for i in xrange(0, len(obj), 255)]
        ] + [construct.Container(block_size=0, data_values='')], ),
        # from Containers, build comment string
        decoder=lambda obj, ctx: ''.join(dsb.data_values
                                         for dsb in obj.blocks),
    )


_image_block = construct.Struct(
    'image',
    construct.Value('block_type', lambda ctx: 'image'),
    construct.Struct(
        'image_descriptor',
        construct.ULInt16('left'),
        construct.ULInt16('top'),
        construct.ULInt16('width'),
        construct.ULInt16('height'),
        construct.EmbeddedBitStruct(
            construct.Flag('lct_flag'),
            construct.Flag('interlace_flag'),
            construct.Flag('sort_flag'),
            construct.Padding(2),  # reserved
            construct.macros.BitField('lct_size', 3),
        ),
    ),
    construct.If(
Пример #4
0
AXSString = construct.Struct("AXSString", construct.ULInt32("length"),
                             construct.Bytes("data", lambda ctx: ctx.length))

AXSKeyEntry = construct.Struct("AXSKeyEntry", construct.Array(2, AXSString),
                               construct.ULInt32("unk"))

AXSKeyMan = construct.Struct(
    "AXSKeyMan",
    construct.ULInt32("nb_entry"),
    #construct.Array(lambda ctx: ctx.nb_entry, AXSKeyEntry))
    construct.Array(1, AXSKeyEntry))

binInfo = construct.Struct(
    "binInfo", construct.ULInt16("a"), construct.ULInt8("b"),
    construct.Value("type", lambda ctx: (ctx["b"] << 16) | ctx["a"]),
    construct.ULInt32("size"), construct.ULInt32("unk_dword_00"),
    construct.ULInt8("unk_byte_00"), construct.ULInt32("type_compression"),
    construct.ULInt32("length"), construct.Bytes("data",
                                                 lambda ctx: ctx.length))

binInfoNext = construct.Struct("binInfoNext", construct.ULInt16("type"),
                               construct.ULInt32("size"),
                               construct.ULInt32("length"),
                               construct.Bytes("data", lambda ctx: ctx.length))


class Buffer:
    def __init__(self, buf):
        self.buf = buf
        self.length = len(self.buf)
Пример #5
0
class FlacReader:
    FRAME_HEADER = construct.Struct(
        'frame_header', construct.Bits('sync', 14),
        construct.Bits('reserved', 2), construct.Bits('block_size', 4),
        construct.Bits('sample_rate', 4),
        construct.Bits('channel_assignment', 4),
        construct.Bits('bits_per_sample', 3), construct.Padding(1),
        construct.IfThenElse(
            'total_channels', lambda ctx1: ctx1['channel_assignment'] <= 7,
            construct.Value('c', lambda ctx2: ctx2['channel_assignment'] + 1),
            construct.Value('c', lambda ctx3: 2)), UTF8('frame_number'),
        construct.IfThenElse(
            'extended_block_size', lambda ctx1: ctx1['block_size'] == 6,
            construct.Bits('b', 8),
            construct.If(lambda ctx2: ctx2['block_size'] == 7,
                         construct.Bits('b', 16))),
        construct.IfThenElse(
            'extended_sample_rate', lambda ctx1: ctx1['sample_rate'] == 12,
            construct.Bits('s', 8),
            construct.If(lambda ctx2: ctx2['sample_rate'] in (13, 14),
                         construct.Bits('s', 16))), construct.Bits('crc8', 8))

    UNARY = construct.Struct(
        'unary',
        construct.RepeatUntil(lambda obj, ctx: obj == '\x01',
                              construct.Field('bytes', 1)),
        construct.Value('value', lambda ctx: len(ctx['bytes']) - 1))

    SUBFRAME_HEADER = construct.Struct(
        'subframe_header', construct.Padding(1),
        construct.Bits('subframe_type', 6),
        construct.Flag('has_wasted_bits_per_sample'),
        construct.IfThenElse('wasted_bits_per_sample',
                             lambda ctx: ctx['has_wasted_bits_per_sample'],
                             PlusOne(Unary('value')),
                             construct.Value('value', lambda ctx2: 0)))

    GET_BLOCKSIZE_FROM_STREAMINFO = -1
    GET_8BIT_BLOCKSIZE_FROM_END_OF_HEADER = -2
    GET_16BIT_BLOCKSIZE_FROM_END_OF_HEADER = -3

    BLOCK_SIZE = (GET_BLOCKSIZE_FROM_STREAMINFO, 192, 576, 1152, 2304, 4608,
                  GET_8BIT_BLOCKSIZE_FROM_END_OF_HEADER,
                  GET_16BIT_BLOCKSIZE_FROM_END_OF_HEADER, 256, 512, 1024, 2048,
                  4096, 8192, 16384, 32768)

    GET_SAMPLE_SIZE_FROM_STREAMINFO = -1
    SAMPLE_SIZE = (GET_SAMPLE_SIZE_FROM_STREAMINFO, 8, 12, None, 16, 20, 24,
                   None)

    def FIXED0(subframe, residual, i):
        subframe.insert(i, residual[i])

    def FIXED1(subframe, residual, i):
        subframe.insert(i, subframe[i - 1] + residual[i])

    def FIXED2(subframe, residual, i):
        subframe.insert(i,
                        ((2 * subframe[i - 1]) - subframe[i - 2] + \
                         residual[i]))

    def FIXED3(subframe, residual, i):
        subframe.insert(i,
                        ((3 * subframe[i - 1]) - (3 * subframe[i - 2]) + \
                         subframe[i - 3] + residual[i]))

    def FIXED4(subframe, residual, i):
        subframe.insert(i,
                        ((4 * subframe[i - 1]) - (6 * subframe[i - 2]) + \
                         (4 * subframe[i - 3]) - subframe[i - 4] + residual[i]))

    #iterates over all of the channels, in order
    def MERGE_INDEPENDENT(channel_list):
        channel_data = [iter(c) for c in channel_list]

        while (True):
            for channel in channel_data:
                yield channel.next()

    def MERGE_LEFT(channel_list):
        channel_left = iter(channel_list[0])
        channel_side = iter(channel_list[1])

        while (True):
            left = channel_left.next()
            side = channel_side.next()

            yield left
            yield left - side

    def MERGE_RIGHT(channel_list):
        channel_side = iter(channel_list[0])
        channel_right = iter(channel_list[1])

        while (True):
            side = channel_side.next()
            right = channel_right.next()

            yield side + right
            yield right

    def MERGE_MID(channel_list):
        channel_mid = iter(channel_list[0])
        channel_side = iter(channel_list[1])

        while (True):
            mid = channel_mid.next()
            side = channel_side.next()

            mid = mid << 1
            mid |= (side & 0x1)

            yield (mid + side) >> 1
            yield (mid - side) >> 1

    CHANNEL_FUNCTIONS = (MERGE_INDEPENDENT, MERGE_INDEPENDENT,
                         MERGE_INDEPENDENT, MERGE_INDEPENDENT,
                         MERGE_INDEPENDENT, MERGE_INDEPENDENT,
                         MERGE_INDEPENDENT, MERGE_INDEPENDENT, MERGE_LEFT,
                         MERGE_RIGHT, MERGE_MID)

    FIXED_FUNCTIONS = (FIXED0, FIXED1, FIXED2, FIXED3, FIXED4)

    def __init__(self, flac_stream):
        self.stream = BufferedStream(flac_stream)
        self.streaminfo = None
        self.bitstream = None

        #ensure the file starts with 'fLaC'
        self.read_stream_marker()

        #initialize self.bitstream
        self.begin_bitstream()

        #find self.streaminfo in case we need it
        self.read_metadata_blocks()

    def close(self):
        if (self.bitstream != None):
            self.bitstream.close()
        else:
            self.stream.close()

    def read_stream_marker(self):
        if (self.stream.read(4) != 'fLaC'):
            raise FlacStreamException('invalid stream marker')

    def read_metadata_blocks(self):
        block = audiotools.FlacAudio.METADATA_BLOCK_HEADER.parse_stream(
            self.stream)
        while (block.last_block == 0):
            if (block.block_type == 0):
                self.streaminfo = audiotools.FlacAudio.STREAMINFO.parse_stream(
                    self.stream)
            else:
                self.stream.seek(block.block_length, 1)

            block = audiotools.FlacAudio.METADATA_BLOCK_HEADER.parse_stream(
                self.stream)
        self.stream.seek(block.block_length, 1)

    def begin_bitstream(self):
        import bitstream

        #self.bitstream = construct.BitStreamReader(self.stream)
        self.bitstream = bitstream.BitStreamReader(self.stream)

    def read_frame(self):
        self.stream.reset_buffer()

        try:
            header = FlacReader.FRAME_HEADER.parse_stream(self.bitstream)
        except construct.core.FieldError:
            return ""

        if (header.sync != 0x3FFE):
            raise FlacStreamException('invalid sync')

        if (crc8(self.stream.getvalue()[0:-1]) != header.crc8):
            raise FlacStreamException('crc8 checksum failed')

        #block_size tells us how many samples we need from each subframe
        block_size = FlacReader.BLOCK_SIZE[header.block_size]
        if (block_size == self.GET_BLOCKSIZE_FROM_STREAMINFO):
            block_size = self.streaminfo.maximum_blocksize

        elif ((block_size == self.GET_8BIT_BLOCKSIZE_FROM_END_OF_HEADER)
              or (block_size == self.GET_16BIT_BLOCKSIZE_FROM_END_OF_HEADER)):
            block_size = header.extended_block_size + 1

        #grab subframe data as 32-bit array objects
        subframe_data = []

        for channel_number in xrange(header.total_channels):
            subframe_data.append(
                self.read_subframe(header, block_size, channel_number))

        crc16sum = crc16(self.stream.getvalue())

        #try to byte-align the stream
        if (len(self.bitstream.buffer) > 0):
            self.bitstream.read(len(self.bitstream.buffer))

        if (crc16sum != construct.Bits('crc16', 16).parse_stream(
                self.bitstream)):
            raise FlacStreamException('crc16 checksum failed')

        #convert our list of subframe data arrays into
        #a string of sample data
        if (FlacReader.SAMPLE_SIZE[header.bits_per_sample] == 16):
            merged_frames = array.array(
                'h', FlacReader.CHANNEL_FUNCTIONS[header.channel_assignment](
                    subframe_data))

            if (audiotools.BIG_ENDIAN):
                merged_frames.byteswap()

            return merged_frames.tostring()

        elif (FlacReader.SAMPLE_SIZE[header.bits_per_sample] == 8):
            merged_frames = array.array(
                'b', FlacReader.CHANNEL_FUNCTIONS[header.channel_assignment](
                    subframe_data))

            return merged_frames.tostring()

        else:
            if (FlacReader.SAMPLE_SIZE[header.bits_per_sample] == \
                self.GET_SAMPLE_SIZE_FROM_STREAMINFO):
                bits_per_sample = self.streaminfo.bits_per_sample + 1

            elif (FlacReader.SAMPLE_SIZE[header.bits_per_sample] == None):
                raise FlacStreamException('invalid bits per sample')

            else:
                bits_per_sample = FlacReader.SAMPLE_SIZE[
                    header.bits_per_sample]

            stream = construct.GreedyRepeater(
                construct.BitStruct(
                    'bits',
                    construct.Bits('value',
                                   bits_per_sample,
                                   swapped=True,
                                   signed=True)))

            return stream.build([
                construct.Container(value=v)
                for v in FlacReader.CHANNEL_FUNCTIONS[
                    header.channel_assignment](subframe_data)
            ])

    def read_subframe(self, frame_header, block_size, channel_number):
        subframe_header = \
                        FlacReader.SUBFRAME_HEADER.parse_stream(self.bitstream)

        #figure out the bits-per-sample of this subframe
        if ((frame_header.channel_assignment == 8) and (channel_number == 1)):
            #if channel is stored as left+difference
            #and this is the difference, add 1 bit
            bits_per_sample = FlacReader.SAMPLE_SIZE[
                frame_header.bits_per_sample] + 1

        elif ((frame_header.channel_assignment == 9)
              and (channel_number == 0)):
            #if channel is stored as difference+right
            #and this is the difference, add 1 bit
            bits_per_sample = FlacReader.SAMPLE_SIZE[
                frame_header.bits_per_sample] + 1

        elif ((frame_header.channel_assignment == 10)
              and (channel_number == 1)):
            #if channel is stored as average+difference
            #and this is the difference, add 1 bit
            bits_per_sample = FlacReader.SAMPLE_SIZE[
                frame_header.bits_per_sample] + 1

        else:
            #otherwise, use the number from the frame header
            bits_per_sample = FlacReader.SAMPLE_SIZE[
                frame_header.bits_per_sample]

        if (subframe_header.has_wasted_bits_per_sample):
            bits_per_sample -= subframe_header.wasted_bits_per_sample

        if (subframe_header.subframe_type == 0):
            subframe = self.read_subframe_constant(block_size, bits_per_sample)

        elif (subframe_header.subframe_type == 1):
            subframe = self.read_subframe_verbatim(block_size, bits_per_sample)

        elif ((subframe_header.subframe_type & 0x38) == 0x08):
            subframe = self.read_subframe_fixed(
                subframe_header.subframe_type & 0x07, block_size,
                bits_per_sample)

        elif ((subframe_header.subframe_type & 0x20) == 0x20):
            subframe = self.read_subframe_lpc(
                (subframe_header.subframe_type & 0x1F) + 1, block_size,
                bits_per_sample)

        else:
            raise FlacStreamException('invalid subframe type')

        if (subframe_header.has_wasted_bits_per_sample):
            return array.array('i', [
                i << subframe_header.wasted_bits_per_sample for i in subframe
            ])
        else:
            return subframe

    def read_subframe_constant(self, block_size, bits_per_sample):
        sample = construct.Bits('b',
                                bits_per_sample).parse_stream(self.bitstream)

        subframe = array.array('i', [sample] * block_size)

        return subframe

    def read_subframe_verbatim(self, block_size, bits_per_sample):
        return array.array(
            'i',
            construct.StrictRepeater(
                block_size,
                construct.Bits("samples", bits_per_sample,
                               signed=True)).parse_stream(self.bitstream))

    def read_subframe_fixed(self, order, block_size, bits_per_sample):
        samples = construct.StrictRepeater(
            order,
            construct.Bits("warm_up_samples", bits_per_sample, signed=True))

        subframe = array.array('i', samples.parse_stream(self.bitstream))

        residual = self.read_residual(block_size, order)

        fixed_func = self.FIXED_FUNCTIONS[order]

        for i in xrange(len(subframe), block_size):
            fixed_func(subframe, residual, i)

        return subframe

    def read_subframe_lpc(self, order, block_size, bits_per_sample):
        samples = construct.StrictRepeater(
            order,
            construct.Bits("warm_up_samples", bits_per_sample, signed=True))

        subframe = array.array('i', samples.parse_stream(self.bitstream))

        lpc_precision = construct.Bits('lpc_precision', 4).parse_stream(
            self.bitstream) + 1

        lpc_shift = construct.Bits('lpc_shift', 5).parse_stream(self.bitstream)

        coefficients = array.array(
            'i',
            construct.StrictRepeater(
                order,
                construct.Bits('coefficients', lpc_precision,
                               signed=True)).parse_stream(self.bitstream))

        residual = self.read_residual(block_size, order)

        for i in xrange(len(subframe), block_size):
            subframe.insert(i,
                            (sum(
                [coefficients[j] * subframe[i - j - 1] for j in
                 xrange(0,len(coefficients))]) >> lpc_shift) + \
                            residual[i])

        return subframe

    def read_residual(self, block_size, predictor_order):
        rice = array.array('i')

        #add some dummy rice so that the Rice index matches
        #that of the rest of the subframe
        for i in xrange(predictor_order):
            rice.append(0)

        coding_method = self.bitstream.read(2)
        if (coding_method == '\x00\x00'):
            rice2 = False
        elif (coding_method == '\x00\x01'):
            rice2 = True
        else:
            raise FlacStreamException('invalid residual coding method')

        partition_order = construct.Bits('partition_order',
                                         4).parse_stream(self.bitstream)

        if (partition_order > 0):
            total_samples = ((block_size / 2**partition_order) -
                             predictor_order)
            rice.extend(self.read_encoded_rice(total_samples, rice2))

            for i in xrange(1, 2**partition_order):
                total_samples = (block_size / 2**partition_order)

                rice.extend(self.read_encoded_rice(total_samples, rice2))
        else:
            rice.extend(
                self.read_encoded_rice(block_size - predictor_order, rice2))

        return rice

    def read_encoded_rice(self, total_samples, rice2=False):
        bin_to_int = construct.lib.binary.bin_to_int

        samples = array.array('i')

        if (not rice2):
            rice_parameter = construct.Bits('rice_parameter',
                                            4).parse_stream(self.bitstream)
        else:
            rice_parameter = construct.Bits('rice_parameter',
                                            5).parse_stream(self.bitstream)

        if (rice_parameter != 0xF):
            #a Rice encoded residual
            for x in xrange(total_samples):

                #count the number of 0 bits before the next 1 bit
                #(unary encoding)
                #to find our most significant bits
                msb = 0
                s = self.bitstream.read(1)
                while (s != '\x01'):
                    msb += 1
                    s = self.bitstream.read(1)

                #grab the proper number of least significant bits
                lsb = bin_to_int(self.bitstream.read(rice_parameter))

                #combine msb and lsb to get the Rice-encoded value
                value = (msb << rice_parameter) | lsb
                if ((value & 0x1) == 0x1):  #negative
                    samples.append(-(value >> 1) - 1)
                else:  #positive
                    samples.append(value >> 1)
        else:
            #unencoded residual

            bits_per_sample = construct.Bits('escape_code',
                                             5).parse_stream(self.bitstream)

            sample = construct.Bits("sample", bits_per_sample, signed=True)

            for x in xrange(total_samples):
                samples.append(sample.parse_stream(self.bitstream))

        return samples
Пример #6
0
def MakeRva(name):
    return construct.Embed(construct.Struct('EmbeddedRva',
        construct.ULInt32(name),
        construct.Value('VA', lambda ctx: idaapi.get_imagebase() + ctx[name])
    ))