コード例 #1
0
class SaveReader():
    """Class designed to retrieve basic data from files."""
    def __init__(self, file_name):
        self.file = open(file_name, 'r')
        self.stream = ConstBitStream(self.file)

    def __enter__(self):
        return self

    def __exit__(self, type_, value, traceback):
        self.file.close()

    def read_bytes(self, count):
        """Read a number of bytes and return a bitstring."""
        return self.stream.read(count * 8)

    def find_blocks(self):
        """Find all data blocks and return a tuple of their offsets."""
        return tuple(self.stream.findall('0x40000000', bytealigned=True))

    def read_int(self):
        """Read a 4 byte little endian int."""
        return self.stream.read(32).intle

    def read_ints(self, count):
        """Return a tuple of ints."""
        return tuple(
            map(lambda x: x.read(32).intle,
                self.read_bytes(count * 4).cut(32)))

    def read_string(self):
        """Read a string with the length given in the first 4 bytes."""
        return self.stream.read('bytes:{}'.format(self.read_int())).decode(
            "utf-8", 'replace')
コード例 #2
0
def find_offsets():
    s = ConstBitStream(filename=filename)
    global patterns
    pattern = patterns[patchloc]
    find = list(
        s.findall(pattern,
                  text_offset,
                  text_offset + text_size,
                  bytealigned=True))  # Only search within the .text segment
    for off in find:
        # Fix offset
        off_fix = int(off / 8)

        if off_fix < 0x10000 or off_fix > 0x3FFFC:  # Limit range
            continue

        # Calculate instruction offset
        global final
        global hexval
        final = off_fix - 4
        hexval = '0x{0:0{1}X}'.format(
            final, 6
        )  #change int back to uppercase hex (make sure we also print leading zero)
コード例 #3
0
class FileReader:
    """ Some basic functionality for reading data from Binary files. """
    def __init__(self, filename):
        self.filename = filename
        if isinstance(filename, str):
            self.file = open(filename, 'rb')
            self.bits = ConstBitStream(open(filename, 'rb'))

    def __enter__(self):
        return self

    def __exit__(self, type, value, traceback):
        self.file.close()

    def skip_bytes(self, count=1):
        self.bits.read('pad:{0}'.format(count * 8))

    def peek_int(self):
        return self.bits.peek(32).uintle

    def forward_to_first_non_zero_byte(self, start, end):
        self.bits.pos = start
        while self.bits.pos < end and self.bits.read(8).intle == 0:
            pass
        self.bits.pos -= 8

    def read_strings_from_block(self, start, end, stopAtEmptyString=False):
        self.bits.pos = start
        r = []
        while self.bits.pos < end:
            s = self.read_string()
            if s == "" and stopAtEmptyString:
                return r
            r.append(s)
        return tuple(r)

    def read_int(self):
        """ Read a single little endian 4 byte integer """
        return self.bits.read(32).intle

    def findall(self, bs):
        return self.bits.findall(bs, bytealigned=True)

    def read_bytes(self, count):
        return self.bits.read(count * 8)

    def read_byte(self, skip=0):
        i = self.bits.read(8).uint
        if skip > 0:
            self.skip_bytes(skip)

        return i

    def read_string_safe(self):
        return self.bits.read('bytes:{0}'.format(
            self.read_byte(skip=3))).decode("utf-8", 'replace')

    def find(self, bs, start, end):
        return self.bits.find(bs, start, end, True)

    def find_first(self, bs):
        return self.bits.find(bs)

    def extract_compressed_payloads(self):
        files = []
        occ = self.findall('0x789C')

        i = 0
        readSize = 2**12

        for pos in occ:
            self.bits.pos = pos

            #read the start of the stream into a buffer.
            if (self.bits.length - self.pos) < 8 * 2**12:
                readSize = int((self.bits.length - self.pos) / 8)

            buf = self.bits.read('bytes:{0}'.format(readSize))
            zo = zlib.decompressobj()

            #start the decompression
            try:
                stream = zo.decompress(buf)
            except zlib.error:  # right magic number but not a zlib stream.
                continue

            while zo.unused_data == b'' and readSize >= 2**12:
                if (self.bits.length - self.pos) < 8 * 2**12:
                    readSize = int((self.bits.length - self.pos) / 8)

                block = self.bits.read('bytes:{0}'.format(readSize))
                if len(block) > 0:
                    try:
                        stream += zo.decompress(block)
                    except zlib.error:
                        pass
                else:
                    break  # we've reached EOF

            with open(self.filename + '_' + str(i) + '.decompressed',
                      'wb') as fh:
                fh.write(stream)

            files.append(self.filename + '_' + str(i) + '.decompressed')

            i += 1

        return files

    @property
    def pos(self):
        return self.bits.pos

    @pos.setter
    def pos(self, value):
        self.bits.pos = value

    def read_string(self):
        """ Read an undelimited string with the length given in the first 4 bytes """
        return self.bits.read('bytes:{0}'.format(self.read_int())).decode(
            "utf-8", 'replace')
コード例 #4
0
def zfs_search(search_file_path, pool_name, target_pool_name="kdiwlcik", buffer_size=buffer_size_default, print_starts_ends_only=False, starts=None, ends=None, tmp_dir="/tmp", loop_device=sp.check_output([losetup, "-f"]).strip(), ):
    #if search_file_path != None:
    #    search_bytes = open(search_file_path, "r")
    #else:
    #    search_bytes = sys.stdin
    #    logger.info("no input file specified, reading from stdin")
    
    #raise RuntimeError("as long issue https://github.com/zfsonlinux/zfs/issues/2830 isn't fixed in the zpool command it doesn't make sense to use the script because copying files takes > 1 month regarding the number of combination, data volume and decreasing performance of a driver becoming fuller and fuller - on the other hand if it is fixed or a workaround found the script will be very efficient")
    
    # check privileges first (this is polite)
    if os.getuid() != 0:
        raise RuntimeError("Privileges are necessary to invoke zpool import tests, exiting")
    # validate loop_device option (assume that losetup -f always returns a 
    # valid and usable result)
    if re.match("/dev/loop[0-9]+", loop_device) is None:
        raise ValueError("loop_device '%s' is not a valid loop device specification" % (loop_device,))
        # @TODO: more checks for loop_device adequacy are necessary
    logger.info("using loop device %s" % (loop_device,))

    if print_starts_ends_only and (starts != None or ends != None):
        raise ValueError("starts or ends specified together with print-starts-ends-only which doesn't make sense (you don't want simply the list you specified on command line to be printed)")

    if search_file_path is None:
        raise ValueError("search_file_path mustn't be None")
    if not os.path.exists(search_file_path):
        raise ValueError("search_file_path '%s' doesn't exist" % (search_file_path,))
    #if not os.path.isfile(search_file_path): # return false for device files
    #    raise ValueError("search_file_path '%s' isn't a file, but has to be" % (search_file_path,))
    search_bytes = open(search_file_path, "r")

    # Can initialise from files, bytes, etc.
    if starts is None or ends is None:
        s = ConstBitStream(search_bytes) # if argument name is omitted, auto is used
    if starts is None:
        bitstring_result = list(s.findall(zfs_start_bytes, bytealigned=True))
        bytealigned_bitstring_result = [x/8 for x in bitstring_result]
        starts = sorted(bytealigned_bitstring_result) # ConstBitStream.find returns the bit position (rather than byte position)
        logger.info("found starts '%s'" % (str(starts)))
    else:
        starts = [int(x) for x in starts]
        logger.info("using starts\n%s\nspecified on command line" % (str(starts)))
    if ends is None:
        bitstring_result = list(s.findall(zfs_end_bytes, bytealigned=True))
        bytealigned_bitstring_result = [x/8 for x in bitstring_result]
        ends = sorted(bytealigned_bitstring_result, reverse=True) # reverse causes testing from largest possible to smallest possible (this eventually causes I/O overhead, but possibility to find a pool in the largest set is much higher)
        logger.info("found ends '%s'" % (str(ends)))
    else:
        ends = [int(x) for x in ends]
        logger.info("using ends\n%s\nspecified on command line" % (str(ends)))

    if print_starts_ends_only:
        logger.info("found start points\n%s\n and end points\n%s\nExiting" % (str(starts), str(ends)))
        return
    logger.info("discarding start positions which don't have a corresponding start position after %s bytes" % (label_size, ))
    valid_starts = []
    for start in starts:
        for start0 in starts:
	    if start0 == start + label_size:
	        valid_starts.append(start)
	        # do nothing with start0 because it might be valid for some strange reason, but if it is, it is more valid than start because there're always 2 ZFS pool labels
    logger.info("The remaining valid starts are '%s'" % (str(valid_starts)))
    starts = valid_starts
    
    logger.info("discarding end positions which don't have a corresponding end position after %s bytes" % (label_size, ))
    valid_ends = []
    for end in ends:
        for end0 in ends:
	    if end0 == end+ label_size:
	        valid_ends.append(end)
    logger.info("The remaining valid ends are '%s'" % (str(valid_ends)))
    ends = valid_ends

    logger.info("trying all %s combinations of %s start and %s end points from largest to smallest eventual result" % (str(len(starts)*len(ends)), str(len(starts)), str(len(ends)), ))
    for start in starts:
        for end in ends:
            if end < start:
                logger.info("skipping occurance of end at '%s' before start at '%s'" % (str(end),str(start)))
                continue
            end = end + zfs_end_tail_bytes_count
            
            sp.check_call([losetup, "-o", str(start), "--sizelimit", str(end-start), loop_device, search_file_path])
            logger.info("mounting subset of search file %s from byte %s to byte %s under %s" % (search_file_path, str(start), str(end), loop_device))
            
            # test zpool import
            zpool_import_process = sp.Popen([zpool, "import", "-D", ], stdout=sp.PIPE, stderr=sp.PIPE) # there's no difference in returncode between no results and successful listing of possible import -> parse output
            zpool_import_process.wait()
            zpool_import_output_tuple = zpool_import_process.communicate()
            zpool_import_output = zpool_import_output_tuple[1] # no pool available message is written onto stderr; subprocess.Popen.communicate can be invoked only once, second invokation causes error because performing I/O on closed file
            zpool_import_output_stdout = zpool_import_output_tuple[0]
            logger.debug("The output of the ''zpool import'' test command is:\n%s\n\n\n%s\n\n" % (zpool_import_output, zpool_import_output_stdout, ))
            if zpool_import_process.returncode == 0 and (zpool_import_output is None or (zpool_import_output.strip() != "no pools available to import" and not "state: UNAVAIL" in zpool_import_output)) and (zpool_import_output_stdout is None or (not "state: UNAVAIL" in zpool_import_output and not "state: UNAVAIL" in zpool_import_output_stdout)): # zpool import returncodes are useless (finding a pool with status UNAVAIL returns 0) 
                logger.info("interval %s to %s possibly contains a valid zpool. The output of the ''zpool import'' test command is:\n%s\n\n\n%s\n\nSkipping further search" % (str(start), str(end), zpool_import_output, zpool_import_output_stdout))
                logger.info("the loop device '%s' still provides the pool. Move the data from it to a reliable pool as soon as possible and detach the loop device yourself." % (loop_device,))
                return
            sp.check_call([losetup, "-d", loop_device]) # only detach loop device if import wasn't successful because otherwise the newly rescued pooled is displayed as faulted because the underlying loop device is no longer available

    return
コード例 #5
0
# Search to Start of Frame 0 code on byte boundary
foundMoviOffset = s.find('0x6D6F7669', bytealigned=True)
if foundMoviOffset:
    moviOffset = foundMoviOffset[0] / 8
    print("Found movi signature at byte offset %X" % moviOffset)
else:
    print "Signature movi not found"
print ("Current bytepos %X" % s.bytepos)
foundIdx1Offset = s.find('0x69647831', bytealigned=True)
if foundIdx1Offset:
    idx1Offset = foundIdx1Offset[0] / 8
    print("Found idx1 signature at byte offset %X" % idx1Offset)
else:
    print "Signature idx1 not found"
print ("Current bytepos %X" % s.bytepos)
found01dcOffset = s.findall('0x30316463', bytealigned=True)
for i in found01dcOffset:
    i = (i /8) + 8
    print("%X" % i)
    s.bytepos = i
    print s.bytepos
    timeStamp = s.read(64).bin
    print timeStamp

    print ("Time is %d" % timeStamp)
    # print filetime_to_dt(timeStamp)
    # s.bytepos = i + 4
    # print s.bytepos
    # timelow = s.read(32).Q
    # t = float(timehigh)*2**32 + timelow
    # print (t*1e-7 - 11644473600)
コード例 #6
0
class FileReader:
    """ Some basic functionality for reading data from Binary files. """

    def __init__(self, filename):
        self.filename = filename
        if isinstance(filename, str):
            self.file = open(filename, 'rb')
            self.bits = ConstBitStream(open(filename, 'rb'))

    def __enter__(self):
        return self

    def __exit__(self, type, value, traceback):
        self.file.close()

    def skip_bytes(self,count=1):
        self.bits.read('pad:{0}'.format(count*8))

    def peek_int(self):
        return self.bits.peek(32).uintle

    def forward_to_first_non_zero_byte(self, start, end):
        self.bits.pos = start
        while self.bits.pos < end and self.bits.read(8).intle == 0:
            pass
        self.bits.pos -= 8

    def read_strings_from_block(self, start, end, stopAtEmptyString=False):
        self.bits.pos = start
        r = []
        while self.bits.pos < end:
            s = self.read_string()
            if s == "" and stopAtEmptyString:
                return r
            r.append(s)
        return tuple(r)

    def read_int(self):
        """ Read a single little endian 4 byte integer """
        return self.bits.read(32).intle

    def findall(self,bs):
        return self.bits.findall(bs,bytealigned=True)

    def read_bytes(self, count):
        return self.bits.read(count*8)

    def read_byte(self, skip = 0):
        i = self.bits.read(8).uint
        if skip > 0:
            self.skip_bytes(skip)

        return i

    def read_string_safe(self):
        return self.bits.read('bytes:{0}'.format(self.read_byte(skip=3))).decode("utf-8", 'replace')

    def find(self, bs, start, end):
        return self.bits.find(bs,start, end, True )

    def find_first(self, bs):
        return self.bits.find(bs)

    def extract_compressed_payloads(self):
        files = []
        occ = self.findall('0x789C')

        i = 0
        readSize = 2**12

        for pos in occ:
            self.bits.pos = pos

            #read the start of the stream into a buffer.
            if (self.bits.length - self.pos) < 8*2**12:
                readSize = int((self.bits.length - self.pos) / 8)

            buf = self.bits.read('bytes:{0}'.format(readSize))
            zo = zlib.decompressobj()

            #start the decompression
            try:
                stream = zo.decompress(buf)
            except zlib.error: # right magic number but not a zlib stream.
                continue

            while zo.unused_data == b'' and readSize >= 2**12:
                if (self.bits.length - self.pos) < 8*2**12:
                    readSize = int((self.bits.length - self.pos) / 8)

                block = self.bits.read('bytes:{0}'.format(readSize))
                if len(block)> 0:
                    try:
                        stream += zo.decompress(block)
                    except zlib.error:
                        pass
                else:
                    break # we've reached EOF

            with open(self.filename + '_' + str(i) + '.decompressed', 'wb') as fh:
                fh.write(stream)

            files.append(self.filename + '_' + str(i) + '.decompressed')

            i+=1

        return files

    @property
    def pos(self):
        return self.bits.pos

    @pos.setter
    def pos(self, value):
        self.bits.pos = value

    def read_string(self):
        """ Read an undelimited string with the length given in the first 4 bytes """
        return self.bits.read('bytes:{0}'.format(self.read_int())).decode("utf-8", 'replace')
コード例 #7
0
def binary_search(pattern_file_path, search_file_path, match_flag,
                  match_file_path):
    '''
    Function for searching through binary files 
    '''
    #bd_logger("Starting binary search...")

    pattern_file = open(pattern_file_path, 'rb')
    search_file = open(search_file_path, 'rb')

    pattern_data = pattern_file.read()

    search_file_size = os.path.getsize(search_file_path)

    try:
        s = ConstBitStream(search_file)
    except:
        bd_logger("Couldn't nmap an empty file! --> " + search_file_path)
        return
    occurances = s.findall(pattern_file, bytealigned=True)
    occurances = list(occurances)
    totalOccurances = len(occurances)
    match_arr = []

    for i in range(0, len(occurances)):
        occuranceOffset_dec = int(occurances[i] / 8)
        occuranceOffset_hex = hex(int(occurances[i] / 8))
        print(
            str(i + 1) + ') ' + 'Offset_hex: ' + str(occuranceOffset_hex) +
            '  Offset_dec: ' + str(occuranceOffset_dec) + " File_name: " +
            str(search_file_path.split("\\")[-1]) + " File_size: " +
            str(hex(search_file_size)) + " \\ " + str(search_file_size))

        if match_flag == 1:
            match_arr.append(occuranceOffset_dec)

    pattern_file.close()
    search_file.close()

    if match_flag == 1:

        match_file = open(match_file_path, "rt")

        for match_entry in match_arr:

            print("\n### " + "match_entry: " + str(match_entry) + " ###")
            match_file.seek(0)

            i = 0
            for line in match_file:
                #print(line)
                i += 1
                i_mem_address = int(
                    line.split(" file_offset=")[0].split("mem_address=")[-1])
                i_file_offset = int(line.split(" file_offset=")[-1])
                i_match_entry = int(match_entry)

                if i_file_offset > i_match_entry:
                    #print("F_OFF: " + str(i_file_offset) )
                    break

            j = 0
            match_file.seek(0)
            for line in match_file:
                j += 1

                if j == i - 1:
                    print("MATCHED LINE: " + line.rstrip("\n"))
                    i_mem_address = int(
                        line.split(" file_offset=")[0].split("mem_address=")
                        [-1])
                    i_file_offset = int(line.split(" file_offset=")[-1])
                    i_match_entry = int(match_entry)
                    i_off_diff = int(i_match_entry - i_file_offset)
                    i_real_mem_address = int(i_mem_address + i_off_diff)

                    print("REAL_MEM_ADRESS_dec=" + str(i_real_mem_address) +
                          "  REAL_MEM_ADRESS_hex=" +
                          str(hex(i_real_mem_address)) +
                          "  page_address_dec=" + str(i_mem_address) +
                          "  page_address_hex=" + str(hex(i_mem_address)))
コード例 #8
0
# Pull out the tempo, offset is number of BITS
s.pos = TEMPO_OFFSET
preciseBPM = s.read('uintle:24')
songTempo = preciseBPM / 10000
debugPrint("Tempo BPM is {} ({})".format(songTempo, hex(preciseBPM)))

# Pull out the time signature
s.pos = TIME_SIGNATURE_OFFSET
numerator = s.read('uintle:8')
denominator = s.read('uintle:8')
debugPrint("Time signature is {}/{}".format(numerator, 2**denominator))

# Generate an ordered list of offsets pointing to bits of the
# binary data that we are interested in
offset_list = list(s.findall('0x71537645', bytealigned=True))  #qSvE
offset_list.extend(list(s.findall('0x7165534D', bytealigned=True)))  #qeSM

#offset_list.extend(list(s.findall('0x6B617254', bytealigned = True)))
#offset_list.extend(list(s.findall('0x74536e49', bytealigned = True)))
#offset_list.extend(list(s.findall('0x74537854', bytealigned = True)))
#offset_list.extend(list(s.findall('0x69766e45', bytealigned = True)))
sorted_offset_list = sorted(offset_list)

for thisOffset in sorted_offset_list:
    s.pos = thisOffset

    if bDebug:
        debugPrint("Byte offset {}".format(thisOffset))
        dumphex(64, s)