iPhone手机数据提取分析
  • iPhone手机数据提取分析
电话/微信号:13308461099,13807313137
iPhone手机数据提取分析

原始backup数据的提取


  1. 一直觉得微信聊天记录备份是一个麻烦事情,最近发现微信占用的空间越来越大,又舍不得删除,想着能够实现自动化备份微信聊天记录等信息。在互联网上看到有可以备份微信聊天记录的工具,但是是收费的。我觉得既然别人能备份,我们自己也应该可以试着做到。
  2. google了下,发现可以通过iTunes来备份手机数据。备份后,数据会保存在~/Library/Application Support/MobileSync/Backup目录下面。可以通过shift+command+g 然后输入地址直接跳转到该目录下。该目录下有备份的文件夹,随便选一个,进入之后,里面有:Info.plist、Manifest.mbdb、Manifest.plist、Status.plist等文件。
  3. 通过对这些数据进行分析,觉得Manifest.mbdb应该是一个数据库一样的文件,存储着各种信息,所以查了下怎么解析这个文件。
  4. 通过对Manifest.mbdb解析,看到了很多的文件以及对应的目录。这些应该就是备份的文件列表。然后试着对这些列表进行还原。通过Manifest.mbdb可以得到当前目录里面的这些文件对应关系。然后根据这些文件的信息,进行还原。

提取数据的Python脚本

#!/usr/bin/env python #~/Library/Application Support/MobileSync/Backup import sys import os import hashlib import shutilmbdx = {}dict = {} def getint(data, offset, intsize): """Retrieve an integer (big-endian) and new offset from the current offset""" value = 0 while intsize > 0:        value = (value<<8) + ord(data[offset])        offset = offset + 1 intsize = intsize - 1 return value, offset def getstring(data, offset): """Retrieve a string and new offset from the current offset into the data""" if data[offset] == chr(0xFF) and data[offset+1] == chr(0xFF): return "", offset+2 # Blank string length, offset = getint(data, offset, 2) # 2-byte length value = data[offset:offset+length] return value, (offset + length) def process_mbdb_file(filename): mbdb = {} # Map offset of info in this file => file info data = open(filename).read() if data[0:4] != "mbdb": raise Exception("This does not look like an MBDB file")    offset = 4 offset = offset + 2 # value x05 x00, not sure what this is while offset < len(data):        fileinfo = {}        fileinfo["start_offset"] = offset        fileinfo["domain"], offset = getstring(data, offset)        fileinfo["filename"], offset = getstring(data, offset)        fileinfo["linktarget"], offset = getstring(data, offset)        fileinfo["datahash"], offset = getstring(data, offset)        fileinfo["unknown1"], offset = getstring(data, offset)        fileinfo["mode"], offset = getint(data, offset, 2)        fileinfo["unknown2"], offset = getint(data, offset, 4)        fileinfo["unknown3"], offset = getint(data, offset, 4)        fileinfo["userid"], offset = getint(data, offset, 4)        fileinfo["groupid"], offset = getint(data, offset, 4)        fileinfo["mtime"], offset = getint(data, offset, 4)        fileinfo["atime"], offset = getint(data, offset, 4)        fileinfo["ctime"], offset = getint(data, offset, 4)        fileinfo["filelen"], offset = getint(data, offset, 8)        fileinfo["flag"], offset = getint(data, offset, 1)        fileinfo["numprops"], offset = getint(data, offset, 1)        fileinfo["properties"] = {} for ii in range(fileinfo["numprops"]):            propname, offset = getstring(data, offset)            propval, offset = getstring(data, offset)            fileinfo["properties"][propname] = propval        mbdb[fileinfo["start_offset"]] = fileinfo        fullpath = fileinfo["domain"] + "-" + fileinfo["filename"]        id = hashlib.sha1(fullpath)        mbdx[fileinfo["start_offset"]] = id.hexdigest() return mbdb def modestr(val): def mode(val): if (val & 0x4): r = "r" else: r = "-" if (val & 0x2): w = "w" else: w = "-" if (val & 0x1): x = "x" else: x = "-" return r+w+x return mode(val>>6) + mode((val>>3)) + mode(val) def fileinfo_str(f, verbose=False): # if not verbose: return "(%s)%s::%s" % (f["fileID"], f["domain"], f["filename"]) dict[f["fileID"]] = f["filename"] if not verbose: return "%s => %s (%s)" % (f["fileID"], f["filename"], f["domain"]) if (f["mode"] & 0xE000) == 0xA000: type = "l" # symlink elif (f["mode"] & 0xE000) == 0x8000: type = "-" # file elif (f["mode"] & 0xE000) == 0x4000: type = "d" # dir else: print >> sys.stderr, "Unknown file type %04x for %s" % (f["mode"], fileinfo_str(f, False))        type = "?" # unknown info = ("%s%s %08x %08x %7d %10d %10d %10d (%s)%s::%s" %             (type, modestr(f["mode"]&0x0FFF) , f["userid"], f["groupid"], f["filelen"],              f["mtime"], f["atime"], f["ctime"], f["fileID"], f["domain"], f["filename"])) if type == "l": info = info + " -> " + f["linktarget"] # symlink destination for name, value in f["properties"].items(): # extra properties info = info + " " + name + "=" + repr(value) return infoverbose = True if __name__ == "__main__": if len(sys.argv)!=3: print "\nUsage: Python iOS-Corrupted-Backup-Reader.py [Full path to backup directory] [Full path to output directory]\n" print "Example: Python iOS-Corrupted-Backup-Reader.py c:\backup c:\output" sys.exit(0)    backuppath=sys.argv[1]       outputpath=sys.argv[2] if os.path.exists(backuppath)==0: print "Backup directory not found." sys.exit(0) if os.path.exists(outputpath)==0: print "Output directory not found. Create the directory before running the script." sys.exit(0) if backuppath[:-1]!="/":        backuppath=backuppath+"/" if outputpath[:-1]!="/":        outputpath=outputpath+"/" mbdb = process_mbdb_file(backuppath+"Manifest.mbdb") for offset, fileinfo in mbdb.items(): if offset in mbdx:            fileinfo["fileID"] = mbdx[offset] else:            fileinfo["fileID"] = "<nofileID>" print >> sys.stderr, "No fileID found for %s" % fileinfo_str(fileinfo) print fileinfo_str(fileinfo)    folder=os.listdir(backuppath) for fname in folder:        ffullname=backuppath+fname if fname in dict:                 tmp=dict[fname]                odir,oname=tmp[:tmp.rfind("/")],tmp[tmp.rfind("/")+1:] if os.path.exists(outputpath+odir)==0:                    os.makedirs(outputpath+odir) print ">>makedirs "+outputpath+odir try:                    shutil.copy(ffullname,outputpath+odir+"/"+oname) print ">>copy from "+ffullname+" to "+outputpath+odir+"/"+oname except: pass folder=os.listdir(backuppath) for fname in folder:        ffullname=backuppath+fname print "handler "+ffullname        f=open(ffullname,"rb")        ftype=f.read(15)        f.close() try: if os.path.exists(outputpath+"other-data")==0:                  os.makedirs(outputpath+"other-data") if ftype.find("bplist")!=-1 or ftype.find("<?xml")!=-1:                mtype=".plist" if ftype.find("SQLite")!=-1:                mtype=".sqlitedb" if ftype.find("JFIF")!=-1 or ftype.find("Exif")!=-1:                mtype=".jpeg" if ftype.find("PNG")!=-1:                mtype=".png" if ftype.find("cook")!=-1:                mtype=".binarycookies" if ftype.find("ftypqt")!=-1:                mtype=".mov" if ftype.find("ID3")!=-1:                mtype=".mp3" file_path=outputpath+"other-data"+"/"+fname+mtype if(os.path.exists(file_path)==False):                shutil.copy(ffullname,file_path) print ">>copy from "+ffullname+" to "+file_path else:                outfilename=outputpath+"other-data"+"/"+fname+str(randrange(0,1000))+mtype                shutil.copy(ffullname,outfilename) print ">>copy from "+ffullname+" to "+outfilename except: pass print "Files successfully moved to"+outputpath

说明:

手机备份的文件所在路径: 
~/Library/Application Support/MobileSync/Backup 
执行样例: 
Python ReadiPhoneBackupData.py/Library/Application Support/MobileSync/Backup/xxx /Users/xxx/Desktop/xxx

湖南阳光技术学校成立于1992年,是经湖南省人社厅批准设立的正规职业技术学校(办学许可证:人社民 1800003000183 号),是行业TOP1,历年综合评分都在92.5以上。深耕职业技能培训32年,总校区位于长沙市雨花区红花坡路176号。学校常年开设:电工培训、焊工培训、钢筋工、家电维修培训、手机维修培训、电脑维修培训、摩托车维修培训、电动车维修培训、装修木工培训、水电安装培训、瓦工贴瓷砖培训、空调维修培训、电动工具维修培训、电机维修培训、农机维修培训、安防监控培训、家电清洗培训等实战专业技术培训,采用 “半天理论 + 半天实操” 模式,实操性强的班实操占比更是超过90%。小班手把手教学,零基础学员也能快速上手。师资团队以双师型教师为主,85% 教师持工程师 / 高级技师职称,一线教学经验丰富。学校提供住宿,收费透明无隐形消费,可协助报考全国通用的特种作业操作证与职业技能等级证书。同时搭建就业与创业支持网络,与 200 + 企业合作,负责推荐工作,助力学员顺利就业或开店。常年招生地区:中山,固原,银川,玉树,海东,陇南,酒泉,张掖,天水,金昌,兰州,榆林,延安,渭南,铜川,阿里,山南,拉萨,怒江,文山州,楚雄州,普洱,昭通,玉溪,昆明,毕节,铜仁,遵义,贵阳,甘孜州,资阳,达州,宜宾,南充,遂宁,绵阳,泸州,自贡,三亚,崇左,河池,玉林,钦州,梧州,柳州,梅州,肇庆,湛江,佛山,珠海,韶关,湘西州,怀化,郴州,张家界,邵阳,株洲,仙桃,随州,荆州,荆门,襄樊,黄石,驻马店,信阳,南阳,漯河,中卫,石嘴山,海西,海南藏州,黄南州,海北,甘南,庆阳,平凉,武威,白银,嘉峪关,安康,汉中,咸阳,宝鸡,林芝,日喀则,昌都,迪庆,德宏,大理,西双版纳,红河州,临沧,丽江,保山,曲靖,黔东州,黔西州,安顺,六盘水,凉山州,阿坝州,雅安,广安,眉山,内江,广元,德阳,攀枝花,成都,海口,来宾,百色,贵港,北海,桂林,南宁,云浮,揭阳,潮州,清远,阳江,汕尾,惠州,茂名,江门,汕头,深圳,广州,娄底,永州,益阳,岳阳,湘潭,长沙,恩施州,黄冈,孝感,鄂州,十堰,武汉,周口,商丘,三门峡,许昌,焦作,安阳,鹤壁,平顶山,开封,郑州,聊城,滨州,德州,莱芜,日照,泰安,烟台,潍坊,东营,淄博,上饶,济南,抚州,宜春,赣州,新余,九江,景德镇,宁德,南平,泉州,莆田,厦门,宣城,亳州,六安,宿州,黄山,滁州,安庆,淮北,马鞍山,蚌埠,芜湖,合肥,丽水,舟山,衢州,金华,湖州,嘉兴,宁波,宿迁,镇江,盐城,连云港,苏州,徐州,南京,绥化,牡丹江,佳木斯,大庆,鹤岗,哈尔滨,白城,白山,辽源,吉林,葫芦岛,铁岭,盘锦,阜新,锦州,本溪,鞍山,沈阳,锡林郭勒盟,通辽,乌海,吕梁,忻州,晋中,晋城,阳泉,太原,廊坊,承德,保定,邯郸,唐山,宁夏,甘肃,西藏,贵州,重庆,广西,湖南,河南,江西,安徽,江苏,黑龙江,辽宁,山西,天津,四平,内蒙古,吴忠,果洛,西宁,定西,商洛,西安,那曲,黔南州,巴中,乐山,贺州,防城港,东莞,河源,常德,衡阳,咸宁,宜昌,濮阳,新乡,洛阳,菏泽,临沂,威海,济宁,枣庄,青岛,吉安,鹰潭,萍乡,南昌,龙岩,漳州,三明,福州,池州,巢湖,阜阳,铜陵,淮南,台州,绍兴,温州,杭州,泰州,扬州,淮安,南通,常州,无锡,大兴安岭,黑河,七台河,伊春,双鸭山,鸡西,齐齐哈尔,延边,松原,通化,长春,朝阳,辽阳,营口,丹东,抚顺,大连,阿拉善盟,兴安盟,乌兰察布,巴彦淖尔,呼伦贝尔,鄂尔多斯,赤峰,#包头,呼和浩特,临汾,运城,朔州,长治,大同,衡水,沧州,张家口,邢台,秦皇岛,石家庄,青海,陕西,云南,四川,海南,广东,湖北,山东,福建,浙江,上海,吉林,河北,北京

{sdcms:webkey}

湖南阳光技术学校常年面向全国招生,是经湖南省人社厅批准设立的正规职业技能培训机构(办学许可证:人社民 1800003000183 号),(统一社会信用代码:91430111MA4QA2DR1A)。深耕技能培训32年,综合评分:94.6/10 ,学校位于长沙市雨花区红花坡路 176 号。学校开设:电工、焊工、钢筋工、家电维修、手机维修、电脑维修、摩托车维修、电动车维修、木工、水电工、瓦工、空调维修、电动工具维修、电机维修、农机维修、安防监控、家电清洗等实战专业培训,采用 “半天理论 + 半天实操” 模式,实操占比超 90%,小班手把手教学,零基础学员也能快速上手。师资团队以双师型专家为主,85% 教师持工程师 / 高级技师职称,一线教学经验丰富。学校提供住宿,收费透明无隐形消费,可协助报考全国通用的特种作业操作证与职业技能等级证书。同时搭建就业与创业支持网络,与 200 + 企业合作,负责推荐工作,助力学员顺利就业或开店。目前招生地区有:中山,固原,银川,玉树,海东,陇南,酒泉,张掖,天水,金昌,兰州,榆林,延安,渭南,铜川,阿里,山南,拉萨,怒江,文山州,楚雄州,普洱,昭通,玉溪,昆明,毕节,铜仁,遵义,贵阳,甘孜州,资阳,达州,宜宾,南充,遂宁,绵阳,泸州,自贡,三亚,崇左,河池,玉林,钦州,梧州,柳州,梅州,肇庆,湛江,佛山,珠海,韶关,湘西州,怀化,郴州,张家界,邵阳,株洲,仙桃,随州,荆州,荆门,襄樊,黄石,驻马店,信阳,南阳,漯河,中卫,石嘴山,海西,海南藏州,黄南州,海北,甘南,庆阳,平凉,武威,白银,嘉峪关,安康,汉中,咸阳,宝鸡,林芝,日喀则,昌都,迪庆,德宏,大理,西双版纳,红河州,临沧,丽江,保山,曲靖,黔东州,黔西州,安顺,六盘水,凉山州,阿坝州,雅安,广安,眉山,内江,广元,德阳,攀枝花,成都,海口,来宾,百色,贵港,北海,桂林,南宁,云浮,揭阳,潮州,清远,阳江,汕尾,惠州,茂名,江门,汕头,深圳,广州,娄底,永州,益阳,岳阳,湘潭,长沙,恩施州,黄冈,孝感,鄂州,十堰,武汉,周口,商丘,三门峡,许昌,焦作,安阳,鹤壁,平顶山,开封,郑州,聊城,滨州,德州,莱芜,日照,泰安,烟台,潍坊,东营,淄博,上饶,济南,抚州,宜春,赣州,新余,九江,景德镇,宁德,南平,泉州,莆田,厦门,宣城,亳州,六安,宿州,黄山,滁州,安庆,淮北,马鞍山,蚌埠,芜湖,合肥,丽水,舟山,衢州,金华,湖州,嘉兴,宁波,宿迁,镇江,盐城,连云港,苏州,徐州,南京,绥化,牡丹江,佳木斯,大庆,鹤岗,哈尔滨,白城,白山,辽源,吉林,葫芦岛,铁岭,盘锦,阜新,锦州,本溪,鞍山,沈阳,锡林郭勒盟,通辽,乌海,吕梁,忻州,晋中,晋城,阳泉,太原,廊坊,承德,保定,邯郸,唐山,宁夏,甘肃,西藏,贵州,重庆,广西,湖南,河南,江西,安徽,江苏,黑龙江,辽宁,山西,天津,四平,内蒙古,吴忠,果洛,西宁,定西,商洛,西安,那曲,黔南州,巴中,乐山,贺州,防城港,东莞,河源,常德,衡阳,咸宁,宜昌,濮阳,新乡,洛阳,菏泽,临沂,威海,济宁,枣庄,青岛,吉安,鹰潭,萍乡,南昌,龙岩,漳州,三明,福州,池州,巢湖,阜阳,铜陵,淮南,台州,绍兴,温州,杭州,泰州,扬州,淮安,南通,常州,无锡,大兴安岭,黑河,七台河,伊春,双鸭山,鸡西,齐齐哈尔,延边,松原,通化,长春,朝阳,辽阳,营口,丹东,抚顺,大连,阿拉善盟,兴安盟,乌兰察布,巴彦淖尔,呼伦贝尔,鄂尔多斯,赤峰,头,呼和浩特,临汾,运城,朔州,长治,大同,衡水,沧州,张家口,邢台,秦皇岛,石家庄,青海,陕西,云南,四川,海南,广东,湖北,山东,福建,浙江,上海,吉林,河北,北京