I am putting the final touches on my android app. The app is a full networking game, so it is always using the internet when you are running it. I want to prevent someone from extracting the .apk from the phone, decompiling the code and then changing and extending my classes to do bad things to my server. Here is how the app sets up the networking:
Client connects to the server
Server sends client a "session key" that is used for encryption
Server and client communicate with encrypted data based on the key they share
Now, I'm worried someone will decompile my code and change it so that they can do whatever they want in the game. Is there a way to make sure the classes haven't been changed? Is there a way to check the size of a .class file during runtime? Anyone have any ideas?
Whatever you do to your code, potential attacker is able to change it in any way she or he finds it feasible. You basically can't protect your application from being modified. And any protection you put in there can be disabled/removed.
You can do different tricks to make "hacking" harder though. For example, use obfuscation (if its Java code). This usually slows down reverse engineering significantly.
As everyone says, and as you probably know, there's no 100% security. But the place to start for Android that Google has built in is ProGuard.
If you are doing your game entirely in Java you can use ProGuard to obfuscate the application code, thus when it is turned into Smali by a hacker, the code is very difficult for a human to read.
If you have the option of including shared libraries, you can include the needed code in C++ to verify file sizes and integration, etc.
Related
I have learned from this post Reverse engineering from an APK file to a project that it is possible to get the java files from an apk. Does this mean a hacker can see my code?
Yes, but if seeing your code makes your app less secure, then your app's security model was flawed from the beginning. Any code or data that users shouldn't have access to should be run or stored only on your server, not on the users' devices.
Also, beware of snake oil obfuscators that claim to make it impossible to reverse-engineer your code. None of these work; anything your device can execute can be reverse-engineered with enough effort (except maybe SGX, but that doesn't exist on phones).
I have a small "Business Activity Monitor" written in Java. The program is usually installed on the server of my customers and it accesses their database and brings informations about the data obtained. My goal is to write a version of the program for the Web. I've actually written one in PHP. However, for the web application to access the database on my customer's server, I need to leave the source code inside the server machine. And that I cannot do (security reasons). So: is there anyway to write an application that would access my costumer's database and perform the necessary data manipulation without having to leave the source code on his machine? I hope I made myself clear!
You could do it by making a central server where you do the actual processing (whatever you want to do). But that means it's a lot of work and if it's customer data, you need to make the connection really safe.
If you don't want to do it this way, it's better to leave your script at the server. You could try to obfuscate it, but that means you're just making it harder to read.
Also don't make the mistake of thinking writing in java automatically "hides" my source. It's compiled but you can decompile java code also.
An example of this: http://jd.benow.ca/
Possible answer: compile the php code
see it here: Can you "compile" PHP code?
For example, http://www.phpcompiler.org/ is able to compile your php files into a relative secured binary format.
Disclaimer: I don't use it myself, and don't write php anymore since a decade
I'm trying to make sure that someone can't recompile my obfuscated application and then send malicious data to my server. I am doing an SSLed PHP_POST of my application's versionCode and packageName. These POSTED variables are all encrypted via asymmetrical encryption along with signature verification which will be changed per every version upgrade. I have thought of using checksums but those methods are not supported officially by Google and research has shown that they are not error-proof meaning that they could potentially disrupt legitimate users.
On top of all of this is a ban-on-site via IP/Mac Address/IMEI/Serial/Android_ID/etc when something is detected that is 100% not legit.
I understand that nothing could be 100% secured and the difference between a good security and a bad one is the time/money/effort it takes to break a security is valued higher than the item being protected by the security. With this in mind, are there any other methods I could use to protect my application or any ideas I should implement to add onto current security?
On a side-note, how easy is it to decompile/recompile an apk(jar) that's been obfuscated and would it be easier once its been done once? (aka, it doesn't matter how many times I change the key because the application is already compromised and the decompiler can simply look at the same spot where my last key was)
First thing, first, don't do your own crypto. If you are properly(!) doing SSL that is probably enough to protect data in transit against tampering, etc. What you need to do is authenticate your app somehow which is generally tricky, because you need to keep the credentials in the app. There are different ways around that, but currently the standard (and Google-endorsed way) is to use Google Play services to obtain a token and verify it in your server app. Details here: http://android-developers.blogspot.jp/2013/01/verifying-back-end-calls-from-android.html
This not perfect, but is probably better than most non-standard solutions you can come up with.
Decompiling is generally easy, and obfuscation doesn't change much, since it is trivial to find the places where you are calling system APIs (to get MAC addresses, hash, encrypt, etc.)
I have a dilemma. Basically, I've given a group of people I'm friends with a program that utilizes source code that I don't want anyone outside the group knowing of. We all know Java is absolutely horrible at doing any level of obfuscation, as most obfuscation tools only rename objects, scramble code, etc. I've used such tools, but to be honest I'd like to go as far as possible with the security of the program.
Since the application requires a username, password, and other identifiers to log in to the server it uses, I was beginning to wonder if a unique AES key could be generated for the user to secure the JAR.
Basically, upon running a launcher of sorts to log in, the launcher app may request an AES key from the server, and use it to decrypt a secured JAR it's downloaded from the server already. The key would be completely unique to each user, which would mean the server would have to encrypt the JAR differently for each user.
Now, I know how crazy this sounds. But since this is such a low-level thing, I need to know if there is a way you can somehow both decrypt and run a JAR from any type of stream. Or, if that isn't possible, would it be reasonable to decrypt the file, run it, then re-encrypt it?
Of course you can decrypt and run Java bytecode on the fly - bytecode manipulation libraries such as ASM even go as far as creating new classes dynamically.
But, quite honestly, if something actually runs on a computer then its code is definitely going to be available to anyone with the knowledge. Java, especially, is even more convenient since it allows far better access to the bytecode of a class that is loaded by the JVM than any natively compiled language.
You could theoretically take your obfuscation a bit further by using JNA/JNI and a native shared library or two. But, in the hands of a determined attacker no measure will protect your code completely - it would just take more time for them to figure out how your algorithms work. And if you are concerned about piracy, well, we are in the era of virtualization; you can actually clone whole computer systems from top to bottom with a couple of key presses - you figure out the rest...
The only potentially viable solution would be to offer your software as a service, with all the issues entailed by that approach - and you would still not have absolute security.
If you are that concerned about protecting your intellectual property, then get a lawyer and consider publishing your algorithms in some form - obscurity will only go so far. It will not stop someone from doing black-box analysis on your system and quite often just knowing that something is possible is enough.
Please stop trying to find technical solutions to a problem that is so obviously not of a technical nature...
My answer would be to keep the server information outside of the jar entirely. Use a parameter or configuration file to point to where to get that information. Then the jar file has no secrets in it. Only the server where the code runs has that information. You can then do things like make the configuration file readable only by the user that can run the code in the jar.
How can I retrieve the bytecode and make a hash to see if someone has manipulated my bytecode in-memory or on file?
EDIT:
Does signing the binaries protect the code from being modified and executed? As much as I want to protect my users from making sure they are running my software. I would also like to protect the program (server) from being used by a hacked client.
How do I detect from the server side if someone tampered with my client?
So you are trying to prevent some process with the same (or higher) privilege level than your application from manipulating your application?
That's a task that's doomed to fail. Because if you add your security checks, what would prevent the attacker from modifying your isSecure() method by replacing it with a simple return true;?
I think you need to clarify your requirements (at least I'm having trouble understanding what you are looking for).
In security-related areas, you always need to answer two questions, befor you can even start to tackle a problem:
What am I trying to protect?
What capabilities does an attacker have?
In your case, I believe you are trying to protect a Java client's class files from being modified. In that case the answer depends on what the (potential) attacker can do.
If the attacker actually has admin privileges on the machine the client is running on, then there is essentially nothing you can do. As saua above points out, if you cannot trust the the system you're running on, you're doomed.
If the attacker can only modify the class files before they reach the client maching, then signing your JAR files will let your clients detect the manipulation.
Maybe you want to sign your jar files instead?
What you want should be possible via Intrumentation, by adding custom Transformer. See http://java.sun.com/j2se/1.5.0/docs/api/java/lang/instrument/package-summary.html
Custom classloader also does the job, as it gets bytecode when class is defined.
How do i server side detect if someone tampered with my client?
You can not. On the internet nobody knows if you're a dog ;-)
Seriously: the only option server-side for making any assumptions about the client, is in the information sent back over the network. By encrypting the protocol and making it sufficiently hard to reverse-engineer, you can make it hard for an intruder to hack the client, but not impossible.
NGSCB (formerly known as Palladium) is designed to make this more secure, but this has its own set of issues.
You can create your own classloader and do the checking manually, or you can sign your code and let the java runtime do the job for you.
Signing the jars will protect the code from being modified. Signing involves creating a signature based on your private key. The public key is embedded in the jar with these signatures. Java will validate the signatures against your public key and refuse to load modified classes.
A hacked client will be a little harder to prevent. First an attacked would have to reverse engineer your protocol. You could take a step toward preventing this with a java obfuscator, but ultimately the attacker could just watch the wire and reverse engineer the protocol from the traffic. Even if you encrypt the client-server comms (this isn't exactly easy, considering using a protocol that already does it for you ... SSH or HTTPS) you will ultimately still be suceptible to a man-in-the-middle attack.
What exactly are you trying to protect against?
On the client, you can call getResourceAsStream with the path name to the class file in your jar.
That answers one part of your question ("How can i retrieve the bytecode"). Other answers cover the larger issues well.