Ataque dos Clones: Tecnologias Modernas de Condução de Bot

“Agora você escreve o programa mais difícil da sua vida, que simplesmente somará dois números”
Irina Ryzhova


Os jogos inteligentes de apostas online são um petisco para os bots. Mesmo que os desenvolvedores de software de jogos gastem muito dinheiro na captura de bots, como nas salas de pôquer on-line, por exemplo, ainda há uma alta probabilidade de encontrar um "bot inteligente", o jogo com o qual será individual. Especialmente se o bot for absolutamente invulnerável ... Pois nenhum dinheiro protegerá o sistema pelo qual passa muito dinheiro.


Fig. 1. Botovodia vem


Ameaça oculta


Jogos intelectuais de jogos de azar não são seguros. Especialmente inseguros são aqueles onde o dinheiro real gira. A insegurança deles se manifesta principalmente no fato de que é impossível saber com certeza com quem você está jogando: com uma pessoa viva ou com um bot. No segundo caso, o jogo estará em um objetivo. Nos jogos de "interesse", xadrez e damas no mail.ru, por exemplo, os proprietários de jogos online olham para o botovotirovanie com os dedos. Nos jogos on-line multijogador, que de certa forma apresentam dinheiro ao vivo, um pouco mais de atenção é dada à captura de bots. No entanto, mesmo que a abordagem para suprimir o botswood seja extremamente séria - como foi feito, por exemplo, nas salas de pôquer on-line - ainda há uma alta probabilidade de tropeçar em um bot.

Os desenvolvedores de software de pôquer gastam muito dinheiro expondo bots e, no entanto, o botswana de pôquer on-line está crescendo. Pois nenhum dinheiro pode proteger o sistema pelo qual passa muito dinheiro. Botovodov e coletores de bots, - analisando os truques dos oponentes e tomando as contramedidas apropriadas -, vencem alternadamente. Alguém pode pensar que a batalha entre eles nunca terminará. No entanto, existe um esquema seguro de condução de bots na frente do qual os coletores de bots passam. É interessante que, mesmo que os "combatentes da justiça" tenham em suas mãos em detalhes os códigos-fonte comentados do bot, eles não serão capazes de estabelecer o fato de seu uso. A implementação desse esquema é um evento caro, no entanto, como o benefício potencial é grande, o esquema é bastante relevante.

#

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




: , .Primeiro, o bot tira fotos do estado atual do jogo - seja por uma captura de tela ou pela interceptação do tráfego da rede. Em segundo lugar, o bot decide o que fazer nas circunstâncias, às vezes recorrendo a software de terceiros (por exemplo, no caso do xadrez, ele pode interagir com algum tipo de mecanismo de xadrez). Finalmente, em terceiro lugar, o bot emula a interação do usuário com o teclado e o mouse. Além disso, esse ciclo ternário - que os coletores de bot procuram rastrear e quebrar - se repete. Nesse sentido, a batalha entre botovodov e "lutadores pela justiça" ocorre em três frentes. Essa batalha tem uma história longa e emocionante, no entanto, focaremos apenas seu duelo final, no qual os “lutadores pela justiça”, em face de um robô absolutamente invulnerável, sofreram um fiasco incondicional.

A tecnologia invulnerável é alcançada através da fotografia invisível, análise invisível e emulação invisível. É impossível fazer isso em um computador. Primeiro de tudo, porque o software de pôquer moderno possui os elementos de um rootkit.

#

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

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

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

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

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


, .. , .A solução é iniciar o bot não na estação de trabalho em que o jogo é jogado, mas em um computador separado - um emulador. Então, sujeito a três condições paranóicas, o software de pôquer não terá a chance de reconhecer o fato da emulação: 1) a estação de trabalho e o emulador não devem poder se comunicar pela rede; 2) para fotografar o estado atual do jogo, você deve usar a saída analógica da placa de vídeo, - conectada ao “computador de tela” usando uma placa de captura de vídeo; 3) para emular o teclado e o mouse, use um dispositivo de software de hardware, cuja entrada esteja conectada ao computador emulador e a saída - para duas estações de trabalho PS / 2 nas quais o jogo está sendo executado. É a saída de vídeo analógica e o PS / 2 que o software de pôquer não sabe que algum equipamento adicional está conectado ao computador.



Ao emular teclado e mouse, você deve levar em consideração as circunstâncias biométricas e tecnométricas relevantes, que também podem ser monitoradas pelo software de pôquer. Quanto à biometria, ao emular o teclado e o mouse, deve-se tomar cuidado para emular os movimentos do corpo, semelhantes à verdade. Deve-se ter em mente que, em primeiro lugar, uma pessoa viva não pode tocar em um ritmo estável por um longo período imediatamente em 16 mesas simultaneamente - especialmente em um monitor de oito polegadas. Em segundo lugar, uma pessoa viva não pode jogar 28 horas por dia, 6 dias por semana. Finalmente, em terceiro lugar, os movimentos de uma pessoa viva podem mudar - dependendo de quanto tempo ele passou no computador. Para emular circunstâncias biométricas plausíveis, você precisará: 1) "PS / 2-sniffer" - loção de software e hardware,que escutará o fluxo de dados enviado pelo teclado e mouse à porta PS / 2 e salvará tudo o que for ouvido em um arquivo separado, que no futuro será usado para emular circunstâncias biométricas plausíveis; 2) uma pessoa viva que realmente jogará poker online enquanto o bot estiver planejado para ser incluído - são suas ações que serão gravadas pelo “sniffer PS / 2”.

Quanto à tecnometria, cada teclado e mouse tem sua própria “caligrafia”. Ele pode ser rastreado analisando em um nível baixo o fluxo bruto de sinais que vêm deles para o computador. Portanto, se várias estações de trabalho estiverem envolvidas na condução bot de uma só vez, em seguida, na preparação para emulação biométrica, para cada uma delas é necessário: 1) organizar uma escuta individual, - com teclados e mouses diferentes, 2) plantar pessoas diferentes para cada estação de trabalho cujas ações serão ser fixado com um "farejador PS / 2". A necessidade do segundo parágrafo se deve ao fato de cada pessoa usar o mouse e o teclado individualmente. Com material estatístico extensivo suficiente, é possível determinar com um grau suficiente de certeza quem está sentado no computador, mesmo que o usuário não esteja autenticado.

# -

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


Assim, é feita a preparação para a emulação com parâmetros biométricos e tecnométricos plausíveis. Agora resta lembrar que teclado e mouse correspondem a qual usuário - e nunca quebre essa correspondência. Ignorar biometria e tecnometria ou sua emulação implausível pode levar ao bloqueio de contas sem explicação. Sujeito a todas as precauções, não importa quão paranóicas possam parecer, pode-se contar com bots invulneráveis.


Elementos do bot invulnerável



Fig. 2. Bot

invulnerável Um bot invulnerável é um complexo de hardware e software que inclui toda uma frota de computadores que resolverá 6 tarefas fundamentalmente diferentes. Além de algumas loções para hardware e software. Mais duas pessoas vivas, por observar e responder a situações de emergência.

1. Uma estação de trabalho (com IP dedicado ou PROXY de alta qualidade), onde são lançadas 9 salas de pôquer ao mesmo tempo. Ele deve ter uma placa de vídeo com saída de vídeo analógica de alta definição e um monitor grande, porque muitas salas em um monitor pequeno parecem suspeitas. É economicamente mais econômico usar não uma estação de trabalho - mas cerca de dez ao mesmo tempo. Nesse caso, o bot pode ser iniciado simultaneamente em 90 quartos ao mesmo tempo.

2. Screener - um computador poderoso com uma placa de captura de vídeo, conectada por meio de um divisor de vídeo a todas as estações de trabalho. A tarefa do examinador é reconhecer os sinais recebidos e convertê-los em uma forma estrutural. Esses dados serão posteriormente utilizados para 1) gravar no banco de dados, 2) análises e 3) tomar decisões para ação.

3. Analista - um computador poderoso que trabalha com o princípio de um servidor meteorológico, mas, em vez de fenômenos naturais, acumula todos os dados possíveis de pôquer - conta. De fato, há muito mais informações no poker do computador do que no poker ao vivo. Mas o problema é que, sem o software auxiliar, é quase impossível rastreá-los. E o uso desse software é interrompido de todas as formas possíveis - você pode ser banido se o usar em uma estação de trabalho.

4. Spy - contas separadas das quais o jogo não é jogado, mas apenas uma coleção seqüencial de todas as informações disponíveis em todas as salas disponíveis. Deve haver vários espiões, porque, se a mesma conta se conectar ao jogo e se encerrar no final, ela poderá lançar uma moeda sistemática no cofrinho de suspeitas e, quando esse cofrinho estiver cheio, simplesmente fechamos a conta sem fornecer nenhum motivo. Um "espião" deve funcionar com o mesmo princípio que uma "estação de trabalho". Pode parecer que há tela de software e emulação de software suficientes de um mouse com um teclado. No entanto, como o software de pôquer pode se vincular ao hardware e às contas subsequentes do coelho, a triagem e a emulação de hardware devem ser feitas para um espião - assim como para uma estação de trabalho.

5. Emulador - um computador cujo poder não é fundamental. Está conectado a vários divisores para mouse e teclado. A partir desses divisores, os fios vão para as entradas PS / 2 do mouse e do teclado para cada uma das estações de trabalho e espiões. Este computador recebe comandos do analista e os envia para as estações de trabalho. Levando em consideração os recursos de hardware do mouse e teclado e as características fisiológicas do comportamento da pessoa que trabalha por trás deles (biometria e tecnometria).

6. Dois observadores vivos. Já não são computadores, ou seja, pessoas vivas. Eles são necessários, porque os desenvolvedores do software de pôquer não estão dormindo e, a qualquer momento, podem executar algum teste exclusivo para identificar os drivers dos bots. Uma pessoa não é suficiente - porque ela pode sair de acordo com a necessidade ou pulverizar o nariz e, nesse momento, alguma situação de emergência surgirá. Há situações em que tudo é decidido por segundos. Portanto, é importante que alguém esteja sempre perto das máquinas. Para que, quando o “botão vermelho acender” (quando o analista encontrar um comportamento desconhecido), uma pessoa possa dizer a ele o que fazer (escreva algo no bate-papo ou feche a janela). E, em nenhum caso, você pode ir diretamente para a estação de trabalho, para não quebrar o modelo comportamental correspondente do teclado e do mouse.As ações devem ser executadas apenas através do "posto de comando".

7. Posto de comando - um computador cujo poder também não é fundamental. Ele deve estar conectado apenas ao emulador. Essa é exatamente a máquina na qual dois observadores vivos se sentam e através dos quais, se necessário, fazem os ajustes necessários no comportamento do bot.


Toques finais


Então, esses são 7 elementos de um bot invulnerável. Ao conectá-los, observe que o rastreador, o analista e o emulador trocam dados pela rede. A interação com estações de trabalho e espiões ocorre estritamente através da saída analógica da placa de vídeo e do PS / 2. Além disso, esses computadores devem estar fisicamente separados de todos os outros. Não se pode falar em comunicação entre eles pela rede. Devido à complexidade de um complexo de software e hardware, também é importante ter o cuidado de minimizar os erros associados ao fator humano. Para fazer isso, o emulador, entre outras coisas, cuida do lançamento de todo o software necessário nas estações de trabalho e em um espião. Um examinador, um analista e um emulador devem estar em alerta imediatamente após serem ligados - o software correspondente deve estar simplesmente na inicialização.


Nova esperança



Fig. 3. Nova esperança

O esquema descrito de dirigir bot, mesmo com uma familiarização superficial com ele, não é para os fracos de coração. Mas o acima é dado, embora detalhado, mas ainda assim - sua descrição superficial. Para sua implementação, não se deve ter uma qualificação técnica robusta, tanto em programação quanto em eletrônica. Ao programar, um desenvolvedor precisará de conhecimentos de áreas como matemática discreta, aproximação de splines, transformadas de wavelets, redes neurais, máquinas de estado, lógica nebulosa, programação multithread, processamento de sinal digital. Ao implementar o hardware do bot, o desenvolvedor precisará de conhecimentos de áreas como sistemas de microprocessadores, tecnologia digital e de microprocessadores, trabalhando com microcontroladores e FPGAs, noções básicas de engenharia elétrica, programação de drivers de baixo nível, arquitetura de SO e arquitetura de processador.

#

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


Portanto, este é um esquema seguro de condução de bots. Como foi dito no início, é interessante que, mesmo que os “combatentes da justiça” tenham em suas mãos comentários detalhados sobre os códigos-fonte do bot, eles não serão capazes de estabelecer o fato de seu uso. Enquanto um bot comum - sem a função de invisibilidade - "lutadores pela justiça" pode rastrear, mesmo sem sua fonte. As tecnologias modernas, em particular os rootkits, que os desenvolvedores de software de pôquer têm grandes esperanças, permitem que eles se aprofundem no sistema operacional e assim por diante. agir de acordo com o princípio de "ficar sentado, olhando para longe". Com o desenvolvimento de rootkits e outras tecnologias de proteção, os “lutadores pela justiça” têm uma nova esperança de vitória incondicional. No entanto, o esquema acima de dirigir com segurança bot reduz todas essas esperanças a nada.A implementação desse esquema é um evento caro, no entanto, como o benefício potencial é grande, o esquema é bastante relevante. Portanto, faz sentido ousar.


Vingança dos Sith


Mal disse o que fez. Atreva-se! Mas vale a pena dedicar algum tempo ao restante do artigo? Um engenheiro de TI de primeira classe, cuja afiliação com a liga principal da cena X é confirmada por algo mais significativo do que apenas um belo selo em um diploma, definitivamente não vale a pena. Em seu arsenal X, já existem truques místicos suficientes para "vingar" bots antigos sem a ajuda de outra pessoa, que uma vez bloqueou o oxigênio no "lado positivo da força".

Desenvolvedores avançados, cujo envolvimento com a cena X é apenas devido ao seu virtuosismo em C ++ e assembler, não devem perder tempo, mas por um motivo diferente, eles não o farão. O grau de detalhe do material apresentado é insuficiente para eles, pois neste artigo não apenas muitas tarefas triviais de programação são deliberadamente deixadas de fora (um desenvolvedor avançado lida com elas uma a duas), mas também alguns conceitos fundamentais de engenharia. Quanto aos scripts de script, que nem falam C ++ conversador e assembler, não há dúvida sobre os benefícios deste artigo para eles.

No entanto, um engenheiro comum, que já deixou o desenvolvimento na adolescência (que desenvolveu um pouco de engenhosidade em engenharia), mas ainda não entrou na era da engenharia para adultos, encontrará aqui idéias interessantes que o ajudarão a perceber o bot invulnerável. Na medida em que ele já é capaz de encontrar soluções simples para tarefas aparentemente complexas, usando os recursos disponíveis. E este é precisamente o poder místico que é valorizado na cena X, tanto nos lados claros quanto escuros. A capacidade de possuí-lo é o que distingue um engenheiro de um desenvolvedor. Então, vamos definir os “lutadores pela justiça” no calor, mostrando do que o lado sombrio do poder é capaz.


Império contra-ataca



Fig. 4. O império contra-ataca As

boas notícias: a parte mais difícil acabou. O plano de ação estratégico, que também é uma declaração informal do problema, está pronto. Agora resta apenas especificar e detalhar um pouco - descrever em ações táticas. No estágio de detalhamento, o mais importante é caminhar com calma "do geral para o particular" e assim por diante. para formar o quadro do projeto futuro. Ao mesmo tempo, sem entrar em detalhes da implementação de unidades funcionais específicas, mas simplesmente consertando-as. Cuidaremos de seus detalhes mais tarde, quando o quadro já estiver completamente pronto.

#

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


Para maior clareza, usaremos a sintaxe da linguagem Fort (não confunda com Fortran). Essa é uma linguagem única que naturalmente favorece o movimento racional da engenharia. A beleza de uma abordagem tão “emprestada por Fort” é que todas as deficiências conceituais do projeto são identificadas na costa, e não no meio de sua implementação, o que desde o início contribui para o desenvolvimento de alta qualidade. Sem a necessidade de refatoração subsequente. Assim, o quadro "de geral para particular":
A estrutura "de geral para particular"
: -
  - -
  - -
  - --
  -
;

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

: -
   --
  - -
  --
;

: -
  - --
  - -
  --
;

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

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

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

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

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

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

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

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


Outra vantagem de usar a sintaxe da linguagem Fort ao elaborar a estrutura geral do projeto é a capacidade de compilar imediatamente o texto escrito. Porque este texto é ele próprio um programa. Em princípio, se você implementar todos os nós funcionais ausentes usando a linguagem Fort e adicioná-los à estrutura acima, obterá o mesmo bot invulnerável em que estamos trabalhando. Será muito conciso. No entanto, os trechos de código abaixo serão escritos em linguagens mais tradicionais - C ++ e assembler. A apresentação “emprestada a forte” neste caso é interessante apenas para fins ilustrativos da estrutura geral do projeto. Então, “calmamente de geral para particular” passou, agora vamos considerar com mais detalhes os detalhes da implementação de alguns nós funcionais do bot.


Fotografia invisível


Aqui temos três tarefas fundamentais: 1) encontrar uma solução de hardware aceitável, 2) desenvolver uma estrutura de dados que será lida nas fotos, 3) implementar uma função de reconhecimento. O resultado da fase de fotografia deve ser uma estrutura de dados completa e redundante, com base na qual o autômato da lógica será capaz de identificar exclusivamente o estado atual do jogo - para o menor número possível de fotos consecutivas.

1. Quanto à solução de hardware, a opção ideal (do ponto de vista econômico e do ponto de vista da facilidade da programação subseqüente) é que todos os sinais de vídeo converjam em um divisor de vídeo, que pode ser trocado de um computador. Nesse caso, a tarefa do rastreador pode ser executada por um computador com uma placa de captura de vídeo. Para cada espião e estação de trabalho, neste caso, será necessário criar uma pasta - as capturas de tela correspondentes serão salvas lá. Se essa opção não puder ser implementada (devido à inacessibilidade do equipamento apropriado e / ou devido a qualificações técnicas insuficientes para adaptar o equipamento existente às suas próprias necessidades), você poderá usar vários computadores conectados a uma rede local,em cada uma das quais haverá várias placas de captura de vídeo - uma para cada "espião" e "estação de trabalho". Nesse caso, será necessário adicionar todos os bitmaps selecionados a uma pasta de rede compartilhada ou gravar nos soquetes do aplicativo cliente-servidor, que coletarão todos os bitmaps em um único local. Para baixar bitmaps, para fins do reconhecimento subsequente, você pode usar o seguinte código:
Baixar 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. Quanto à estrutura de dados, pode ser a seguinte:
Estrutura de dados
// 
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. Uma das opções possíveis para a função de reconhecimento é configurar uma rede neural para isso. Este tópico merece uma discussão separada; portanto, não falaremos sobre a abordagem de rede neural neste artigo. Uma opção mais simples é anexar aos bitmaps correspondentes. Aqui está a aparência da estrutura de dados correspondente:

Estrutura de dados de reconhecimento
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;


A maneira mais fácil de preenchê-lo é manual. Basta tirar uma captura de tela, abri-la no Photoshop, ativar a ferramenta Conta-gotas e reescrever os números das áreas de interesse para nós. Esta decisão não pode ser considerada concisa, mesmo com um grande esforço. Além disso, possui uma limitação significativa - mesmo as menores alterações no cronograma do software de pôquer farão com que o bot pare de funcionar. No entanto, se a qualificação técnica não permitir que você invente algo mais interessante, eis a aparência da preparação para o "reconhecimento manual" (aqui está apenas uma pequena seleção do código de quase 2000 linhas):
Reconhecimento manual
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;
}


E aqui está um exemplo de código que usa esses bitmaps para reconhecimento:
Exemplo de código de reconhecimento
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;



De uma maneira ou de outra - apesar de usarmos uma rede neural, pelo menos com as mãos, pelo menos com algo em terceiro lugar - no reconhecimento, quatro áreas fundamentalmente diferentes devem ser levadas em consideração: 1) estática (aquelas em que, segundo a teoria, nada acontece); incluindo externo ao software de pôquer (por exemplo, algum tipo de ação surge fora do cliente de pôquer, supostamente do sistema Windows, mas na verdade - verifica a possibilidade de botabilidade); 2) dinâmica altamente informativa (tamanho da pilha, jogador atual, cartas na mesa, etc.); 3) dinâmico pouco informativo (locais onde as mensagens raramente aparecem e conversam); 4) dinâmico não informativo (por exemplo, áreas nas quais ocorre a animação da distribuição de cartões).


Análise invisível


A parte analítica do bot, no caso do pôquer, é um mecanismo de interação com o banco de dados - já que quase todas as "informações" relevantes ao pôquer online dependem da análise do modelo comportamental dos oponentes dos jogos. A opção ideal aqui é o seu próprio Oracle em casa, indispensável em trabalhos intensivos com um grande banco de dados que inclui centenas de milhares de registros. Nomeadamente, haverá muitos deles se você planeja se envolver seriamente na agricultura botânica e por um longo tempo. Se você só precisa de um bot para entrar, não poderá gastar dinheiro com o Oracle. O DBMS do MS Access também é bastante adequado - você pode contatá-lo facilmente do seu programa, por exemplo, através do ODBC. Aqui está o que pode parecer:
Interação com o 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;
}


Se não se trata de pôquer, mas de xadrez, por exemplo, uma troca com um mecanismo de xadrez de terceiros pode ser implementada como uma parte analítica. Por exemplo, veja como interagir com Fritz:
Interação com o mecanismo analítico
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;
}



Outra ferramenta que pode ser útil na programação de análises é a chamada. "Máquinas de estados finitos". Veja como eles podem ser usados ​​em jogos multiplayer online (este é um fragmento do bot do jogo "Keepers of Power"):
Exemplo de máquina de estado
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;
  }




Emulação invisível


Existem duas etapas - preparatória e operacional. Um e outro implicam não apenas escrever os programas apropriados, mas também trabalhar com ferro. Aqui você não pode ficar sem imersão em microcontroladores. Felizmente, não há necessidade de reinventar a roda - existem soluções prontas de software e hardware que podem ser facilmente encontradas na Internet. Incluindo o código fonte do programa para o microcontrolador, que pode ser facilmente adaptado às suas necessidades.

Quanto à fase preparatória (registrando horas de trabalho com o mouse e o teclado), aqui, se desejar, você pode fazer sem dispositivos de hardware. Você pode escrever um filtro de driver que captura chamadas para IOCTL_INTERNAL_I8042_HOOK_KEYBOARD. Como base, você pode usar o programa ctrl2cap, cujo código fonte está disponível no DDK. No entanto, esta solução não é universal - é melhor usar um sniffer de hardware.

Quanto à fase operacional, definitivamente não há como prescindir de dispositivos de hardware. Uma das soluções possíveis poderia ser a comunicação com um dispositivo de microcontrolador (que também será um divisor em combinação), por um lado, através do RS-232 e, por outro lado, através de um buquê de PS / 2. Para trabalhar com o RS-232, existem duas opções - você pode usar ferramentas comuns do Windows e se comunicar via CreateFile / ReadFile / WriteFile com a porta RS-232 ou diretamente pelas portas de entrada / saída. No segundo caso, você precisará escrever um driver simples que desbloqueie o acesso às portas de E / S, porque, por padrão, no Windows, o acesso a elas está fechado. Afaste-se do pecado. Se você ainda conseguiu acessar as portas de entrada / saída, eis o código para a troca de dados via RS-232:
Código 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


Portanto, é compreensível o mecanismo para interceptar e emular sinais do teclado com um mouse; resta apenas descobrir como criar um modelo de comportamento confiável do ponto de vista da biometria a partir de um fluxo contínuo de dados de teclado e mouse recebidos de um farejador. Além disso, uma das tarefas mais interessantes nesse estágio é como mover o mouse do ponto inicial para outro, definido especificamente.

Uma das soluções possíveis inclui dois elementos: 1) configurar a rede neural, 2) ajustar o movimento e ensinar a rede neural a trabalhar em conjunto com o "rastreador". Com essa abordagem, é possível treinar uma rede neural com mínimo envolvimento humano. O algoritmo de treinamento de rede neural pode ser o seguinte:
  1. Selecionamos coordenadas aleatórias para onde o mouse deve ser movido.
  2. Nós os alimentamos junto com as coordenadas atuais da rede neural.
  3. Observamos o quanto a rede neural estava errada.
  4. Ajustamos a rede neural.
  5. Repita 1-4 até vitorioso. Dados os dados recebidos do sniffer de hardware, para que a rede neural não apenas mova com precisão o cursor do mouse, mas também o faça biometricamente de maneira plausível.



O que vem a seguir


A implementação desse esquema de rede neural, bem como o esquema de reconhecimento de tela de rede neural mencionado acima, é um tópico para uma discussão separada que está além do escopo deste artigo. Essas duas tarefas que foram além do escopo do artigo são os "conceitos fundamentais de engenharia" que o "engenheiro intermediário" é convidado a resolver de maneira independente. Quanto aos "problemas triviais de programação", a implementação da maioria deles também não está incluída neste artigo. As dez listagens listadas no artigo são apenas uma semente, projetada para ajudar a promover o apetite da engenharia.

Outro ponto importante. Usando este artigo ao desenvolver seu próprio bot, você deve entender: quando várias opções alternativas (ideais e comprometidas) são oferecidas para implementar um nó funcional específico, a opção é retórica. Entende-se que a opção ideal será usada. Se você fizer compromissos, mesmo que apenas um, o bot ficará vulnerável aos contra-ataques do "lado positivo da força".


O retorno dos Jedi



Fig. 5. Retorno dos Jedi

Então, o esquema acima descrito de condução invulnerável de bots, que em face dos "combatentes da justiça" - afirma ser a vitória final e irrevogável. No entanto, seria chato se os Jedi do "lado positivo do poder" não tivessem a oportunidade de opor nada às mulheres-robôs. Além disso, se isso não fosse possível, o autor - tentando aderir ao "lado positivo da força" - não publicaria esse esquema. Além disso, quero acreditar que uma parte significativa dos leitores também adere ao "lado positivo da força" e seu interesse não está em abusar desse esquema, mas em como resistir a ele. O artigo não fornece códigos fonte detalhados e omite alguns conceitos fundamentais de engenharia - precisamente para evitar abusos.

Algumas palavras sobre como você pode resistir ao esquema descrito de produção botânica. Ela é praticamente invulnerável. No entanto, a possibilidade teórica de sua descoberta permanece. Esse recurso está associado ao rastreamento do comportamento atípico do mouse que pode escorregar, mesmo no caso de emulação de alta qualidade. O fato é que o mouse carrega muitas "informações biométricas" em sua cauda, ​​- expressas na linguagem do pôquer. Ela é a mais próxima da pessoa. O menor movimento muscular causado por uma mudança no contexto emocional - tudo isso afeta a forma como seguramos o mouse em nossas mãos.

A esse respeito, o autor do artigo possui um estudo biônico original, sob o título de trabalho "Arquitetura Integrada do Homo Sapiens", que inclui uma descrição da fisiologia e da psique de uma pessoa - em modelos adequados para a operação de TI. Graças aos resultados positivos deste estudo, sinto o direito moral de tornar público o esquema de condução bot “invulnerável”, porque o "lado positivo do poder" tem uma chance de vencer. A partir deste estudo, entre outras coisas, pode-se entender como o uso do mouse, através da interface da medula espinhal, está relacionado à nossa atividade mental. Até certo ponto, isso permite, figurativamente falando, ler os pensamentos da pessoa que colocou a mão no mouse. É nessa “leitura de pensamentos” que se vê um possível vetor de contra-ataques de “lutadores pela justiça”.

T.O. a batalha entre os lados escuro e claro da força continua. Alguns tentam fingir ser pessoas, enquanto outros monitoram o comportamento atípico do mouse. Criar um emulador de mouse virtuoso é como criar um sabre de luz Jedi. E descobrir o fato da emulação virtuosa é o mesmo que repelir o golpe desta espada com outro sabre de luz. Então, quem será mais forte?


O despertar do poder



Fig. 6. Despertar do poder

De um jeito ou de outro, não importa de que lado tomemos - por bots ou contra eles - precisamos melhorar a técnica de possuir um sabre de luz. No sentido de desenvolver o músculo da engenharia em si mesmo. Seu principal componente é a capacidade de se concentrar na tarefa, de estar "aqui e agora". Essencialmente, essa perfeição yogue é samadhi. Samadhi em sânscrito significa - concentração total em um assunto. Concentração total! Se você capta um feixe solar com uma lente, a superfície para a qual você apontou é acesa. Da mesma forma, em engenharia. Toda a energia que temos, precisamos nos concentrar como lentes e usá-las na engenharia. Mas não use sua energia em detrimento, como crianças que tomam uma lente e começam a queimar formigas. A energia criativa deve ser usada para o bem.

# #

-, – , – IDE , , : «#define QUESTION bb || !bb». « – », . – 5000 , – , : , – « ». , «-», «-». , , , , . . , « », 1880- , , . – - ,o que pode ser lido em detalhes nas páginas do Srimad-Bhagavatam, que corresponde ao som da OM, da mesma maneira que as linguagens de programação modernas de alto nível correspondem ao assembler (para obter mais detalhes, consulte "Código do código" ).


A base da concentração é um núcleo espiritual, para o qual você pode usar um dispositivo de alta tecnologia como um "livro". Bom livro espiritual, é claro. Um “livro” é a última palavra em tecnologia: 1) abre com um movimento do pulso, 2) é equipado com uma tela sem tremulação, 3) possui uma carga eterna na bateria. Para o autor do artigo, este é o Srimad-Bhagavatam (estritamente proibido nos tempos soviéticos). Você pode ler sobre isso no artigo “Missão do Bhagavatam” .

Além disso, para se concentrar, não importa quão comum, você precisa de um tom saudável do corpo e do espírito. Existem muitas maneiras de tonificar. Para o autor deste artigo, por exemplo, esta é uma dieta vegetariana (cozinha védica), roupas esportivas (kmc para esquiar) e meditação de mantras (recitação de Hare Krsna, Hare Krsna, Krsna Krsna, Hare Hare / Hare Rama, Hare Rama, Rama Rama, Hare Hare). Você pode ler sobre esse mantra no artigo "Princípio do Hare Krishna Mantra" . Você pode usar minha experiência ou usar algo de sua preferência. E que a força venha conosco.

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


All Articles