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.
Related
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.
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.
I have developed a system using Digital Signatures
The program is written in Java
Provider = "BC"
SIGNATURE_ALGORITHM = "SHA256withRSA"
Keys
The Client holds the public key
The Server holds the private key
License Generation
Clients request a license from the server
Server decides if they should get a licenses
Creates a signed object and sends it back to the client
I am wondering about easy ways to hack a system like this and what I can do to prevent it.
How can I prevent a user from decompiling my code and inserting their own code? (I am aware of proguard but hear that it can be worked around). I am also a little worried about a user creating a false licensing server and somehow modifying the source code to point to their server (because I will be releasing the licensing and server code to the public).
When dealing with cryptography and security - if it's of any real importance to you - never use anything home-made.
Always use a proper library.
The margin for bugs and mistakes in this field are huge. Your applications security deserves better.
How can I prevent a user from decompiling my code and inserting their own code?
The short answer is that you can't. You can make it harder (e.g. obfuscation) but you simply cannot prevent it. The fact that most computer games are cracked within days of release is evidence of this.
Turning to the rest of your question: the design looks fine. It's hard to prevent a fake licensing server, but maybe it's not going to be a likely attack anyway. The attacker could just remove the license check from the client instead.
As #Yuval points out, rolling your own crypto is a Bad Idea, but you seem to be doing it the right way by using BouncyCastle. Just make sure you always "sign what you mean", that is sign the license itself rather than, say, encrypting the license and signing the encrypted version.
BouncyCastle's lightweight API provides tools for signing arbitrary blobs of data; I'd recommend you use that rather than Java's cumbersome "provider" interface.
You should also take care to ensure the physical security of the private key. If that gets compromised then you're in real trouble. It may be worth thinking about a mechanism for revoking compromised licences and replacing them with new ones.
I'm not even sure if this is possible, but is it feasible to secure, end-to-end runtime data on an uncontrolled client?
Specifically, is there any functionality in Java to take in encrypted data, process it and send it back out encrypted, all without exposing the data in plaintext to a curious 3rd party that has full access to the client?
Also, I know that code obfuscation is merely an annoyance to a dedicated individual with a decompiler, so I'm assuming for this scenario that the attack party has full source/operating knowledge.
I'm interested in answers either way. If there is no existing functionality, would it be feasible given Java's architecture? If Java can't do it, is there another language/platform that could? I'm fearing this may require special hardware.
To have a chance at doing what you are talking about, you need special hardware. You can't have a secure layer "on top" of an insecure layer. For example, if the attacker has full control over the hardware, he can always compromise the OS running on that host.
The special hardware is called a "Trusted Platform Module," or TPM. This supports remote attestation, which would allow you to verify that a client has not been tampered with. Some parts of the TPM are available on many computers (my Dell laptop, for example). In fact, I think all computers purchased by the US federal government are required to have a TPM. However, most consumers do not enable the TPM, and there's a lot of hostility toward TPM from privacy advocates. I'm also unsure how many machines with a TPM include the remote attestation capability.
Anyway, the bottom line is that you can't give someone a secret, and the key to the secret, and expect it to remain a secret. You have to retain control over the whole stack, top-to-bottom. Trusted Treacherous Computing allows you do do that, even if you don't legally own the hardware in question.
It is fundamentally not possible to be completely secure if the client is not locked down. At some point the bytes will exist in memory, and that memory can be read by hostile applications.
If your goal isn't to make it completely secure but merely inconvenient for the casually curious, then just be sure to not write the data to temporary files or anywhere else that would be trivial to examine.
Not only "can't be done", but "easy to compromise".
Look at 'aspect-oriented programming' and byte-compiler classes. This is normally used for things like inserting database transactions, performance logging, logging statements (so you can drop the calls from the source code and make it a lot cleaner), access control (so you separate the implementation and authorization), etc. There are a lot of extremely useful things you can do if you can quietly wrap one class with another.
But that also means it's trivial to wrap your classes to capture all of the unencrypted messages within your application, encryption keys, etc. I think I can get in even if you do everything in a single long procedure, although it might take a little more effort.