Compare commits

..

21 Commits
3.x ... master

Author SHA1 Message Date
Levent Duivel 9a3ce60629
Windows-compatible version.
Requires 7z to be present in PATH
2021-08-06 01:43:33 +05:00
Alone_Monkey 56e99b2138
Merge pull request #122 from alex1704/master
fix name 'KeyFileName' is not defined error
2020-06-01 12:22:21 +08:00
alex1704 9e75f6bca3 name 'KeyFileName' is not defined error 2020-06-01 01:04:26 +03:00
Alone_Monkey 56737ae57c
Merge pull request #121 from alex1704/master
Allow to specify SSH private key file path in options
2020-05-31 10:06:13 +08:00
alex1704 8b5b5332fd Allow to specify SSH private key file path in options 2020-05-31 01:41:51 +03:00
Alone_Monkey 850a38efd2
Merge pull request #98 from xiofee/master
Fix: py3 can't concat str to bytes
2020-03-08 09:16:32 +08:00
xiofee c5eff3b063 fix py3 str 2020-02-08 02:05:39 +08:00
Alone_Monkey 64b58d1c3e
Merge pull request #96 from fishso/master
fix python3 show error :'str' object has no attribute 'decode'
2020-01-15 19:04:45 +08:00
yujunfeng 9850158401 fix python3 show error :'str' object has no attribute 'decode' 2020-01-15 15:32:40 +08:00
Alone_Monkey 2363a00550
Merge pull request #91 from Hamz-a/master
added optional arguments for parsing SSH host, port, username, password
2019-12-16 15:33:10 +08:00
Hamza 2405c99d17 added optional arguments for parsing SSH host, port, username, password 2019-12-15 23:04:22 +01:00
Alone_Monkey 8a47ae4ff8
Merge pull request #88 from everettjf/master
support both python 2.x and 3.x
2019-11-16 11:10:35 +08:00
everettjf 35a749f270 support both python 2.x and 3.x 2019-11-16 11:00:56 +08:00
AloneMonkey f88043a222 [bugfix] dlopen parameter problem. 2019-07-24 10:59:06 +08:00
AloneMonkey 160a6e7419 [bugfix] fix for frida 12.5 2019-05-09 20:11:57 +08:00
AloneMonkey a39c11e38c [feature] auto load all frameworks and dylibs. 2019-05-02 23:26:09 +08:00
Alone_Monkey b2581409b1
change frida to frida-tools 2018-11-10 17:17:51 +08:00
AloneMonkey a9b9c9fbf5 fix bug 2018-07-14 19:26:29 +08:00
Alone_Monkey 187446d3c1
Update README.md 2018-07-13 16:51:05 +08:00
Alone_Monkey 71499f4d91
Compatible with previous versions 2018-07-13 16:41:48 +08:00
Alone_Monkey e53e81ecc3
change type tether to usb 2018-07-13 09:27:12 +08:00
2 changed files with 60 additions and 20 deletions

View File

@ -1,13 +1,13 @@
# frida-ios-dump
Pull a decrypted IPA from a jailbroken device
## Usage
1. Install [frida](http://www.frida.re/) on device
2. `sudo pip install -r requirements.txt --upgrade` (Python 2.7)
3. `sudo pip3 install -r requirements.txt --upgrade` (Python 3.x)
4. Run usbmuxd/iproxy SSH forwarding over USB (Default 2222 -> 22). e.g. `iproxy 2222 22`
5. Run ./dump.py `Display name` or `Bundle identifier`
2. `sudo pip install -r requirements.txt --upgrade`
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`
For SSH/SCP make sure you have your public key added to the target device's ~/.ssh/authorized_keys file.
@ -40,6 +40,11 @@ Congratulations!!! You've got a decrypted IPA file.
Drag to [MonkeyDev](https://github.com/AloneMonkey/MonkeyDev), Happy hacking!
## Support
Python 2.x and 3.x
### issues
If the following error occurs:

67
dump.py
View File

@ -1,27 +1,32 @@
#!/usr/bin/env python3
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author : AloneMonkey
# blog: www.alonemonkey.com
from __future__ import print_function
from __future__ import unicode_literals
import sys
import codecs
import frida
import threading
import os
import shutil
import time
import argparse
import tempfile
import subprocess
import re
import paramiko
from paramiko import SSHClient
from scp import SCPClient
from tqdm import tqdm
import traceback
IS_PY2 = sys.version_info[0] < 3
if IS_PY2:
reload(sys)
sys.setdefaultencoding('utf8')
script_dir = os.path.dirname(os.path.realpath(__file__))
DUMP_JS = os.path.join(script_dir, 'dump.js')
@ -30,6 +35,7 @@ User = 'root'
Password = 'alpine'
Host = 'localhost'
Port = 2222
KeyFileName = None
TEMP_DIR = tempfile.gettempdir()
PAYLOAD_DIR = 'Payload'
@ -71,19 +77,22 @@ def generate_ipa(path, display_name):
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)
try:
os.rename(from_dir, to_dir)
except FileExistsError:
os.remove(to_dir)
os.rename(from_dir, to_dir)
target_dir = './' + PAYLOAD_DIR
zip_args = ('zip', '-qr', os.path.join(os.getcwd(), ipa_filename), target_dir)
zip_args = ("7z", "a", "-r", f"{os.getcwd()}/{ipa_filename}.zip", "-w", f"{target_dir}", "-mem=AES256")
subprocess.check_call(zip_args, cwd=TEMP_DIR)
shutil.rmtree(PAYLOAD_PATH)
os.rename(f"{os.getcwd()}/{ipa_filename}.zip", f"{os.getcwd()}/{ipa_filename}")
os.system('rmdir /S /Q "{}"'.format(PAYLOAD_PATH))
except Exception as e:
print(e)
print(f"{type(e)}: {e}")
finished.set()
def on_message(message, data):
@ -91,7 +100,11 @@ def on_message(message, data):
last_sent = [0]
def progress(filename, size, sent):
t.desc = os.path.basename(filename).decode("utf-8")
baseName = os.path.basename(filename)
if IS_PY2 or isinstance(baseName, bytes):
t.desc = baseName.decode("utf-8")
else:
t.desc = baseName
t.total = size
t.update(sent - last_sent[0])
last_sent[0] = 0 if size == sent else sent
@ -110,10 +123,12 @@ def on_message(message, data):
chmod_dir = os.path.join(PAYLOAD_PATH, os.path.basename(dump_path))
chmod_args = ('chmod', '655', chmod_dir)
"""
try:
subprocess.check_call(chmod_args)
except subprocess.CalledProcessError as err:
print(err)
"""
index = origin_path.find('.app/')
file_dict[os.path.basename(dump_path)] = origin_path[index + 5:]
@ -128,11 +143,12 @@ def on_message(message, data):
chmod_dir = os.path.join(PAYLOAD_PATH, os.path.basename(app_path))
chmod_args = ('chmod', '755', chmod_dir)
"""
try:
subprocess.check_call(chmod_args)
except subprocess.CalledProcessError as err:
print(err)
"""
file_dict['app'] = os.path.basename(app_path)
if 'done' in payload:
@ -232,7 +248,7 @@ def create_dir(path):
path = path.strip()
path = path.rstrip('\\')
if os.path.exists(path):
shutil.rmtree(path)
os.system('rmdir /S /Q "{}"'.format(path))
try:
os.makedirs(path)
except os.error as err:
@ -282,7 +298,13 @@ if __name__ == '__main__':
parser = argparse.ArgumentParser(description='frida-ios-dump (by AloneMonkey v2.0)')
parser.add_argument('-l', '--list', dest='list_applications', action='store_true', help='List the installed apps')
parser.add_argument('-o', '--output', dest='output_ipa', help='Specify name of the decrypted IPA')
parser.add_argument('-H', '--host', dest='ssh_host', help='Specify SSH hostname')
parser.add_argument('-p', '--port', dest='ssh_port', help='Specify SSH port')
parser.add_argument('-u', '--user', dest='ssh_user', help='Specify SSH username')
parser.add_argument('-P', '--password', dest='ssh_password', help='Specify SSH password')
parser.add_argument('-K', '--key_filename', dest='ssh_key_filename', help='Specify SSH private key file path')
parser.add_argument('target', nargs='?', help='Bundle identifier or display name of the target app')
args = parser.parse_args()
exit_code = 0
@ -299,11 +321,22 @@ if __name__ == '__main__':
else:
name_or_bundleid = args.target
output_ipa = args.output_ipa
# update ssh args
if args.ssh_host:
Host = args.ssh_host
if args.ssh_port:
Port = int(args.ssh_port)
if args.ssh_user:
User = args.ssh_user
if args.ssh_password:
Password = args.ssh_password
if args.ssh_key_filename:
KeyFileName = args.ssh_key_filename
try:
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(Host, port=Port, username=User, password=Password)
ssh.connect(Host, port=Port, username=User, password=Password, key_filename=KeyFileName)
create_dir(PAYLOAD_PATH)
(session, display_name, bundle_identifier) = open_target_app(device, name_or_bundleid)
@ -313,10 +346,12 @@ if __name__ == '__main__':
if session:
start_dump(session, output_ipa)
except paramiko.ssh_exception.NoValidConnectionsError as e:
print(e)
print(e)
print('Try specifying -H/--hostname and/or -p/--port')
exit_code = 1
except paramiko.AuthenticationException as e:
print(e)
print(e)
print('Try specifying -u/--username and/or -P/--password')
exit_code = 1
except Exception as e:
print('*** Caught exception: %s: %s' % (e.__class__, e))
@ -327,6 +362,6 @@ if __name__ == '__main__':
ssh.close()
if os.path.exists(PAYLOAD_PATH):
shutil.rmtree(PAYLOAD_PATH)
os.system('rmdir /S /Q "{}"'.format(PAYLOAD_PATH))
sys.exit(exit_code)