support both python 2.x and 3.x

This commit is contained in:
everettjf 2019-11-16 11:00:56 +08:00
parent f88043a222
commit 35a749f270
2 changed files with 37 additions and 31 deletions

View File

@ -1,12 +1,11 @@
**python 3 please checkout 3.x branch**
# frida-ios-dump # frida-ios-dump
Pull a decrypted IPA from a jailbroken device Pull a decrypted IPA from a jailbroken device
## Usage ## Usage
1. Install [frida](http://www.frida.re/) on device 1. Install [frida](http://www.frida.re/) on device
2. `sudo pip install -r requirements.txt --upgrade` (Python 2.7) 2. `sudo pip install -r requirements.txt --upgrade`
3. Run usbmuxd/iproxy SSH forwarding over USB (Default 2222 -> 22). e.g. `iproxy 2222 22` 3. Run usbmuxd/iproxy SSH forwarding over USB (Default 2222 -> 22). e.g. `iproxy 2222 22`
4. Run ./dump.py `Display name` or `Bundle identifier` 4. Run ./dump.py `Display name` or `Bundle identifier`
@ -41,6 +40,11 @@ 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!
## Support
Python 2.x and 3.x
### issues ### issues
If the following error occurs: If the following error occurs:

54
dump.py
View File

@ -4,6 +4,8 @@
# Author : AloneMonkey # Author : AloneMonkey
# blog: www.alonemonkey.com # blog: www.alonemonkey.com
from __future__ import print_function
from __future__ import unicode_literals
import sys import sys
import codecs import codecs
import frida import frida
@ -15,13 +17,13 @@ import argparse
import tempfile import tempfile
import subprocess import subprocess
import re import re
import paramiko import paramiko
from paramiko import SSHClient from paramiko import SSHClient
from scp import SCPClient from scp import SCPClient
from tqdm import tqdm from tqdm import tqdm
import traceback import traceback
if sys.version_info[0] < 3:
reload(sys) reload(sys)
sys.setdefaultencoding('utf8') sys.setdefaultencoding('utf8')
@ -46,7 +48,6 @@ def get_usb_iphone():
Type = 'usb' Type = 'usb'
if int(frida.__version__.split('.')[0]) < 12: if int(frida.__version__.split('.')[0]) < 12:
Type = 'tether' Type = 'tether'
device_manager = frida.get_device_manager() device_manager = frida.get_device_manager()
changed = threading.Event() changed = threading.Event()
@ -59,7 +60,7 @@ def get_usb_iphone():
while device is None: while device is None:
devices = [dev for dev in device_manager.enumerate_devices() if dev.type == Type] devices = [dev for dev in device_manager.enumerate_devices() if dev.type == Type]
if len(devices) == 0: if len(devices) == 0:
print 'Waiting for USB device...' print('Waiting for USB device...')
changed.wait() changed.wait()
else: else:
device = devices[0] device = devices[0]
@ -72,7 +73,7 @@ def get_usb_iphone():
def generate_ipa(path, display_name): def generate_ipa(path, display_name):
ipa_filename = display_name + '.ipa' ipa_filename = display_name + '.ipa'
print 'Generating "{}"'.format(ipa_filename) print('Generating "{}"'.format(ipa_filename))
try: try:
app_name = file_dict['app'] app_name = file_dict['app']
@ -86,9 +87,8 @@ def generate_ipa(path, display_name):
zip_args = ('zip', '-qr', os.path.join(os.getcwd(), ipa_filename), target_dir) zip_args = ('zip', '-qr', os.path.join(os.getcwd(), ipa_filename), target_dir)
subprocess.check_call(zip_args, cwd=TEMP_DIR) subprocess.check_call(zip_args, cwd=TEMP_DIR)
shutil.rmtree(PAYLOAD_PATH) shutil.rmtree(PAYLOAD_PATH)
print
except Exception as e: except Exception as e:
print e print(e)
finished.set() finished.set()
def on_message(message, data): def on_message(message, data):
@ -96,7 +96,7 @@ def on_message(message, data):
last_sent = [0] last_sent = [0]
def progress(filename, size, sent): def progress(filename, size, sent):
t.desc = os.path.basename(filename) t.desc = os.path.basename(filename).decode("utf-8")
t.total = size t.total = size
t.update(sent - last_sent[0]) t.update(sent - last_sent[0])
last_sent[0] = 0 if size == sent else sent last_sent[0] = 0 if size == sent else sent
@ -108,7 +108,7 @@ def on_message(message, data):
dump_path = payload['dump'] dump_path = payload['dump']
scp_from = dump_path scp_from = dump_path
scp_to = PAYLOAD_PATH + u'/' scp_to = PAYLOAD_PATH + '/'
with SCPClient(ssh.get_transport(), progress = progress, socket_timeout = 60) as scp: with SCPClient(ssh.get_transport(), progress = progress, socket_timeout = 60) as scp:
scp.get(scp_from, scp_to) scp.get(scp_from, scp_to)
@ -118,7 +118,7 @@ def on_message(message, data):
try: try:
subprocess.check_call(chmod_args) subprocess.check_call(chmod_args)
except subprocess.CalledProcessError as err: except subprocess.CalledProcessError as err:
print err print(err)
index = origin_path.find('.app/') index = origin_path.find('.app/')
file_dict[os.path.basename(dump_path)] = origin_path[index + 5:] file_dict[os.path.basename(dump_path)] = origin_path[index + 5:]
@ -127,7 +127,7 @@ def on_message(message, data):
app_path = payload['app'] app_path = payload['app']
scp_from = app_path scp_from = app_path
scp_to = PAYLOAD_PATH + u'/' scp_to = PAYLOAD_PATH + '/'
with SCPClient(ssh.get_transport(), progress = progress, socket_timeout = 60) as scp: with SCPClient(ssh.get_transport(), progress = progress, socket_timeout = 60) as scp:
scp.get(scp_from, scp_to, recursive=True) scp.get(scp_from, scp_to, recursive=True)
@ -136,7 +136,7 @@ def on_message(message, data):
try: try:
subprocess.check_call(chmod_args) subprocess.check_call(chmod_args)
except subprocess.CalledProcessError as err: except subprocess.CalledProcessError as err:
print err print(err)
file_dict['app'] = os.path.basename(app_path) file_dict['app'] = os.path.basename(app_path)
@ -192,8 +192,7 @@ def get_applications(device):
try: try:
applications = device.enumerate_applications() applications = device.enumerate_applications()
except Exception as e: except Exception as e:
print 'Failed to enumerate applications: %s' % e sys.exit('Failed to enumerate applications: %s' % e)
return
return applications return applications
@ -212,15 +211,15 @@ def list_applications(device):
header_format = '%' + str(pid_column_width) + 's ' + '%-' + str(name_column_width) + 's ' + '%-' + str( header_format = '%' + str(pid_column_width) + 's ' + '%-' + str(name_column_width) + 's ' + '%-' + str(
identifier_column_width) + 's' identifier_column_width) + 's'
print header_format % ('PID', 'Name', 'Identifier') print(header_format % ('PID', 'Name', 'Identifier'))
print '%s %s %s' % (pid_column_width * '-', name_column_width * '-', identifier_column_width * '-') 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( line_format = '%' + str(pid_column_width) + 's ' + '%-' + str(name_column_width) + 's ' + '%-' + str(
identifier_column_width) + 's' identifier_column_width) + 's'
for application in sorted(applications, key=cmp_to_key(compare_applications)): for application in sorted(applications, key=cmp_to_key(compare_applications)):
if application.pid == 0: if application.pid == 0:
print line_format % ('-', application.name, application.identifier) print(line_format % ('-', application.name, application.identifier))
else: else:
print line_format % (application.pid, application.name, application.identifier) print(line_format % (application.pid, application.name, application.identifier))
def load_js_file(session, filename): def load_js_file(session, filename):
@ -242,11 +241,11 @@ def create_dir(path):
try: try:
os.makedirs(path) os.makedirs(path)
except os.error as err: except os.error as err:
print err print(err)
def open_target_app(device, name_or_bundleid): def open_target_app(device, name_or_bundleid):
print 'Start the target app {}'.format(name_or_bundleid) print('Start the target app {}'.format(name_or_bundleid))
pid = '' pid = ''
session = None session = None
@ -266,13 +265,13 @@ def open_target_app(device, name_or_bundleid):
else: else:
session = device.attach(pid) session = device.attach(pid)
except Exception as e: except Exception as e:
print e print(e)
return session, display_name, bundle_identifier return session, display_name, bundle_identifier
def start_dump(session, ipa_name): def start_dump(session, ipa_name):
print 'Dumping {} to {}'.format(display_name, TEMP_DIR) print('Dumping {} to {}'.format(display_name, TEMP_DIR))
script = load_js_file(session, DUMP_JS) script = load_js_file(session, DUMP_JS)
script.post('dump') script.post('dump')
@ -293,11 +292,14 @@ if __name__ == '__main__':
exit_code = 0 exit_code = 0
ssh = None ssh = None
if not len(sys.argv[1:]):
parser.print_help()
sys.exit(exit_code)
device = get_usb_iphone() device = get_usb_iphone()
if len(sys.argv[1:]) == 0: if args.list_applications:
parser.print_help()
elif args.list_applications:
list_applications(device) list_applications(device)
else: else:
name_or_bundleid = args.target name_or_bundleid = args.target
@ -316,10 +318,10 @@ if __name__ == '__main__':
if session: if session:
start_dump(session, output_ipa) start_dump(session, output_ipa)
except paramiko.ssh_exception.NoValidConnectionsError as e: except paramiko.ssh_exception.NoValidConnectionsError as e:
print e print(e)
exit_code = 1 exit_code = 1
except paramiko.AuthenticationException as e: except paramiko.AuthenticationException as e:
print e print(e)
exit_code = 1 exit_code = 1
except Exception as e: except Exception as e:
print('*** Caught exception: %s: %s' % (e.__class__, e)) print('*** Caught exception: %s: %s' % (e.__class__, e))