Nouveaux Concepts: Utilisation du presse-papiers avec les messages Windows Nouvelles fonctions d'API: SendDlgItemMessage |
Dans ce tutoriel, nous allons créer un keygen simple et ajouter du code pour une procédure de génération de série exemple qui peut être substituée à un algorithme de génération de série extrait de n'importe quelle routine de protection. Nous ajouterons également du code pour copier la série générée dans le presse-papiers. Lancez WinAsm comme d'habitude, créez un nouveau projet exe standard et ajoutez un nouveau script de ressources. Dans l'onglet Ressources de la barre d'exploration du projet, cliquez sur Ajouter une nouvelle boîte de dialogue, puis sur Ressources pour ajouter notre icône (identique au dernier tutoriel). Ajoutez 2 contrôles d'édition pour entrer notre nom et afficher notre série, 2 contrôles statiques pour étiqueter les zones d'édition et 3 boutons comme indiqué : Modifiez le style de la boîte de dialogue pour inclure DS_CENTER, les 2 Labels statiques pour inclure SS_CENTERIMAGE et la zone d'édition de la série pour inclure ES_READONLY. Le script est inclus dans la section du code source sous le nom simplekeygen.rc. Passez maintenant à simplekeygen.asm dans la barre d'exploration du projet et collez le code de la section du codes sources. Voici le corps principal de l'application : Suivi de la procédure de dialogue : Et de la procédure de génération qui calcule le numéro de série : Maintenant, nous allons analyser le code ci-dessus. Variables Il y a 2 variables de chaîne non initialisées dans lesquelles est stocker l'entrée de l'utilisateur (nom) et la série calculée. La procédure de dialogue Nous avons des routines pour traiter l'entrée de l'utilisateur à partir de nos 3 boutons. En réponse au bouton Generate, nous obtenons simplement l'entrée de l'utilisateur à partir de la zone d'édition du nom et la stockons dans la variable de chaîne NameBuffer, appelons notre routine Generate et affichons le N° de série calculé dans la zone d'édition Serial. Le bouton Copy permet de copier ce qui est affiché dans la zone d'édition Serial dans le presse-papiers. Cela est réalisé entièrement en envoyant des messages Windows à la zone d'édition Serial. C'est beaucoup plus facile que d'écrire des instructions d'assemblage pour effectuer la même opération, car le code pour cela est plutôt désordonné. Notez que d'après Win32.hlp, le texte à copier doit d'abord être sélectionné : et le code pour sélectionner l'intégralité du contenu d'une zone d'édition est : Il est important de noter qu'il existe des messages Windows permettant d'accomplir un grand nombre de tâches dans Windows sans écrire de code volumineux pour effectuer la même tâche. Le bouton Exit fonctionne comme décrit précédemment. La procédure Generate et les Labels La fonction Generate est une routine d'exemple simple qui inverse l'ordre des lettres de la chaîne saisie dans la zone d'édition du nom. Notez que nous ne passons aucun paramètre à la fonction et elle ne renvoie pas de valeur en tant que telle. Il n'y a donc aucun avantage à écrire un prototype pour cela et à l'appeler avec invoke. La routine a été d'abord écrite sans les lignes
test eax,eax Cependant, cliquer sur Generate provoquerait un plantage si NameBuffer était vide (c'est-à-dire s'il n'y avait pas d'entrée utilisateur). La première instruction lstrlen calcule la longueur de la chaîne dans NameBuffer et place le résultat dans eax. Selon le fichier Win32.hlp : "La fonction lstrlen renvoie la longueur en octets (version ANSI) ou en caractères (version Unicode) de la chaîne spécifiée (sans inclure le caractère nul de fin)". L'instruction Test eax, eax définit le flag zéro si eax est zéro et jle est un saut conditionnel (jump si less ou equal) qui saute à l'étiquette NOINPUT et à l'instruction ret si le flag zéro est défini. En d'autres termes, la fonction Generate se termine simplement sans exécuter aucune de ses instructions internes au lieu de planter s'il n'y a pas d'entrée utilisateur. Les Labels sont des noms que vous pouvez attribuer pour marquer une partie du code afin de sauter à une instruction conditionnelle. Lorsqu'une étiquette est définie, elle est suivie d'un deux-points, mais lorsque l'étiquette apparaît dans l'instruction de saut, les deux-points sont omis. Si la longueur de la chaîne dans eax est supérieure à zéro, elle est copiée dans ecx grâce à l'instruction mov. ECX est couramment utilisé comme compteur pour spécifier combien de fois une instruction de boucle doit être exécutée, dans ce cas pour traiter chaque caractère de la chaîne, puis revenir. Ensuite, les adresses mémoire des variables NameBuffer et SerialBuffer sont copiées dans esi et edi. Ces deux registres sont utilisés pour indexer la source et la destination des manipulations de chaînes. @@: déclare une étiquette anonyme. Dans les longues routines utilisant de nombreux sauts ou boucles, il est fastidieux de taper différents noms pour toutes les Labels nécessaires. MASM peut donc utiliser des Labels anonymes pour les sauts courts ou boucles. Pour utiliser l'étiquette dans le code, @f saute en avant vers le prochain @@:, et @b saute en arrière vers le @@: le plus proche. Enfin, la routine de renversement de la chaîne fonctionne de la manière suivante : Tout d'abord, le compteur ecx est décrémenté de 1 afin que la boucle finale se termine sur un zéro plutôt que sur un 1. Par exemple, si la longueur de la chaîne Name est de 6 caractères, ecx va maintenant boucler de 5 à 0 et la routine sera exécutée 6 fois. Esi contient l'adresse du premier octet (caractère) de NameBuffer. Ainsi, lorsque ecx=0, esi+ecx pointe vers le premier caractère, et lorsque ecx=5, esi+ecx pointe vers le dernier caractère. La première instruction mov copie le dernier octet de NameBuffer dans le registre edx, le byte inférieur (appelé dl). La deuxième instruction mov copie ce byte dans le premier byte de SerialBuffer (stocké dans edi). Ensuite, la valeur de edi est incrémentée de 1 pour pointer vers le deuxième byte de SerialBuffer en prévision de la prochaine boucle de la routine. Enfin, une opération logique OR est effectuée sur ecx, ce qui définirait le flag zéro si ecx atteignait zéro. L'instruction ja (jump si au-dessus) saute si le flag zéro n'est PAS défini. En d'autres termes, la routine continue de boucler jusqu'à ce que ecx atteigne 0, puis elle passe à l'instruction ret et retourne à la procédure de dialogue. C'est une façon très simple d'écrire une fonction. Vous pouvez passer un certain nombre de paramètres à vos propres fonctions et faire en sorte que la fonction renvoie soit un résultat, soit un indicateur de succès/erreur dans eax, comme le font les fonctions API. Écrire un prototype pour la fonction permettra d'utiliser invoke. Nous aborderons cela dans le prochain tutoriel et personnaliserons notre Keygen avec des graphiques et un son.
|
Copyright (C)- xtx Team (2021)