While reversing Android apps, usually they are obfuscated ( I think it is included in the standard build process ), but when you are start to be familier with objective C (or swift) binaries there are really straight forward, with a nice disassembler and script, in my experience much faster.
Request signing, certificate pinning etc are not actually target at reverse engineers, more like to snoopers, replay attackers etc.
Also I agree with 4 totally, there is no point there, you should do your security on server side, instead of client side. (Except games I guess, which they can ban players etc, making it a cat and mouse game there can work pretty good actually)
Much harder targets, like obfuscated c++, or VMs (bytecode interpreters etc) usually helps with #4, but still then, it just slows down. (This slow down combined with regular changes in protection is basically targeted to make reverse engineers to give up)
Obfuscated control flow is like hell especially in c++ (ex: pokemon etc) but as I said I am comparing average android vs IOS. Once you have rooted platform you have much wider tool set of course.
I remember reading something years back about Java decompiling, and I believe it said that all Java code is decompileable except for inner classes and nested try-catch. Assuming my memory and the source are correct (which might not be the case), why hasn't it become standard practice for developers who don't want their app reverse-engineered to just put every class inside a wrapper class? I can imagine there could even be tools for doing this at compile time so that you wouldn't need to manually deal with the indirection when writing the code.
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
https://www.acloudtree.com/hacking-java-bytecode-for-program...
As for nested try-catch... I don't see how that would be an issue unless the compiler somehow merges them into a single block. Which, as long as it's semantically equivalent, doesn't matter at all.
I could probably have gone deeper and found more functions to patch, but I don't know smali so everything was guessing and matching up to the java decompiled source (and the original source which seems to have been Moxie's?)
(>$100 billion company making the app with >1 million users.)
Edit: oh another trick usually works is to change transport to HTTP from HTTPS, just changing endpoint to something you control and changing it to http (with little hex editing the endpoint), and reverse proxy with mitmproxy/charles to the target, you can speed up process.
So basically for app endpoint will be charles/mitmproxy machine, then from there, you will make https request to real API server
https://casper.io/ is an example of doing this (for SnapChat) - they used to take registrations for their own API. Not sure how it's working out for them these days.
(but it was definitely easier than in the blog post!)
If you don't feel like RE'ing the API, you can always just supply the inputs to the app yourself from somewhere else. ("All problems in computer science can be solved by another level of indirection", as the saying goes.)
But...
Security depends on ‘sense of security’, when people think platform is more secure, they tend to ignore/skip a lot of parts on security. Developer tend to skip edge cases (such as pizza API in this thread). When they are developing on secure platforms, they tend to skip more.
For example if you are developing for not jailbroken platform, you trust platform DRM (mostly consoles), and skip a lot of parts, you put the certificate pinning, and call it a day. When platform is broken, you are totally exposed.
But when you are developing for web, you are exposed from the beginning, you dont have that sense of security anymore, so you try to fix all edge cases.
It's a very simple principle: the relevant data must necessarily be exposed, even if only in memory, at some point. Like any other DRM, it's imperfect.
1. Android typically is easier for this kind of work (you don't even need a rooted/jailbroken device, and it's all Java/smali),
2. That said, instead of installing an entire framework like Xposed that hooks the process to bypass certificate pinning, you can usually just decompile the APK and nop out all the function calls in the smali related to checking if the certificate is correct, then recompile/resign it for your device (again, easier on Android than iOS),
3. Request signing is increasingly implemented on APIs with any sort of business value, but you can almost always bypass it within an hour by searching through the application for functions related to things like "HMAC", figuring out exactly which request inputs are put into the algorithm in which order, and seeing where/how the secret key is stored (or loaded, as it were),
4. There is no true way to protect an API on a mobile app. You can only make it more or less difficult to secure. The best you can do is a frequently rotated secret key stored in shared libraries with weird parameters attached to the signing algorithm. To make up for this savvy companies typically reduce the cover time required (i.e. change the secret key very frequently by updating the app weekly or biweekly) or by using using a secret key with several parts generated from components in .so files, which are significantly more tedious to reverse.