Comment verrouiller les classes Java compilées pour empêcher la décompilation?

Comment verrouiller les classes Java compilées pour empêcher la décompilation?

Je sais que ce sujet doit être très bien discuté sur Internet, mais je ne suis parvenu à aucune conclusion après les avoir référés.

Beaucoup de gens suggèrent un obfuscator, mais ils ne font que renommer les classes, les méthodes et les champs avec des séquences de caractères difficiles à mémoriser, 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 Java moyenne peut utiliser JAD pour décomstackr le fichier de classe et récupérer facilement la valeur du mot de passe (définie comme constante) ainsi que pour décrypter les données en écrivant un petit programme indépendant!

Ou bien ces composants sensibles devraient-ils être construits en code natif (par exemple, VC ++) et les appeler via JNI ?

Tant qu’ils ont access aux données chiffrées et aux logiciels qui les déchiffrent, vous ne pouvez en aucun cas les sécuriser complètement. Cela a déjà été résolu: 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, difficile, pas impossible – sauf si vous pouvez lier votre produit directement aux fonctionnalités stockées dans la “boîte noire”, comme, par exemple, les serveurs de jeux en ligne.

Disclaimer: 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 clés asymésortingques pourraient fonctionner:

  • déployer une licence chiffrée avec une clé publique pour déchiffrer
  • laisser le client créer une nouvelle licence et vous l’envoyer pour chiffrement
  • renvoyer une nouvelle licence au client.

Je ne suis pas sûr, mais je pense que le client peut chiffrer 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 obtenez réellement des informations auprès du bon client – vous êtes maintenant responsable des clés …

Peu importe ce que vous faites, il peut être «décompilé». Heck, vous pouvez juste 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 aussi besoin.

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. Rendez l’utilisateur responsable de la recherche de cette clé.

Jetez un coup d’œil à l’article de JavaWorld Cracking Java byte-code encryption par Vladimir Roubtsov. Cela explique pourquoi le cryptage des fichiers de classe est essentiellement inutile.

@jatanp: ou mieux encore, ils peuvent décomstackr, supprimer le code de licence et recomstackr. Avec Java, je ne pense pas vraiment qu’il existe une solution adéquate, à l’épreuve du piratage, à ce problème. Même un petit dongle maléfique ne pourrait pas empêcher cela avec Java.

Mes propres responsables commerciaux s’inquiètent de cela et je pense trop. Mais là encore, nous vendons notre application à de grandes entresockets qui ont tendance à respecter les conditions de licence – généralement un environnement sûr grâce aux compteurs de fèves et aux avocats. Le fait de se décomstackr peut être illégal si votre licence est écrite correctement.

Donc, je dois demander, avez-vous vraiment besoin d’une protection renforcée comme vous le souhaitez pour votre application? À quoi ressemble votre clientèle? (Corporates? Ou les masses de joueurs adolescents, où ce serait plus d’un problème?)

Je ne pense pas qu’il existe une méthode antipiratage hors ligne efficace. L’indussortinge du jeu vidéo a essayé de trouver cela plusieurs fois et ses programmes ont toujours été piratés. La seule solution est que le programme doit être exécuté en ligne et connecté à vos serveurs, afin que vous puissiez vérifier la clé de l’incidence, et qu’il n’y ait qu’une seule connexion active par le preneur de licence à la fois. C’est comme ça que fonctionne World of Warcraft ou Diablo . Même difficile, des serveurs privés ont été développés pour contourner la sécurité.

Cela étant dit, je ne crois pas que les grandes et moyennes entresockets utilisent des logiciels copiés illégaux, car le coût de la licence pour eux est minime (peut-être que je ne sais pas combien vous devez payer pour votre programme) par rapport à le coût d’une version d’essai.

Si vous recherchez une solution de licence, vous pouvez consulter l’ API TrueLicense . C’est basé sur l’utilisation de clés asymésortingques. Cependant, cela ne signifie pas que votre application ne peut pas être craquée. Chaque application peut être fissurée avec suffisamment d’effort. Comme l’a répondu Stu , ce qui est vraiment important, c’est de déterminer la protection dont vous avez besoin.

Vous pouvez utiliser le cryptage de code octet sans crainte.

Le fait est que l’article cité ci-dessus «Cracking Java Byte-Code Encryption» contient une erreur logique. La principale revendication de l’article est que, avant de ClassLoader.defineClass(...) l’exécution, toutes les classes doivent être déchiffrées et transmises à la ClassLoader.defineClass(...) . Mais ce n’est pas vrai.

L’hypothèse manquée ici est 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 JRE standard, vous ne pouvez pas intercepter la defineClass(...) car le java standard n’a pas d’API à cette fin, et si vous utilisez JRE modifié avec ClassLoader patché ou tout autre “hacker sortingck” ne peut pas le faire parce que l’application Java protégée ne fonctionnera pas du tout, et donc vous n’aurez rien à intercepter. Et quel que soit l’outil de recherche de patch utilisé ou le truc utilisé par les pirates. Ces détails techniques sont une toute autre histoire.

Q: Si je crypte mes fichiers .class et utilise un chargeur de classe personnalisé pour les charger et les déchiffrer à 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 octet Java est presque aussi ancien que le langage lui-même. Malgré une gamme d’outils de brouillage disponibles sur le marché, les programmeurs novices de Java continuent de réfléchir à de nouveaux moyens astucieux de protéger leur propriété intellectuelle. Dans cette édition de Java Q & A, je dissipe certains mythes autour d’une idée fréquemment reprise dans les forums de discussion.

L’extrême facilité avec laquelle les fichiers Java .class peuvent être reconstruits dans des sources Java qui ressemblent beaucoup aux originaux a beaucoup à voir avec les objectives et les compromis de la conception des codes d’octets Java. Entre autres choses, le code d’octet Java a été conçu pour assurer la compacité, l’indépendance de la plate-forme, la mobilité du réseau et la facilité d’parsing par des interprètes de code octet et des compilateurs dynamics JIT (juste à temps) / HotSpot. Les fichiers .class compilés expriment sans doute l’intention du programmeur si clairement qu’ils pourraient être plus faciles à parsingr que le code source d’origine.

Plusieurs choses peuvent être faites, sinon pour éviter la décompilation complète, du moins pour la rendre plus difficile. Par exemple, en post-compilation, vous pouvez masser les données .class pour rendre le code octet plus difficile à lire lorsqu’il est décompilé ou plus difficile à décomstackr en code Java valide (ou les deux). Des techniques comme l’exécution d’une surcharge de nom de méthode extrême fonctionnent bien pour le premier, et la manipulation du stream de contrôle pour créer des structures de contrôle impossibles à représenter via la syntaxe Java fonctionne bien pour le second. Les obfuscateurs commerciaux les plus réussis utilisent un mélange de ces techniques et d’autres.

Malheureusement, les deux approches doivent réellement changer le code que la JVM exécutera et de nombreux utilisateurs craignent (à juste titre) que cette transformation ajoute de nouveaux bogues à leurs applications. En outre, le changement de méthode et de champ peut entraîner l’arrêt des appels de reflection. 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.). En plus des 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 la stack d’exception d’origine peut devenir difficile.

Ensuite, il y a la possibilité de masquer le code source Java d’origine. Mais fondamentalement, cela provoque un ensemble de problèmes similaires. Crypter, pas obscurcir?

Peut-être que ce qui précède vous a fait penser: “Et bien, au lieu de manipuler le code d’octet, je crypte toutes mes classes après la compilation et les décrypte à la volée (ce qui peut être fait avec un chargeur de classe personnalisé)? code d’octet original et pourtant il n’ya rien à décomstackr ou à désosser, non?

Malheureusement, vous auriez tort, à la fois en pensant que vous avez été les premiers à trouver 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.