Skip to content

Commit

Permalink
apk: Allow gadget config file customization from CLI
Browse files Browse the repository at this point in the history
Add a -c/--gadget-config flag, valid when --gadget is also in use, that
adds arbitrary entries to the injected gadget's config file's
"interaction" section[1].

[1]: https://frida.re/docs/gadget/
  • Loading branch information
tchebb committed Oct 8, 2024
1 parent 732c92e commit d34733a
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 9 deletions.
1 change: 1 addition & 0 deletions completions/frida.fish
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ complete --command frida-create --no-files --require-parameter --short-option=t
add_base_arguments frida-apk
complete --command frida-apk --force-files --short-option=o --long-option=output --description="output path"
complete --command frida-apk --force-files --short-option=g --long-option=gadget --description="inject the specified gadget library"
complete --command frida-apk --force-files --short-option=c --long-option=gadget-config --description="set the given key=value gadget interaction config"


######## frida-compile ########
Expand Down
37 changes: 28 additions & 9 deletions frida_tools/apk.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import struct
from enum import IntEnum
from io import BufferedReader
from typing import BinaryIO, List
from typing import BinaryIO, Dict, List
from zipfile import ZipFile


Expand All @@ -16,11 +16,9 @@
LD_PRELOAD="$(dirname "$0")/{GADGET_NAME}" "$@"
"""

GADGET_CONFIG = {
"interaction": {
"type": "listen",
"on_load": "wait",
},
GADGET_INTERACTION_CONFIG = {
"type": "listen",
"on_load": "wait",
}


Expand All @@ -35,6 +33,15 @@ def _add_options(self, parser: argparse.ArgumentParser) -> None:
parser.add_argument("-o", "--output", help="output path", metavar="OUTPUT")
parser.add_argument("-g", "--gadget", type=argparse.FileType("rb"),
help="inject the specified gadget library", metavar="GADGET")

def key_val_type(arg: str) -> tuple[str, str]:
split = arg.split("=", 1)
if len(split) == 1:
raise argparse.ArgumentTypeError("config entry must be of form key=value")
return (split[0], split[1])
parser.add_argument("-c", "--gadget-config", type=key_val_type, action="append",
help="set the given key=value gadget interaction config", metavar="GADGET_CONFIG")

parser.add_argument("apk", help="apk file")

def _needs_device(self) -> bool:
Expand All @@ -44,6 +51,10 @@ def _initialize(self, parser: argparse.ArgumentParser, options: argparse.Namespa
self._output_path = options.output
self._path = options.apk
self._gadget = options.gadget
self._gadget_config = options.gadget_config

if self._gadget_config and self._gadget is None:
parser.error("cannot configure gadget without injecting gadget")

if not self._path.endswith(".apk"):
parser.error("path must end in .apk")
Expand All @@ -57,7 +68,15 @@ def _start(self) -> None:
if self._gadget is not None:
gadget_arch = get_gadget_arch(self._gadget)
lib_dir = f"lib/{gadget_arch}/"
inject(self._gadget.name, lib_dir, self._output_path)

config = {
"interaction": {
**GADGET_INTERACTION_CONFIG,
**dict(self._gadget_config)
}
}

inject(self._gadget.name, lib_dir, config, self._output_path)
except Exception as e:
self._update_status(f"Error: {e}")
self._exit(1)
Expand Down Expand Up @@ -118,11 +137,11 @@ def debug(path: str, output_path: str) -> None:
oz.writestr(info.filename, f.read(), info.compress_type)


def inject(gadget_so: str, lib_dir: str, output_apk: str) -> None:
def inject(gadget_so: str, lib_dir: str, config: Dict[str, Dict[str, str]], output_apk: str) -> None:
config_name = GADGET_NAME.removesuffix(".so") + ".config.so"
with ZipFile(output_apk, "a") as oz:
oz.writestr(lib_dir + "wrap.sh", WRAP_SCRIPT)
oz.writestr(lib_dir + config_name, json.dumps(GADGET_CONFIG))
oz.writestr(lib_dir + config_name, json.dumps(config))
oz.write(gadget_so, lib_dir + GADGET_NAME)


Expand Down

0 comments on commit d34733a

Please sign in to comment.