Attaque des clones: technologies modernes de conduite de robots

"Maintenant, vous écrivez le programme le plus difficile de votre vie qui additionnera simplement deux chiffres"
Irina Ryzhova


Les jeux en ligne de jeu intelligents sont une friandise pour les bots. Même si les développeurs de logiciels de jeu dépensent beaucoup d'argent pour attraper des bots, comme dans les salles de poker en ligne, par exemple, il y a encore une forte probabilité de tomber sur un «bot intelligent», avec lequel le jeu sera en tête-à-tête. Surtout si le bot est absolument invulnérable ... Car aucun argent ne protégera le système par lequel beaucoup d'argent passe.


Fig. 1. Botovody come


Menace cachée


Les jeux en ligne de jeux de hasard intellectuels ne sont pas sûrs. Particulièrement dangereux sont ceux où l'argent réel tourne. Leur insécurité se manifeste principalement par le fait qu'il est impossible de savoir avec certitude avec qui vous jouez: avec une personne vivante, ou avec un bot. Dans le second cas, le match sera dans un seul but. Dans les jeux d '"intérêt", - les échecs et les dames sur mail.ru, par exemple, - les propriétaires de jeux en ligne regardent botovotirovanie avec leurs doigts. Dans les jeux en ligne multijoueurs, qui comportent dans une certaine mesure de l'argent en direct, un peu plus d'attention est accordée à la capture de robots. Cependant, même si l'approche pour supprimer le botswood est extrêmement sérieuse - comme cela a été fait par exemple dans les salles de poker en ligne - il y a toujours une forte probabilité de tomber dans un bot.

Les développeurs de logiciels de poker dépensent beaucoup d'argent pour exposer les bots, et néanmoins, le poker en ligne au Botswana est en plein essor. Car aucun argent ne peut protéger le système par lequel beaucoup d'argent passe. Botovodov et les attrapeurs de bots, - analysant les tours des adversaires et prenant les contre-mesures appropriées, - gagnent alternativement. Quelqu'un peut penser que la bataille entre eux ne finira jamais. Cependant, il existe un système de conduite de robots sécurisé devant lequel les capteurs de robots passent. Il est intéressant de noter que, même si les "combattants pour la justice" auront en main les codes source commentés du bot, ils ne pourront pas établir le fait de son utilisation. La mise en œuvre de ce régime est un événement coûteux, cependant, puisque l'avantage potentiel est grand, le régime est tout à fait pertinent.

#

– , . – , . ( , ), «-» ( , - ). , , , , -, . , . , , , - ( ); , .. - . - , . - (3, , , , ..). . . . – - -- ( , ). -, , , , , – . - – - , - ( . « »).




: , .Tout d'abord, le bot prend des photos de l'état actuel du jeu - soit par capture d'écran, soit en interceptant le trafic réseau. Deuxièmement, le bot décide quoi faire dans les circonstances, recourant parfois à un logiciel tiers (par exemple, dans le cas des échecs, il peut interagir avec une sorte de moteur d'échecs). Enfin, troisièmement, le bot émule l'interaction de l'utilisateur avec le clavier et la souris. De plus, ce cycle ternaire - que les attrapeurs de robots cherchent à suivre et à rompre - se répète. En conséquence, la bataille entre Botovodov et «combattants pour la justice» se déroule sur trois fronts. Cette bataille a une histoire longue et passionnante, cependant, nous nous concentrerons uniquement sur son duel final, dans lequel les «combattants pour la justice», face à un robot absolument invulnérable, ont subi un fiasco inconditionnel.

La technologie de bouteille invulnérable est obtenue grâce à la photographie invisible, l'analyse invisible et l'émulation invisible. Il est impossible de le faire sur un seul ordinateur. Tout d'abord, parce que les logiciels de poker modernes ont les éléments d'un rootkit.

#

. , , , , - : « , ». - « » « » . , , – .

, . , . , – , , -. – .

, , , : «» , . , – , – , «- ».

– . , « », « » . , – , – . , , – .

, , . , , . , , , , - , . – «».


, .. , .La solution consiste à lancer le bot non pas sur la station de travail à partir de laquelle le jeu est joué, mais sur un ordinateur distinct - un émulateur. Ensuite, sous réserve de trois conditions paranoïaques, le logiciel de poker n'aura pas la possibilité de reconnaître le fait de l'émulation: 1) la station de travail et l'émulateur ne devraient pas pouvoir communiquer sur le réseau; 2) pour photographier l'état actuel du jeu, vous devez utiliser la sortie analogique de la carte vidéo, - connectée à «l'ordinateur screener» à l'aide d'une carte de capture vidéo; 3) pour émuler le clavier et la souris, vous devez utiliser un gadget matériel-logiciel dont l'entrée est connectée à l'ordinateur émulateur et la sortie - à deux postes de travail PS / 2 à partir desquels le jeu est joué. C'est la sortie vidéo analogique et PS / 2 que le logiciel de poker ne sait pas que certains équipements supplémentaires sont connectés à l'ordinateur.



Lors de l'émulation du clavier et de la souris, vous devez tenir compte des circonstances biométriques et technométriques pertinentes, qui peuvent également être surveillées par un logiciel de poker. En ce qui concerne la biométrie, lors de l'émulation du clavier et de la souris, des précautions doivent être prises pour émuler les mouvements du corps sont similaires à la vérité. Il convient de garder à l'esprit que, tout d'abord, une personne vivante ne peut pas jouer à un rythme stable et pendant une longue période immédiatement sur 16 tables simultanément - en particulier sur un moniteur de huit pouces. Deuxièmement, une personne vivante ne peut pas jouer 28 heures par jour, 6 jours par semaine. Enfin, troisièmement, les mouvements d'une personne vivante peuvent changer - en fonction du temps passé sur l'ordinateur. Pour émuler des circonstances biométriques plausibles, vous aurez besoin de: 1) "PS / 2-sniffer" - lotion logicielle et matérielle,qui écoutera le flux de données envoyées par le clavier et la souris au port PS / 2, et enregistrera tout ce qui est entendu dans un fichier séparé, qui sera ensuite utilisé pour émuler des circonstances biométriques plausibles; 2) une personne en direct qui jouera vraiment au poker en ligne aussi longtemps que le bot est prévu d'être inclus - ce sont ses actions qui seront enregistrées par le "PS / 2-sniffer".

Quant à la technométrie, chaque clavier et souris a sa propre «écriture» unique. Il peut être suivi en analysant à un faible niveau le flux brut de signaux qui en proviennent vers l'ordinateur. Par conséquent, si plusieurs postes de travail sont impliqués dans la conduite de robots à la fois, alors en préparation de l'émulation biométrique, pour chacun d'eux, il est nécessaire: 1) d'organiser une écoute individuelle, - avec différents claviers et différentes souris, 2) de planter des personnes différentes pour chaque poste de travail dont les actions seront être fixé avec un "renifleur PS / 2". La nécessité du deuxième paragraphe est due au fait que chaque personne utilise la souris et le clavier individuellement. Avec suffisamment de matériel statistique étendu, il est possible de déterminer avec un degré de certitude suffisant qui est assis devant l'ordinateur, même si l'utilisateur n'est pas authentifié.

# -

, , « »: , – , « ». , - « », , . , . , – «-» «-» – . -, , – , : , , , , . , , - , , .


Ainsi, la préparation de l'émulation avec des paramètres biométriques et technométriques plausibles est effectuée. Il ne reste plus qu'à se rappeler quel clavier et souris correspondent à quel utilisateur - et ne jamais rompre cette correspondance. Ignorer la biométrie et la technométrie ou leur émulation peu plausible peut entraîner un blocage de compte sans explication. Sous réserve de toutes les précautions, aussi banales qu'elles puissent paraître, on peut compter sur une mise en bouteille invulnérable.


Éléments du robot invulnérable



Fig. 2. Bot

invulnérable Un bot invulnérable est un complexe matériel-logiciel qui comprend toute une flotte d'ordinateurs qui résoudra 6 tâches fondamentalement différentes. Plus quelques lotions matérielles et logicielles. Plus deux personnes vivantes, pour observer et répondre aux situations d'urgence.

1. Une station de travail (avec IP dédiée ou PROXY de haute qualité), où 9 salles de poker sont lancées en même temps. Il devrait avoir une carte vidéo avec une sortie vidéo analogique haute définition et un grand moniteur, car de nombreuses pièces sur un petit moniteur semblent suspectes. Il est économiquement plus rentable d'utiliser non pas un poste de travail, mais une dizaine à la fois. Dans ce cas, le bot peut être lancé simultanément dans 90 chambres à la fois.

2. Screener - un ordinateur puissant avec une carte de capture vidéo, qui est connecté via un répartiteur vidéo à tous les postes de travail. Le cribleur a pour tâche de reconnaître les signaux reçus et de les traduire sous une forme structurelle. Ces données seront ensuite utilisées pour 1) écrire dans la base de données, 2) analyser et 3) prendre des décisions d'action.

3. Analyste - un ordinateur puissant qui fonctionne sur le principe d'un serveur météorologique, mais au lieu de phénomènes naturels accumule toutes les données de poker possibles - raconte. En fait, il y a beaucoup plus de tell au poker informatique qu'au poker live. Mais le problème est que sans logiciel auxiliaire, il est presque impossible de les suivre. Et l'utilisation d'un tel logiciel est arrêtée de toutes les manières possibles - vous pouvez obtenir une interdiction si vous l'utilisez sur un poste de travail.

4. Spy - comptes séparés à partir desquels le jeu n'est pas joué, mais juste une collection séquentielle de toutes les informations disponibles de toutes les salles disponibles. Il devrait y avoir plusieurs espions, car si le même compte se connecte avec notre jeu et se déconnecte à la fin, il peut jeter une pièce systématique dans la tirelire des soupçons, et lorsque cette tirelire est pleine, nous fermons simplement le compte sans donner de raison. Un "espion" devrait fonctionner sur le même principe qu'un "poste de travail". Il peut sembler qu'il y ait suffisamment d'écran logiciel et d'émulation logicielle d'une souris avec un clavier. Cependant, étant donné que le logiciel de poker peut potentiellement se lier au matériel et aux comptes de lapin ultérieurs, le filtrage et l'émulation du matériel doivent être effectués pour un espion - ainsi que pour un poste de travail.

5. Emulator - un ordinateur dont la puissance n'est pas fondamentale. Il est connecté à plusieurs répartiteurs pour souris et clavier. À partir de ces répartiteurs, les fils vont aux entrées PS / 2 pour la souris et le clavier à chacun des postes de travail et des espions. Cet ordinateur reçoit les commandes de l'analyste et les envoie aux postes de travail. Prise en compte des caractéristiques matérielles de la souris et du clavier, et des caractéristiques physiologiques du comportement de la personne travaillant derrière elles (biométrie et technométrie).

6. Deux observateurs vivants. Ce ne sont plus des ordinateurs, à savoir des êtres vivants. Ils sont nécessaires, car les développeurs de logiciels de poker ne dorment pas, et à tout moment ils peuvent exécuter un test unique pour identifier les pilotes du bot. Une personne ne suffit pas - car elle peut partir en fonction des besoins ou se poudrer le nez, et à ce moment, une situation d'urgence se produira. Il y a des situations où tout est décidé par secondes. Par conséquent, il est important que quelqu'un soit toujours à proximité des machines. De sorte que lorsque le «bouton rouge s'allume» (lorsque l'analyste rencontre un comportement inconnu), une personne peut lui dire quoi faire (écrire quelque chose dans le chat ou fermer la fenêtre). Et en aucun cas vous ne pouvez vous rendre directement sur le poste de travail, afin de ne pas casser le modèle comportemental correspondant du clavier et de la souris.Les actions doivent être effectuées uniquement via le «poste de commandement».

7. Poste de commandement - un ordinateur dont la puissance n'est pas non plus fondamentale. Il ne doit être connecté qu'à l'émulateur. C'est exactement la machine dans laquelle deux observateurs vivants sont assis et à travers laquelle, si nécessaire, ils effectuent les ajustements nécessaires au comportement du bot.


Touche finale


Donc, ce sont 7 éléments d'un bot invulnérable. Lors de leur connexion, il convient de noter que le filtreur, l'analyste et l'émulateur échangent des données sur le réseau. L'interaction avec les postes de travail et les espions se fait strictement via la sortie analogique de la carte vidéo et du PS / 2. De plus, ces ordinateurs doivent être physiquement séparés de tout le monde. Il ne peut être question de communication entre eux sur le réseau. En raison de la complexité d'un tel complexe logiciel et matériel, il est également important de prendre soin de minimiser les erreurs associées au facteur humain. Pour ce faire, l'émulateur, entre autres, se charge de lancer tous les logiciels nécessaires sur les postes de travail et sur un espion. Un écran, un analyste et un émulateur doivent être en alerte immédiatement après avoir été allumés - le logiciel correspondant doit simplement être au démarrage.


Un nouvel espoir



Fig. 3. Nouvel espoir

Le schéma décrit de conduite de bot, même avec une familiarisation superficielle avec lui, n'est pas pour les faibles de cœur. Mais ce qui précède est donné, bien que détaillé, mais quand même - sa description superficielle. Pour sa mise en œuvre, il ne faut pas avoir une qualification technique lourde, tant en programmation qu'en électronique. Lors de la programmation, un développeur aura besoin de connaissances dans des domaines tels que les mathématiques discrètes, l'approximation spline, les transformées en ondelettes, les réseaux de neurones, les machines à états, la logique floue, la programmation multithread, le traitement numérique du signal. Lors de la mise en œuvre du matériel du bot, le développeur aura besoin de connaissances dans des domaines tels que les systèmes de microprocesseur, la technologie numérique et à microprocesseur, le travail avec les microcontrôleurs et les FPGA, les bases de l'ingénierie électrique, la programmation des pilotes de bas niveau, l'architecture du système d'exploitation et l'architecture du processeur.

#

– , « ». , – , , – , . , . , – SetWindowsHookEx, CreateToolHelpSnapshot32, EnumProcessModules, – . . , : , PokerStars , Visual Studio.


Donc, c'est un schéma de conduite de bot sûr. Comme cela a été dit au début, il est intéressant de noter que, même si les «combattants pour la justice» auront entre les mains des codes source de commentaires détaillés pour le bot, ils ne pourront pas établir le fait de son utilisation. Alors qu'un robot ordinaire - sans la fonction d'invisibilité - les «combattants pour la justice» peuvent suivre, même sans sa source. Les technologies modernes, en particulier les rootkits, que les développeurs de logiciels de poker espèrent beaucoup, leur permettent de creuser profondément dans le système d'exploitation, etc. agir selon le principe "assis haut, regardant loin". Avec le développement de rootkits et d'autres technologies de protection, les «combattants pour la justice» ont un nouvel espoir de victoire inconditionnelle. Cependant, le schéma ci-dessus de conduite sécuritaire des robots réduit à néant tous ces espoirs.La mise en œuvre de ce régime est une entreprise coûteuse, cependant, puisque l'avantage potentiel est grand, le régime est tout à fait pertinent. Il est donc logique d'oser.


La vengeance des Sith


Aussitôt dit, aussitôt fait. Osez! Mais cela vaut-il la peine de passer du temps sur le reste de l'article? Un ingénieur informatique de première classe, dont l'affiliation à la ligue supérieure de la scène X est confirmée par quelque chose de plus significatif que juste un beau sceau dans un diplôme, ne vaut certainement pas la peine. Dans son arsenal X, il y a déjà suffisamment de trucs mystiques pour "venger" de vieux bots sans l'aide de quelqu'un d'autre, qui a autrefois bloqué l'oxygène du "bon côté de la force".

Les développeurs avancés, dont l'implication dans la scène X n'est due qu'à leur virtuosité en C ++ et assembleur, ne devraient pas perdre de temps, mais pour une raison différente, ils ne le feront pas. Le degré de détail du matériel présenté est insuffisant pour eux, car dans cet article non seulement de nombreuses tâches de programmation triviales sont délibérément laissées de côté (un développeur avancé les traite de un à deux, soit trois), mais aussi certains concepts d'ingénierie fondamentaux. Quant aux scripts de script, qui ne parlent même pas de C ++ conversationnel et d'assembleur, il n'est pas question des avantages de cet article pour eux.

Cependant, un ingénieur moyen, qui a déjà quitté le développement de l'adolescence (qui a développé un peu d'ingéniosité en ingénierie), mais qui n'est pas encore entré dans l'ère de l'ingénierie des adultes, trouvera ici des idées intéressantes qui l'aideront à réaliser un robot invulnérable. Dans la mesure où il est déjà en mesure de trouver des solutions simples pour des tâches apparemment complexes, en utilisant les ressources disponibles. Et c'est précisément le pouvoir mystique qui est valorisé sur la scène X, à la fois sur la lumière et les côtés sombres de celle-ci. La capacité de le posséder est ce qui distingue un ingénieur d'un développeur. Alors, mettons le feu aux «combattants pour la justice», montrant de quoi le côté obscur du pouvoir est capable.


L'Empire contre-attaque



Fig. 4. L'Empire contre-attaque La

bonne nouvelle: la partie la plus difficile est terminée. Le plan d'action stratégique, qui est également une déclaration informelle du problème, est prêt. Maintenant, il ne reste plus qu'à préciser et à détailler - à décrire dans les actions tactiques. Au stade du détail, le plus important est de marcher calmement «du général au particulier», etc. pour former le cadre du futur projet. Dans le même temps, sans entrer dans les détails de la mise en œuvre d'unités fonctionnelles spécifiques, mais simplement en les fixant. Nous nous occuperons de leurs détails plus tard, lorsque le cadre sera déjà complètement prêt.

#

, – . , – . 99- . 10- , , , , : « , ». , IDE .


Pour plus de clarté, nous utiliserons la syntaxe du langage Fort (à ne pas confondre avec Fortran). Il s'agit d'un langage unique qui favorise naturellement le mouvement rationnel de l'ingénierie. La beauté d'une telle approche «fort empruntée» est que toutes les lacunes conceptuelles du projet sont identifiées sur le rivage, et non au milieu de sa mise en œuvre, ce qui contribue dès le début à un développement de haute qualité. Sans besoin de refactoring ultérieur. Ainsi, le cadre "du général au particulier":
Le cadre "du général au particulier"
: -
  - -
  - -
  - --
  -
;

: --
  - !!!!!!
  - !!!!!!
  - !!!!!!
  - 
  - -
;

: -
   --
  - -
  --
;

: -
  - --
  - -
  --
;

: !!!!!!
  --- -
  -- -
  --
;

: -
  ---
  -----
  --
;

: --
  -- -
  - -
  - -
  - -
  - -
  ---
  - 
;

: !!!!!!
  -- --
  -- -
  -- -
  -- --
  -
  --
  ---
  --
;

: !!!!!!
  ---
  --
  -
  -
  --
;

: !!!!!!
  --
  ---
;

: !!!-!!!
  --
  ---
;

: --
  --
  ---
  ---
;


Un autre avantage de l'utilisation de la syntaxe du langage Fort lors de l'élaboration du cadre général du projet est la possibilité de compiler immédiatement le texte écrit. Parce que ce texte est lui-même un programme. En principe, si vous implémentez tous les nœuds fonctionnels manquants à l'aide du langage Fort et les ajoutez au framework ci-dessus, vous obtenez le même bot invulnérable sur lequel nous travaillons. Cela se passera de manière très concise. Cependant, les extraits de code ci-dessous seront écrits dans des langages plus traditionnels - C ++ et assembleur. La présentation «emprunté» dans ce cas n'est intéressante qu'à des fins d'illustration du cadre général du projet. Ainsi, «calmement du général au particulier» s'est déroulé, nous allons maintenant examiner plus en détail les détails de la mise en œuvre de certains nœuds fonctionnels du bot.


Photographie invisible


Ici, nous avons trois tâches fondamentales: 1) trouver une solution matérielle acceptable, 2) développer une structure de données qui sera lue à partir de photos, 3) mettre en œuvre une fonction de reconnaissance. Le résultat de la phase de photographie devrait être une structure de données complète et redondante, sur laquelle l'automate de la logique peut identifier de manière unique l'état actuel du jeu - pour le plus petit nombre possible de prises de vue consécutives.

1. En ce qui concerne la solution matérielle, l'option idéale (d'un point de vue économique et du point de vue de la facilité de programmation ultérieure) est que tous les signaux vidéo convergent sur un répartiteur vidéo, qui pourrait être commuté depuis un ordinateur. Dans ce cas, la tâche de filtrage peut être effectuée par un ordinateur avec une carte de capture vidéo. Pour chaque espion et poste de travail dans ce cas, il sera nécessaire de créer un dossier - les captures d'écran correspondantes y seront enregistrées. Si cette option ne peut pas être mise en œuvre (en raison de l'inaccessibilité de l'équipement approprié et / ou en raison de qualifications techniques insuffisantes pour adapter l'équipement existant à vos propres besoins), alors vous pouvez utiliser plusieurs ordinateurs connectés à un réseau local,dans chacune desquelles il y aura plusieurs cartes de capture vidéo - une pour chaque «espion» et «poste de travail». Dans ce cas, vous devrez soit ajouter tous les bitmaps analysés à un dossier réseau partagé, soit écrire sur les sockets d'application client-serveur, qui collecteront tous les bitmaps en un seul endroit. Pour télécharger des bitmaps, aux fins de leur reconnaissance ultérieure, vous pouvez utiliser le code suivant:
Télécharger des bitmaps
void LoadRamaFromFile(LPCSTR lpcszFileName, HDC *lphdcRama)
{
  HANDLE hBitmap = LoadImage(0, lpcszFileName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
  *lphdcRama = CreateCompatibleDC(NULL); //    
  SelectObject(*lphdcRama, hBitmap);   //    
  DeleteObject(hBitmap);         //  
}


2. Quant à la structure des données, elle peut être la suivante:
Structure des données
// 
typedef enum ROUND
{
  RES_WAITINGBLINDS, //   ( )
  RES_FLOPHIDDEN,  //  ,      ()
  PREFLOP,      // 
  FLOP,       // 
  TURN,       // 
  RIVER,       // 
  UNKNOWN,      // 
  ZSTATE
} *LPROUND;

//                         //
typedef enum ACTION
{
  AC_POSTSB,   //   
  AC_POSTBB,   //   
  AC_POSTSBANDBB,
  AC_CHECK,    //    
  AC_BET,     //   
  AC_RAISE,    //   
  AC_CALL,    //   
  AC_FOLD,    //  
  AC_ALLIN,    //  
  AC_SITOUT,   //            
  AC_MUCK,    //   
  AC_SHOWCARDS,  //   
  AC_NONE,    //  ,     (  )
  AC_TNB,     //    ( )
  AC_ZSTATE
} *LPACTION;

//    
typedef struct tagSITA_UVACHA
{
  char  szNickname[STR_SIZE_NICKNAME];  // 
  char  szStack[STR_SIZE_STACK];     //  
  char  szHoleCards[STR_SIZE_HOLECARDS]; //     ( )
  ACTION  action;
} SITA_UVACHA, *LPSITA_UVACHA;

//    
typedef struct tagRAMA_UVACHA
{
  SITA_UVACHA  sita[MAX_COUNT_SITA];   //    
  DWORD  dwCountSita;           //    
  DWORD  dwBUPos;             //  
  char  szPOT[STR_SIZE_POT];       //  
  char  szBoardCards[STR_SIZE_HOLECARDS]; // ,    
  ROUND  round;              //  
} RAMA_UVACHA, *LPRAMA_UVACHA;

////////////////////////////

typedef struct tagKRISHNA_UVACHA
{
  RAMA_UVACHA  rama;
  DWORD    dwFirstSaid;    //      
  DWORD    dwLastSaid;     //      
  ACTION    last_action;    //     
} KRISHNA_UVACHA, *LPKRISHNA_UVACHA;


3. L'une des options possibles pour la fonction de reconnaissance est de configurer un réseau neuronal pour cela. Ce sujet mérite une discussion séparée, donc nous ne parlerons pas de l'approche du réseau neuronal dans cet article. Une option plus simple consiste à attacher aux images bitmap correspondantes. Voici à quoi pourrait ressembler la structure de données correspondante:

Structure des données de reconnaissance
typedef struct tagSURJA_CRAPH_DATA
{
  BYTE  PATTERN_LETTER[COUNT_LETTERS][SIZE_PATTERN_LETTER];       //  
  BYTE  LETTER_CODE[COUNT_LETTERS];                   //  
  BYTE  LETTER_SIZE[COUNT_LETTERS];                   //  

  BYTE  PATTERN_INSCRIPT[COUNT_INSCRIPTIONS][SIZE_PATTERN_INSCRIPTION]; //   
  char  INSCRIPTION_TEXT[COUNT_INSCRIPTIONS][SIZE_INSCRIPTION_TEXT];  //  
  BYTE  PATTERN_CARD[COUNT_CARDS][SIZE_PATTERN_CARD];          //  
  char  CARD_TEXT[COUNT_CARDS][SIZE_CARD_TEXT];             //  
  BYTE  PATTERN_HOLEHIDDEN[COUNT_HOLEHIDDEN][SIZE_PATTERN_HOLEHIDDEN]; //    
  char  HOLEHIDDEN_TEXT[COUNT_HOLEHIDDEN][SIZE_HOLEHIDDEN_TEXT];    //     
} SURJA_CRAPH_DATA, *LPSURJA_GRAPH_DATA;


Le moyen le plus simple de le remplir est manuel. Prenez simplement une capture d'écran, ouvrez-la dans Photoshop, activez l'outil pipette et réécrivez les chiffres des zones qui nous intéressent. Cette décision ne peut pas être qualifiée de concise, même avec un gros tronçon. De plus, il a une limitation importante - même les changements les plus mineurs dans le calendrier du logiciel de poker entraîneront l'arrêt du robot. Cependant, si la qualification technique ne vous permet pas de trouver quelque chose de plus intéressant, voici à quoi pourrait ressembler la préparation à la «reconnaissance manuelle» (voici seulement une petite sélection du code de près de 2000 lignes):
Reconnaissance manuelle
BOOL LoadGraphData()
{
//=====================     ================
  memset(m_BramaGraphData.ptRamaCoords,  0,  sizeof(POINT)*COUNT_VARRIOUS_RAMA*COUNT_RAMA_VALUES);
  memset(m_BramaGraphData.ptSitaCoords,  0,  sizeof(POINT)*COUNT_VARRIOUS_RAMA*MAX_COUNT_SITA*COUNT_SITA_VALUES);
  memset(m_BramaGraphData.ptRecognizeSize,0,  sizeof(POINT)*COUNT_VAL_SIZE);
//=====================  9-  ===============
  m_BramaGraphData.ptRamaCoords[INDEX_RAMA_AT_9_SITA][INDEX_VAL_RAMA_POT].x  = 210;
  m_BramaGraphData.ptRamaCoords[INDEX_RAMA_AT_9_SITA][INDEX_VAL_RAMA_POT].y  = 34;
  m_BramaGraphData.ptSitaCoords[INDEX_RAMA_AT_9_SITA][0][INDEX_VAL_SITA_NICKNAME].x    = 340;
  m_BramaGraphData.ptSitaCoords[INDEX_RAMA_AT_9_SITA][0][INDEX_VAL_SITA_NICKNAME].y    = 44;
  m_BramaGraphData.ptSitaCoords[INDEX_RAMA_AT_9_SITA][1][INDEX_VAL_SITA_NICKNAME].x    = 423;
  m_BramaGraphData.ptSitaCoords[INDEX_RAMA_AT_9_SITA][1][INDEX_VAL_SITA_NICKNAME].y    = 77;
  m_BramaGraphData.ptSitaCoords[INDEX_RAMA_AT_9_SITA][2][INDEX_VAL_SITA_INSCRIPTION].x  = 438;
  m_BramaGraphData.ptSitaCoords[INDEX_RAMA_AT_9_SITA][2][INDEX_VAL_SITA_INSCRIPTION].y  = 165;
//=====================  10-  ==============
//=====================    ==================
  m_BramaGraphData.PATTERN_LETTER[PAT_0][0] = b01111000;
  m_BramaGraphData.PATTERN_LETTER[PAT_0][1] = b10000100;
  m_BramaGraphData.PATTERN_LETTER[PAT_8][2] = b10100100;
  m_BramaGraphData.PATTERN_LETTER[PAT_8][3] = b01011000;
  m_BramaGraphData.LETTER_CODE[PAT_0] = '0';
  m_BramaGraphData.LETTER_CODE[PAT_1] = '1';
  m_BramaGraphData.LETTER_CODE[PAT_2] = '2';
//=====================     ================
  m_BramaGraphData.PATTERN_INSCRIPT[PAT_INSCRIPTION_SEATOPEN][0]  = 55;
  m_BramaGraphData.PATTERN_INSCRIPT[PAT_INSCRIPTION_SEATOPEN][1]  = 56;
  m_BramaGraphData.PATTERN_INSCRIPT[PAT_INSCRIPTION_SEATOPEN][2]  = 124;
  m_BramaGraphData.PATTERN_INSCRIPT[PAT_INSCRIPTION_SEATOPEN][3]  = 215;
//=====================     ==================
  lstrcpy(m_BramaGraphData.INSCRIPTION_TEXT[PAT_INSCRIPTION_SEATOPEN],  "SEATOPEN");
  lstrcpy(m_BramaGraphData.INSCRIPTION_TEXT[PAT_INSCRIPTION_EMPTYSEAT],  "EMPTYSEAT");
  lstrcpy(m_BramaGraphData.INSCRIPTION_TEXT[PAT_INSCRIPTION_CALL],    "CALL");
  lstrcpy(m_BramaGraphData.INSCRIPTION_TEXT[PAT_INSCRIPTION_BET],      "BET");
//=====================    =======================
  m_BramaGraphData.PATTERN_CARD[PAT_CARD_EMPTY][0] = 30;
  m_BramaGraphData.PATTERN_CARD[PAT_CARD_EMPTY][1] = 30;
  m_BramaGraphData.PATTERN_CARD[PAT_CARD_EMPTY][2] = 30;
  m_BramaGraphData.PATTERN_CARD[PAT_CARD_HIDE][6] = 188;
  m_BramaGraphData.PATTERN_CARD[PAT_CARD_HIDE][7] = 151;
//=====================    ==================
  lstrcpy(m_BramaGraphData.CARD_TEXT[PAT_CARD_EMPTY],  "");
  lstrcpy(m_BramaGraphData.CARD_TEXT[PAT_CARD_HIDE],  "hid");
  lstrcpy(m_BramaGraphData.CARD_TEXT[PAT_CARD_2C],  "2C");
  lstrcpy(m_BramaGraphData.CARD_TEXT[PAT_CARD_4H],  "4H");
//=====================     =================
//=====================      ===
  lstrcpy(m_BramaGraphData.HOLEHIDDEN_TEXT[PAT_HOLEHIDDEN_EMPTY],  "");
  lstrcpy(m_BramaGraphData.HOLEHIDDEN_TEXT[PAT_HOLEHIDDEN_ONE],  "one-hidden");
  lstrcpy(m_BramaGraphData.HOLEHIDDEN_TEXT[PAT_HOLEHIDDEN_TWO],  "hidden");
//=====================   ===========================
  m_BramaGraphData.PATTERN_MISC[PAT_MISC_BUTTON][0] = 216;
  m_BramaGraphData.PATTERN_MISC[PAT_MISC_BUTTON][1] = 72;
  m_BramaGraphData.PATTERN_MISC[PAT_MISC_BUTTON][2] = 8;
  m_BramaGraphData.PATTERN_MISC[PAT_MISC_BUTTON][3] = 151;
  m_BramaGraphData.PATTERN_MISC[PAT_MISC_BUTTON][4] = 221;
  m_BramaGraphData.PATTERN_MISC[PAT_MISC_BUTTON][5] = 194;
  m_BramaGraphData.PATTERN_MISC[PAT_MISC_BUTTON][6] = 231;

  return TRUE;
}


Et voici un exemple de code qui utilise ces bitmaps pour la reconnaissance:
Exemple de code de reconnaissance
typedef struct tagSURJA_CRAPH_DATA
{
  BYTE  PATTERN_LETTER[COUNT_LETTERS][SIZE_PATTERN_LETTER];       //  
  BYTE  LETTER_CODE[COUNT_LETTERS];                   //  
  BYTE  LETTER_SIZE[COUNT_LETTERS];                   //  

  BYTE  PATTERN_INSCRIPT[COUNT_INSCRIPTIONS][SIZE_PATTERN_INSCRIPTION]; //   
  char  INSCRIPTION_TEXT[COUNT_INSCRIPTIONS][SIZE_INSCRIPTION_TEXT];  //  
  BYTE  PATTERN_CARD[COUNT_CARDS][SIZE_PATTERN_CARD];          //  
  char  CARD_TEXT[COUNT_CARDS][SIZE_CARD_TEXT];             //  
  BYTE  PATTERN_HOLEHIDDEN[COUNT_HOLEHIDDEN][SIZE_PATTERN_HOLEHIDDEN]; //    
  char  HOLEHIDDEN_TEXT[COUNT_HOLEHIDDEN][SIZE_HOLEHIDDEN_TEXT];    //     
} SURJA_CRAPH_DATA, *LPSURJA_GRAPH_DATA;



D'une manière ou d'une autre - même si nous utilisons un réseau de neurones, au moins avec nos mains, au moins avec quelque chose de tiers - en reconnaissance, quatre domaines fondamentalement différents doivent être pris en compte: 1) statique (ceux où, selon la théorie, rien ne se passe jamais); dont externe au logiciel de poker (par exemple, une sorte d'action survient en dehors du client de poker, soi-disant du système Windows, mais en fait - vérifie la botabilité); 2) dynamique hautement informative (taille de la pile, joueur actuel, cartes sur la table, etc.); 3) dynamique peu informative (endroits où les messages apparaissent rarement et discutent); 4) dynamique non informative (par exemple, les zones dans lesquelles l'animation de la distribution des cartes se produit).


Analyse invisible


La partie analytique du bot, dans le cas du poker, est un mécanisme d'interaction avec la base de données - puisque presque tous les «tell» pertinents au poker en ligne reposent sur l'analyse du modèle comportemental des adversaires de jeu. L'option idéale ici est votre propre maison Oracle, qui est indispensable dans un travail intensif avec une grande base de données qui comprend des centaines de milliers d'enregistrements. À savoir, il y en aura tellement si vous envisagez de vous engager sérieusement et longtemps dans l'agriculture botanique. Si vous avez juste besoin d'un bot pour vous adonner, vous ne pouvez pas dépenser d'argent pour l'Oracle. Le SGBD MS Access est également tout à fait approprié - vous pouvez facilement le contacter à partir de votre programme, par exemple via ODBC. Voici à quoi cela pourrait ressembler:
Interaction avec MS Access
BOOL InitODBC()
{
  SQLRETURN    ret;
  SQLSMALLINT    Length;

  ret = SQLAllocHandle(SQL_HANDLE_ENV, SQL_HANDLE_NULL, &hEnv);
  if (SQL_SUCCESS != ret && SQL_SUCCESS_WITH_INFO != ret)
    return FALSE;

  ret = SQLSetEnvAttr(hEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, NULL);
  if (SQL_SUCCESS != ret && SQL_SUCCESS_WITH_INFO != ret)
    return FALSE;

  ret = SQLAllocHandle(SQL_HANDLE_DBC, hEnv, &hConn);
  if (SQL_SUCCESS != ret && SQL_SUCCESS_WITH_INFO != ret)
    return FALSE;

  lstrcpyn(szConnect, STR_CONNECT, MAXSIZE_CONNECTSTR);
  ret = SQLDriverConnect(hConn, NULL, (SQLTCHAR *) szConnect, lstrlen(szConnect), (SQLTCHAR *) szConnect, MAXSIZE_CONNECTSTR, &Length, SQL_DRIVER_COMPLETE);
  if (SQL_SUCCESS != ret && SQL_SUCCESS_WITH_INFO != ret)
    return FALSE;

  return TRUE;
}

void DoneODBC()
{
  SQLDisconnect(hConn);
  SQLFreeHandle(SQL_HANDLE_DBC, hConn);
  SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
}



BOOL InsertInDB(LPCSTR lpcszText, LPCSTR lpcszTitle, DWORD dwLocale)
{
  SQLHANDLE  hStmt;
  SQLRETURN  ret;
  char    szTitle[SIZE_TITLE];
  char    szQuery[MAXSIZE_QUERYSTR];


  //          //
  ret = SQLAllocHandle(SQL_HANDLE_STMT, hConn, &hStmt);
  if (SQL_SUCCESS != ret && SQL_SUCCESS_WITH_INFO != ret)
    return FALSE;

  wsprintf(szQuery, "INSERT INTO index (text, title, locale) VALUES ('%s', '%s', %d)", lpcszText, szTitle, dwLocale);

  ret = SQLExecDirect(hStmt, (SQLTCHAR *) szQuery, lstrlen(szQuery));

  if (SQL_SUCCESS != ret && SQL_SUCCESS_WITH_INFO != ret)
    return FALSE;
  SQLFreeHandle(SQL_HANDLE_STMT, hStmt);

  return TRUE;
}


S'il ne s'agit pas de poker, mais d'échecs, par exemple, alors un échange avec un moteur d'échecs tiers peut être implémenté en tant que partie analytique. Par exemple, voici comment interagir avec Fritz:
Interaction avec le moteur analytique
BOOL SendData2Fritz(char szFritz[100])
//    //
{
  if (!FritzStr2Clipboard(szFritz))
    return FALSE;
  SendMessage(m_hwndFritz, WM_COMMAND, MAKELONG(IDM_PASTE_POSITION, 0), 0); 
  Sleep(2);
  SendMessage(m_hwndFritz, WM_COMMAND, MAKELONG(IDM_MOVE_NOW, 0), 0); 

  return TRUE;
}


BOOL ReceiveDataFromFritz(int busy[8][8], LPBOOL lpbEndGame)
//     //
{
  char szFritz[100];

  *lpbEndGame = FALSE;

  SendMessage(m_hwndFritz, WM_COMMAND, MAKELONG(IDM_COPY_POSITION, 0), 0);
  if (!Clipboard2FritzStr(szFritz))
    return FALSE;
  return TRUE;
}

BOOL FritzStr2Clipboard(LPCSTR lpcszFritz)
//         //
{
  HGLOBAL hGlobalMemory;    //   
  LPVOID pGlobalMemory;     //   

  hGlobalMemory = GlobalAlloc(GHND, lstrlen(lpcszFritz)+1);
  if (hGlobalMemory == NULL)
    return FALSE;
  pGlobalMemory = GlobalLock(hGlobalMemory);
  lstrcpy((LPSTR) pGlobalMemory, lpcszFritz);
  GlobalUnlock(hGlobalMemory);

  if (!OpenClipboard(NULL))
    return FALSE;
  if (!EmptyClipboard())
    return FALSE;
  SetClipboardData(CF_TEXT, hGlobalMemory);
  CloseClipboard();

  return TRUE;
}

BOOL Clipboard2FritzStr(LPSTR lpszFritz)
//        //
{
  HANDLE hClipMemory;    //   
  LPVOID pClipMemory;    //     

  if (IsClipboardFormatAvailable(CF_TEXT))
  {
    if (!OpenClipboard(NULL))
      return FALSE;
    hClipMemory = GetClipboardData(CF_TEXT);
    if (hClipMemory == NULL)
      return FALSE;
    pClipMemory = GlobalLock(hClipMemory);
    lstrcpyn(lpszFritz, (LPSTR) pClipMemory, 100);
    GlobalUnlock(hClipMemory);
    CloseClipboard();
  }
  return TRUE;
}



Un autre outil qui peut être utile lors de la programmation de l'analyse est le soi-disant. "Machines à états finis". Voici comment ils peuvent être utilisés dans les jeux multijoueurs en ligne (ceci est un fragment du bot du jeu "Keepers of Power"):
Exemple de machine d'état
typedef enum AUTOMATA_BATLE
{
  //  
  AS_BATLE_BEGIN,
  AS_BATLE_END,
  AS_BATLE_ERROR,

  AS_BATLE_TEST2MOB,     // ,    
  AS_BATLE_WAIT2NICK,    //    
  AS_BATLE_WAIT2MOB,     //   
  AS_BATLE_PROCESS,     //   ,    
  AS_BATLE_CLICK2OK_1,    //  OK
  AS_BATLE_WAITCHANGE,    //   
  AS_BATLE_CLICK2MONEY,   //    ""
  AS_BATLE_TEST2DROP,    //     (  "")
  AS_BATLE_CLICK2DROP,    //    ""
  AS_BATLE_CLICK2CLOSE,   //    ""
  AS_BATLE_WAIT2DROP,    //     
  AS_BATLE_CLICK2TAKEALL,  //  " "
  AS_BATLE_WAIT2CONFIRM,   //  
  AS_BATLE_CLICK2OK_2,    //  
  AS_BATLE_WAIT2BACK,    //   
  AS_BATLE_CLICK2BACK,    //  ""
  AS_BATLE_WAIT2STARTWINDOW, //    
  AS_BATLE_WAIT2NEXT     //  30 
};



AUTOMATA_BATLE CAutomataBatle::GoStep(HDC hdc)
{
  char szMessage[255];

  switch (m_automata_batle)
  {
  //        //
  case AS_BATLE_BEGIN:
    m_automata_batle = AS_BATLE_WAIT2STARTWINDOW;
    SetWindowText(m_hwndControl, "  ");
    break;
  case AS_BATLE_WAIT2STARTWINDOW:
    if (IsStartPresent(hdc))
    {
      SetWindowText(m_hwndControl, " ");
      m_automata_batle = AS_BATLE_TEST2MOB;
    }
    break;
  case AS_BATLE_TEST2MOB:
    if (IsMechPresent(hdc))
      if (!ClickMenuItem(INDEX_GOBATLE))
        return AS_BATLE_ERROR;
    if (IsCellEmpty(hdc))
    {
      SetWindowText(m_hwndControl, "  ");
      m_automata_batle = AS_BATLE_END;
    }
    else
    {
      hwndBatle = NULL;
      EnumChildWindows(m_hwndMain, EnumWindowsProcBatle, NULL);

      if (NULL != hwndBatle)
      {
        SetWindowText(m_hwndControl, "  ");
        m_automata_batle = AS_BATLE_WAIT2NICK;
      }
    }
    break;
  case AS_BATLE_WAIT2NICK:
    if (IsNickPresent(hdc))
    {
      SetWindowText(m_hwndControl, "  ");
      m_automata_batle = AS_BATLE_WAIT2MOB;
    }
    break;
  case AS_BATLE_WAIT2MOB:
    if (!IsNickOpEmpty(hdc))
    {
      SetWindowText(m_hwndControl, " ");
      m_automata_batle = AS_BATLE_PROCESS;
    }
    break;
  case AS_BATLE_PROCESS:
    if (!IsBatleEnd(hdc))
    {
      if (!ClickMenuItem2Window(hwndBatle, INDEX_STRIKE))
        return AS_BATLE_ERROR;
    }
    else
    {
      SetWindowText(m_hwndControl, "  ");
      m_automata_batle = AS_BATLE_CLICK2OK_1;
    }
    break;
  case AS_BATLE_CLICK2OK_1:
    if (!ClickMenuItem2Window(hwndBatle, INDEX_OK2BATLEEND))
      return AS_BATLE_ERROR;
    SetWindowText(m_hwndControl, "  ");
    m_automata_batle = AS_BATLE_WAITCHANGE;
    break;
  case AS_BATLE_WAITCHANGE:
    if (IsChangePresent(hdc))
    {
      SetWindowText(m_hwndControl, " ");
      m_automata_batle = AS_BATLE_CLICK2MONEY;
    }
    break;
  case AS_BATLE_CLICK2MONEY:
    if (!ClickMenuItem(INDEX_MONEY))
      return AS_BATLE_ERROR;
      SetWindowText(m_hwndControl, " ");
    m_automata_batle = AS_BATLE_TEST2DROP;
    break;
  case AS_BATLE_TEST2DROP:
    if (IsButtonDropPresent(hdc))
    {
      SetWindowText(m_hwndControl, "  \"\"");
      m_automata_batle = AS_BATLE_CLICK2DROP;
    }
    else if (IsButtonClosePresent(hdc))
    {
      SetWindowText(m_hwndControl, " ,   \"\"");
      m_automata_batle = AS_BATLE_CLICK2CLOSE;
    }
    break;
  case AS_BATLE_CLICK2DROP:
    if (IsButtonDropPresent(hdc))
    {
      if (!ClickMenuItem(INDEX_DROP))
        return AS_BATLE_ERROR;
    }
    else
    if (IsDropPresent(hdc))
    {
      SetWindowText(m_hwndControl, "  ");
      m_automata_batle = AS_BATLE_WAIT2DROP;
    }
    else if (IsStartPresent(hdc))
      m_automata_batle = AS_BATLE_WAIT2STARTWINDOW;
    break;
  case AS_BATLE_CLICK2CLOSE:
    if (!ClickMenuItem(INDEX_CLOSE))
      return AS_BATLE_ERROR;
    if (IsStartPresent(hdc))
    {
      SetWindowText(m_hwndControl, "  ");
      m_dwWait = 0;
      m_automata_batle = AS_BATLE_WAIT2NEXT;
    }
    break;
  case AS_BATLE_WAIT2DROP:
    if (IsDropPresent(hdc))
    {
      SetWindowText(m_hwndControl, "  ");
      m_automata_batle = AS_BATLE_CLICK2TAKEALL;
    }
    break;
  case AS_BATLE_CLICK2TAKEALL:
    if (!ClickMenuItem(INDEX_TAKEALL))
      return AS_BATLE_ERROR;
    SetWindowText(m_hwndControl, "  ");
    m_automata_batle = AS_BATLE_WAIT2CONFIRM;
    break;
  case AS_BATLE_WAIT2CONFIRM:
    if (IsConfirmPresent(hdc))
    {
      SetWindowText(m_hwndControl, "");
      m_automata_batle = AS_BATLE_CLICK2OK_2;
    }
    break;
  case AS_BATLE_CLICK2OK_2:
    if (!ClickMenuItem(INDEX_OK2TAKEALL))
      return AS_BATLE_ERROR;
    if (!IsConfirmPresent(hdc))
    {
      SetWindowText(m_hwndControl, "  \"\"");
      m_automata_batle = AS_BATLE_WAIT2BACK;
    }
    break;
  case AS_BATLE_WAIT2BACK:
    if (IsBackPresent(hdc))
    {
      SetWindowText(m_hwndControl, "  \"\"");
      m_automata_batle = AS_BATLE_CLICK2BACK;
    }
    break;
  case AS_BATLE_CLICK2BACK:
    if (!ClickMenuItem(INDEX_BACK))
      return AS_BATLE_ERROR;
    if (IsStartPresent(hdc))
    {
      SetWindowText(m_hwndControl, "  ");
      m_dwWait = 0;
      m_automata_batle = AS_BATLE_WAIT2NEXT;
    }
    break;
  case AS_BATLE_WAIT2NEXT:
    if (m_dwWait >= WAIT_2NEXTBATTLE)
    {
      SetWindowText(m_hwndControl, "  ");
      m_automata_batle = AS_BATLE_WAIT2STARTWINDOW;
    }
    else
    {
      wsprintf(szMessage, "(%d  %d) ...", m_dwWait/2, WAIT_2NEXTBATTLE/2);
      SetWindowText(m_hwndControl, szMessage);
      m_dwWait++;
    }
    break;
  case AS_BATLE_END:
    m_automata_batle = AS_BATLE_BEGIN;
    break;
  }




Émulation invisible


Il y a deux étapes - préparatoire et opérationnelle. L'un et l'autre impliquent non seulement d'écrire les programmes appropriés, mais aussi de travailler avec le fer. Ici, vous ne pouvez pas vous passer de l'immersion dans des microcontrôleurs. Heureusement, il n'est pas nécessaire de réinventer la roue - il existe des solutions logicielles et matérielles prêtes à l'emploi qui peuvent être facilement trouvées sur Internet. Y compris le code source du programme pour le microcontrôleur, qui peut facilement être adapté à vos besoins.

Quant à la phase préparatoire (enregistrement des heures de travail avec la souris et le clavier), ici, si vous le souhaitez, vous pouvez vous passer de gadgets matériels. Vous pouvez écrire un filtre de pilote qui capture les appels vers IOCTL_INTERNAL_I8042_HOOK_KEYBOARD. Vous pouvez prendre le programme ctrl2cap comme base, dont les codes sources sont disponibles dans le DDK. Cependant, cette solution n'est pas universelle - il est préférable d'utiliser un renifleur matériel.

Quant à la phase opérationnelle, il n'y a certainement aucun moyen de se passer de gadgets matériels. L'une des solutions possibles pourrait être la communication avec un dispositif à microcontrôleur (qui sera également un séparateur en combinaison) d'une part via RS-232, et d'autre part via un bouquet PS / 2. Pour travailler avec RS-232, il existe deux options - vous pouvez soit utiliser les outils Windows habituels et communiquer via CreateFile / ReadFile / WriteFile avec le port RS-232, soit directement via les ports d'entrée / sortie. Dans le second cas, vous devrez écrire un pilote simple qui déverrouille l'accès aux ports d'E / S, car par défaut dans Windows, l'accès à ces ports est fermé. Éloignez-vous du péché. Si vous avez quand même réussi à accéder aux ports d'entrée / sortie, alors voici le code pour échanger des données via RS-232:
Code RS-232
#define dataport  0x02F8   //   COM2
#define irport   0x02F9   //       
#define manager   0x02FB   //  
#define statline  0x02FD   //  
#define upr1    0x00BB      
#define upr2    0x003B
#define freq    0x000C   //    (9600 )

DWORD OpenPort()
/*  COM- */
{
  __asm
  {
    mov  eax, upr1    //   0  1    
    mov  edx, manager
    out  dx, al

    mov  eax, freq    //    
    mov  edx, dataport
    out  dx, al     //       

    mov  al, ah
    mov  edx, irport
    out  dx, al     //       

    mov  eax, upr2
    mov  edx, manager
    out  dx, al

    mov  al, 0      //  
    mov  edx, irport
    out  dx, al
  }
}

DWORD WriteByte(BYTE data)
/*    COM- */
{
  __asm
  {
    mov  al, data    //    
    mov  edx, dataport
    out  dx, al     //     
waitout:
    mov  edx, statline
    in   al, dx     //   
    mov  ah, al
    and  al, 0x40    // ,    
    jz   waitout     //   – 
  }
} // void WriteByte

BOOL ReadByte(BYTE data)
/*    COM- */
{
  int cntWait = 0;

  __asm
  {
    mov  edx, statline
    xor  ecx, ecx
waitread:
    add  cntWait, 1
    cmp  cntWait, 0xFFFF
    jz   error
    in   al, dx     //   
    mov  bl, al     // ,   
    and  eax, 1
    jz   waitread    //    –  
    mov  edx, dataport  //   –   
    xor  eax, eax
    in   al, dx     //     
    mov  data, al
error:
  }
  if (cntWait != 0xFFFF)
    return TRUE;
  else
    return FALSE;
} // BYTE ReadByte


Ainsi, le mécanisme d'interception et d'émulation des signaux du clavier avec une souris est compréhensible, il ne reste plus qu'à comprendre comment créer un modèle de comportement crédible du point de vue de la biométrie à partir d'un flux continu de données de clavier et de souris reçues d'un renifleur. En outre, l'une des tâches les plus intéressantes à ce stade est de savoir comment déplacer la souris du point de départ à un autre, spécifiquement défini.

L'une des solutions possibles comprend deux éléments: 1) configurer le réseau neuronal, 2) ajuster le mouvement et apprendre au réseau neuronal à travailler en tandem avec le "screener". Avec cette approche, il est possible de former un réseau neuronal avec une implication humaine minimale. L'algorithme d'apprentissage du réseau neuronal peut être le suivant:
  1. Nous sélectionnons des coordonnées aléatoires où la souris doit être déplacée.
  2. Nous les alimentons avec les coordonnées actuelles du réseau neuronal.
  3. Nous regardons à quel point le réseau neuronal s'est trompé.
  4. Nous ajustons le réseau neuronal.
  5. Répétez 1-4 jusqu'à la victoire. Compte tenu des données reçues du renifleur matériel, de sorte que le réseau neuronal non seulement déplace avec précision le curseur de la souris, mais le fait également de manière biométrique plausible.



Et ensuite


La mise en œuvre de ce schéma de réseau de neurones, ainsi que le schéma de reconnaissance d'écran de réseau de neurones mentionné ci-dessus, est un sujet de discussion séparé qui dépasse le cadre de cet article. Ces deux tâches qui dépassent le cadre de l'article sont les «concepts d'ingénierie fondamentaux» que «l'ingénieur intermédiaire» est invité à résoudre de façon indépendante. Quant aux «problèmes de programmation triviaux», la mise en œuvre de la plupart d'entre eux n'est pas non plus incluse dans cet article. Ces 10 listes répertoriées dans l'article ne sont qu'une graine, conçue pour favoriser l'appétit des ingénieurs.

Un autre point important. En utilisant cet article lors du développement de votre propre bot, vous devez comprendre: lorsque plusieurs options alternatives (idéales et compromis) sont proposées pour implémenter un nœud fonctionnel particulier, le choix est rhétorique. Il est entendu que l'option idéale sera utilisée. Si vous faites des compromis, ne fût-ce qu'un seul, le bot sera vulnérable aux contre-attaques du «côté brillant de la force».


Le retour des Jedi



Fig. 5. Retour du Jedi

So, le schéma de conduite de robots invulnérables décrit ci-dessus, qui, face aux "combattants pour la justice" - prétend être la victoire ultime et irrévocable. Cependant, ce serait ennuyeux si les Jedi du "bon côté du pouvoir" n'avaient pas l'opportunité de s'opposer aux botswomens. De plus, si cela n’était pas possible, l’auteur - essayant d’adhérer au «côté positif de la force» - ne publierait pas ce plan. De plus, je veux croire qu'une partie importante des lecteurs adhère également au «côté positif de la force» et leur intérêt n'est pas d'abuser de ce schéma, mais de savoir comment y résister. L'article ne fournit pas de codes source détaillés et omet certains concepts d'ingénierie fondamentaux - précisément afin d'éviter les abus.

Quelques mots sur la façon dont vous pouvez résister au schéma de production botanique décrit. Elle est pratiquement invulnérable. Cependant, la possibilité théorique de sa découverte demeure. Cette fonctionnalité est associée au suivi du comportement atypique d'une souris qui peut glisser, même dans le cas d'une émulation de haute qualité. Le fait est que la souris porte sur sa queue de nombreux «récits biométriques», exprimés en langage poker. Elle est la plus proche de la personne. Le moindre mouvement musculaire provoqué par un changement du fond émotionnel - tout cela affecte la façon dont nous tenons la souris dans nos mains.

À cet égard, l'auteur de l'article a une étude bionique originale, sous le titre de travail "Architecture intégrée de l'Homo Sapiens", qui comprend une description de la physiologie et de la psyché d'une personne - dans des modèles adaptés à l'exploitation informatique. Grâce aux résultats positifs de cette étude, je ressens le droit moral de rendre public le schéma de conduite de robots «invulnérable», car le «bon côté du pouvoir» a une chance de gagner. À partir de cette étude, on peut entre autres comprendre comment notre utilisation de la souris, via l'interface de la moelle épinière, est liée à notre activité mentale. Dans une certaine mesure, cela permet, au sens figuré, de lire les pensées de la personne qui a posé sa main sur la souris. C'est dans cette «lecture des pensées» que l'on voit un éventuel vecteur de contre-attaques de «combattants pour la justice».

T.O. la bataille entre les côtés obscur et clair de la force continue. Certains essaient de faire semblant d'être des gens, tandis que d'autres surveillent le comportement atypique de la souris. Créer un émulateur de souris virtuose, c'est comme créer un sabre laser Jedi. Et découvrir le fait de l'émulation virtuose revient à repousser le coup de cette épée avec un autre sabre laser. Alors, qui sera le plus fort?


L'éveil du pouvoir



Fig. 6. Éveil du pouvoir

D'une manière ou d'une autre, peu importe de quel côté nous prenons - pour les bots ou contre eux - nous devons améliorer la technique de possession d'un sabre laser. Dans le sens de développer le muscle de l'ingéniosité d'ingénierie en soi. Son composant principal est la capacité de se concentrer sur la tâche, d'être «ici et maintenant». Essentiellement, cette perfection yogique est le samadhi. Samadhi en sanskrit signifie - pleine concentration sur un sujet. Pleine concentration! Si vous ramassez un faisceau solaire avec une lentille, la surface sur laquelle vous l'avez pointé s'enflamme. De même, en ingénierie. Toute l'énergie que nous avons, nous devons nous concentrer comme une lentille et l'utiliser en ingénierie. Mais n'utilisez pas son énergie au détriment, comme les enfants qui prennent un objectif et commencent à brûler les fourmis. L'énergie créatrice doit être utilisée pour de bon.

# #

-, – , – IDE , , : «#define QUESTION bb || !bb». « – », . – 5000 , – , : , – « ». , «-», «-». , , , , . . , « », 1880- , , . – - ,ce qui peut être lu en détail sur les pages de Srimad-Bhagavatam, qui correspond au son OM de la même manière que les langages de programmation de haut niveau modernes correspondent à l'assembleur (pour plus de détails voir "Code # code" ).


La base de la concentration est un noyau spirituel, pour l'affûtage dont vous pouvez utiliser un gadget de haute technologie comme un «livre». Bon livre spirituel, bien sûr. Un «livre» est le dernier mot de la technologie: 1) il s'ouvre d'un coup de poignet, 2) il est équipé d'un écran sans scintillement, 3) il a une charge de batterie éternelle. Pour l'auteur de l'article, il s'agit de Srimad-Bhagavatam (strictement interdit à l'époque soviétique). Vous pouvez en lire plus dans l'article «Mission du Bhagavatam» .

De plus, pour la concentration, aussi banale soit-elle, vous avez besoin d'un ton sain du corps et de l'esprit. Il y a plusieurs façons de se tonifier. Pour l'auteur de cet article, par exemple, il s'agit d'un régime végétarien (cuisine védique), de vêtements de sport (kmc pour le ski) et de méditation mantra (récitation de Hare Krsna, Hare Krsna, Krsna Krsna, Hare Hare / Hare Rama, Hare Rama, Rama Rama, Hare Hare). Vous pouvez lire sur ce mantra dans l'article «Principe du mantra Hare Krishna» . Vous pouvez utiliser mon expérience ou utiliser votre propre expérience. Et que la force vienne avec nous.

Source: https://habr.com/ru/post/fr389433/


All Articles