J'ai besoin de stocker des informations sensibles (une clé de chiffrement symétrique que je souhaite garder privée) dans mon application C ++. L'approche simple est de faire ceci:
std::string myKey = "mysupersupersecretpasswordthatyouwillneverguess";
Cependant, l'exécution de l'application à travers le strings
processus (ou tout autre qui extrait des chaînes d'une application binaire) révélera la chaîne ci-dessus.
Quelles techniques devraient être utilisées pour masquer ces données sensibles?
Éditer:
OK, à peu près vous avez tous dit "votre exécutable peut être rétro-ingénierie" - bien sûr! Ceci est une bête noire de la mienne, alors je vais déclamer un peu ici:
Pourquoi est-ce que 99% (OK, alors peut-être que j'exagère un peu) de toutes les questions liées à la sécurité sur ce site reçoivent une réponse avec un torrent de "il n'y a aucun moyen possible de créer un programme parfaitement sécurisé" - ce n'est pas utile répondre! La sécurité est une échelle mobile entre une utilisabilité parfaite et aucune sécurité à une extrémité, et une sécurité parfaite mais aucune convivialité à l'autre.
Le fait est que vous choisissez votre position sur cette échelle mobile en fonction de ce que vous essayez de faire et de l'environnement dans lequel votre logiciel fonctionnera. Je n'écris pas d'application pour une installation militaire, j'écris une application pour un PC domestique . J'ai besoin de crypter des données sur un réseau non approuvé avec une clé de cryptage pré-connue. Dans ces cas, la "sécurité par l'obscurité" est probablement suffisante! Bien sûr, quelqu'un avec suffisamment de temps, d'énergie et de compétences pourrait effectuer une rétro-ingénierie du binaire et trouver le mot de passe, mais devinez quoi? Je m'en fous:
Le temps qu'il me faut pour implémenter un système sécurisé de premier ordre coûte plus cher que la perte de ventes due aux versions fissurées (non pas que je vends réellement cela, mais vous comprenez mon point). Cette tendance du ciel bleu «faisons-le de la meilleure façon possible» dans la programmation chez les nouveaux programmeurs est pour le moins insensée.
Merci d'avoir pris le temps de répondre à cette question - ils ont été très utiles. Malheureusement, je ne peux accepter qu'une seule réponse, mais j'ai voté toutes les réponses utiles.
Réponses:
Fondamentalement, toute personne ayant accès à votre programme et un débogueur peut et va trouver la clé dans l'application si elles le souhaitent.
Mais, si vous voulez simplement vous assurer que la clé ne s'affiche pas lors de l'exécution
strings
sur votre binaire, vous pouvez par exemple vous assurer que la clé n'est pas dans la plage imprimable.Clé obscurcissante avec XOR
Par exemple, vous pouvez utiliser XOR pour diviser la clé en deux tableaux d'octets:
Si vous créez key1 avec la même longueur d'octet que
key
vous pouvez utiliser des valeurs d'octets (complètement) aléatoires, puis calculerkey2
:Vous pouvez le faire dans votre environnement de génération, puis uniquement stocker
key1
etkey2
dans votre application.Protéger votre binaire
Une autre approche consiste à utiliser un outil pour protéger votre binaire. Par exemple, il existe plusieurs outils de sécurité qui peuvent s'assurer que votre binaire est obscurci et démarre une machine virtuelle sur laquelle il s'exécute. Cela rend le débogage (euh) difficile, et c'est aussi la façon conventionnelle de protéger de nombreuses applications sécurisées de qualité commerciale (aussi, hélas, les logiciels malveillants).
L'un des principaux outils est Themida , qui fait un excellent travail de protection de vos binaires. Il est souvent utilisé par des programmes bien connus, tels que Spotify, pour se protéger contre l'ingénierie inverse. Il a des fonctionnalités pour empêcher le débogage dans des programmes tels que OllyDbg et Ida Pro.
Il existe également une liste plus longue, peut-être un peu obsolète, d' outils pour protéger votre binaire .
Certains d'entre eux sont gratuits.
Correspondance de mot de passe
Quelqu'un ici a discuté du mot de passe de hachage + sel.
Si vous avez besoin de stocker la clé pour la comparer à un type de mot de passe soumis par l'utilisateur, vous devez utiliser une fonction de hachage unidirectionnelle, de préférence en combinant un nom d'utilisateur, un mot de passe et un sel. Le problème avec cela, cependant, est que votre application doit connaître le sel pour pouvoir faire le sens unique et comparer les hachages résultants. Vous devez donc toujours stocker le sel quelque part dans votre application. Mais, comme le souligne @Edward dans les commentaires ci-dessous, cela protégera efficacement contre une attaque par dictionnaire utilisant, par exemple, des tables arc-en-ciel.
Enfin, vous pouvez utiliser une combinaison de toutes les techniques ci-dessus.
la source
Tout d'abord, sachez que vous ne pouvez rien faire pour arrêter un hacker suffisamment déterminé, et il y en a beaucoup autour. La protection de chaque jeu et console autour est finalement fissurée, donc ce n'est qu'une solution temporaire.
Il y a 4 choses que vous pouvez faire pour augmenter vos chances de rester caché pendant un certain temps.
1) Cachez les éléments de la chaîne d'une manière ou d'une autre - quelque chose d'évident comme xoring (l'opérateur ^) la chaîne avec une autre chaîne sera suffisamment bonne pour rendre la chaîne impossible à rechercher.
2) Divisez la chaîne en morceaux - divisez votre chaîne et mettez-en des morceaux en méthodes étrangement nommées dans des modules étranges. Ne facilitez pas la recherche et la recherche de la méthode contenant la chaîne. Bien sûr, une méthode devra appeler tous ces bits, mais cela rend les choses un peu plus difficiles.
3) Ne construisez jamais la chaîne en mémoire - la plupart des pirates utilisent des outils qui leur permettent de voir la chaîne en mémoire après l'avoir encodée. Si possible, évitez cela. Si, par exemple, vous envoyez la clé à un serveur, envoyez-la caractère par caractère, de sorte que toute la chaîne ne soit jamais présente. Bien sûr, si vous l'utilisez à partir de quelque chose comme l'encodage RSA, alors c'est plus compliqué.
4) Faites un algorithme ad hoc - en plus de tout cela, ajoutez une touche unique ou deux. Ajoutez peut-être simplement 1 à tout ce que vous produisez, ou effectuez un chiffrement deux fois ou ajoutez un sucre. Cela rend juste un peu plus difficile pour le pirate informatique qui sait déjà quoi rechercher quand quelqu'un utilise, par exemple, le hachage vanilla md5 ou le cryptage RSA.
Surtout, assurez-vous que ce n'est pas trop important quand (et ce le sera quand si votre application devient suffisamment populaire) votre clé est découverte!
la source
Une stratégie que j'ai utilisée dans le passé consiste à créer un tableau de personnages apparemment aléatoires. Vous insérez initialement, puis localisez vos caractères particuliers avec un processus algébrique où chaque étape de 0 à N produira un nombre <taille du tableau qui contient le caractère suivant dans votre chaîne obscurcie. (Cette réponse se sent maintenant obscurcie!)
Exemple:
Étant donné un tableau de caractères (les nombres et les tirets sont pour référence seulement)
Et une équation dont les six premiers résultats sont: 3, 6, 7, 10, 21, 47
Céderait le mot "HELLO!" du tableau ci-dessus.
la source
Je suis d'accord avec @Checkers, votre exécutable peut être rétro-conçu.
Un peu mieux est de le créer dynamiquement, par exemple:
la source
Bien entendu, stocker des données privées dans un logiciel livré à l'utilisateur est toujours un risque. Tout ingénieur suffisamment formé (et dédié) pourrait procéder à une rétro-ingénierie des données.
Cela étant dit, vous pouvez souvent sécuriser suffisamment les choses en élevant la barrière que les gens doivent surmonter pour révéler vos données privées. C'est généralement un bon compromis.
Dans votre cas, vous pouvez encombrer vos chaînes de données non imprimables, puis les décoder au moment de l'exécution à l'aide d'une simple fonction d'aide, comme ceci:
la source
J'ai créé un outil de cryptage simple pour les chaînes, il peut générer automatiquement des chaînes cryptées et dispose de quelques options supplémentaires pour le faire, quelques exemples:
Chaîne comme variable globale:
En tant que chaîne unicode avec boucle de décryptage:
Chaîne comme variable globale:
la source
Un peu dépendant de ce que vous essayez de protéger, comme le souligne Joshperry. Par expérience, je dirais que si cela fait partie d'un système de licence pour protéger votre logiciel, ne vous inquiétez pas. Ils procéderont éventuellement à une rétro-ingénierie. Utilisez simplement un chiffrement simple comme ROT-13 pour le protéger des attaques simples (ligne exécutant des chaînes dessus). Si c'est pour sécuriser les données sensibles des utilisateurs, je me demanderais si la protection de ces données avec une clé privée stockée localement est une sage décision. Encore une fois, cela revient à ce que vous essayez de protéger.
EDIT: Si vous allez le faire, une combinaison de techniques que Chris souligne sera bien meilleure que rot13.
la source
Comme cela a été dit précédemment, il n'y a aucun moyen de protéger totalement votre corde. Mais il existe des moyens de le protéger avec une sécurité raisonnable.
Quand j'ai dû faire cela, j'ai mis une chaîne d'apparence innocente dans le code (un avis de droit d'auteur, par exemple, ou une fausse invite utilisateur ou tout autre élément qui ne sera pas modifié par quelqu'un corrigeant un code non lié), crypté cela en utilisant lui-même comme clé, haché cela (en ajoutant du sel) et utilisé le résultat comme clé pour chiffrer ce que je voulais réellement chiffrer.
Bien sûr, cela pourrait être piraté, mais il faut un hacker déterminé pour le faire.
la source
Si vous êtes sur DPAPI utilisateur Windows, http://msdn.microsoft.com/en-us/library/ms995355.aspx
Comme indiqué dans un article précédent, si vous êtes sur Mac, utilisez le trousseau.
Fondamentalement, toutes ces idées mignonnes sur la façon de stocker votre clé privée dans votre binaire sont suffisamment pauvres du point de vue de la sécurité pour que vous ne devriez pas les faire. Quiconque obtient votre clé privée est un gros problème, ne la gardez pas dans votre programme. Selon la façon dont vous importez votre application, vous pouvez conserver vos clés privées sur une carte à puce, sur un ordinateur distant avec lequel votre code communique ou vous pouvez faire ce que font la plupart des gens et la conserver dans un endroit très sécurisé sur l'ordinateur local (la clé " store "qui est un peu comme un registre sécurisé étrange) qui est protégé par des autorisations et toute la force de votre système d'exploitation.
C'est un problème résolu et la réponse n'est PAS de garder la clé à l'intérieur de votre programme :)
la source
Essayez ceci . Le code source explique comment chiffrer et déchiffrer à la volée toutes les chaînes d'un projet Visual Studio c ++ donné.
la source
Une méthode que j'ai récemment essayée est:
part1
part2
part1
etpart2
part1
. Il vérifiera l'intégrité des données privées.MACRO pour remplir les données:
Supposons que les données privées soient de 4 octets. Nous définissons une macro pour cela qui enregistre les données avec des instructions d'affectation dans un ordre aléatoire.
Maintenant, utilisez cette macro dans le code où vous devez enregistrer
part1
etpart2
, comme suit:la source
Au lieu de stocker la clé privée dans votre exécutable, vous souhaiterez peut-être la demander à l'utilisateur et la stocker au moyen d'un gestionnaire de mots de passe externe , quelque chose de similaire à Mac OS X Keychain Access.
la source
Dépend du contexte, mais vous pouvez simplement stocker le hachage de la clé plus un sel (chaîne constante, facile à obscurcir).
Ensuite, lorsque (si) l'utilisateur entre la clé, vous ajoutez le sel , calculez le hachage et comparez.
Le sel est probablement inutile dans ce cas, il arrête une attaque de dictionnaire par force brute si le hachage peut être isolé (une recherche Google a également été connue pour fonctionner).
Un hacker n'a encore qu'à insérer une instruction jmp quelque part pour contourner le tout, mais c'est un peu plus compliqué qu'une simple recherche de texte.
la source
Il existe un obfuscate de projet (très léger) en-tête uniquement créé par adamyaxley qui fonctionne parfaitement. Il est basé sur des fonctions lambda et des macros et crypte les chaînes littéralement avec un chiffrement XOR au moment de la compilation. Si nécessaire, nous pouvons changer la graine de chaque chaîne.
Le code suivant ne stockera pas la chaîne "hello world" dans le binaire compilé.
J'ai testé avec c ++ 17 et Visual Studio 2019, et vérifie via IDA et je confirme que la chaîne est masquée. Un avantage précieux par rapport à ADVobfuscator est qu'il est convertible en std :: string (tout en étant toujours caché dans le binaire compilé):
la source