Compare commits

21 Commits
3.x ... master

Author SHA1 Message Date
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)