If you're the reverse engineer and I'm the app author, you find/replace my CA file. Then I respond (or anticipate!) by checksumming the file to detect tampering. Then you respond by find/replace on the checksum.
Then I obfuscate the checksum string. Then you respond by faking out the platform's checksum API so that it always returns true. Then I respond by computing a checksum that I know should fail and verifying that the checksum API isn't just always returning true. Then you respond by faking out the platform checksum API with a whitelist of blobs whose checksum it should lie about.
Then I respond by statically linking my own checksum verification code into my binary instead of calling the platform's. Then you respond by patching my binary to jump around the code. Then I respond by using code obfuscation techniques.
And on and on. Given enough time and resources, any implementation I create can be subverted. But if I'm a huge tech company, I can afford a lot of time and resources too, if I want to. I can't eliminate it, but maybe I can make it something that rarely happens.
The whole cracking scene can afford far more time and resources than any one tech company. All adding protections does is make a more valuable target, because crackers love a good challenge.
"There's always a crack in everything. It's how the light gets in."
Can? Sure! Would?
Security is one of those things that most people say they care about, but they are really not willing to pay for. Big companies have resources, but they are also in the business of making money, so they will put most of those resources to work on features that produce a ROI. Security is a huge cost center, and even when taken seriously it will be pursued only to the degree that it addresses/mitigates risks enough to conduct business.
http://www.cnn.com/TECH/computing/9908/20/aolbug.idg/index.h...
From the point of view of software, it's impossible in principle to tell whether or not the code being executed does what the user wants it to, and only what the user wants it to. Half of that is the halting problem, the other half is that "what user wants" is an General-AI-complete problem. Moreover, the software can't even tell the difference between "the user" and "a malicious third party".
In meatspace we solve this problem with rules and laws. Software, for better or worse, moves around too fast.
I gave it a thought, and decided I don't need apps to be able to obtain highly elevated privileges, root or similar. This is, indeed, dangerous, esp. regarding ADB root access (a rogue "charger" + an accidental wrong tap[1] = totally compromised device that can be only fixed by full re-flashing). I needed my own firmware that does things my way, signed with the keys I control.
So I did. Now all the "secure" apps are happy, and I still have the control over my device's behavior.
( Okay, I've cheated - I had to sanitize androidboot.verifiedbootstate when kernel initializes, because I can't control the bootloader :( )
[1] Hm, maybe password-authenticated root access is okay, though... But not a typical "tap to allow" dialog.
Certificate pinning is a hurdle to reverse engineering, but a surmountable one, at least on Android. Since the app is running on a phone where you may potentially have root, you can pick it apart with a debugger and see the traffic before it leaves the phone. This is technically challenging, but it is something that people do sometimes.