Software Engineering
application-design app decompile
Updated Fri, 09 Sep 2022 06:46:20 GMT

How do app developers protect their app when a user decompiles it?


I've been trying my hand at building apps with Flutter and Dart. I noticed in my apps that if someone decompiled my app they could access a whole lot of things I didn't want them to access.

For example, if I am calling my database to set the users 'active' status to False when they cancel their plan they could just comment out that bit of code and they get access to the entire app again despite having cancelled their plan.

Since this is my first app, my backend is Firebase. The app handles everything and calls Firestore when it needs to read or write data.

  1. Is this something to really worry about?

  2. If so should I be using something like Firebase Cloud Functions?

  3. Should I be creating a proper backend? If so what would its structure be? Would my app just be a client for the backend?




Solution

I used to be a full-time binary reverse engineer, and I still spend about 80% of my time reverse-engineering software (legally).

There are some good answers here already, but I wanted to add a few touches.

Legal Aspect

I'm not a lawyer. But as far as I'm concerned (and many others too), reverse-engineering doesn't really become legally enforceable until you've done something with the knowledge. Think about this situation:

Say I'm a reverse engineer and I download your app. I disconnect my "lab" machine from the network. Now, I decompile, disassemble, and debug your app, taking detailed notes of how it works. After doing all of this, I wipe out my lab machine and it never sees the network.

Then, I do nothing with that knowledge, because it's a weekend hobby and I just enjoy decompiling things.

It's debatable whether or not this is illegal and more importantly, it's unenforceable. There is no way you, your lawyer, or anyone else will ever know that I did this unless I'm already suspected of copyright violations, patent violations, or some other crime. Even if you sued me, what would you sue me for? I never published, distributed, advertised, told anyone, or did any kind of monetary damage to your business whatsoever. What would your "damages" be? For this reason, the vast majority of the time (view that EFF page that was linked in a comment earlier), real prosecution stems from cause of some (usually major) perceived loss by the software development firm or copyright/patent holder.

The trick is that a reverse engineer may actually use some of the knowledge that he/she/they learned from your app code, and do things that will be hard for you to detect or prove. If a reverse engineer copied your code word-for-word, and then sold it in another app, this would be easier to detect. However, if they write code that does the same thing but is structured entirely different, this would be difficult to detect or prove, etc...

Learn about who would target your app and why?

What are the type of people who would like to reverse engineer your app? Why? What would they get out of it?

Are they hobbyists who enjoy your app and could potentially even be helping your business by fostering a community of hacker enthusiasts? Are they business competitors? If so, who? What is their motive? How much would they gain?

These questions are all very important to ask because at the end of the day, the more time you invest in locking down your code, the more costly it is to you and the more costly it is to the adversary to reverse engineer. You must find the sweet spot between spending some time on application hardening to the point where it makes most technical people not want to bother spending time trying to thwart your app's defenses.

Five Suggestions

  1. Create a so-called "Threat Model." This is where you sit down and think about your application's modules and components, and do research on which areas would most likely be compromised and how. You map these out, many times in a diagram, and then use that threat model to address them as best as you can in the implementation. Perhaps you model out 10 threats, but decide that only 3 are most likely, and address those 3 in the code or architecture.

  2. Adopt an architecture which trusts the client application as little as possible. While the device owner can always view the app's code and the network traffic, they cannot always access the server. There are certain things you can store on the server, such as sensitive API keys, that cannot be accessed by the attacker. Look into "AWS Secrets Manager," or "HashiCorp Vault," for example. For every client module, ask yourself "Would it be ok if an attacker could see the inner workings of this?" "Why not?" and make necessary adjustments.

  3. Apply obfuscation if your threat model requires it. With obfuscation, the sky is the limit. The reality is, it is an effective protection mechanism in many cases. I hear people bashing on obfuscation a lot. They say things like

    Obfuscation will never stop a determined attacker because it can always be reversed, the CPU needs to see the code, and so on.

    The reality is, as a reverse engineer, if whatever you've done has made cracking into your app take 2-3 weeks instead of an hour (or even 3 hours instead of 5 minutes), I'm only cracking into your app if I really really want something. Most peoples' apps are frankly not that popular or interesting. Sectors which need to take extra measures would include financial, government, video game anti-hacking/anti-cheat, and so on...

    Furthermore, the above argument is nonsensical. Cryptography doesn't stop people from getting your data, it just slows them... Yet you're viewing this page right now over TLS. Most door locks are easily picked by a skilled lockpicker in seconds, people can be shot through bullet-proof vests, and people sometimes die in a car accident when wearing a seatbelt... So should we not lock doors, wear vests, and wear our seatbelts? No, that would be silly, as these devices reduce the likelihood of a problem, just like obfuscation, symbol stripping, developing a more secure architecture, using a Secrets Manager service to store your API secrets, and other hardening techniques that help prevent reverse engineering.

    Say I'm a competitor and I want to learn how to make an app like yours. I'm going to the app store and searching for similar apps. I find 10 and download them all. I do a string search through each. 7 of them turn up nothing useful, and 3 I find unstripped symbols, credentials, or other hints... Which apps do you think I'm going to be copying? The 3. You don't want to be those 3.

  4. Scan your source code for sensitive strings such as API secrets, sensitive keys, admin passwords, database passwords, email addresses, AWS keys, and so on. I usually search for words like "secret", "password", "passphrase", ".com", "http" using a tool called ripgrep. There will be false positives, but you may be surprised at what you find. There are automated tools which help accomplish this, such as truffleHog

  5. After you build your application, run the strings utility or a similar utility on it. View the output both manually and using a text search like ripgrep or grep. You'll be surprised at what you find.

Know about deobfuscators and look for them

Lastly, know that various obfuscators out there have deobfuscators and "unpackers." One such example is de4dot, which deobfuscates about 20 different C#/.NET obfuscator outputs. So, if your idea of protecting something sensitive is just using a commodity obfuscator, there's a high chance that there is also a deobfuscator or other folks online who are discussing deobfuscating it, and it would be useful for you to research them before you decide to use an obfuscator.

Why bother obfuscating when I can open de4dot and deobfuscate your entire program in 2 seconds by searching "[insert language here] deobfuscator?" On the other hand, if your team uses some custom obfuscation techniques, it may actually be harder for your adversaries because they would need a deeper understanding of deobfuscation and obfuscation techniques aside from searching the web for deobfuscators and just running one real quick.





Comments (5)

  • +0 – I agree with most of this, but "cryptography doesn't stop people from getting your data, it just slows them" is very misleading. Cryptography using a properly implemented and modern algorithm does stop someone accessing your data, provided that they haven't got some shortcut to the key (e.g. a narrow password search space). This is because brute forcing such a key is infeasible. — Jun 21, 2020 at 15:13  
  • +0 – @candied_orange I'm not sure what your point is. "brute force that takes longer than the heat death of the universe" is considered infeasible enough by most people, and was exactly my point. We're not talking about knowing you transmitted data (that's a separate topic), we're talking about "stop[ping] people from getting your data". Sure we can nitpick and say that waiting until after heat death is "slowing down", but for practical purposes it's the same as stopping. — Jun 21, 2020 at 15:25  
  • +0 – @candied_orange Under our current understanding of the laws of physics, there is no possible way to wait until the heat death of the universe and then continue to do useful work. So yes, you stop them. Either way, this is being pointlessly pedantic and isn't useful information for any kind of practical purpose. — Jun 21, 2020 at 15:33  
  • +5 – As a security professional, I would suggest you take the bit about cryptography out, since it seems like you agree it's not really accurate, even if not about exactly how inaccurate. As far as bruteforcing goes, I can assure you that no possible performance advance in CPUs will make bruteforcing of modern cryptographic system practical without SOME other qualitative change, meaning either (1) a mathematical break of the cryptosystem involved, beyond just "faster machines", or (2) a practical application of quantum computers (which breaks some systems but not others, on current knowledge.) — Jun 22, 2020 at 00:02  
  • +7 – For some context: My laptop can do about 10^6 AES decryptions per second. The Internet tells me a very fast CPU could plausibly do 10^8. (Exact numbers don't matter.) Cracking 128-bit AES with that very fast CPU therefore requires not 47371983 years, but around 1,000,000,000,000,000,000,000,000,000 years (two thousand trillion times greater). If you add 20 years of Moore's Law at 1.5x/year (though reality has not kept up), and assume a billion of those machines, you get "only" 30 billion years. And at some point during those 20 years, we can switch to AES-256 if we really feel threatened. — Jun 22, 2020 at 00:17