Comment verrouiller les classes Java compilées pour éviter la décompilation?
Je sais que ce sujet doit être très bien discuté sur Internet, mais je n'ai pu tirer aucune conclusion après les avoir référés.
Beaucoup de gens suggèrent l'obfuscateur, mais ils ne font que renommer les classes, les méthodes et les champs avec des séquences de caractères difficiles à retenir, mais qu'en est-il des valeurs constantes sensibles?
Par exemple, vous avez développé le composant de chiffrement et de déchiffrement basé sur une technique de chiffrement basée sur un mot de passe. Maintenant, dans ce cas, toute personne moyenne de Java peut utiliser JAD pour décompiler le fichier de classe et récupérer facilement la valeur du mot de passe (définie comme constante) ainsi que le sel et à son tour peut décrypter les données en écrivant un petit programme indépendant!
Ou ces composants sensibles devraient-ils être construits en code natif (par exemple, VC ++) et les appeler via JNI ?
la source
Réponses:
Certains des obfuscateurs de bytecode Java les plus avancés font bien plus que simplement modifier les noms de classes. Zelix KlassMaster , par exemple, peut également brouiller votre flux de code d'une manière qui le rend vraiment difficile à suivre et fonctionne comme un excellent optimiseur de code ...
De plus, de nombreux obfuscateurs sont également capables de brouiller vos constantes de chaîne et de supprimer le code inutilisé.
Une autre solution possible ( qui n'exclut pas nécessairement l'obfuscation) consiste à utiliser des fichiers JAR chiffrés et un chargeur de classe personnalisé qui effectue le déchiffrement (de préférence en utilisant la bibliothèque d'exécution native).
Troisièmement (et offrant peut-être la protection la plus forte) consiste à utiliser des compilateurs natifs à l'avance comme GCC ou Excelsior JET , par exemple, qui compilent votre code Java directement dans un binaire natif spécifique à la plate-forme.
Dans tous les cas, vous devez vous rappeler que, comme le dit le dicton estonien, "les écluses sont pour les animaux". Ce qui signifie que chaque bit de code est disponible (chargé en mémoire) pendant l'exécution et avec suffisamment de compétences, de détermination et de motivation, les gens peuvent décompiler, déchiffrer et pirater votre code ... Votre travail consiste simplement à rendre le processus aussi inconfortable que vous pouvez et continuez à faire fonctionner la chose ...
la source
Tant qu'ils ont accès aux données cryptées et au logiciel qui les déchiffre, il n'y a pratiquement aucun moyen de le rendre complètement sécurisé. La façon dont cela a été résolu auparavant est d'utiliser une forme de boîte noire externe pour gérer le cryptage / décryptage, comme les dongles, les serveurs d'authentification à distance, etc. Mais même dans ce cas, étant donné que l'utilisateur a un accès complet à son propre système, cela ne fait que faire les choses difficile, pas impossible - à moins que vous ne puissiez lier directement votre produit à la fonctionnalité stockée dans la «boîte noire», comme, par exemple, les serveurs de jeux en ligne.
la source
Avertissement: je ne suis pas un expert en sécurité.
Cela semble être une mauvaise idée: vous laissez quelqu'un crypter des choses avec une clé «cachée» que vous lui donnez. Je ne pense pas que cela puisse être sécurisé.
Peut-être que les touches asymétriques pourraient fonctionner:
Je ne suis pas sûr, mais je pense que le client peut réellement crypter la clé de licence avec la clé publique que vous lui avez donnée. Vous pouvez ensuite le déchiffrer avec votre clé privée et le rechiffrer également.
Vous pouvez conserver une paire de clés publique / privée distincte par client pour vous assurer que vous recevez réellement des informations du bon client - maintenant vous êtes responsable des clés ...
la source
Peu importe ce que vous faites, il peut être «décompilé». Heck, vous pouvez simplement le démonter. Ou regardez une image mémoire pour trouver vos constantes. Vous voyez, l'ordinateur a besoin de les connaître, donc votre code en aura besoin aussi.
Que faire à ce sujet?
Essayez de ne pas envoyer la clé en tant que constante codée en dur dans votre code: conservez-la en tant que paramètre par utilisateur. Rendre l'utilisateur responsable de la gestion de cette clé.
la source
@jatanp: ou mieux encore, ils peuvent décompiler, supprimer le code de licence et recompiler. Avec Java, je ne pense pas vraiment qu'il existe une solution appropriée et infaillible à ce problème. Même un petit dongle maléfique ne pourrait empêcher cela avec Java.
Mes propres directeurs commerciaux s'inquiètent de cela, et je pense trop. Mais là encore, nous vendons notre application à de grandes entreprises qui ont tendance à respecter les conditions de licence - généralement un environnement sûr grâce aux compteurs de haricots et aux avocats. Le fait de se décompiler peut être illégal si votre licence est écrite correctement.
Alors, je dois vous demander, avez-vous vraiment besoin d'une protection renforcée comme vous le souhaitez pour votre application? À quoi ressemble votre clientèle? (Entreprises? Ou les masses de joueurs adolescents, où ce serait plus un problème?)
la source
Si vous recherchez une solution de licence, vous pouvez consulter l' API TrueLicense . Il est basé sur l'utilisation de touches asymétriques. Cependant, cela ne signifie pas que votre application ne peut pas être fissurée. Chaque application peut être craquée avec suffisamment d'efforts. Ce qui est vraiment important, comme l'a répondu Stu , est de déterminer la protection dont vous avez besoin.
la source
Je ne pense pas qu'il existe une méthode antipiratage hors ligne efficace. L'industrie du jeu vidéo a essayé de le constater à plusieurs reprises et ses programmes ont toujours été piratés. La seule solution est que le programme doit être exécuté en ligne connecté à vos serveurs, afin que vous puissiez vérifier la clé de lincense, et qu'il n'y ait qu'une seule connexion active par le titulaire de licence à la fois. C'est ainsi que fonctionne World of Warcraft ou Diablo . Même les plus difficiles, il existe des serveurs privés développés pour contourner la sécurité.
Cela dit, je ne pense pas que les moyennes / grandes entreprises utilisent des logiciels copiés illégaux, car le coût de la licence est minime (peut-être, je ne sais pas combien vous allez facturer votre programme) par rapport à le coût d'une version d'essai.
la source
Vous pouvez utiliser le cryptage byte-code sans crainte.
Le fait est que l'article cité ci-dessus «Cracking Java byte-code encryption» contient une erreur de logique. La principale revendication du papier est qu'avant l'exécution, toutes les classes doivent être déchiffrées et passées à la
ClassLoader.defineClass(...)
méthode . Mais ce n'est pas vrai.L'hypothèse manquée ici est à condition qu'ils s'exécutent dans un environnement d'exécution Java authentique ou standard . Rien ne peut obliger l'application Java protégée non seulement à lancer ces classes, mais même à les déchiffrer et à les transmettre
ClassLoader
. En d'autres termes, si vous êtes dans le JRE standard, vous ne pouvez pas intercepter ladefineClass(...)
méthode car le java standard n'a pas d'API à cet effet, et si vous utilisez un JRE modifié avec patchéClassLoader
ou tout autre «truc de hacker», vous ne pouvez pas le faire car protégé java ne fonctionnera pas du tout et vous n'aurez donc rien à intercepter. Et ce n'est absolument pas grave quel «outil de recherche de patch» est utilisé ou quelle astuce est utilisée par les pirates. Ces détails techniques sont une tout autre histoire.la source
Q: Si je crypte mes fichiers .class et que j'utilise un chargeur de classe personnalisé pour les charger et les décrypter à la volée, cela empêchera-t-il la décompilation?
R: Le problème de la prévention de la décompilation du code d'octet Java est presque aussi ancien que le langage lui-même. Malgré une gamme d'outils d'obscurcissement disponibles sur le marché, les programmeurs Java novices continuent de penser à des moyens nouveaux et intelligents de protéger leur propriété intellectuelle. Dans cet épisode de questions-réponses Java, je dissipe certains mythes autour d'une idée fréquemment reformulée dans les forums de discussion.
L'extrême facilité avec laquelle les fichiers Java .class peuvent être reconstruits en sources Java qui ressemblent étroitement aux originaux a beaucoup à voir avec les objectifs et les compromis de conception de code octet Java. Entre autres choses, le code d'octet Java a été conçu pour la compacité, l'indépendance de la plate-forme, la mobilité du réseau et la facilité d'analyse par des interpréteurs de code d'octet et des compilateurs dynamiques JIT (juste à temps) / HotSpot. On peut soutenir que les fichiers .class compilés expriment si clairement l'intention du programmeur qu'ils pourraient être plus faciles à analyser que le code source d'origine.
Plusieurs choses peuvent être faites, sinon pour empêcher complètement la décompilation, du moins pour la rendre plus difficile. Par exemple, comme étape de post-compilation, vous pouvez masser les données .class pour rendre le code d'octet plus difficile à lire lorsqu'il est décompilé ou plus difficile à décompiler en code Java valide (ou les deux). Des techniques telles que la surcharge extrême des noms de méthode fonctionnent bien pour la première, et la manipulation du flux de contrôle pour créer des structures de contrôle qu'il n'est pas possible de représenter via la syntaxe Java fonctionnent bien pour la seconde. Les obfuscateurs commerciaux les plus réussis utilisent un mélange de ces techniques et d'autres.
Malheureusement, les deux approches doivent en fait changer le code que la JVM exécutera, et de nombreux utilisateurs craignent (à juste titre) que cette transformation puisse ajouter de nouveaux bogues à leurs applications. En outre, le changement de nom de méthode et de champ peut entraîner l'arrêt des appels de réflexion. La modification des noms de classe et de package réels peut casser plusieurs autres API Java (JNDI (Java Naming and Directory Interface), fournisseurs d'URL, etc.). Outre les noms modifiés, si l'association entre les décalages de code d'octet de classe et les numéros de ligne source est modifiée, la récupération des traces de pile d'exceptions d'origine peut devenir difficile.
Ensuite, il y a la possibilité de masquer le code source Java d'origine. Mais fondamentalement, cela pose un ensemble similaire de problèmes. Crypter, pas obscurcir?
Peut-être que ce qui précède vous a fait penser: "Eh bien, et si au lieu de manipuler du code d'octet je crypte toutes mes classes après compilation et les décrypte à la volée dans la JVM (ce qui peut être fait avec un chargeur de classe personnalisé)? Ensuite, la JVM exécute mon le code d'octet original et pourtant il n'y a rien à décompiler ou à désosser, non? "
Malheureusement, vous vous trompez, à la fois en pensant que vous avez été le premier à avoir cette idée et en pensant que cela fonctionne réellement. Et la raison n'a rien à voir avec la force de votre schéma de cryptage.
la source