The great thing about Android applications is that often they generally decompile quite nice into human readable Java so the barrier of entry can be quite low to start reversing.
Grab a copy of JADX[1] - it will decompress and decompile the APK files. If you don't have an Android handset, use an emulator and/or grab APKs from apkpure[2]
Dynamic analysis is a bit more challenging. In my blog post I use Frida[3] extensively.
If you get started on something and get stuck/looking for support, feel free to DM me on Twitter (handle in HN profile), more then happy to help.
I honestly don't know what's a good way of getting started on reverse engineering. There's a bunch of everything about Windows executables in particular, including "crackmes", but native machine code is a level up from JVM bytecode. Java classes and Android dex files can be decompiled back to sensible source with a good chance that you get something that can be compiled again. No such luck for native code — C/C++ compilation is a lossy process by its nature, especially the optimizations. Ghidra does a decent job but still requires a non-zero amount of manual assistance. Flash games also were good to hone one's reverse engineering skills since ActionScript decompilers did a pretty darn good job.
Anyway. To decompile dex to Java source, there's jadx: https://github.com/skylot/jadx
Since decompilation is sometimes lossy, there's apktool for when you want to put the app back together after tinkering with it: https://github.com/iBotPeaches/Apktool
It goes without saying that you also need a JDK and the Android SDK. In particular, you need apksigner form the SDK to sign the unsigned apks generated by apktool. You can also automate things a bit and use adb to deploy them to your device.
What I usually do is get a high-level overview of the app in jadx, and then modify the smali (dalvik bytecode in text form, very assembly-like) files generated by apktool.
A week ago I purchased a bluetooth device that takes some measurements. You require an Android or iOS application. The first thing the iOS app did was request permission for your location. Immediate fired up MITMproxy [1] running in transparent `--mode wireguard` and installed it's certificate in the iOS trust store. It was sending a whole bunch of data to China and HK. Since I don't have a jailbroken iPhone, it's off to Android.
For BLE scanning, Android does require permissions for location, but this application is using a Chinese branded tracking SDK and sending encrypted blobs (within already encrypted TLS). So it's time to start reversing and instrumenting the runtime.
Well - not so easy, they used a commercial packer that encrypts their compiled bytecode and decrypts and I think executes it within C++ library that might be an actual interpreter. I managed to pull the Dalvik bytecode out of memory using Frida[2] after the packer had decrypted the base application and converted it to java bytecode with dex2jar[3] then into decompiled java with jadx [4].
Since the developer relied on the packer to hide/obfuscate their software, it's quite easy to follow the deobsfucated code. The libraries that do the location tracking on the otherhand are obfuscated so now I'm at the stage of identifying where to hook before the encrypted blobs are sent to servers in China.
Here it would be nice to have a call flow graph generated based on the static decompiled java code - can anyone recommend anything?
I've sunk about 8 hours into this so far. The message here is that to understand what some applications on your phone does you need to really invest time and effort. The developers increase the cost to the consumer to know what their application is doing by obfuscation, encryption and packing. It's asymmetric. Also note: the play store and apple store state the app does not send data, which is demonstrably false.
I can also see that the tracking SDK has what looks like functionality to dynamically invoke code - which would break the terms and conditions of the app stores.
At some point I will reimplement it's primary BLE functionality and release it as opensource to the public and perhaps write a blog post.
[1] https://mitmproxy.org/posts/wireguard-mode/
[2] https://frida.re/docs/android/
Note that scripts like this are extremely useful, but in the long term they're cobbling together a lot of tools and will become brittle or difficult to use across versions. I suggest that even if it works for you today, understanding exactly what's happening under the hood will help if the tool becomes unsupported long-term.
[1] https://github.com/skylot/jadx
[2] https://github.com/mmastrac/longshot
[3] https://grack.com/blog/2022/12/02/hacking-bluetooth-to-brew-...
The listed books should help with that! I think Practical Malware Analysis really is a good start, even for that. When looking at malware you also try to find important functionality and the book teaches you how to get there quickly.
> I'd also like to have a go at modifying firmware of embedded devices, eg a car head unit with a stupid splash screen on startup that I'd like to disable.
There are probably forums for that, where you can find some info. There's also a nostarch book on car hacking (https://nostarch.com/carhacking) and for embedded (https://nostarch.com/hardwarehacking). I haven't read either, but it might be worth to check out some reviews for it. Maybe they're good and can help you achieve your goals.
The difficulty probably depends on how new the car is. In case you need to actually find a vulnerability in the infotainment system to get proper access, something like Hacking: The Art of Exploitation (https://nostarch.com/hacking2.htm), which I heard many good things about, is probably a good read. But if it's too new it might be too time consuming (see e.g. https://www.youtube.com/watch?v=k_F4wHc4h6k)
> For example I have a camera with wifi functionality, and you can control it from a phone app. It would be cool if I could somehow control that from the command line, or create my own basic app for the PC to control it. On top of that it would be good if I could modify the firmware to make it automatically start up in that remote control mode.
I think getting at least a CLI client could be relatively easy. For that you probably don't even need to reverse a binary using IDA/Ghidra/Binary Ninja. You can try to get the .apk file of the app and decompile it using something like jadx (https://github.com/skylot/jadx/). You'll receive mostly readable Java code. It can try to deobfuscate names, if they're obfuscated. The code you're interested in is probably somewhere under "com.manufacturer...".
How easy it is to modify the firmware once again likely depends on how old or new the camera is. They could, for example, have some integrity checks that keep you from doing that. But I have absolutely zero experience here, so it might as well be really easy. I think there could be forums for this, too.
Also be warned that modifying the firmware of your car or camera can break (parts of) them if things go wrong. E.g. I accidentally (soft) bricked a device because I tried to flash it from within a VM. I don't know how big the risk in your cases is, maybe there isn't any. But it's a good idea to read lots before accidentally breaking something expensive!
Happy I could help you :)
IIUC, the permissions apps request ultimately just enable access to certain APIs; they don't do anything on their own: https://stackoverflow.com/questions/24858462/how-to-check-if... (see 1st comment). So apps like https://play.google.com/store/apps/details?id=sk.styk.martin... and https://play.google.com/store/apps/details?id=com.ubqsoft.se... basically reason about the ceiling of everything an app might use across its lifetime. It's arguably a tad misrepresentative, like seeing a wall of text from a distance can be scary.
Furthermore, the very orthogonal way permissions are categorized relative to internal API architecture is woefully unintuitive at best, making it next to impossible to come up with good summary judgements of what a given app might be trying to do. For example, a given game might want access to your "cell ID information" because the analytics SDK it uses is overly invasive (while the game itself never needs the info), while a smart-device controller app might request "real-time location information" (I forget exactly what the permission is called) just because the smart device happens to use BTLE (Bluetooth LE), because BTLE's fast connect/disconnect characteristics made it ripe for abuse by indoor location tracking systems in shops and whatnot, and so Android had to make that the permission name since it's impossible to determine programmatically what a given BTLE connection is being used for.
So not only is the mapping from policy to implementation a case of a pile of arrows all pointing at each other, the current permissions model has a really big "wait what" problem because it's based around enabling access to APIs ahead-of-time so they can be used when needed. Android's trying to go down a just-in-time model where for example something requests access to storage as and when needed (I think this is called "instant" permissions); this contextualizes and thus justifies the request, allowing for more informed consent.
With the ahead-of-time way things work nowadays, though... I'd be a bit bullish that APKTool on its own would be useful. You're basically in an equivalent situation to wondering why a given Chrome extension might be asking for a certain permission, only to download the CRX, unzip it, and find everything minified. Intractable? Check. "Now what?": check. Suspicious? Good question :(
In practice a reasonable number of Chrome extensions incidentally aren't minified and contain perfectly readable source, sometimes even with comments (which is great for figuring out how other developers have solved certain complex integration problems ;D) - but the bytecode-based nature of the Java runtime means you're always working with some level of minification. Control flow is generally always somewhat permuted in much the same way pseudo-decompiled C code doesn't quite look the same as the original. If a given app isn't using obfuscation, you might be able to see some symbol names however.
Android Studio adds the Proguard obfuscator (which ships for free with 'Studio) into the build instructions of every new project by default, but switched off by default to make builds faster. Once enabled by just changing a couple build settings to "true", obfuscation Just Works™ without any additional steps. Given this state of commoditization it's often a good question whether an app's symbols are available or not.
JADX (https://github.com/skylot/jadx) is one tool people mostly use to fight their way through this status quo. Like with IDA, you generally need a very good idea of exactly what you want to do when using it (particularly when symbols are unavailable). "Find why this wants all these permissions" is a sadly very open-ended question from this low-level perspective. :(
FWIW, there are "interestinger" obfuscators that Proguard out there; I once wondered how a random Chinese smart-device companion app worked internally, and found that it shipped with a .so (shared library!)-based obfuscation/protection runtime. Frida (https://frida.re/) proved particularly awesome here, as it turned that for all the obfuscation and insanity the runtime brought to the table, it was to hide the application's original .dex files, which it briefly wrote to a temporary location on launch - so that was just a question of winning a race condition in an Android emulator. Frida is honestly a pretty amazing tool, and picks up almost everywhere JADX and similar decompilers/static analysers leave off. You either run it in the background on rooted devices or bundle Frida into a given app (using JADX to inject the shared library, and also to actually modify the app's bytecode to launch Frida), and then it basically makes V8 (yes, the JavaScript interpreter) available over ADB so you can play around with the app remotely (hook Java threads, make them run whatever code you want, etc) in a dedicated thread the app cannot block. Yes, it's that crazy, and yes, that sort of flexibility lets you do almost anything (once you figure out how to express it...). lol
TL;DR: You are sadly fundamentally correct in your gut assumption that this is a generally intractable question to straightforwardly answer. :(
I think one of the most viable realistic goals in pursuit of ideal privacy is to run all traffic through a captive proxy and install CA certificates on at least all phones to enable MITMing all TLS traffic. I've seen the occasional comment on here by people who have done just that; they just uninstall whatever doesn't cooperate (with certificate pinning etc). I've been wanting to do this myself for quite a while but don't have the hardware to pull it off effectively/seamlessly yet. FWIW, device policy controller apps can install CA certificates and start VPNs without any persistent notifications cluttering up the screen (:D) - and they're surprisingly easy to write.
If there was a specific angle or takeaway I'd like to focus on here, it's that the ecosystem has organically evolved into a headdesk-inducingly awkward but still so incredibly interesting status quo, that sadly requires a bit of attention-span buy-in to get past all the "...!!! *run away*", but in much the same way that learning about Slackware taught me a tonne about Linux (and sed, incidentally, because it was one of the few things that weren't corrupted on the install CD I used, haha) that I wouldn't have known if I hadn't taken everything apart and gone "ok, now maintain this mess", this provides a great hands-on opportunity to learn about network security (it's kind of amazing how the pieces of the current status quo fit together - and then disappear!). I'm looking forward to playing around more when I get the chance.
I love using Jadx (https://github.com/skylot/jadx) to get a better understanding of the code in Java and then use APKTool to reverse engineer, decompile and recompile the app
If you are interested, Frida is also an amazing tool that makes certain type of reverse engineerings a lot easier compared to using APKTool. I wrote an article on that as well: https://yasoob.me/posts/reverse-engineering-nike-run-club-us...
Reverse engineering is a very exciting field and the moment you learn and figure out one concept you realize there is a lot more out there for you to figure out.
That was my "Ah-ha!" moment in using Gradle.
JADX is really nice - there’s a decent GUI, and it also supports exporting the whole thing as an Android Studio project so you can directly take advantage of the refactor tools there for more deobfuscation. It also has a smarter decompiler than JD as it’s specialized to go straight from dex to Java (JD makes a trip through the classic JVM class format, which loses some nuance of dex).
Of course, many of the apps I’m taking apart have native components, for which I use GHIDRA and IDA.
In general I have found that most smaller app developers don't obfuscate at all, and often you can find hardcoded keys/secrets in these smaller applications.
[1] https://developer.android.com/studio/build/shrink-code.html