CLI Reference and Usage#

Compiling AIDL#

python3 -m bshark.compiler -I $ANDROID_SRC compile $CLASS_NAME --output $OUTPUT_DIR

This will generate a JSON file with the qualified class name (e.g. com.example.SomeClass) in the OUTPUT_DIR directory. The structure depends on the input class (either an interface or a parcelable declaration):

 1{
 2    "name": "com.example.SomeClass",
 3    "methods": [
 4        {
 5            "name": "someMethod",
 6            "tc": 1,
 7            "oneway": true,
 8            "retval": null,
 9            "arguments": [
10                {
11                    "name": "someArg",
12                    "call": "readInt",
13                    "direction": 0
14                }
15            ]
16        }
17    ]
 1{
 2    "name": "com.example.SomeClass",
 3    "type": "PARCELABLE_JAVA",
 4    "fields": [
 5        {
 6            "name": "someField",
 7            "call": "readInt"
 8        }
 9    ]
10}

Note

AIDL files must be in the $ANDROID_SRC directory, which can be downloaded from the Android Open Source Repository. For instance, the input name com.example.SomeClass.json should be located in $ANDROID_SRC/com/example/SomeClass.[aidl|java|json].

Batch Compilation#

python3 -m bshark.compiler -I $ANDROID_SRC batch-compile -o $OUTPUT_DIR --recursive --force

This will generate a JSON file for ALL AIDL files in the $ANDROID_SRC directory under the $OUTPUT_DIR directory. Note that this command tires to import all previously compiled AIDL files from the output directory first.

Inspecting AIDL files#

python3 -m bshark.compiler -I $ANDROID_SRC info $CLASS_NAME

This will print the various information about the loaded AIDL file including the internal parsed file and defined data. For example:

python3 -m bshark.compiler -I $ANDROID_SRC info android.accounts.Account
Units of android.accounts.Account
└── android.accounts.Account
    ├── Methods: 8
    ├── Constructors: 4
    ├── Members: 7
    ├── Compiled: False
    ├── Parcelable
       ├── Creator: True
       └── Ctor: True
    └── Info
        ├── QName: 'android.accounts.Account'
        ├── RPath: 'android/accounts/Account.java'
        └── Lang: 'java'

Decoding Transactions#

There is currently no CLI support for decoding transaction messages. The internal parser will try to decode as much details as poosible from the received data.

Decode a single message from received bytes#
 1import frida
 2
 3from caterpillar.shortcuts import unpack
 4
 5from bshark.agent import TransactionListener, Agent
 6from bshark.parcel import IncomingMessage, OutgoingMessage
 7
 8loader = ... # you have to import all JSON files first
 9
10class MyListener(TransactionListener):
11    def on_transaction(self, code: int, data: bytes):
12        # transaction started
13        msg = unpack(
14            IncomingMessage,
15            data,
16            android_version=..., # the version of the Android OS
17            code=code,           # the code of the transaction
18            loader=loader        # the global loader instance (with all cached structs)
19        )
20        # ...
21
22    def on_reply(self, code: int, interface: str, data: bytes):
23        reply = unpack(
24            OutgoingMessage,
25            data,
26            android_version=..., # the version of the Android OS
27            code=code,           # the code of the transaction
28            loader=loader        # the global loader instance (with all cached structs)
29            interface=interface  # the name of the interface
30        )
31        # ...
32
33device: frida.core.Device = ...
34agent = Agent(
35    loader,
36    android_version=...,  # the version of the Android OS
37    device=device,        # the device to attach to
38    listener=MyListener() # the transaction listener
39)
40
41# either spawn an app or attach to an existing process
42pid = ...
43agent.attach(pid)
44# or
45agent.spawn('com.example.app')