bdsm - For utter dominance over Android's Binder RPC
Android's Binder is indubitably one of its least documented, (unnecessarily?) complex, yet crucial mechanisms, as it underpins nearly all IPC/RPC in the system. I've taken to the painful task of explicating every last bit of it in Volume II (Chapter 8, the longest in the book..), and throughout it have been using a tool of my own devising. This tool takes another tool of mine, bindump(j), and combines its functionality with AOSP's service and dumpsys.
Bindump, Dumpsys, Service & More
redfin:/ $ /data/local/tmp/bdsm
Usage: bdsm [-h|-?]
bdsm [ns] list
bdsm [ns] check SERVICE
bdsm [ns] methods SERVICE # To list methods (if AIDL is loaded)
bdsm [ns] call SERVICE _meth_ [ _args_ ] ...
Where _meth_ is a method number, name (if AIDL is loaded),
or builtin (_PNG, _PID, _EXT, _NTF, _RPC, etc)
and _args_ are optional arguments (if AIDL is loaded), and types will be auto-determined
bdsm [ns] dump SERVICE # As per 'dumpsys' tool
bdsm [ns] users SERVICE # As per my 'bindump' tool (try 'all' for SERVICE)
bdsm [ns] owner SERVICE # As per my 'bindump' tool (try 'all' for SERVICE)
Where: [ns] is optionally 'binder' (default), 'hwbinder' or 'vndbinder'
Environment variables:
JCOLOR: The usual curses based coloring
JDEBUG: To get the behind the scenes binder transaction dumps, and other debug info
JAIDL: Path to AIDL directory (to override default, /data/local/tmp/aidl)
This is bdsm - Bindump, Dumpsys, Service & more, compiled on Jun 15 2022
This tool is part of the resources for 'Android Internals', Volume II, by Jonathan Levin
Free for non-commercial use at http://NewAndroidBook.com/
For commercial use (and pure C non-AOSP [hw]binder library) mailto://products@Technologeeks.com
If you find this useful, please go to http://NewAndroidBook.com/counter?bdsm,
so I can get an idea of how many users I have. Also - I'll gladly take bug reports/feature requests.
bindump
My bindump is a 100% original tool I had originally derived from service. Android 8.0 broke my implementation, forcing me to rewrite it from scratch, with my own low-level Binder interface, rather than libbinder. The tool has its own detailed page, detailing how to use it to list the owners and users of [vnd]Binder users. As of today, it is effectively deprecated in favor of bdsm, which supports all of its functions.
The main use here is bdsm users (or owner), which will find who uses a particular Binder service (or is its owner), like so (su -c is actually not required for /dev/binder - force of habit there):
This is wicked useful. In the example above, users of SurfaceFlinger mean anyone who has registered a surface (i.e. has a view) - and I will explain that in Volume IV someday. Similar interesting services are power (wakelocks) activity (app components), etc. The "owner" is useful for pinpointing services hosted by their own binaries - especially if in the vendor space:
Most users are probably familiar with dumpsys (or dumpstate, which uses it). This tool is really a fairly simple client which consists of :
Look up service node through servicemanager
Spin a thread to send a DUMP_TRANSACTION to looked up service, along with a pipe (as a Binderize FD)
Let remote to dump output to pipe, read in main thread till EOF and repeat to stdout.
So now that, too, is integrated into bdsm*. The only difference is I stick to a single thread and (at least for now) directly give out the stdout handle (i.e. direct to working terminal or '>' redirection. But it still works similarly.
AOSP's service is a generic Binder client, and absolutely one of its most useful CLI utilities. Although it steadily improves (floats and fds at last!), it still falls very short of its true promise. Most of what bdsm does is first match service's capabilities, then address this utility's shortcomings.
Use "list" just like service list to get a list of all registered Binder endpoints - But use "vnd" or "hw" to perform the same on the vndbinder or hwbinder. The former (requiring root since shell can't open(2)/dev/vndbinder) is like vndservice that you can sometimes find in /vendor/bin. The latter is like lshal (and uses an entirely different protocol..
Use "check" to check if a service exists.
Use "call" the same old fashioned way, groping in the dark for the right method number, hoping you get it right :-)
More**
This is where things get interesting: I've compiled bdsm with my own AIDL parsing library, which I call aidlwise. This is really a simple AIDL parser, but opens up wonderful possibilities - once you install the AIDLs. By default, put them all (from AOSP) into /data/local/tmp/aidl, and then bdsm does the rest:
First, using methods will tell you if the AIDL has been parsed successfully, *and* number the methods for you. Pretty basic, but saves you SO MUCH TIME over doing it manually! grep is your friend here, to find methods by partial name
Bug fix: service won't call any process refusing INTERFACE_TRANSACTION (_NTF), erroneously claiming it wasn't found.
You can now call the default methods (_PNG, _PID, etc) by name, instead of figuring out the hard coded number.
If you have AIDLs installed you can call a method by name (case insensitive), without painful argument types (i.e. no more i32, s16), since I can pick up the argument definitions from the AIDL. Note at this point only primitive types are supported, but that still is useful.
oriole:/ $ /data/local/tmp/bdsm call package isPackageAvailable com.android.chrome 0
Returned boolean: true (0x1)
oriole:/ $ /data/local/tmp/bdsm call window showGlobalActions
oriole:/ $ /data/local/tmp/bdsm call window _NTF
android.view.IWindowManager
oriole:/ $ /data/local/tmp/bdsm call window _PNG
oriole:/ $ /data/local/tmp/bdsm call window _PID
1378
oriole:/ $ /data/local/tmp/bdsm call procstats 1 # Raw types I can't recognized are dumped in hex, like service
0x0000: 00 00 00 00 84 AE 03 00 54 54 53 50 28 00 00 00 ........TTSP(...
0x0010: 10 00 00 00 08 00 00 00 0A 00 00 00 10 00 00 00 ................
0x0020: 00 10 00 00 01 00 00 00 6D 3E FA 60 6F 01 00 00 ........m>.`o...
0x0030: 9F 29 00 00 00 00 00 00 1E 7F BF 00 00 00 00 00 .)..............
0x0040: 9F 29 00 00 00 00 00 00 32 5A 49 00 00 00 00 00 .)......2ZI.....
...
0x3AF70: 01 00 00 00 00 00 00 00 85 2A 64 66 7F 01 00 00 .........*df....
0x3AF80: 0B 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00
# Objects are automatically recognized
Object 0 is a filedescriptor (4 = /data/system/procstats/state-2022-04-17-02-37-09.bin)!
Object 1 is a filedescriptor (5 = /data/system/procstats/state-2022-04-09-09-51-52.bin)!
Object 2 is a filedescriptor (6 = /data/system/procstats/state-2022-04-08-20-47-09.bin)!
Object 3 is a filedescriptor (7 = /data/system/procstats/state-2022-04-08-17-47-08.bin)!
Object 4 is a filedescriptor (8 = /data/system/procstats/state-2022-04-08-14-47-06.bin)!
Object 5 is a filedescriptor (9 = /data/system/procstats/state-2022-04-08-11-47-04.bin)!
Object 6 is a filedescriptor (10 = /data/system/procstats/state-2022-04-08-08-47-03.bin)!
Object 7 is a filedescriptor (11 = /data/system/procstats/state-2022-04-08-05-47-01.bin)!
CAVEAT: You *HAVE* to use the AIDLs from the AOSP build your device is running. GOOGL freely edits their AIDL and messes up method numbering frequently (especially in beta releases, but even in _r version updates). It's not me. It's them. There's actually a way to figure out the correct method number at runtime without AIDL, but it's too complicated for the moment.
Note: A nice added benefit of installing AIDL files is that jtrace(j) (which I've also compiled with AIDLwise) will automatically load them when parsing Binder calls, and tell you the method names and arguments!
Questions/comments/etc
always welcome.
This tool (like all my tools) contains no code from AOSP, and is entirely 100% proprietary, original code
Upload to your and then (from root) tar xvf /data/local/tmp/bdsm.tgz, which will also expand all the AIDL files to /data/local/tmp/aidl. An experimental ARMv7 version (runs on my 64-bit device but might need fixing for legacy 32-bit devices, which I no longer have) is here. Let me know if it needs any fixes (though note Android deprecates 32-bit as of 8.0 and eliminates it entirely in 13.0).
* - Without the 'D' of 'dumpsys' I'd have ended up with BSM - which I dearly love as an artifact of my beloved Solaris (even more so, now that AAPL killed it in macOS 10.18 in favor of EndpointSecurity.framework..
** - without 'M'ore I'd have ended up with "bds", which would piss off my Israeli readers. Also, considering OpenBinder's origins (and the excruciating suffering inflicted upon me over the years as I tried to figure out how Binder works), I think I ended up with the most apt name possible (with love to @hackbod).