stackplz Documentation

repository·dev·Indexed 23 days ago

https://github.com/seeflowerx/stackplz

An eBPF-based stack tracing tool for Android (kernel 5.10+) that provides capabilities for tracing syscalls, hooking user-space libraries via uprobes, and setting hardware breakpoints. It features an RPC server for Frida integration, native and Java stack trace output, and advanced filtering rules for captured data.

Tokens
4.1K
Snippets
8
Records
31
Agent score
81%

What's inside stackplz

  1. Configure uprobe hook points

    dev

    A uprobe configuration targets an ELF file via the library field.

    Key Fields:

    • type: Must be uprobe.
    • library: The ELF file to hook (e.g., libc.so or a full path). Supports split APK .so files.
    • points: A list of hook points. Note: A single uprobe hook supports a maximum of 6 points per execution.

    Point Configuration:

    • name: Either the symbol name (e.g., __openat) or a hexadecimal offset starting with 0x.
    • params: A list of parameters to read when the hook is hit.
    {
        "type": "uprobe",
        "library": "libc.so",
        "points": [
            {
                "name": "__openat",
                "params": [
                    {"type": "str", "reg": "x1", "filter": ["w:/data/data"]}
                ]
            }
        ]
    }
  2. Configure syscall hook points

    dev

    A syscall configuration targets system calls. If the -s/--syscall CLI flag is not used, all syscalls defined in the config will be hooked.

    Key Fields:

    • type: Must be syscall.
    • points: A list of syscall hook points.

    Point Configuration:

    • nr: The unique system call number.
    • name: A custom name for the syscall.
    • params: A list of parameters to read.
    • more: (Syscall only) Controls when to read detailed struct info. Options: enter, exit, or all (both).
    {
        "type": "syscall",
        "points": [
            {
                "nr": 29,
                "name": "ioctl",
                "params": [
                    {"name": "fd", "type": "int"},
                    {"name": "cmd", "type": "ptr", "filter": ["eq:0xc0306201"]},
                    {"name": "arg", "type": "ptr"},
                    {"name": "ret", "type": "ptr"}
                ]
            }
        ]
    }
  3. Batch trace processes and syscalls by group

    dev

    Instead of individual package names, you can use process groups with the -n/--name flag.

    Process Groups: root, system, shell, app, iso.

    • Use --no-uid <uid> to exclude a specific UID from an app group trace.
    • Use comma-separated names to combine groups (e.g., com.package,iso).

    Syscall Groups: Use the % prefix with the -s/--syscall flag.

    • %file: %attr, %file
    • %process: %exec, %clone, %process
    • %net: %net, %send, %recv, %read, %write
    • %signal: %signal
    • %kill: %kill, %exit, %dup
    • %epoll: %epoll, %stat
    • %stat: %epoll, %stat
    • all: All syscalls.
  4. Trace libc functions with --point or -w

    dev

    To hook functions within a shared library (like libc.so), use the --point or -w flag.

    By default, stackplz targets /apex/com.android.runtime/lib64/bionic/libc.so. To target a different library, use the --lib flag. You can specify the library by its name (it will search the default library directories) or by its full path (recommended if the library is not in standard paths, e.g., by checking /proc/{pid}/maps).

    Syntax for --point/-w: {symbol/base_offset}{+offset}[arg_types]

    • symbol: The function name.
    • base_offset: An offset from the library base.
    • +offset: An offset added to the symbol or base.
    • arg_types: A comma-separated list of types in brackets.
  5. Run stackplz with a configuration file

    dev

    To use stackplz with a specific configuration, use the -c flag. You can also use --dumphex for hex output and --color for colored terminal output.

    Example command:

    ./stackplz -n com.coolapk.market -c tests/config_uprobe_test_complex.json --dumphex --color
  6. Compile stackplz and deploy to Android

    dev

    To compile the project, ensure you have downloaded and extracted the Android NDK (e.g., android-ndk-r25b) and updated the NDK_ROOT path in build.sh to point to your extracted NDK directory.

    1. Run the build script from the project root:
    ./build.sh
    1. The compiled binaries will be located in the bin/ directory.

    2. Deploy the stackplz executable to an Android device using ADB:

    adb push bin/stackplz /data/local/tmp
    ./build.sh
    adb push bin/stackplz /data/local/tmp
  7. Pause and resume processes with --kill

    dev

    You can use the --kill flag to send a signal to a process when a specific hook point is hit. This is useful for dumping memory at a specific moment.

    • To pause: Use --kill SIGSTOP.
    • To resume:
      • In v3.0.0 and later, type c and press Enter in the terminal where stackplz is running.
      • Alternatively, use kill -SIGCONT <pid> from a root shell.
  8. Trace syscalls with stackplz

    dev

    Use the --syscall (or -s) flag to trace specific system calls. You can provide a comma-separated list of syscall names. To trace all syscalls, use all.

    Customizing syscall parameter types: To hook a syscall and read its arguments, append type suffixes to the syscall name in the -w (uprobe) syntax:

    • Append s/ss to a uprobe hook to convert it to a syscall hook. ss indicates that data should be read both at the syscall entry and exit.
    • Append x to a type to output it as hex.

    Refer to Linux kernel syscall tables for valid names.

  9. Use stackplz RPC for Frida integration

    dev

    stackplz includes an RPC server mode designed for remote hardware breakpoint triggering via Frida.

    1. Start the server: Run ./stackplz --rpc --stack.
    2. Connect the client: Use a Frida script (e.g., frida_hw_brk.js) to interact with the server.
    3. Configure port: The default listener is 127.0.0.1:41718. You can change this using the --rpc-path option.
    ./stackplz --rpc --stack
  10. Prepare the build environment for stackplz

    dev

    The build process requires specific modified versions of ebpf and ebpfmanager. These three projects must be placed in the same directory before starting the build. The build is designed for Linux x86_64 environments.

    1. Clone the required repositories into a single directory:
    git clone https://github.com/SeeFlowerX/ebpf
    git clone https://github.com/SeeFlowerX/ebpfmanager
    git clone https://github.com/SeeFlowerX/stackplz
    1. Run the environment preparation script from the stackplz root directory. Note: You may need a global proxy or tools like proxychains to download dependencies successfully.
    ./build_env.sh
  11. Configure stack trace and Java stack details

    dev

    Enhance trace output with stack information:

    • --stack: Include the native stack trace.
    • --jstack: Attempt to output a detailed Java stack trace. Note: This must be used with --kill SIGSTOP to pause the app; you can resume by typing c in the terminal.
    • --showpc: Show Program Counter.
    • --showtime: Output the timestamp of the event (ensures precise chronological order).
    • --showuid: Output the UID of the triggering process.
  12. Apply filtering rules to traces

    dev

    Filter events using blacklists, whitelists, or value comparisons.

    • Blacklist/Whitelist: Use -f w:<pattern> for whitelisting or -f b:<pattern> for blacklisting (e.g., file paths).
    • LR Comparison: Use -f eq:<value> to compare the Link Register (LR) against a specific value.
    • Buffer Data Comparison: Use -f bx:<hex_value> to compare up to 8 bytes of buffer data (requires a buffer type like buf in the hook definition).