def parse_trait_plist(self): if 'PTImageIOFormatLayerSpecificDataInfoKey' in self.traits.keys(): arcd_plist = biplist.readPlistFromString(self.traits['PTImageIOFormatLayerSpecificDataInfoKey']) self.trait_plist = NSArchivedPlist.load(arcd_plist).real_plist if '_STATE_DATA_' in self.trait_plist.keys(): arplist2 = biplist.readPlistFromString(self.trait_plist['_STATE_DATA_']) self.state_plist = NSArchivedPlist.load(arplist2).real_plist
def get_prep_value(self, value): if value: try: biplist.readPlistFromString(value) except biplist.InvalidPlistException: return biplist.writePlistToString( value, binary=True) else: return value return value
def read_xattr_metadata(file_list): """For the given list of files read us the kMDItemDescription and kMDItemKeywords.""" meta_data = [] for file in file_list: md = {} attrs = xattr.listxattr(file) if 'com.apple.metadata:kMDItemDescription' in attrs: md['Caption-Abstract'] = biplist.readPlistFromString(xattr.getxattr(file, 'com.apple.metadata:kMDItemDescription')) if 'com.apple.metadata:kMDItemKeywords' in attrs: md['Keywords'] = biplist.readPlistFromString(xattr.getxattr(file, 'com.apple.metadata:kMDItemKeywords')) meta_data.append(md) return meta_data
def get_rating(path): """Get star rating for `path`. Args: path (unicode): File whose rating to retrieve. Raises: IOError: Raised if call to `getxattr` fails. Returns: float or None: Star rating of `path`. """ p = c_path(path) size = xattr.getxattr(p, RATING_KEY_C, None, 0, 0, 0) if size == -1: # No rating set return None buf = create_string_buffer(size) success = xattr.getxattr(p, RATING_KEY_C, buf, c_uint64(size), 0, 0) if success == -1: raise IOError('getxattr failed for path `{}`'.format(path)) # print('got raw rating : {!r}'.format(buf.raw)) return readPlistFromString(buf.raw)
def parse(self): import biplist header = self.stream[:5].encode('hex') if header.startswith('030000'): # Ignore PING requests logger.info('[Client] PING: %d', int(header[-4:], 16)) self.stream = self.stream[5:] header = self.stream[:5].encode('hex') chunkSize = 1000000 if not header.startswith('0200') else int(header[-6:], 16) if chunkSize < len(self.stream) + 5: plistData = self.stream[5:chunkSize + 5] plist = biplist.readPlistFromString(plistData) if 'sessionValidationData' in plist.get('properties', {}): plist['properties']['sessionValidationData'] = plist['properties']['sessionValidationData'].encode('hex') self.keys['sessionValidationData'] = plist['properties']['sessionValidationData'] self.keys['assistantId'] = plist['properties']['assistantId'] self.keys['speechId'] = plist['properties']['speechId'] if 'packets' in plist.get('properties', {}): encodedPackets = [] with open('data.spx', 'a+') as f: for packet in plist['properties']['packets']: f.write(packet) #encodedPackets.append(packet.encode('hex')) #plist['properties']['packets'] = encodedPackets logger.info('[Client]') logger.info(pprint.pformat(plist)) self.stream = self.stream[chunkSize+5:]
def get_raw_tags(path): if 'com.apple.metadata:_kMDItemUserTags' in xattr.listxattr(path): d = xattr.getxattr(path, 'com.apple.metadata:_kMDItemUserTags') d = biplist.readPlistFromString(d) return d else: return []
def precheck(self): """ Checks if an archive looks like this kind of app. Have to examine within the zipfile, b/c we don't want to make temp dirs just yet. This recapitulates a very similar precheck in the Bundle class """ relative_app_dir = None is_native = False if (self.is_archive_extension_match() and zipfile.is_zipfile(self.path)): log.debug("this is an archive, and a zipfile") z = zipfile.ZipFile(self.path) apps = set() file_list = z.namelist() for file_name in file_list: matched = re.match(self.app_dir_pattern, file_name) if matched: apps.add(matched.group(1)) if len(apps) == 1: log.debug("found one app") relative_app_dir = apps.pop() plist_path = join(relative_app_dir, "Info.plist") plist_bytes = z.read(plist_path) plist = biplist.readPlistFromString(plist_bytes) is_native = is_info_plist_native(plist) log.debug("is_native: {}".format(is_native)) if len(apps) > 1: log.warning('more than one app found in archive') return (relative_app_dir, is_native)
def rawDataReceived(self, data): """ This is where the main Siri protocol handling is done. Raw data consists of: (aaccee02)?<zlib_packed_data> Once decompressed the data takes the form: (header)(body) The header is a binary hex representation of is one of three things: 0200000000 0300000000 0400000000 Where: 02... indicated a binary plist payload (followed by the payload size) 03... indicates a iphone->server ping (followed by the sequence id) 04... indicates a server->iphone pong (followed by the sequence id) And the trailing digits are provided in base 16. The body is a binary plist. The aaccee02 header is immediately forwarded, as are ping/pong packets. 04... packets are parsed and passed through `process_plist` before being re-injected (or discarded). """ if self.zlib_d.unconsumed_tail: data = self.zlib_d.unconsumed_tail + data if hexlify(data[0:4]) == "aaccee02": self.peer.transport.write(data[0:4]) data = data[4:] ## Add `data` to decompress stream udata = self.zlib_d.decompress(data) if udata: ## If we get decompressed output, process it header = hexlify(udata[0:5]) if header[1] in [3, 4]: ## Ping/Pong packets - pass them straight through return self.peer.transport.write(data) size = int(header[2:], 16) body = udata[5 : (size + 5)] if body: ## Parse the plist data plist = readPlistFromString(body) ## and have the server/client process it direction = ">" if self.__class__ == SiriProxyServer else "<" self.logger.info("%s %s %s" % (direction, plist["class"], plist.get("refId", ""))) self.logger.debug("%s" % pprint.pformat(plist)) plist = self.process_plist(plist) if plist: ## Stop blocking if it's a new session if self.blocking and self.ref_id != plist["refId"]: self.blocking = False ## Never block transcription packets, they're too useful if not self.blocking or plist["class"] == "SpeechRecognized": self.inject_plist(plist) else: self.logger.info("! %s %s" % (plist["class"], plist.get("refId", ""))) if plist["class"] == "SpeechRecognized": self.process_speech(plist) else: self.logger.info("! %s %s" % (plist["class"], plist.get("refId", "")))
def finder_tags(fname): """ OS X Finder tags are stored in an extended attribute named com.apple.metadata:_kMDItemUserTags. Its value is a binary property list that contains a single array of strings. """ pl = getxattr(fname, 'com.apple.metadata:_kMDItemUserTags') return readPlistFromString(pl)
def _get_bplisthtml(self, buf): parsed = biplist.readPlistFromString(buf) html = """<button class="btn btn-primary btn-sm" onclick="hideshow(this);"> Show XML <span class="glyphicon glyphicon-chevron-down"></span> </button>""" content = biplist.writePlistToString(parsed,False) html += self._get_xmlhtml(content, hidden=True) return html
def convert(data, args): class holder(): pass placeholder = holder() placeholder.pretty = True if len(args) == 1: if (args[0] == "json" or args[0] == "JSON"): # xml2json() converts newlines and tabs in strings to "\n" & "\t". # Stripping them out of XML before conversion to JSON. rawxml = writePlistToString(readPlistFromString(data),binary=False) rawxml = rawxml.replace("\t","") rawxml = rawxml.replace("\n","") return [xml2json(rawxml,placeholder)] else: return [writePlistToString(readPlistFromString(data),binary=False)]
def from_plist(self, content): """ Given some binary plist data, returns a Python dictionary of the decoded data. """ if biplist is None: raise ImproperlyConfigured("Usage of the plist aspects requires biplist.") return biplist.readPlistFromString(content)
def call(url): headers = {'User-Agent': "Path/2.1.2 CFNetwork/548.0.4 Darwin/11.0.0", 'Accept': "*/*", 'Accept-Charset': "utf-8", 'Accept-Language': "en-us", 'Accept-Encoding': "gzip, deflate", 'X-PATH-CLIENT': "iOS/2.1.2", 'X-PATH-TIMEZONE': "UTC", 'X-PATH-LOCALE': "en_US", 'X-PATH-LANGUAGE': "en", 'Authorization': "Basic %s" % base64.encodestring("%s:%s" % (config.PATH_USERNAME, config.PATH_PASSWORD)).strip()} response = urllib2.urlopen(urllib2.Request(url, headers=headers)).read() return biplist.readPlistFromString(response)
def parse_response(self, response): headers = response.headers content_type = headers.get('content-type') if content_type == 'application/x-plist': try: result = json.dumps(biplist.readPlistFromString(response.content), indent=4, default=str) except Exception, e: result = response.content logger.warning("Response parser: {err}".format(err=e))
def process_compressed_data(self): self.unzipped_input += self.decompressor.decompress(self.rawData) self.rawData = "" while self.hasNextObj(): obj = self.read_next_object_from_unzipped() if type(obj) == Ping: self.received_ping(obj.num) if type(obj) == ServerObject: plist = biplist.readPlistFromString(obj.plist) self.received_plist(plist)
def __init__(self, path): super(iOSInfo, self).__init__(path) self._archive = zipfile.ZipFile(path, 'r') root = self._archive.namelist()[1] plist = biplist.readPlistFromString(self._archive.read(root + 'Info.plist')) self.update( name=plist['CFBundleIdentifier'], version=plist['CFBundleShortVersionString'], version_code=plist['CFBundleVersion'], executable_path=root + plist['CFBundleExecutable'], )
def to_python(self, value): if value == "": return None try: if isinstance(value, basestring): return biplist.readPlistFromString( base64.decodestring(value)) return value except (ValueError, biplist.InvalidPlistException): pass return value
def get_plist_data_from_string (data): """Parse plist data for a string. Tries biplist, falling back to plistlib.""" if has_biplist: return biplist.readPlistFromString(data) # fall back to normal plistlist try: return plistlib.readPlistFromString(data) except Exception: # not parseable (eg. not well-formed, or binary) return {}
def analyzeIpa(ipaPath): zipObj = zipfile.ZipFile(ipaPath) #解析plist plistPath = findInPath(zipObj, 'Payload/[^/]*.app/Info.plist') plistDict = biplist.readPlistFromString(zipObj.read(plistPath)) #png pngPath = findInPath(zipObj, 'Payload/[^/]*.app/Icon-144.png') zipObj.extract(pngPath) # print(pngPath, os.path.basename(pngPath)) # shutil.move(os.path.join(curPath, pngPath), curPath )
def readPlist(path): if not os.path.isabs(path): path = storage(path) if isinstance(path, (six.binary_type)): return biplist.readPlist(path) with codecs.open(path, "r", "utf-8") as f: s = f.read() return biplist.readPlistFromString(s)
def from_plist(self, content): """ Given some binary plist data, returns a Python dictionary of the decoded data. """ if biplist is None: raise ImproperlyConfigured("Usage of the plist aspects requires biplist.") if isinstance(content, six.text_type): content = smart_bytes(content) return biplist.readPlistFromString(content)
def hdiutil(cmd, *args, **kwargs): plist = kwargs.get('plist', True) all_args = ['/usr/bin/hdiutil', cmd] all_args.extend(args) if plist: all_args.append('-plist') p = subprocess.Popen(all_args, stdout=subprocess.PIPE, close_fds=True) output, errors = p.communicate() if plist: results = biplist.readPlistFromString(output) else: results = output retcode = p.wait() return retcode, results
def analyse_ipa(ipa_file): with zipfile.ZipFile(ipa_file, "r") as ipa: ipa_info = {} files = ipa.namelist() info_plist = fnmatch.filter(files, "Payload/*.app/Info.plist")[0] info_plist_bin = ipa.read(info_plist) try: info = biplist.readPlistFromString(info_plist_bin) ipa_info = info except: pass ipa.close() return ipa_info return None
def __init__(self, pxm_fp1): with open(pxm_fp1, 'rb') as pxm_fd1: assert (struct.unpack('<8s', pxm_fd1.read(8))[0] == 'PXMDMETA'), 'Invalid magic number.' h_pl_len = struct.unpack('<i', pxm_fd1.read(4))[0] plist_bytes = pxm_fd1.read(h_pl_len) h_pl = biplist.readPlistFromString(plist_bytes) ap1 = NSArchivedPlist.load(h_pl) # d1 = dict(zip([(h_pl['$objects'][k]) for k in h_pl['$objects'][1]['NS.keys']], # [(h_pl['$objects'][v]) for v in h_pl['$objects'][1]['NS.objects']])) # # d1['PTImageIOFormatBasicMetaLayerNamesInfoKey'] = \ # [(h_pl['$objects'][v1].get('NS.string')) for v1 in # d1['PTImageIOFormatBasicMetaLayerNamesInfoKey']['NS.objects']] # # d1['PTImageIOFormatBasicMetaVersionInfoKey'] = \ # dict(zip([(h_pl['$objects'][k]) for k in d1['PTImageIOFormatBasicMetaVersionInfoKey']['NS.keys']], # [(h_pl['$objects'][v]) for v in d1['PTImageIOFormatBasicMetaVersionInfoKey']['NS.objects']])) # # d1['PTImageIOFormatBasicMetaVersionInfoKey']['PTImageIOPlatformMacOS'] = \ # dict(zip([(h_pl['$objects'][k]) for k in # d1['PTImageIOFormatBasicMetaVersionInfoKey']['PTImageIOPlatformMacOS']['NS.keys']], # [(h_pl['$objects'][v]) for v in # d1['PTImageIOFormatBasicMetaVersionInfoKey']['PTImageIOPlatformMacOS']['NS.objects']])) self.pmx_fo = PXMFile() self.pmx_fo.root_plist = ap1.real_plist pxm_fd1.read(43) sql_bytes = pxm_fd1.read() self.sql_db = PXMSqlDB(sql_bytes) for row1 in self.sql_db.cursor.execute( "SELECT layer_uuid, parent_uuid, index_at_parent, type from document_layer;"): self.pmx_fo.layers.append(PXMLayer.from_row(*row1)) self.pmx_fo.build_layer_dict() for row2 in self.sql_db.cursor.execute("SELECT layer_uuid, name, value from layer_info;"): self.pmx_fo.layers_dict[row2[0]].traits[row2[1]] = row2[2] for l in self.pmx_fo.layers: l.parse_trait_plist() print("hi")
def do_POST(self): # print `self.path` # print self.headers if self.path == "/fp-setup": chal_data = self.rfile.read(int(self.headers["Content-Length"])) # print "chal", `chal_data` print "Calculating AirPlay challenge stage %d..." % self.sap_stage st = time.clock() response = self.sap.challenge(3, chal_data, self.sap_stage) et = time.clock() print "Done! Took %.2f seconds." % (et-st) self.sap_stage += 1 # print "resp", `response` self.send_response(200) self.send_header("Date", self.date_time_string()) self.send_header("Content-Type", "application/octet-stream") self.send_header("Content-Length", str(len(response))) self.end_headers() self.wfile.write(response) elif self.path == "/stream": device_id = int(self.headers["X-Apple-Device-ID"], 16) con = self.server.parent.connections[device_id] bplist_data = self.rfile.read(int(self.headers["Content-Length"])) bplist = biplist.readPlistFromString(bplist_data) # print `bplist` assert bplist['deviceID'] == device_id iv = bplist['param2'] print "Decrypting AirPlay key..." st = time.clock() key = self.sap.decrypt_key(bplist['param1']) et = time.clock() print "Done! Took %.2f seconds. AirPlay key: %s" % (et-st, key.encode("hex")) con.handle_mirroring_video_stream(self.rfile, key, iv) self.close_connection = 1 else: self.send_error(404)
def _get_app_info(self): """Find application's Info.plist and read it""" info_plist = None for data in self.filelist: if re.match(self.info_plist_regex, data.filename): info_plist = data if not info_plist: self._raise_ipa_error() info_plist = self.read(info_plist) self.app_info = readPlistFromString(info_plist) return self.app_info
def get_tabs(): # First make an empty (without tab data) request to get the latest registry string. payload_plist = generate_plist(False, [], DEVICE_UUID, DEVICE_NAME) response = make_request(payload_plist) response_plist = plistlib.readPlistFromString(response) registry_version = response_plist["apps"][0]["registry-version"] #print plistlib.writePlistToString(response_plist) print registry_version # dump current tabs for device in response_plist["apps"][0]["keys"]: pprint.pprint(biplist.readPlistFromString(device["data"].data[12:])) #print plistlib.loads(device["data"][12:], fmt=plistlib.FMT_BINARY) #py3.4 return (registry_version, response_plist)
def handlePlay(self): global g_lastEvent location = "" position = 0.0 g_lastEvent = EVENT_NONE if self.contentType == "application/x-apple-binary-plist": log(xbmc.LOGDEBUG, "parse binary plist") plist = biplist.readPlistFromString(self.body) if 'Start-Position' in plist: position = float(plist['Start-Position']) if 'Content-Location' in plist: location = plist['Content-Location'] else: # Get URL to play startIdx = self.body.find("Content-Location: ") if startIdx == -1: self.sendGeneralResponse(AIRPLAY_STATUS_NOT_IMPLEMENTED) return startIdx += len("Content-Location: ") endIdx = self.body.find('\n', startIdx) location = self.body[startIdx : endIdx] startIdx = self.body.find("Start-Position") if startIdx != -1: startIdx += len("Start-Position: ") endIdx = self.body.find('\n', startIdx) position = float(self.body[startIdx : endIdx]) if len(location): #url encode useragent dict = { 'User-Agent' : 'AppleCoreMedia/1.0.0.8F455 (AppleTV; U; CPU OS 4_3 like Mac OS X; de_de)'} userAgent = urllib.urlencode(dict) location = location + "|" + userAgent log(xbmc.LOGDEBUG, "position: " + str(position)) if position > 0.0: posPercent = position * 100 listitem = xbmcgui.ListItem() listitem.setProperty('StartPercent', str(posPercent)) xbmc.Player(xbmc.PLAYER_CORE_DVDPLAYER).play(location, listitem) else: xbmc.Player(xbmc.PLAYER_CORE_DVDPLAYER).play(location) self.sendReverseEvent(EVENT_PLAYING) else: log(xbmc.LOGERROR, "no location found in play header") self.sendGeneralResponse(AIRPLAY_STATUS_OK)
def write_xattr_metadata(file_list, meta_data): if meta_data.has_key('caption'): #Simple, just replace all the captions bipl = biplist.writePlistToString(meta_data['caption']) for file in file_list: xattr.setxattr(file, 'com.apple.metadata:kMDItemDescription', bipl) if meta_data.has_key('keywords'): #A little more involved. For each file, load original keywords, #then remove or add the relevant keywords for file in file_list: if 'com.apple.metadata:kMDItemKeywords' in xattr.listxattr(file): orig_keywd_list = set(biplist.readPlistFromString(xattr.getxattr(file, 'com.apple.metadata:kMDItemKeywords'))) else: orig_keywd_list = set([]) for keyword in meta_data['keywords']: if keyword[0] == '+': orig_keywd_list.add(keyword[1]) if keyword[0] == '-': orig_keywd_list.remove(keyword[1]) xattr.setxattr(file, 'com.apple.metadata:kMDItemKeywords', biplist.writePlistToString(list(orig_keywd_list)))
def parse(self): import biplist header = self.stream[:5].encode('hex') if header.startswith('040000'): # Ignore PONG requests logger.info('[Server] PONG: %d', int(header[-4:], 16)) self.stream = self.stream[5:] header = self.stream[:5].encode('hex') chunkSize = 1000000 if not header.startswith('0200') else int(header[-6:], 16) if chunkSize < len(self.stream) + 5: plistData = self.stream[5:chunkSize + 5] plist = biplist.readPlistFromString(plistData) logger.info('[Server]') logger.info(pprint.pformat(plist)) if plist.get('class', '') == 'GetSessionCertificateResponse': der = plist['properties']['certificate'][6:] self.processCertificate(der) self.stream = self.stream[chunkSize+5:]
def doit(basedir): ipas = glob.glob(basedir + "/*.ipa") for fn in ipas: x = zipfile.ZipFile(fn) y = x.namelist() infoplist = "" execFile = "" for n in y: if n[-11:] == "/Info.plist": infoplist = n if infoplist == "": return plistData = x.read(infoplist) plist = biplist.readPlistFromString(plistData) if "CFBundleDisplayName" in plist: appname = plist["CFBundleDisplayName"] elif "CFBundleName" in plist: appname = plist["CFBundleName"] else: appname = plist["CFBundleIdentifier"] appname += (32 - len(appname)) * " " if "CFBundleExecutable" not in plist: continue l = len(plist["CFBundleExecutable"]) for n in y: if n[-l:] == plist["CFBundleExecutable"]: execFile = n if execFile == "": print "Cannot find execFile" continue data = x.read(execFile) tname = "ipapiescan_XABCDEF" f = open(tname, "w+b") f.write(data) f.close() output = subprocess.check_output(["otool", "-vh", tname]) archstr = "" if output.find("ARM V6") != -1: archstr += "armv6" bestarch = "armv6" if output.find("ARM V7") != -1: if archstr == "": archstr = " armv7" else: archstr += "|armv7" bestarch = "armv7" if bestarch == "armv6": archstr += " " if archstr == "": print "%s - illegal architecture" % (appname) print output else: output = subprocess.check_output( ["otool", "-arch", bestarch, "-vh", tname]) if output.find("PIE") == -1: pie = "NO_PIE" #print output else: pie = "PIE " output = subprocess.check_output( ["otool", "-arch", bestarch, "-lv", tname]) if output.find("LC_VERSION_MIN_IPHONEOS") == -1: minversion = "N/A" else: #print output p = re.compile( 'LC_VERSION_MIN_IPHONEOS[^v]*version[^0-9]+([0-9]+\.[0-9]+)', re.MULTILINE | re.DOTALL) x = p.search(output) minversion = x.groups(0)[0] print "%s - %s - %s - %s" % (appname, archstr, pie, minversion) os.unlink(tname)
def get_info(cls, relative_bundle_dir, zipfile_obj): plist_path = cls._get_plist_path(relative_bundle_dir) plist_bytes = zipfile_obj.read( plist_path.encode('utf-8').decode('cp437')) return biplist.readPlistFromString(plist_bytes)
def main(): ipa = input("请拖入要重签名的.ipa:").strip() provision = input("请拖入对应的签名文件.mobileprovision:").strip() log("● 正在获取本地证书列表") output = subprocess.getoutput("security find-identity -v -p codesigning") wraplist = getWrapped(output, "\"", "\"") log("● 正在解析签名文件") output = subprocess.getoutput("security cms -D -i " + provision) output = output[output.find("<?xml"):] cer_content = getWrapped(output, "<data>", "</data>")[0] match_cer = None for name in wraplist: content = getCerContentByName(name) if cer_content == content: match_cer = name break if match_cer == None: error("× 没有安装该证书对应的签名文件") try: plist = biplist.readPlistFromString(bytes(output, "utf-8")) identify = plist['Entitlements']['application-identifier'] pos = identify.find('.') provision_uuid = plist['UUID'] provision_name = plist['Name'] provision_team = identify[:pos] provision_id = identify[pos + 1:] except Exception as e: error("× 签名文件解析失败") log("● 正在解压.ipa") base_path = os.path.dirname(ipa) unzip_path = os.path.join(base_path, ".ipa_resign_temp") if os.path.exists(unzip_path): shutil.rmtree(unzip_path, True) os.system("unzip -q " + ipa + " -d " + unzip_path) log("● 解压完成") # input("● ipa已经解压到.ipa_resign_temp目录,现在你可以随意修改包内的内容,修改完成后任意键继续") payload = os.path.join(unzip_path, "Payload") app_path = None for file in os.listdir(payload): if re.match(".*\.app", file): app_path = os.path.join(payload, file) break log("● 正在删除原始签名文件") sign_path = os.path.join(app_path, "_CodeSignature") if os.path.exists(sign_path): shutil.rmtree(sign_path, True) log("● 正在复制新的签名文件") shutil.copyfile(provision, os.path.join(app_path, "embedded.mobileprovision")) log("● 正在修改包名") info_plist = os.path.join(app_path, "Info.plist") try: plist = biplist.readPlist(info_plist) plist["CFBundleIdentifier"] = provision_id biplist.writePlist(plist, info_plist) except Exception as e: error("× Info.plist解析失败", e) log("● 正在重签名") entitlements = createEntitlementsFile(unzip_path, provision_team, provision_id) os.system("/usr/bin/codesign -f -s \"{}\" --entitlements {} {}".format( match_cer, entitlements, app_path)) # os.system("/usr/bin/codesign --verify " + app_path) # os.system("codesign -vv -d " + app_path) log("● 重签名成功") log("● 正在生成新的.ipa") resign_ipa = ipa[:-4] + "-resign.ipa" my_commands = "cd " + unzip_path my_commands = my_commands + ";chmod -R +x Payload" my_commands = my_commands + ";zip -qr " + resign_ipa + " Payload" os.system(my_commands) shutil.rmtree(unzip_path, True) os.system("open " + base_path) log("● 任务已完成")
def get_info(cls, relative_bundle_dir, zipfile_obj): plist_path = cls._get_plist_path(relative_bundle_dir) plist_bytes = zipfile_obj.read(plist_path) return biplist.readPlistFromString(plist_bytes)
def decode(bytes): return biplist.readPlistFromString(bytes)
def getFolderDecryptedCopy(self, relativePath=None, targetFolder=None, temporary=False, includeDomains=None, excludeDomains=None, includeFiles=None, excludeFiles=None): """Recreates under targetFolder an entire folder (relativePath) found into an iOS backup. Parameters ---------- relativePath : str Semi full path name of a backup file. Something like 'Media/PhotoData/Metadata' targetFolder : str, optional Folder where to store decrypted files, creates the folder tree under current folder if omitted. temporary : str, optional Creates a temporary file (using tempfile module) in a temporary folder. Use targetFolder if omitted. includeDomains : str, list, optional Retrieve files only from this single or list of iOS backup domains. excludeDomains : str, list, optional Retrieve files from all but this single or list of iOS backup domains. includeFiles : str, list, optional SQL friendly file name matches. For example "%JPG" will retrieve only files ending with JPG. Pass a list of filters to be more effective. excludeFiles : str, list, optional SQL friendly file name matches to exclude. For example "%MOV" will retrieve all but files ending with MOV. Pass a list of filters to be more effective. Returns ------- List of dicts with info about all files retrieved. """ if not self.manifestDB: raise Exception( "Object not yet innitialized or can't find decrypted files catalog ({})" .format(iOSbackup.catalog['manifestDB'])) if not relativePath: relativePath = '' if not includeDomains: raise Exception( "relativePath and includeDomains cannot be empty at the same time" ) if temporary: targetRootFolder = tempfile.TemporaryDirectory( suffix=f"---{fileName}", dir=targetFolder) targetRootFolder = targetRootFolder.name else: if targetFolder: targetRootFolder = targetFolder else: targetRootFolder = '.' additionalFilters = [] if includeDomains: if type(includeDomains) == list: additionalFilters.append('domain IN ({})'.format(','.join( "'" + item + "'" for item in includeDomains))) else: additionalFilters.append( '''domain = '{}' '''.format(includeDomains)) if excludeDomains: if type(excludeDomains) == list: additionalFilters.append('domain NOT IN ({})'.format(','.join( "'" + item + "'" for item in excludeDomains))) else: additionalFilters.append( '''domain != '{}' '''.format(excludeDomains)) if includeFiles: ifiles = [] if type(includeFiles) == list: for i in includeFiles: ifiles.append(f"relativePath LIKE '{i}'") ifiles = '(' + ' OR '.join(ifiles) + ')' additionalFilters.append(ifiles) else: additionalFilters.append(f"relativePath LIKE '{includeFiles}'") if excludeFiles: ifiles = [] if type(excludeFiles) == list: for i in excludeFiles: ifiles.append(f"relativePath NOT LIKE '{i}'") ifiles = '(' + ' AND '.join(ifiles) + ')' additionalFilters.append(ifiles) else: additionalFilters.append( f"relativePath NOT LIKE '{excludeFiles}'") if len(additionalFilters) > 0: additionalFilters.insert( 0, '') # so we dont brake SQL due to lack of 'AND' catalog = sqlite3.connect(self.manifestDB) catalog.row_factory = sqlite3.Row query = "SELECT * FROM Files WHERE relativePath LIKE '{relativePath}%' {additionalFilters} ORDER BY domain, relativePath".format( relativePath=relativePath, additionalFilters=' AND '.join(additionalFilters)) backupFiles = catalog.cursor().execute(query).fetchall() fileList = [] for payload in backupFiles: payload = dict(payload) payload['manifest'] = biplist.readPlistFromString(payload['file']) del payload['file'] # Compute target file with path physicalTarget = os.path.join(targetRootFolder, payload['domain'], payload['relativePath']) # Create parent folder to contain it Path(os.path.dirname(physicalTarget)).mkdir(parents=True, exist_ok=True) # payload.keys()==['manifest','fileID','domain'] info = self.getFileDecryptedCopy( manifestEntry=payload, targetFolder=os.path.dirname(physicalTarget), targetName=os.path.basename(physicalTarget)) # with open(physicalTarget,'wb',info['mode']) as output: # output.write(decrypted) # info['originalFilePath']=relativePath # info['domain']=f['domain'] # info['backupFile']=f['fileID'] fileList.append(info) catalog.close() return fileList