From fd88a4818cca22de1d2dc6714e68fad0ba219770 Mon Sep 17 00:00:00 2001 From: AloneMonkey Date: Tue, 30 Jan 2018 14:01:59 +0800 Subject: [PATCH] [update] support dump specified bundle id --- app.js | 25 +++++++- dump.py | 185 +++++++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 180 insertions(+), 30 deletions(-) diff --git a/app.js b/app.js index 699a1c9..2bcd376 100644 --- a/app.js +++ b/app.js @@ -20,12 +20,33 @@ function getbundleid(name){ 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) { - const bundleid = getbundleid(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: "ok"}); + send({ opened: displayname }); } recv(handleMessage); \ No newline at end of file diff --git a/dump.py b/dump.py index 47016f8..3b75e3b 100755 --- a/dump.py +++ b/dump.py @@ -11,6 +11,7 @@ import threading import os import shutil import time +import getopt reload(sys) sys.setdefaultencoding('utf8') @@ -26,6 +27,15 @@ finished = threading.Event() global session global name +#show usage +def usage(): + print '-------------------------frida-ios-dump(by AloneMonkey v2.0)----------------------------' + 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' % ('-l','List the app has been installed.'); + 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(): dManager = frida.get_device_manager(); changed = threading.Event() @@ -60,9 +70,11 @@ def gen_ipa(target): 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"] @@ -79,8 +91,89 @@ def on_message(message,data): if payload.has_key("done"): gen_ipa(os.getcwd()+"/"+OUTPUT) finished.set(); - -def loadJsFile(session, filename): + +def compare_applications(a, b): + a_is_running = a.pid != 0 + b_is_running = b.pid != 0 + if a_is_running == b_is_running: + if a.name > b.name: + return 1 + elif a.name < b.name: + return -1 + else: + return 0 + elif a_is_running: + return -1 + else: + return 1 + +def cmp_to_key(mycmp): + "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(): + device = get_usb_iphone() + + try: + applications = device.enumerate_applications() + except Exception as e: + print "Failed to enumerate applications: %s" % e + exit(1) + return + + return applications + +def list_applications(): + applications = get_applications() + + if len(applications) > 0: + pid_column_width = max(map(lambda app: len("%d" % 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) + +def get_pid_by_bundleid(bundleid): + applications = get_applications() + + return [app.pid for app in applications if app.identifier == bundleid][0] + +def find_target_app(isbundleid, value): + applications = get_applications() + + 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): source = '' with codecs.open(filename,'r','utf-8') as f: source = source + f.read(); @@ -89,12 +182,12 @@ def loadJsFile(session, filename): script.load() return script -def ClearAndQuit(session): +def clear_and_quit(session): if session: session.detach() sys.exit(0) -def createDir(path): +def create_dir(path): path = path.strip() path = path.rstrip("\\") if not os.path.exists(path): @@ -102,40 +195,76 @@ def createDir(path): else: print path + u" is existed!"; -def main(target): - global session - global name - session = None +def open_target_app(isbundleid, value): device = get_usb_iphone(); - #open app name = u'SpringBoard'; print "open target app......" session = device.attach(name); - script = loadJsFile(session, APP_JS); - name = target.decode('utf8'); - script.post(name); + script = load_js_file(session, APP_JS); + if not isbundleid: + script.post({'name': value}) + else: + script.post({'bundleid': value}) opened.wait(); session.detach(); - createDir(os.getcwd()+"/"+OUTPUT) + create_dir(os.getcwd()+"/"+OUTPUT) print 'Waiting for the application to open......' time.sleep(5); + +def start_dump(target): print "start dump target app......" - session = device.attach(name); - script = loadJsFile(session, DUMP_JS); + device = get_usb_iphone(); + session = device.attach(target); + script = load_js_file(session, DUMP_JS); script.post("dump"); finished.wait(); - ClearAndQuit(session); + clear_and_quit(session); + +def dump_by_display_name(display_name): + open_target_app( 0, display_name) + start_dump(display_name); + +def dump_by_bundleid(bundleid): + open_target_app( 1, bundleid) + start_dump(get_pid_by_bundleid(bundleid)); + +def check_args(): + if len(sys.argv) < 2: + usage() + sys.exit(1) + + try: + opts,args = getopt.getopt(sys.argv[1:],"hlb:",["help"]); + except getopt.GetoptError: + usage() + sys.exit(2) + + for opt,value in opts: + if opt in ("-h","--help"): + 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: + name = sys.argv[1].decode('utf8'); + if not find_target_app(0, name): + print "can not find target app '%s'" % name + else: + dump_by_display_name(name) + sys.exit(0) if __name__ == "__main__": - if len(sys.argv) < 2: - print "usage: ./dump.py 微信" - sys.exit(0) - else: - try: - main(sys.argv[1]) - except KeyboardInterrupt: - if session: - session.detach() - sys.exit() - except: - pass \ No newline at end of file + try: + check_args() + pass + except KeyboardInterrupt: + if session: + session.detach() + sys.exit() + except: + pass \ No newline at end of file