Cleaned up the python in the app and made app spawning faster / more reliable

This commit is contained in:
Cameron Lowell Palmer 2018-02-01 16:03:00 +01:00 committed by Cameron Lowell Palmer
parent 42ff6d12b8
commit 90c17279d2
5 changed files with 289 additions and 314 deletions

4
.gitignore vendored
View File

@ -1 +1,5 @@
.DS_Store .DS_Store
.idea
*.ipa
frida/

View File

@ -1,50 +1,37 @@
# frida-ios-dump # frida-ios-dump
pull decrypted ipa from jailbreak device Pull a decrypted IPA from a jailbroken device
### Usage ## Usage
## 1. install [frida](http://www.frida.re/) on device and mac 1. Install [frida](http://www.frida.re/) on device and mac
2. Run usbmuxd/iproxy SSH forwarding over USB (Default 2222 -> 22)
## 2. iproxy 2222 22 3. Run ./dump.py `Display name` or `Bundle identifier`
## 3. ./dump.py 微信
``` ```
➜ frida-ios-dump ./dump.py 微信 ./dump.py Aftenposten
open target app...... Start the target app Aftenposten
start dump target app...... Dumping Aftenposten to /var/folders/wn/9v1hs8ds6nv_xj7g95zxyl140000gn/T
start dump /var/containers/Bundle/Application/6665AA28-68CC-4845-8610-7010E96061C6/WeChat.app/WeChat start dump /var/containers/Bundle/Application/66423A80-0AFE-471C-BC9B-B571107D3C27/AftenpostenApp.app/AftenpostenApp
WeChat 100% 68MB 11.4MB/s 00:05 start dump /private/var/containers/Bundle/Application/66423A80-0AFE-471C-BC9B-B571107D3C27/AftenpostenApp.app/Frameworks/AFNetworking.framework/AFNetworking
start dump /private/var/containers/Bundle/Application/6665AA28-68CC-4845-8610-7010E96061C6/WeChat.app/Frameworks/WCDB.framework/WCDB start dump /private/var/containers/Bundle/Application/66423A80-0AFE-471C-BC9B-B571107D3C27/AftenpostenApp.app/Frameworks/ATInternet_iOS_ObjC_SDK.framework/ATInternet_iOS_ObjC_SDK
WCDB 100% 2555KB 11.0MB/s 00:00 start dump /private/var/containers/Bundle/Application/66423A80-0AFE-471C-BC9B-B571107D3C27/AftenpostenApp.app/Frameworks/SPTEventCollector.framework/SPTEventCollector
start dump /private/var/containers/Bundle/Application/6665AA28-68CC-4845-8610-7010E96061C6/WeChat.app/Frameworks/MMCommon.framework/MMCommon start dump /private/var/containers/Bundle/Application/66423A80-0AFE-471C-BC9B-B571107D3C27/AftenpostenApp.app/Frameworks/SPiDSDK.framework/SPiDSDK
MMCommon 100% 979KB 10.6MB/s 00:00 start dump /private/var/containers/Bundle/Application/66423A80-0AFE-471C-BC9B-B571107D3C27/AftenpostenApp.app/Frameworks/libswiftCore.dylib
start dump /private/var/containers/Bundle/Application/6665AA28-68CC-4845-8610-7010E96061C6/WeChat.app/Frameworks/MultiMedia.framework/MultiMedia start dump /private/var/containers/Bundle/Application/66423A80-0AFE-471C-BC9B-B571107D3C27/AftenpostenApp.app/Frameworks/libswiftCoreData.dylib
MultiMedia 100% 6801KB 11.1MB/s 00:00 start dump /private/var/containers/Bundle/Application/66423A80-0AFE-471C-BC9B-B571107D3C27/AftenpostenApp.app/Frameworks/libswiftCoreGraphics.dylib
start dump /private/var/containers/Bundle/Application/6665AA28-68CC-4845-8610-7010E96061C6/WeChat.app/Frameworks/mars.framework/mars start dump /private/var/containers/Bundle/Application/66423A80-0AFE-471C-BC9B-B571107D3C27/AftenpostenApp.app/Frameworks/libswiftCoreImage.dylib
mars 100% 7462KB 11.1MB/s 00:00 start dump /private/var/containers/Bundle/Application/66423A80-0AFE-471C-BC9B-B571107D3C27/AftenpostenApp.app/Frameworks/libswiftCoreLocation.dylib
AppIcon60x60@2x.png 100% 2253 230.9KB/s 00:00 start dump /private/var/containers/Bundle/Application/66423A80-0AFE-471C-BC9B-B571107D3C27/AftenpostenApp.app/Frameworks/libswiftDarwin.dylib
AppIcon60x60@3x.png 100% 4334 834.8KB/s 00:00 start dump /private/var/containers/Bundle/Application/66423A80-0AFE-471C-BC9B-B571107D3C27/AftenpostenApp.app/Frameworks/libswiftDispatch.dylib
AppIcon76x76@2x~ipad.png 100% 2659 620.6KB/s 00:00 start dump /private/var/containers/Bundle/Application/66423A80-0AFE-471C-BC9B-B571107D3C27/AftenpostenApp.app/Frameworks/libswiftFoundation.dylib
AppIcon76x76~ipad.png 100% 1523 358.0KB/s 00:00 start dump /private/var/containers/Bundle/Application/66423A80-0AFE-471C-BC9B-B571107D3C27/AftenpostenApp.app/Frameworks/libswiftObjectiveC.dylib
AppIcon83.5x83.5@2x~ipad.png 100% 2725 568.9KB/s 00:00 start dump /private/var/containers/Bundle/Application/66423A80-0AFE-471C-BC9B-B571107D3C27/AftenpostenApp.app/Frameworks/libswiftQuartzCore.dylib
Assets.car 100% 10MB 11.1MB/s 00:00 start dump /private/var/containers/Bundle/Application/66423A80-0AFE-471C-BC9B-B571107D3C27/AftenpostenApp.app/Frameworks/libswiftUIKit.dylib
....... Generating Aftenposten.ipa
AppIntentVocabulary.plist 100% 197 52.9KB/s 00:00
AppIntentVocabulary.plist 100% 167 43.9KB/s 00:00 Done.
AppIntentVocabulary.plist 100% 187 50.2KB/s 00:00
InfoPlist.strings 100% 1720 416.4KB/s 00:00
TipsPressTalk@2x.png 100% 14KB 2.2MB/s 00:00
mm.strings 100% 404KB 10.2MB/s 00:00
network_setting.html 100% 1695 450.4KB/s 00:00
InfoPlist.strings 100% 1822 454.1KB/s 00:00
mm.strings 100% 409KB 10.2MB/s 00:00
network_setting.html 100% 1819 477.5KB/s 00:00
InfoPlist.strings 100% 1814 466.8KB/s 00:00
mm.strings 100% 409KB 10.3MB/s 00:00
network_setting.html 100% 1819 404.9KB/s 00:00
``` ```
congratulations!!! You've got a decrypted ipa file. Congratulations!!! You've got a decrypted IPA file.
Drag to [MonkeyDev](https://github.com/AloneMonkey/MonkeyDev), Happy hacking! Drag to [MonkeyDev](https://github.com/AloneMonkey/MonkeyDev), Happy hacking!

52
app.js
View File

@ -1,52 +0,0 @@
//by: AloneMonkey
const LSApplicationWorkspace = ObjC.classes.LSApplicationWorkspace;
function openApplication(appid){
const workspace = LSApplicationWorkspace.defaultWorkspace();
return workspace.openApplicationWithBundleID_(appid);
}
function getbundleid(name){
const workspace = LSApplicationWorkspace.defaultWorkspace();
const apps = workspace.allApplications();
var result;
for(var index = 0; index < apps.count(); index++){
var proxy = apps.objectAtIndex_(index);
if(proxy.localizedName() && proxy.localizedName().toString() == name){
return proxy.bundleIdentifier().toString();
}
}
return ""
};
function getdisplayname(bundleid){
const workspace = LSApplicationWorkspace.defaultWorkspace();
const apps = workspace.allApplications();
var result;
for(var index = 0; index < apps.count(); index++){
var proxy = apps.objectAtIndex_(index);
if(proxy.bundleIdentifier() && proxy.bundleIdentifier().toString() == bundleid){
return proxy.localizedName().toString();
}
}
return ""
}
function handleMessage(message) {
var bundleid;
var displayname;
if(message['name']){
displayname = message['name']
bundleid = getbundleid(displayname);
}else if(message['bundleid']){
bundleid = message['bundleid']
displayname = getdisplayname(bundleid);
}
if(bundleid.length > 0){
openApplication(bundleid);
}
send({ opened: displayname });
}
recv(handleMessage);

14
dump.js
View File

@ -175,9 +175,9 @@ var LC_SEGMENT_64 = 0x19;
var LC_ENCRYPTION_INFO = 0x21; var LC_ENCRYPTION_INFO = 0x21;
var LC_ENCRYPTION_INFO_64 = 0x2C; var LC_ENCRYPTION_INFO_64 = 0x2C;
function pad(str, n) { function pad(str, n) {
return Array(n-str.length+1).join("0")+str; return Array(n-str.length+1).join("0")+str;
} }
function swap32(value) { function swap32(value) {
value = pad(value.toString(16),8) value = pad(value.toString(16),8)
@ -214,7 +214,7 @@ function dumpModule(name) {
if(!access(allocStr(newmodpath),0)){ if(!access(allocStr(newmodpath),0)){
remove(allocStr(newmodpath)); remove(allocStr(newmodpath));
} }
var fmodule = open(newmodpath, O_CREAT | O_RDWR, 0); var fmodule = open(newmodpath, O_CREAT | O_RDWR, 0);
var foldmodule = open(oldmodpath, O_RDONLY, 0); var foldmodule = open(oldmodpath, O_RDONLY, 0);
@ -288,7 +288,7 @@ function dumpModule(name) {
var segments = []; var segments = [];
for (var i = 0; i < ncmds; i++) { for (var i = 0; i < ncmds; i++) {
var cmd = getU32(modbase.add(off)); var cmd = getU32(modbase.add(off));
var cmdsize = getU32(modbase.add(off + 4)); var cmdsize = getU32(modbase.add(off + 4));
if (cmd == LC_ENCRYPTION_INFO || cmd == LC_ENCRYPTION_INFO_64) { if (cmd == LC_ENCRYPTION_INFO || cmd == LC_ENCRYPTION_INFO_64) {
offset_cryptid = off + 16; offset_cryptid = off + 16;
crypt_off = getU32(modbase.add(off + 8)); crypt_off = getU32(modbase.add(off + 8));
@ -305,11 +305,11 @@ function dumpModule(name) {
lseek(fmodule, crypt_off, SEEK_SET); lseek(fmodule, crypt_off, SEEK_SET);
write(fmodule, modbase.add(crypt_off), crypt_size); write(fmodule, modbase.add(crypt_off), crypt_size);
} }
close(fmodule); close(fmodule);
close(foldmodule); close(foldmodule);
return newmodpath return newmodpath
} }
function handleMessage(message) { function handleMessage(message) {
//start dump //start dump

462
dump.py
View File

@ -1,270 +1,306 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
#Author : AloneMonkey # Author : AloneMonkey
#blog: www.alonemonkey.com # blog: www.alonemonkey.com
import sys import sys
import codecs import codecs
import frida import frida
import threading import threading
import os import os
import shutil import shutil
import time import time
import getopt import getopt
import tempfile
import subprocess
reload(sys) reload(sys)
sys.setdefaultencoding('utf8') sys.setdefaultencoding('utf8')
DUMP_JS = './dump.js' script_dir = os.path.dirname(os.path.realpath(__file__))
APP_JS = './app.js'
OUTPUT = "Payload" DUMP_JS = os.path.join(script_dir, 'dump.js')
SSH_USER_HOST='root@localhost:'
SSH_PORT=2222
TEMP_DIR = tempfile.gettempdir()
PAYLOAD_DIR = 'Payload'
PAYLOAD_PATH = os.path.join(TEMP_DIR, PAYLOAD_DIR)
file_dict = {} file_dict = {}
opened = threading.Event()
finished = threading.Event() finished = threading.Event()
global session
global name
#show usage # show usage
def usage(): def usage():
print '-------------------------frida-ios-dump(by AloneMonkey v2.0)----------------------------' print '-------------------------frida-ios-dump(by AloneMonkey v2.0)----------------------------'
print '\t%-20s\t%s' % ('-h,--help','Show help menu.'); print '\t%-20s\t%s' % ('-h,--help', 'Show help menu.')
print '\t%-20s\t%s' % ('displayname','Decrypt the application of the specified display name. ps: ./dump.py 微信'); print '\t%-20s\t%s' % ('name', 'Decrypt the application with the specified display name or bundle identifier. ps: ./dump.py 微信')
print '\t%-20s\t%s' % ('-l','List the app has been installed.'); print '\t%-20s\t%s' % ('-l', 'List the installed apps.')
print '\t%-20s\t%s' % ('-b bundleid','Decrypt the application of the specified bundleid. ps: ./dump.py com.tencent.xin');
exit(0)
def get_usb_iphone(): def get_usb_iphone():
dManager = frida.get_device_manager(); dManager = frida.get_device_manager()
changed = threading.Event() changed = threading.Event()
def on_changed():
changed.set()
dManager.on('changed',on_changed)
device = None def on_changed():
while device is None: changed.set()
devices = [dev for dev in dManager.enumerate_devices() if dev.type == 'tether']
if len(devices) == 0:
print 'Waiting for usb device...'
changed.wait()
else:
device = devices[0]
dManager.off('changed',on_changed) dManager.on('changed', on_changed)
return device
def gen_ipa(target): device = None
try: while device is None:
app_name = file_dict["app"] devices = [dev for dev in dManager.enumerate_devices() if dev.type == 'tether']
for key, value in file_dict.items(): if len(devices) == 0:
if key != "app": print 'Waiting for USB device...'
shutil.move(target +"/"+ key, target + "/" + app_name + "/" + value); changed.wait()
(shotname,extension) = os.path.splitext(app_name) else:
os.system(u''.join(("zip -qr ", name.replace(" ", "\\ "), ".ipa ./Payload")).encode('utf-8').strip()); device = devices[0]
os.system("rm -rf ./Payload");
except Exception as e: dManager.off('changed', on_changed)
print e
finished.set(); return device
def generate_ipa(path, display_name, bundle_identifier):
ipa_filename = display_name.replace(' ', '\\ ') + '.ipa'
print 'Generating {}'.format(ipa_filename)
try:
app_name = file_dict['app']
for key, value in file_dict.items():
from_dir = os.path.join(path, key)
to_dir = os.path.join(path, app_name, value)
if key != 'app':
shutil.move(from_dir, to_dir)
target_dir = './' + PAYLOAD_DIR
zip_args = ('zip', '-qr', os.path.join(os.getcwd(), ipa_filename), target_dir)
subprocess.check_call(zip_args, cwd=TEMP_DIR)
shutil.rmtree(PAYLOAD_PATH)
print
except Exception as e:
print e
finished.set()
def on_message(message, data):
global name
if message.has_key('payload'):
payload = message['payload']
if payload.has_key('opened'):
name = payload['opened']
if payload.has_key('dump'):
origin_path = payload['path']
dump_path = payload['dump']
scp_from = SSH_USER_HOST + dump_path.replace(' ', '\ ')
scp_to = PAYLOAD_PATH + u'/'
scp_args = ('scp', '-P {}'.format(SSH_PORT), scp_from, scp_to)
subprocess.check_call(scp_args)
chmod_dir = os.path.join(PAYLOAD_PATH, os.path.basename(dump_path))
chmod_args = ('chmod', '655', chmod_dir)
subprocess.check_call(chmod_args)
index = origin_path.find('.app/')
file_dict[os.path.basename(dump_path)] = origin_path[index + 5:]
if payload.has_key('app'):
app_path = payload['app']
scp_from = SSH_USER_HOST + app_path.replace(' ', '\ ')
scp_to = PAYLOAD_PATH + u'/'
scp_args = ('scp', '-r', '-P {}'.format(SSH_PORT), scp_from, scp_to)
subprocess.check_call(scp_args)
chmod_dir = os.path.join(PAYLOAD_PATH, os.path.basename(app_path))
chmod_args = ('chmod', '755', chmod_dir)
subprocess.check_call(chmod_args)
file_dict['app'] = os.path.basename(app_path)
if payload.has_key('done'):
finished.set()
def on_message(message,data):
global name;
if message.has_key('payload'):
payload = message['payload']
if payload.has_key("opened"):
name = payload["opened"]
opened.set();
if payload.has_key("dump"):
orign_path = payload["path"]
dumppath = payload["dump"]
os.system(u''.join(("scp -P 2222 root@localhost:", dumppath.replace(" ", "\\\\\ "), u" ./" + OUTPUT + u"/")).encode('utf-8').strip())
os.system(u''.join(("chmod 655 ", u'./' + OUTPUT + u'/', os.path.basename(dumppath.replace(" ", "\\ ")))).encode('utf-8').strip())
index = orign_path.find(".app/")
file_dict[os.path.basename(dumppath)] = orign_path[index+5:]
if payload.has_key("app"):
apppath = payload["app"]
os.system(u''.join(("scp -r -P 2222 root@localhost:", apppath.replace(" ", "\\\\\ "), u" ./" + OUTPUT + u"/")).encode('utf-8').strip())
os.system(u''.join(("chmod 755 ", u'./' + OUTPUT + u'/', os.path.basename(apppath.replace(" ", "\\ ")))).encode('utf-8').strip())
file_dict["app"] = os.path.basename(apppath)
if payload.has_key("done"):
gen_ipa(os.getcwd()+"/"+OUTPUT)
finished.set();
def compare_applications(a, b): def compare_applications(a, b):
a_is_running = a.pid != 0 a_is_running = a.pid != 0
b_is_running = b.pid != 0 b_is_running = b.pid != 0
if a_is_running == b_is_running: if a_is_running == b_is_running:
if a.name > b.name: if a.name > b.name:
return 1 return 1
elif a.name < b.name: elif a.name < b.name:
return -1
else:
return 0
elif a_is_running:
return -1 return -1
else: else:
return 1 return 0
elif a_is_running:
return -1
else:
return 1
def cmp_to_key(mycmp): def cmp_to_key(mycmp):
"Convert a cmp= function into a key= function" 'Convert a cmp= function into a key= function'
class K:
def __init__(self, obj, *args):
self.obj = obj
def __lt__(self, other):
return mycmp(self.obj, other.obj) < 0
def __gt__(self, other):
return mycmp(self.obj, other.obj) > 0
def __eq__(self, other):
return mycmp(self.obj, other.obj) == 0
def __le__(self, other):
return mycmp(self.obj, other.obj) <= 0
def __ge__(self, other):
return mycmp(self.obj, other.obj) >= 0
def __ne__(self, other):
return mycmp(self.obj, other.obj) != 0
return K
def get_applications(): class K:
device = get_usb_iphone() def __init__(self, obj, *args):
self.obj = obj
try: def __lt__(self, other):
applications = device.enumerate_applications() return mycmp(self.obj, other.obj) < 0
except Exception as e:
print "Failed to enumerate applications: %s" % e
exit(1)
return
return applications def __gt__(self, other):
return mycmp(self.obj, other.obj) > 0
def list_applications(): def __eq__(self, other):
applications = get_applications() return mycmp(self.obj, other.obj) == 0
if len(applications) > 0: def __le__(self, other):
pid_column_width = max(map(lambda app: len("%d" % app.pid), applications)) return mycmp(self.obj, other.obj) <= 0
name_column_width = max(map(lambda app: len(app.name), applications))
identifier_column_width = max(map(lambda app: len(app.identifier), applications))
else:
pid_column_width = 0
name_column_width = 0
identifier_column_width = 0
header_format = "%" + str(pid_column_width) + "s " + "%-" + str(name_column_width) + "s " + "%-" + str(identifier_column_width) + "s" def __ge__(self, other):
print header_format % ("PID", "Name", "Identifier") return mycmp(self.obj, other.obj) >= 0
print "%s %s %s" % (pid_column_width * "-", name_column_width * "-", identifier_column_width * "-")
line_format = "%" + str(pid_column_width) + "s " + "%-" + str(name_column_width) + "s " + "%-" + str(identifier_column_width) + "s"
for app in sorted(applications, key=cmp_to_key(compare_applications)):
if app.pid == 0:
print line_format % ("-", app.name, app.identifier)
else:
print line_format % (app.pid, app.name, app.identifier)
def get_pid_by_bundleid(bundleid): def __ne__(self, other):
applications = get_applications() return mycmp(self.obj, other.obj) != 0
return [app.pid for app in applications if app.identifier == bundleid][0] return K
def find_target_app(isbundleid, value):
applications = get_applications() def get_applications(device):
try:
applications = device.enumerate_applications()
except Exception as e:
print 'Failed to enumerate applications: %s' % e
return
return applications
def list_applications(device):
applications = get_applications(device)
if len(applications) > 0:
pid_column_width = max(map(lambda app: len('{}'.format(app.pid)), applications))
name_column_width = max(map(lambda app: len(app.name), applications))
identifier_column_width = max(map(lambda app: len(app.identifier), applications))
else:
pid_column_width = 0
name_column_width = 0
identifier_column_width = 0
header_format = '%' + str(pid_column_width) + 's ' + '%-' + str(name_column_width) + 's ' + '%-' + str(
identifier_column_width) + 's'
print header_format % ('PID', 'Name', 'Identifier')
print '%s %s %s' % (pid_column_width * '-', name_column_width * '-', identifier_column_width * '-')
line_format = '%' + str(pid_column_width) + 's ' + '%-' + str(name_column_width) + 's ' + '%-' + str(
identifier_column_width) + 's'
for app in sorted(applications, key=cmp_to_key(compare_applications)):
if app.pid == 0:
print line_format % ('-', app.name, app.identifier)
else:
print line_format % (app.pid, app.name, app.identifier)
if not isbundleid:
return [app for app in applications if app.name == value]
else:
return [app for app in applications if app.identifier == value]
def load_js_file(session, filename): def load_js_file(session, filename):
source = '' source = ''
with codecs.open(filename,'r','utf-8') as f: with codecs.open(filename, 'r', 'utf-8') as f:
source = source + f.read(); source = source + f.read()
script = session.create_script(source); script = session.create_script(source)
script.on("message",on_message) script.on('message', on_message)
script.load() script.load()
return script
return script
def clear_and_quit(session):
if session:
session.detach()
sys.exit(0)
def create_dir(path): def create_dir(path):
path = path.strip() path = path.strip()
path = path.rstrip("\\") path = path.rstrip('\\')
if not os.path.exists(path): if os.path.exists(path):
os.makedirs(path) print 'Removing {}'.format(path)
else: shutil.rmtree(path)
print path + u" is existed!"; os.makedirs(path)
def open_target_app(isbundleid, value):
device = get_usb_iphone();
name = u'SpringBoard';
print "open target app......"
session = device.attach(name);
script = load_js_file(session, APP_JS);
if not isbundleid:
script.post({'name': value})
else:
script.post({'bundleid': value})
opened.wait();
session.detach();
create_dir(os.getcwd()+"/"+OUTPUT)
print 'Waiting for the application to open......'
time.sleep(5);
def start_dump(target): def open_target_app(device, name_or_bundleid):
print "start dump target app......" print 'Start the target app {}'.format(name_or_bundleid)
device = get_usb_iphone();
session = device.attach(target);
script = load_js_file(session, DUMP_JS);
script.post("dump");
finished.wait();
clear_and_quit(session);
def dump_by_display_name(display_name): display_name = ''
open_target_app( 0, display_name) bundle_identifier = ''
start_dump(display_name); for application in get_applications(device):
if name_or_bundleid == application.identifier or name_or_bundleid == application.name:
display_name = application.name
bundle_identifier = application.identifier
def dump_by_bundleid(bundleid): try:
open_target_app( 1, bundleid) pid = device.spawn([bundle_identifier])
start_dump(get_pid_by_bundleid(bundleid)); device.resume(pid)
create_dir(PAYLOAD_PATH)
time.sleep(1)
except Exception as e:
print e
return (pid, display_name, bundle_identifier)
def start_dump(device, pid, display_name, bundle_identifier):
print 'Dumping {} to {}'.format(display_name, TEMP_DIR)
session = device.attach(pid)
script = load_js_file(session, DUMP_JS)
script.post('dump')
finished.wait()
generate_ipa(PAYLOAD_PATH, display_name, bundle_identifier)
if session:
session.detach()
def check_args(): def check_args():
if len(sys.argv) < 2: if len(sys.argv) < 2:
usage() usage()
sys.exit(1) return 1
try: try:
opts,args = getopt.getopt(sys.argv[1:],"hlb:",["help"]); opts, args = getopt.getopt(sys.argv[1:], 'hl', ['help'])
except getopt.GetoptError: except getopt.GetoptError:
usage() usage()
sys.exit(2) return 2
for opt,value in opts: for opt, value in opts:
if opt in ("-h","--help"): if opt in ('-h', '--help'):
usage() usage()
if opt in ("-l"):
list_applications()
if opt in ("-b"):
if not find_target_app(1, value):
print "can not find target app '%s'" % value
else:
dump_by_bundleid(value)
if len(opts) == 0 and len(sys.argv) == 2: if opt in '-l':
name = sys.argv[1].decode('utf8'); device = get_usb_iphone()
if not find_target_app(0, name): list_applications(device)
print "can not find target app '%s'" % name
else: if len(opts) == 0:
dump_by_display_name(name) name_or_bundleid = ' '.join(sys.argv[1:])
sys.exit(0)
device = get_usb_iphone()
print "Device {}".format(device)
(pid, display_name, bundle_identifier) = open_target_app(device, name_or_bundleid)
start_dump(device, pid, display_name, bundle_identifier)
return 0
if __name__ == '__main__':
exit_code = 0
try:
exit_code = check_args()
except:
exit_code = 1
if os.path.exists(PAYLOAD_PATH):
print 'Deleting ' + PAYLOAD_PATH
shutil.rmtree(PAYLOAD_PATH)
sys.exit(exit_code)
if __name__ == "__main__":
try:
check_args()
pass
except KeyboardInterrupt:
if session:
session.detach()
sys.exit()
except:
pass