sp1d3r

Instrumentating apps for fun and profit

Frida #

Frida is my favourite tool to manipulate code and memory inside processes. However, I find no tutorial which teaches frida for absolute beginners/intermediate programmers. Although there are alternatives for frida on PC (Linux/Windows), I find no good alternative to frida on Android. Anyway, this would be a fun tutorial!

Introduction #

To start, we can obtain frida through pip:

pip install frida frida-tools

The package frida comes with the tool frida and its Python API.

python -c "import frida;"

The above snippet should work fine.

Let’s discuss about the functionality frida offers, by looking at its help:

output of: frida -h
$ frida -h
usage: frida [options] target

positional arguments:
  args                  extra arguments and/or target

options:
  -h, --help            show this help message and exit
  -D ID, --device ID    connect to device with the given ID
  -U, --usb             connect to USB device
  -R, --remote          connect to remote frida-server
  -H HOST, --host HOST  connect to remote frida-server on HOST
  --certificate CERTIFICATE
                        speak TLS with HOST, expecting CERTIFICATE
  --origin ORIGIN       connect to remote server with “Origin” header set to ORIGIN
  --token TOKEN         authenticate with HOST using TOKEN
  --keepalive-interval INTERVAL
                        set keepalive interval in seconds, or 0 to disable (defaults to -1 to auto-select based on transport)
  --p2p                 establish a peer-to-peer connection with target
  --stun-server ADDRESS
                        set STUN server ADDRESS to use with --p2p
  --relay address,username,password,turn-{udp,tcp,tls}
                        add relay to use with --p2p
  -f TARGET, --file TARGET
                        spawn FILE
  -F, --attach-frontmost
                        attach to frontmost application
  -n NAME, --attach-name NAME
                        attach to NAME
  -N IDENTIFIER, --attach-identifier IDENTIFIER
                        attach to IDENTIFIER
  -p PID, --attach-pid PID
                        attach to PID
  -W PATTERN, --await PATTERN
                        await spawn matching PATTERN
  --stdio {inherit,pipe}
                        stdio behavior when spawning (defaults to “inherit”)
  --aux option          set aux option when spawning, such as “uid=(int)42” (supported types are: string, bool, int)
  --realm {native,emulated}
                        realm to attach in
  --runtime {qjs,v8}    script runtime to use
  --debug               enable the Node.js compatible script debugger
  --squelch-crash       if enabled, will not dump crash report to console
  -O FILE, --options-file FILE
                        text file containing additional command line options
  --version             show program's version number and exit
  -l SCRIPT, --load SCRIPT
                        load SCRIPT
  -P PARAMETERS_JSON, --parameters PARAMETERS_JSON
                        parameters as JSON, same as Gadget
  -C USER_CMODULE, --cmodule USER_CMODULE
                        load CMODULE
  --toolchain {any,internal,external}
                        CModule toolchain to use when compiling from source code
  -c CODESHARE_URI, --codeshare CODESHARE_URI
                        load CODESHARE_URI
  -e CODE, --eval CODE  evaluate CODE
  -q                    quiet mode (no prompt) and quit after -l and -e
  -t TIMEOUT, --timeout TIMEOUT
                        seconds to wait before terminating in quiet mode
  --pause               leave main thread paused after spawning program
  -o LOGFILE, --output LOGFILE
                        output to log file
  --eternalize          eternalize the script before exit
  --exit-on-error       exit with code 1 after encountering any exception in the SCRIPT
  --kill-on-exit        kill the spawned program when Frida exits
  --auto-perform        wrap entered code with Java.perform
  --auto-reload         Enable auto reload of provided scripts and c module (on by default, will be required in the future)
  --no-auto-reload      Disable auto reload of provided scripts and c module

But we will only need the following:

frida -f <path/to/file> # spawn file
frida -U <usb> # USB (ADB/android)
frida -p <PID> # attach to PID
frida -l agent.js # frida script

And frida-tools comes with the following tools:

  • frida-apk
  • frida-compile
  • frida-trace
  • frida-itrace
  • frida-join
  • frida-kill
  • frida-ls-devices
  • frida-ps
  • frida-pull
  • frida-push
  • frida-rm
  • frida-trace: which is, very, very useful for tracing specific functions

How does frida work? #

Frida works by injecting a frida-agent.dll into the target process. The agent then communicates with the server and facilitates scripts written in Javascript to load using QuickJS. QuickJS is quoted from its makers as: QuickJS homepage

  • QuickJS is a small and embeddable Javascript engine.
  • It supports the ES2023 specification including modules, asynchronous generators, proxies and BigInt.
  • Small and easily embeddable: just a few C files, no external dependency, 210 KiB of x86 code for a simple hello world program.
  • Small built-in standard library with C library wrappers.

It is appreciable that frida supports basic Data structures has functions to perform DSA:

Let’s get started.

Attaching to a process #

Frida is not a debugger. It is a tool for instrumenting binaries.

Let’s attach frida to a notepad process and observe how it behaves. I am using Windows 11 and Powershell throughout the tutorial.

% notepad
% frida -p $(get-process notepad).id # automatically attach to the first notepad process

Let’s observe the process modules using process hacker.

Awesome! We have the DLL frida-agent.dll injected into the process and have the following console:

Awesome! We can use the console to invoke various Javascript APIs. They are documented here.

For now, let’s enumerate all the loaded modules using Process.enumerateModules(). From the documentation, we have:

Process.enumerateModules(): enumerates modules loaded right now, returning an array of Module objects.
- The first object of the returned array of Module objects is the actual program.

Let’s observe how the Module objects look like:

So, a module object is basically:

{
    "base": "base address of module",
    "name": "name of module",
    "path": "full path to module",
    "size": "size of the module on memory"
}
comments powered by Disqus