def main(): parser = YaffsParser.get_argparser() parser.add_argument("--fraction", help='The file size of the sampled file as a fraction of the original.', type=float, default=0.01, dest="sample_fraction") args = parser.parse_args() image_size = os.path.getsize(args.imagefile) #We use ceiling so that we always have at least one block to grab, even #if the fraction is 0.000000000001 total_num_blocks = image_size / (args.blocksize * (args.chunksize + args.oobsize)) num_blocks = math.ceil(total_num_blocks * args.sample_fraction) num_blocks = int(num_blocks) blocks = YaffsParser.extract_ordered_blocks(args.imagefile, args.chunksize, args.oobsize, args.blocksize, args.tag_offset) sampled_blocks = random.sample(blocks, num_blocks) root, ext = os.path.splitext(args.imagefile) outfile = "%s_sampled_%s%s" % (root, str(args.sample_fraction).replace('.', "d"), ext) print 'Outfile: %s' % outfile with open(args.imagefile, 'rb') as f: with open(outfile, 'wb') as out: for sblock in sampled_blocks: f.seek(sblock.chunk_pairs[0][1].offset) out.write(f.read((args.chunksize + args.oobsize) * args.blocksize))
def guess_block_size(image, chunk_size, oob_size, oob_offset): chunk_pairs = YaffsParser.extract_chunks(image, chunk_size, oob_size) chunks = [c for c, o in chunk_pairs[:1024]] oobs_bytes = YaffsParser.get_oob_bytes(image, chunks, oob_size) oobs = [YaffsOobTag(b, oob_offset) for b in oobs_bytes] prev = -1 counts = [] count = 0 for oob in oobs: if oob.block_seq != prev: if count > 0: counts.append(count) count = 1 prev = oob.block_seq else: count += 1 import collections size, freq = collections.Counter(counts).most_common(1)[0] if freq == 1: print "Unable to determine block size." return None print "Most likely block size: %d" % size return size
def main(): parser = YaffsParser.get_argparser() args = parser.parse_args() #read in and order all of the blocks, by reverse order of sequence number sorted_blocks = YaffsParser.extract_ordered_blocks(args.imagefile, args.chunksize, args.oobsize, args.blocksize, args.tag_offset) objects = YaffsParser.extract_objects(sorted_blocks) current_objects = [o for o in objects if not o.is_deleted] current_file_objects = [] for obj in current_objects: #check the object type from the first header chunk. if len(obj.versions) > 0 and obj.versions[0][0][1].obj_type == 1: current_file_objects.append(obj) print "object_id,name,time_diff,expected,actual" for obj in current_file_objects: missing = get_missing_chunks_by_version(obj) for expected, actual, time_diff, name in missing: if time_diff < 0: pass print "%d\t%s\t%s\t%d\t%d" % (obj.object_id, name, time_diff, expected, actual)
def main(): parser = YaffsParser.get_argparser() args = parser.parse_args() #read in and order all of the blocks, by reverse order of sequence number sorted_blocks = YaffsParser.extract_ordered_blocks(args.imagefile, args.chunksize, args.oobsize, args.blocksize, args.tag_offset) objects = YaffsParser.extract_objects(sorted_blocks) current_objects = [o for o in objects if not o.is_deleted] current_file_objects = [] for obj in current_objects: #check the object type from the first header chunk. if len(obj.versions) > 0 and obj.versions[0][0][1].obj_type == 1: current_file_objects.append(obj) print "object_id,name,chunk_id,count" for obj in current_file_objects: count = 0 name = obj.versions[0][0][1].name for id in obj.chunkDict: if id == 0: continue if len(obj.chunkDict[id]) > 1: print "%d\t%s\t%d\t%d" % (obj.object_id, name, id, len(obj.chunkDict[id]))
def extract_files(image, filenames, chunksize, oobsize, blocksize, oob_tag_offset, versions): """ Extracts the most recent version of every file in the filenames list. """ blocks = YaffsParser.extract_ordered_blocks(image, chunksize, oobsize, blocksize, oob_tag_offset) objects = YaffsParser.extract_objects(blocks) destination = os.path.dirname(image) for name in filenames: extract_file(objects, name, destination, versions)
def main(): parser = YaffsParser.get_argparser() args = parser.parse_args() #read in and order all of the blocks sorted_blocks = YaffsParser.extract_ordered_blocks(args.imagefile, args.pagesize, args.oobsize, args.blocksize, tag_offset=args.tag_offset) missing_set = get_missing_block_numbers(sorted_blocks)
def guess_oob_offset(image, headers, oob_size): oobs_bytes = YaffsParser.get_oob_bytes(image, headers, oob_size) best_parsed = [] # We use -16 because we are looking for 16 bytes in the tag # for parsing for offset in xrange(0, oob_size-16): parsed = [] for bytes in oobs_bytes: parsed_oob = YaffsOobTag(bytes, offset) if not parsed_oob.isHeaderTag: continue else: parsed.append(parsed_oob) if len(parsed) > len(best_parsed): best_offset = offset best_parsed = parsed object_ids = set([o.object_id for o in best_parsed]) if len(object_ids) > 0: print "OOB tag offset is %d" % best_offset print "with %d valid header tags" % len(best_parsed) print "Object id: %s" % str(object_ids) return best_offset print "Unable to determine OOB tag offset." return None
def main(): """ Assume we pass this script the image file path as an argument on the command line. """ DEFAULT_ANCHORS = ['contacts2.db'] DEFAULT_CHUNK_SIZES = [1024, 2048, 4096] DEFAULT_OOB_SIZES = [0, 32, 64, 128] parser = YaffsParser.get_argparser() parser.add_argument("--anchors", help="The filenames to use for anchoring the search. Default: %s" % DEFAULT_ANCHORS, nargs='*', default=DEFAULT_ANCHORS, dest="anchors") parser.add_argument("--chunksizes", help="The chunk sizes to test for. Default: %s" % DEFAULT_CHUNK_SIZES, nargs='*', default=DEFAULT_CHUNK_SIZES, dest="chunk_sizes", type=int) parser.add_argument("--oobsizes", help="The oob sizes to test for. Default: %s" % DEFAULT_OOB_SIZES, nargs='*', default=DEFAULT_OOB_SIZES, dest="oob_sizes", type=int) args = parser.parse_args() print args.imagefile for anchor in args.anchors: print 'Scanning for %s' % anchor scan_file(args.imagefile, anchor, args.chunk_sizes, args.oob_sizes) pass
def main(): """ Assume we pass this script the image file path as an argument on the command line. """ usage = 'usage: %prog [options] imagefile' parser = OptionParser(usage=usage) parser.add_option('--chunksize', action='store', type='int', dest='chunk_size', default=2048) parser.add_option('--oobsize', action='store', type='int', dest='oob_size', default=64) options, args = parser.parse_args() if len(args) != 1: print "Incorrect command line arguments. Missing (or too many) image files" return 1 image = args[0] headers = Scanner.get_anchor_headers(image, options.chunk_size, options.oob_size, 'contacts2.db') oobs = YaffsParser.get_oob_bytes(image, headers, options.oob_size) for oob in oobs: sys.stdout.write(oob) #Separate each oob with 16 'X' Bytes. sys.stdout.write('X'*16)
def count_constant_oobs(image, chunks, oobsize): oobs = YaffsParser.get_oob_bytes(image, chunks, oobsize) constants_count = 0 constant = '\xff' * oobsize for oob in oobs: if oob == constant: constants_count += 1 return constants_count
def main(): parser = YaffsParser.get_argparser() args = parser.parse_args() blocks = YaffsParser.extract_ordered_blocks(args.imagefile, args.chunksize, args.oobsize, args.blocksize, args.tag_offset) objects = YaffsParser.extract_objects(blocks) tuple_set = set() for object in objects: for version in object.versions: tuple_set.add((object.object_id, version[0][1].name)) for tuple in tuple_set: print tuple
def get_headers(image, chunk_size, oob_size): chunk_pairs = YaffsParser.extract_chunks(image, chunk_size, oob_size) #First filter, The first byte should be 0x01 #Litte endian header_chunks = [YaffsHeader(c) for c, obb in chunk_pairs if c.get_bytes(4) == '\x01\00\00\00'] #Now use the second, slower filter. header_chunks = [c for c in header_chunks if YaffsHeader(c).is_valid()] return header_chunks
def main(): """ Assume we pass this scirpt the image file as an argument """ DEFAULT_VERSIONS = [0] parser = YaffsParser.get_argparser() parser.add_argument("--files", help="The files to extract.", nargs='*', dest="files") parser.add_argument("--versions", help="The version numbers to extract, 0 is newest, -1 is oldest", type=int, default=DEFAULT_VERSIONS, nargs='*', dest='version_numbers') args = parser.parse_args() extract_files(args.imagefile, args.files, args.chunksize, args.oobsize, args.blocksize, args.tag_offset, args.version_numbers)
""" This is a quick script for trying to grab the start of the contacts2.db file by making some assumptions about the format of the oob.' The current numbers are hardcoded for the Via Forensics Droid Eris image. """ import Scanner, YaffsParser import sys # I found this manually object_id = '\xb4\x02\x00\x00' chunk_id = '\x01\x00\x00\00' image = sys.argv[1] print image chunk_pairs = YaffsParser.extract_chunks(image, 2048, 64) f = open(image, 'rb') for (chunk, oob_offset) in chunk_pairs: f.seek(oob_offset+34) if object_id == f.read(4) and chunk_id == f.read(4): print 'Found chunk 1' print chunk.get_bytes(3) f.close()
def main(): parser = YaffsParser.get_argparser() args = parser.parse_args() print args.imagefile, args.chunksize, args.oobsize, args.blocksize, args.tag_offset print "Script started: ", datetime.datetime.now() print 'File size: ', os.path.getsize(args.imagefile) #read in and order all of the blocks, by reverse order of sequence number sorted_blocks = YaffsParser.extract_ordered_blocks(args.imagefile, args.chunksize, args.oobsize, args.blocksize, args.tag_offset) nonerased_blocks = [b for b in sorted_blocks if not b.is_erased] print '%d blocks' % len(sorted_blocks) print 'Sequence number range: %d -- %d' \ % (nonerased_blocks[-1].sequence_num, nonerased_blocks[0].sequence_num) print 'Found %d erased blocks.' % (len(sorted_blocks) - len(nonerased_blocks)) #This can happen if the phone is turned off while writing. print 'Found %d blocks with mismatched sequence numbers' \ % len([block for block in sorted_blocks if block.possible_parse_error]) missing_seq_nums = summarize_deleted_blocks.get_missing_block_numbers(sorted_blocks) objects = YaffsParser.extract_objects(sorted_blocks) print 'Found %d objects' % len(objects) print 'Found %d objects with a header.' % len([obj for obj in objects if 0 in obj.chunkDict]) print 'Found %d deleted objects.' % len([obj for obj in objects if obj.is_deleted]) recent_pairs = [] total_pairs_count = 0 for block in sorted_blocks: recent_pairs.extend([(tag, chunk) for tag, chunk in block.chunk_pairs if tag.is_most_recent]) total_pairs_count += len(block.chunk_pairs) print 'Number of Recent chunks: %d' % len(recent_pairs) print 'Total number of chunks: %d' % total_pairs_count print 'Fraction recent: %0.2f' % (float(len(recent_pairs)) / total_pairs_count) last_time = None first_time = None for block in nonerased_blocks: for tag, chunk in block.chunk_pairs: if tag.isHeaderTag: print block.sequence_num last_time = time.ctime(YaffsHeader(chunk).mtime) break if last_time: break for x in xrange(len(nonerased_blocks)-1, 0, -1): block = nonerased_blocks[x] for y in xrange(len(block.chunk_pairs)-1, 0, -1): tag, chunk = block.chunk_pairs[y] if tag.isHeaderTag: print block.sequence_num first_time = time.ctime(YaffsHeader(chunk).mtime) break if first_time: break print 'Oldest object modification: %s' % first_time print 'Newest object modification: %s' % last_time