Skip to content

Commit

Permalink
Bump to 3.9 (#97)
Browse files Browse the repository at this point in the history
* 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](paramiko/paramiko@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] <support@github.com>

* 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](tqdm/tqdm@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] <support@github.com>

* add backtrace to hooking.js

* optimize hook.py

* update readme

* update setup.py

* update requirements

* update requirements

* update changelog

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: noobpk <>
  • Loading branch information
noobpk and dependabot[bot] committed Aug 17, 2023
1 parent 528d40a commit a80d42e
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 50 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
14 changes: 12 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 5 additions & 3 deletions frida-ios-hook/core/hook.py
Original file line number Diff line number Diff line change
Expand Up @@ -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!')
Expand Down
102 changes: 66 additions & 36 deletions frida-ios-hook/hooking.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand All @@ -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!');
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
24 changes: 16 additions & 8 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#!/usr/bin/python3
import sys
import os
from tqdm import tqdm

setup = """#!/usr/bin/python3
import os
Expand All @@ -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

Expand Down

0 comments on commit a80d42e

Please sign in to comment.