Frida Cheatsheet#
Installation (iOS/iPhone 6s)#
To get Frida working on this device you need the specific package frida_17.7.0_iphoneos.deb, see https://github.com/frida/frida/releases.
# Install
scp frida_17.7.0_iphoneos-arm.deb [email protected]:/var/root/
ssh [email protected]
dpkg -i /var/root/frida_17.7.0_iphoneos-arm.deb
# Install via SSH (General alternative)
ssh root@<device-ip>
apt update
apt install re.frida.server
# Start frida-server
frida-server -l 0.0.0.0 &
# or explicitly:
/usr/sbin/frida-server -l 0.0.0.0
# Verify it's running
ps aux | grep frida
Process Enumeration#
| Command | Description |
|---|
frida-ps | List running processes on the local host. |
frida-ps -U | List processes on the connected USB device. |
frida-ps -H <host:port> | List processes on a remote device. |
frida-ps -Uai | List installed applications (Android/iOS). |
frida-ps -Ua | List all installed applications. |
Attaching & Execution#
| Command | Description |
|---|
frida -n <name> | Attach to a process by name. |
frida -p <pid> | Attach to a process by PID. |
frida -f <app_id> | Spawn (launch) the application and attach immediately. |
frida -U -f <app_id> -l script.js | Spawn app on USB device and load a script. |
frida -n <name> -l hook_script.js | Attach to process and load a JavaScript file. |
frida -n <name> -e "console.log('Hi')" | Attach to process and execute inline JavaScript code. |
frida -U -f <app_id> --no-pause | Spawn app and automatically resume execution (no pause). |
Remote Debugging#
| Command | Description |
|---|
frida -H <host>:<port> -n <name> | Attach to a process on a remote device. |
frida -H 192.168.1.100:27042 -f com.app | Spawn an app on a remote device via IP/Port. |
CLI Utilities#
| Command | Description |
|---|
frida-trace | Trace function calls (generates stubs handlers). |
frida-discover | Discover internal functions called by the app. |
frida-kill | Kill a specific session or process. |
frida-ls-devices | List all connected Frida devices. |
Resources:#
From this code, we can notice that all constructor addresses are checked beforehand by the containsAddress function. Therefore, it makes this function a good hooking spot as it is executed before calling the constructor itself. One can use the native SDK of frida-gum to perform this action:
// Address of ImageLoader::containsAddress in /usr/lib/dyld
const uintptr_t containsAddress_ptr = ...;
// Setup hooks with gum_interceptor_attach
GumAttachReturn attach_ret = gum_interceptor_attach(
listener_->interceptor,
/* target */ reinterpret_cast<void*>(containsAddress_ptr),
reinterpret_cast<GumInvocationListener*>(listener_),
/* ID */ reinterpret_cast<void*>(containsAddress_ptr)
);
....
// Equivalent of onEnter in Javascript
void native_listener_on_enter(GumInvocationListener* listener, GumInvocationContext* ic) {
const uintptr_t ctor_function_addr = ic->cpu_context->x[1];
// Do stuff with ctor_function_addr
}
By hooking containsAddress(), we get the control before the execution of the constructors. It gives us the ability to perform the following actions that can help to identify the constructor involved in the crash:
Trace the constructors (see: constructors_trace.log)
Replace/disable a constructor (gum_interceptor_replace)
Detect the first constructor and hook the next ones (gum_interceptor_attach)
// Hook associated with ImageLoader::containsAddress
void native_listener_on_enter(GumInvocationListener* listener,
GumInvocationContext* ic) {
static size_t CTOR_ID = 0;
const uintptr_t ctor_function_addr = ic->cpu_context->x[1];
std::string libname = module_from_addr(ctor_function_addr);
if (libname == "NianticLabsPlugin" && CTOR_ID++ == 3) {
const uintptr_t base_address = base_addr_from_ptr(ctor_function_addr);
auto bin = LIEF::MachO::Parser::parse_from_memory(base_address);
bin->write("/tmp/pokemongo_after_ctor.bin"); // /tmp on the iPhone
}
}