From a80d42ec32b194d15ad3aeb88c58d00087f7acaf Mon Sep 17 00:00:00 2001 From: lethanhphuc <31820707+noobpk@users.noreply.github.com> Date: Thu, 17 Aug 2023 22:27:08 +0700 Subject: [PATCH] Bump to 3.9 (#97) * Bump paramiko from 2.11.0 to 3.3.1 Bumps [paramiko](https://github.com/paramiko/paramiko) from 2.11.0 to 3.3.1. - [Commits](https://github.com/paramiko/paramiko/compare/2.11.0...3.3.1) --- updated-dependencies: - dependency-name: paramiko dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * Bump tqdm from 4.64.1 to 4.66.1 Bumps [tqdm](https://github.com/tqdm/tqdm) from 4.64.1 to 4.66.1. - [Release notes](https://github.com/tqdm/tqdm/releases) - [Commits](https://github.com/tqdm/tqdm/compare/v4.64.1...v4.66.1) --- updated-dependencies: - dependency-name: tqdm dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * add backtrace to hooking.js * optimize hook.py * update readme * update setup.py * update requirements * update requirements * update changelog --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: noobpk <> --- CHANGELOG.md | 13 +++++ README.md | 14 ++++- frida-ios-hook/core/hook.py | 8 +-- frida-ios-hook/hooking.js | 102 +++++++++++++++++++++++------------- requirements.txt | 2 +- setup.py | 24 ++++++--- 6 files changed, 113 insertions(+), 50 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 34727a7..3d15798 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Frida iOS Hook ChangeLog +## [Release 3.9] - 2023-08-17 + +### Added +- Add backtrace to hooking.js + +### Changed +- Update frida version +- Update readme, changelog, requirement + +### Fixed +- Fix issue #85 + + ## [Release 3.8] - 2022-12-11 ### Added diff --git a/README.md b/README.md index ff1c930..a4433c8 100755 --- a/README.md +++ b/README.md @@ -111,13 +111,23 @@ Version: 3.8 git clone -b dev https://github.com/noobpk/frida-ios-hook ``` -## Build +## Environment ``` +[+] Python >= v3.0 (Recommend to use pyenv or virtualenv) + 1. cd frida-ios-hook/ -2. pip3 install -r requirements.txt +2. python3 -m venv py-env +3. source py-env/bin/active +``` + +## Build + +``` +1. pip3 install -r requirements.txt 3. python3 setup.py 4. cd frida-ios-hook +5. ./ioshook -h (--help) ``` ## Usage diff --git a/frida-ios-hook/core/hook.py b/frida-ios-hook/core/hook.py index d1beb28..5aaf68e 100755 --- a/frida-ios-hook/core/hook.py +++ b/frida-ios-hook/core/hook.py @@ -207,12 +207,14 @@ def main(): logger.info('[*] Spawning: ' + options.package) logger.info('[*] Script: ' + options.script) time.sleep(2) - pid = frida.get_usb_device().spawn(options.package) - session = frida.get_usb_device().attach(pid) + device = frida.get_usb_device() + pid = device.spawn(options.package) + time.sleep(1) + session = device.attach(pid) hook = open(options.script, 'r') script = session.create_script(hook.read()) script.load() - frida.get_usb_device().resume(pid) + device.resume(pid) sys.stdin.read() else: logger.error('[x_x] Script not found!') diff --git a/frida-ios-hook/hooking.js b/frida-ios-hook/hooking.js index 255c45c..ec16ef4 100755 --- a/frida-ios-hook/hooking.js +++ b/frida-ios-hook/hooking.js @@ -54,25 +54,61 @@ function search_classes(){ return classes_found; } -function print_arguments(args) { -/* -Frida's Interceptor has no information about the number of arguments, because there is no such -information available at the ABI level (and we don't rely on debug symbols). - -I have implemented this function in order to try to determine how many arguments a method is using. -It stops when: - - The object is not nil - - The argument is not the same as the one before +/** + * The function `print_arguments` takes an array of arguments and prints information about each + * argument, including its type, byte representation in hexadecimal, string representation, and binary + * data representation. + * @param args - The `args` parameter is an array of arguments passed to a function. In this case, it + * seems to be an array of Objective-C objects. */ - var n = 100; - var last_arg = ''; - for (var i = 2; i < n; ++i) { - var arg = (new ObjC.Object(args[i])).toString(); - if (arg == 'nil' || arg == last_arg) { - break; +function print_arguments(args) { + try { + var n = 100; + var last_arg = ''; + for (var i = 2; i < n; ++i) { + var arg = (new ObjC.Object(args[i])).toString(); + if (arg == 'nil' || arg == last_arg) { + break; + } + last_arg = arg; + console.log('\t[+] Dump Arg' + i + ': ' + (new ObjC.Object(args[i])).toString()); + var data = new ObjC.Object(args[i]); + console.log(colors.green, "\t\t[-] Arugment type: ", colors.resetColor); + console.log("\t\t\t", data.$className); + /* Converting Byte to HexString */ + console.log(colors.green, "\t\t[-] Bytes to Hex:", colors.resetColor); + try { + var arg = ObjC.Object(args[2]); + var length = arg.length().valueOf(); + var bytes = arg.bytes(); + var byteString = ""; + for (var i = 0; i < length; i++) { + var byte = bytes.add(i).readU8(); + byteString += byte.toString(16).padStart(2, '0'); // Convert to hex and pad with leading zero if needed + } + console.log("\t\t\t", byteString); + } catch (err_bytes2hex) { + console.log(colors.red, "\t\t\t[x] Cannot convert Byte to Hex. Error: ", err_bytes2hex, colors.resetColor); + } + /* Converting NSData to String */ + console.log(colors.green, "\t\t[-] NSData to String: ", colors.resetColor); + try { + var buf = data.bytes().readUtf8String(data.length()); + console.log("\t\t\t", buf); + } catch (err_nsdata2string) { + console.log(colors.red, "\t\t\t[x] Cannot convert NSData to String. Error: ", err_nsdata2string, colors.resetColor); + } + /* Converting NSData to Binary Data */ + console.log(colors.green, "\t\t[-] NSData to Binary Data: ", colors.resetColor); + try { + var buf = data.bytes().readByteArray(data.length()); + console.log(hexdump(buf, { ansi: true })); + } catch (err_nsdata2bin) { + console.log(colors.red, "\t\t\t[x] Cannot convert NSData to Binary Data. Error: ", err_nsdata2bin, colors.resetColor); + } } - last_arg = arg; - console.log('\t[-] arg' + i + ': ' + (new ObjC.Object(args[i])).toString()); + } catch (err_dump) { + console.log(colors.red, "\t\t\t[x] Cannot dump all arugment in method . Error: ", err_dump, colors.resetColor); } } @@ -97,35 +133,29 @@ if (ObjC.available) onEnter: function (args) { this._className = ObjC.Object(args[0]).toString(); this._methodName = ObjC.selectorAsString(args[1]); - console.log(colors.green,"[+] Detected call to: ",colors.resetColor); + console.log(colors.green, "[+] Detected call to: ", colors.resetColor); console.log(' ' + this._className + ' --> ' + this._methodName); - console.log(colors.green,"[+] Dump Arugment in method: ",colors.resetColor); - // print_arguments(args); - // console.log(ObjC.Object(args[2])); - // var data = new ObjC.Object(args[2]); - console.log(colors.green,"[+] Arugment type: ",colors.resetColor); - // console.log(data.$className); - /* Converting NSData to String */ - // var buf = data.bytes().readUtf8String(data.length()); - console.log(colors.green,"[+] NSData to String: ",colors.resetColor); - // console.log(buf); - /* Converting NSData to Binary Data */ - // var buf = data.bytes().readByteArray(data.length()); - console.log(colors.green,"[+] NSData to Binary Data: ",colors.resetColor); - // console.log(hexdump(buf, { ansi: true })); - + console.log(colors.green, "[+] Dump all arugment in method: ", colors.resetColor); + print_arguments(args); + /* Backtrace */ + console.log(colors.green, "[+] Backtrace: ", colors.resetColor); + try { + console.log(Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join("\n\t")); + } catch (err_backtrace) { + console.log(colors.red, "\t\t\t[x] Cannot backtrace . Error: ", err_backtrace, colors.resetColor); + } }, onLeave: function(returnValues) { - console.log(colors.green,"Return value of: ",colors.resetColor); + console.log(colors.green,"[+] Return value of: ",colors.resetColor); console.log(' ' + this._className + ' --> ' + this._methodName); console.log(colors.green,"\t[-] Type of return value: ",colors.resetColor + Object.prototype.toString.call(returnValues)); console.log(colors.green,"\t[-] Return Value: ",colors.resetColor + returnValues); + console.log(colors.green, "\t[-] Return Value: ", colors.resetColor + JSON.stringify(returnValues, null, 2)); } }); } - } - console.log('\n[*] Starting Intercepting'); + console.log(colors.green,"\n[*] Starting Intercepting", colors.resetColor); } else { console.log('Objective-C Runtime is not available!'); diff --git a/requirements.txt b/requirements.txt index 0148a95..6d606ba 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,7 +3,7 @@ frida==16.1.3 frida-tools==12.2.1 scp==0.14.4 requests==2.31.0 -paramiko==2.11.0 +paramiko==3.3.1 tqdm==4.64.1 psutil reflutter diff --git a/setup.py b/setup.py index 7fa8d4e..0303bdf 100755 --- a/setup.py +++ b/setup.py @@ -1,6 +1,8 @@ #!/usr/bin/python3 import sys import os +from tqdm import tqdm + setup = """#!/usr/bin/python3 import os @@ -25,19 +27,25 @@ def _buildBinary(): try: if sys.platform == 'darwin': - with open('frida-ios-hook/ioshook','w+', encoding="utf-8") as f: - f.write(setup) - os.system('chmod +x frida-ios-hook/ioshook') + for i in tqdm(range(100), colour="red"): + with open('frida-ios-hook/ioshook','w+', encoding="utf-8") as f: + f.write(setup) + os.system('chmod +x frida-ios-hook/ioshook') print("[+] Build executable for Darwin success.") + print("[+] Try ./frida-ios-hook/ioshook -h (--help)") elif sys.platform == 'linux': - with open('frida-ios-hook/ioshook','w+', encoding="utf-8") as f: - f.write(setup) - os.system('chmod +x frida-ios-hook/ioshook') + for i in tqdm(range(100), colour="red"): + with open('frida-ios-hook/ioshook','w+', encoding="utf-8") as f: + f.write(setup) + os.system('chmod +x frida-ios-hook/ioshook') print("[+] Build executable for Linux success.") + print("[+] ./frida-ios-hook/ioshook -h (-help)") elif sys.platform == 'win32': - with open('frida-ios-hook/ioshook.py','w+', encoding="utf-8") as f: - f.write(setup) + for i in tqdm(range(100), colour="red"): + with open('frida-ios-hook/ioshook.py','w+', encoding="utf-8") as f: + f.write(setup) print("[+] Build executable for Windows success.") + print("[+] ./frida-ios-hook/ioshook -h (-help)") except Exception as e: raise e