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.
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')