def read_log(self, file): # clear the log in iphone Utils.cmd_block('cat /dev/null > /var/log/syslog') log_file = open(file) while 1: line = log_file.readline() self.check_log_line(line)
def via_sftp(src): cmd = 'cp {} /tmp/temp.binary'.format(src) Utils.cmd_block(data.client, cmd) src = '/tmp/temp.binary' des = '{}/temp/{}/binary/'.format( os.path.abspath('.'), data.start_time) + data.metadata['bundle_id'] Utils.sftp_get(config.mobile_ip, config.ssh_port, config.mobile_user, config.mobile_password, src, des) return des
def crashed(self): cmd = 'find {} -type f | grep {}'.format(data.crash_report_folder, self.app) if Utils.cmd_block(data.client, cmd).split("\n")[0]: return True else: return False
def get_files(): files = [] dirs = [data.metadata['bundle_directory'], data.metadata['data_directory']] dirs_str = ' '.join(dirs) cmd = '{bin} {dirs_str} -type f -name "*.sqlite"'.format( bin=data.DEVICE_TOOLS['FIND'], dirs_str=dirs_str) temp = Utils.cmd_block(data.client, cmd).split("\n") cmd = '{bin} {dirs_str} -type f -name "*.db"'.format( bin=data.DEVICE_TOOLS['FIND'], dirs_str=dirs_str) temp.extend(Utils.cmd_block(data.client, cmd).split("\n")) for db in temp: if db != '': files.append(db) return files
def parse_plist(self, plist): """Given a plist file, copy it to temp folder, convert it to XML, and run plutil on it.""" # Copy the plist plist_temp = self.build_temp_path_for_file(plist.strip("'")) plist_copy = Utils.escape_path(plist_temp) self.file_copy(plist, plist_copy) # Convert to xml cmd = '{plutil} -convert xml1 {plist}'.format( plutil=data.DEVICE_TOOLS['PLUTIL'], plist=plist_copy) Utils.cmd_block(self.client, cmd) # Cat the content cmd = 'cat {}'.format(plist_copy) out = Utils.cmd_block(self.client, cmd) # Parse it with plistlib out = str(''.join(out).encode('utf-8')) pl = plistlib.readPlistFromString(out) return pl
def __run_otool(self, query, grep=None): """Run otool against a specific architecture.""" cmd = '{bin} {query} {app}'.format(bin=data.DEVICE_TOOLS['OTOOL'], query=query, app=data.metadata['binary_path']) if grep: cmd = "%s | grep -Ei \"%s\"" % (cmd, grep) out = Utils.cmd_block(self.client, cmd).split("\n") return out
def clutch(self): client = data.client clutch_i = Utils.cmd_block(client, 'clutch -i') pat = re.compile(r'.+<(.+)>') clutch_app_id = -1 for line in clutch_i.split('\n'): m = pat.match(line) if m: if m.group(1) == data.app_bundleID: clutch_app_id = int(line.split(':')[0]) if clutch_app_id != -1: Utils.printy( 'the application is encrypted, and use clutch to decrypt', 0) # clean the decrypted ipas already done by clutch cmd = 'rm /private/var/mobile/Documents/Dumped/*.ipa' Utils.cmd_block(client, cmd) self.status = "clutching" # Only dump binary files from the specified bundleID cmd = 'clutch -b ' + str(clutch_app_id) out = Utils.cmd_block(client, cmd) pat = re.compile(r'.+Finished.+to (.+)\[0m') for line in out.split('\n'): m = pat.match(line) if m: # print m.group(1) source = '{path}/{bundle_id}/{binary}'.format( path=m.group(1), bundle_id=data.metadata['bundle_id'], binary=data.metadata['binary_name']) data.static_file_path = bin_get.via_sftp(source) self.status = "done" # if self.status != "done": # Utils.printy('Failed to clutch! Try to dump the decrypted app into a file. ', 2) # self.status = DumpDecrypted.dump_binary() else: # print 'the application is not encrypted' data.static_file_path = bin_get.via_sftp( data.metadata['binary_path'])
def _detect_architectures(self, binary): """Use lipo to detect supported architectures.""" # Run lipo cmd = '{lipo} -info {binary}'.format(lipo=data.DEVICE_TOOLS['LIPO'], binary=binary) out = Utils.cmd_block(self.client, cmd) # Parse output msg = out.strip() res = msg.rsplit(': ')[-1].split(' ') return res
def dump_binary(): try: target_doc_path = data.metadata['data_directory'] + '/Documents' target_doc_file = target_doc_path + '/dumpdecrypted.dylib' Utils.sftp_put(ip=config.mobile_ip, port=config.ssh_port, username=config.mobile_user, password=config.mobile_password, remote_path=target_doc_file, local_file='./tools/dumpdecrypted.dylib') target_bin_path = data.metadata['binary_path'] dump_cmd = 'DYLD_INSERT_LIBRARIES={} {}'.format( target_doc_file, target_bin_path) Utils.cmd_block(data.client, dump_cmd) # get decrypted file from iphone remote_file = './{}.decrypted'.format(data.metadata['binary_name']) data.static_file_path = bin_get.via_sftp(remote_file) return True except Exception: return False
def install_ipa_from_local(ipa_path): if ipa_path: # 从平台下发的任务,经由这个方法,ipa_path有值 ipa = zipfile.ZipFile(ipa_path) pat = re.compile("Payload[/\\\][\w.]+[/\\\]Info.plist") for name in ipa.namelist(): if pat.search(name): plist_path = name break # plist_path = ipa.extract(name) # plist = plistlib.readPlist(plist_path) # data.app_bundleID = plistlib.readPlist(plist_path)["CFBundleIdentifier"] # print data.app_bundleID else: # 从单机版入口,ipa_path为空,需要实时要求用户输入 while True: ipa_path = raw_input(clint.textui.colored.yellow("> >> >>> Input the Path: > ")).strip() if not os.path.exists(ipa_path): Utils.printy_result('No such file ', 0) elif not ipa_path.endswith("ipa"): Utils.printy_result('Not ipa file ', 0) else: break # sftp to iPhone Utils.sftp_put(config.mobile_ip, config.ssh_port, config.mobile_user, config.mobile_password, '/tmp/detect/temp.ipa', ipa_path) if ipa_path: ipa = zipfile.ZipFile(ipa_path) pat = re.compile("Payload[/\\\][\w.]+[/\\\]Info.plist") for name in ipa.namelist(): if pat.search(name): break plist_path = ipa.extract(name) tmp = plist_path + '.tmp' data.app_bundleID = commands.getstatusoutput( 'plutil -extract CFBundleIdentifier xml1 {} -o {}; plutil -p {}'. format(plist_path, tmp, tmp))[1].strip('"') Utils.cmd_block(data.client, 'ipainstaller {}'.format('/tmp/detect/temp.ipa')) return True
def dump(self): try: cmd = './keychain_dumper' out = Utils.cmd_block(self.client, cmd) lines = out.split('\n') for line in lines: if line.startswith('Keychain Data:') and not '(null)' in line: content = line[15:] if content: self.all_keychain_values.append(content) self.filter() except Exception, e: data.logger.warn(e)
def get_files(self): files = [] dirs = [ data.metadata['bundle_directory'], data.metadata['data_directory'] ] dirs_str = ' '.join(dirs) cmd = '{bin} {dirs_str} -type f -name "*.plist"'.format( bin=data.DEVICE_TOOLS['FIND'], dirs_str=dirs_str) temp = Utils.cmd_block(self.client, cmd).split("\n") for f in temp: if f != '': files.append(f) return files
def get(self): cmd = '{bin} -L {app}'.format(bin=data.DEVICE_TOOLS['OTOOL'], app=data.metadata['binary_path']) out = Utils.cmd_block(self.client, cmd).split("\n") if out: try: del out[0] for i in out: i = i.strip('\t') if len(i) > 0: data.shared_lib.append(i) # print "--------------------shared_library-------------------" return True except AttributeError: return False else: return False
def clutch(): clutch_app_id = 0 clutch_success = False client = data.client clutch_i = Utils.cmd_block(client, 'Clutch -i') for line in clutch_i.split('\n'): if data.app_bundleID in line: break clutch_app_id += 1 if clutch_app_id: Utils.printy('the application is encrypted, use Clutch to decrypt', 0) # clean the decrypted ipas already done by clutch cmd = 'rm /private/var/mobile/Documents/Dumped/*.ipa' Utils.cmd_block(client, cmd) cmd = 'rm -rf /var/tmp/clutch/*' Utils.cmd_block(client, cmd) # Only dump binary files from the specified bundleID cmd = 'Clutch -b ' + str(clutch_app_id) out = Utils.cmd_block_limited(client, cmd, 600) dumped_file = Utils.cmd_block(client, 'ls /var/tmp/clutch/*/').split() if data.app_bundleID in dumped_file: clutch_success = True dir = Utils.cmd_block(client, 'ls -H /var/tmp/clutch/').strip() source = '{path}/{bundle_id}/{binary}'.format( path='/var/tmp/clutch/{}'.format(dir), bundle_id=data.metadata['bundle_id'], binary=data.metadata['binary_name']) data.static_file_path = bin_get.via_sftp(source) if not clutch_success: Utils.printy( 'Failed to clutch! Try to dump the decrypted app into a file. ', 2) clutch_success = DumpDecrypted.dump_binary() return clutch_success else: Utils.printy( 'Failed to Clutch. Get the binary might be encrypted. Static Analysis may fail.', 4) data.static_file_path = bin_get.via_sftp(data.metadata['binary_path']) return True
def get_seg_info(): file_path = data.static_file_path # cmd = 'otool -l {}'.format(file_path) # out = commands.getoutput(cmd) cmd = '{bin} -l {app}'.format(bin=data.DEVICE_TOOLS['OTOOL'], app=data.metadata['binary_path']) out = Utils.cmd_block(data.client, cmd) segment_dict = dict() lines = out.split('\n') for i in range(len(lines)): if lines[i] == 'Section': section_name = lines[i + 1][11:] segment_name = lines[i + 2][11:] # print segment_name, '-', section_name if not segment_dict.has_key(segment_name): segment_dict[segment_name] = [] if section_name not in segment_dict[segment_name]: segment_dict[segment_name].append(section_name) data.segment_dict = segment_dict
def __init__(self, app_dy_info): threading.Thread.__init__(self) self.dynamic_socket = None self._stop_event = threading.Event() self.app_info = app_dy_info apps_plist = '/var/mobile/Library/Preferences/com.softsec.iosdefect.app.plist' socket_settings_plist = '/var/mobile/Library/Preferences/com.softsec.iosdefect.socket.plist' Utils.cmd_block( data.client, "plutil -key {} -value {} {}".format(data.app_bundleID, "YES", apps_plist)) Utils.cmd_block( data.client, "plutil -key {} -value {} {}".format("MITMIP", config.socket_ip, socket_settings_plist)) Utils.cmd_block( data.client, "plutil -key {} -value {} {}".format("ServerIP", config.socket_ip, socket_settings_plist)) Utils.cmd_block( data.client, "plutil -key {} -value {} {}".format("ServerPort", config.socket_port, socket_settings_plist))
def delete_old_reports(self): cmd = 'rm -f `find {} -type f | grep {}`'.format( data.crash_report_folder, self.app) Utils.cmd_block(data.client, cmd)
def file_copy(self, src, dst): src, dst = Utils.escape_path(src), Utils.escape_path(dst) cmd = "cp {} {}".format(src, dst) Utils.cmd_block(self.client, cmd)