Quase OCR para obter a senha do VPNBook. PHP + Mikrotik

Recentemente, o VPNBook começou a publicar uma senha em vez de texto sem formatação como uma imagem. "Bem, como assim", pensei, e comecei a procurar maneiras de resolver esse problema. Reconhecemos a senha da "imagem" VPNBook em PHP. E, claro, um script para Mikrotik.

Durante muito tempo, configurei um túnel PPTP VPN automático gratuito a partir do VPNBook.com no meu roteador (Mikrotik) e o usei com sucesso até recentemente. Não vou entrar em detalhes, eles estão descritos no artigo " Configurando o recebimento automático de uma senha para VPN no Mikrotik ". Antes do problema, a senha do VPNBook poderia simplesmente ser extraída da página html, por exemplo, assim:

preg_match('/Password: <strong>([^<]+)/', $homepage, $matches); print($matches[1]) 

E, mais recentemente, a senha se tornou uma "imagem". E o primeiro pensamento foi usar o reconhecimento óptico de texto. Comecei a experimentar os serviços de OCR online e offline, que reconheciam a senha. Dirijo meus cumprimentos a Winand , com quem nos correspondemos sobre esse assunto. Em geral, o último OCR com o qual eu mexi foi o Tesseract, que fora da caixa determinava a senha, mas com erros. Mas ele pode aprender novas fontes, o que eu ia fazer. Quando escolhi uma fonte que parecia uma “fonte de imagem”, surgiu a ideia de que era algo simples, embora parecesse um teminal do Windows ou uma fonte terminal do Linux. E pronto - acabou sendo apenas uma fonte PHP embutida com número (tamanho) 5. Em seguida, abandonei o OCR e escrevi um script PHP que procura por caracteres da senha "picture" no dicionário gerado. Um dicionário é um conjunto de imagens de possíveis caracteres de senha da mesma cor e tamanho. A pesquisa é feita por imagens correspondentes. Aqui está uma engenharia reversa tão simples. Presumo que a versão atual da imagem no VPNBook não dure muito, dada a sua primitividade.

Script Vpnbook.php


Sprite retorna uma string de senha.

 <?php //   $wchar = 9; $hchar = 13; $strDict = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 '; $imgDict = imagecreatetruecolor(2 + strlen($strDict)* $wchar, $hchar); $bg = imagecolorallocate($imgDict, 0xF6, 0xF6, 0xF6); $textcolor = imagecolorallocate($imgDict, 0x4C, 0x4C, 0x4C); imagefill($imgDict, 0, 0, $bg); imagestring($imgDict, 5, 2, 0, $strDict, $textcolor); //  cURL $ch = curl_init(); //  url,      curl_setopt($ch, CURLOPT_URL, 'https://www.vpnbook.com/password.php'); //  ,      string curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1); // also, this seems wise considering output is image. //   $output = curl_exec($ch); //  cURL curl_close($ch); $imgOCR = imagecreatefromstring($output); // $imgOCR = imageCreateFromPng('password.png'); //      10  . 2 + 10*9 = 92 < 100 $maxchar = floor((imagesx($imgOCR) - 2) / 9); $imgBox = imagecreatetruecolor($wchar, $hchar); $hashDict = Array(); //   for ($k = 0; $k < strlen($strDict) ; $k++) { imagecopy($imgBox, $imgDict, 0, 0, 2 + $k * $wchar, 0, $wchar, $hchar); $hashStr = ""; for($y = 0; $y < $hchar ; $y++) for($x = 0; $x < $wchar; $x++) $hashStr .= (imagecolorat($imgBox, $x, $y) != 0xF6F6F6)? '1': '0'; $hashDict[$hashStr] = $strDict[$k]; } //     for ($k = 0; $k < $maxchar ; $k++) { imagecopy($imgBox, $imgOCR, 0, 0, 2 + $k * $wchar, 0, $wchar, $hchar); $hashStr = ""; for($y = 0; $y < $hchar ; $y++) for($x = 0; $x < $wchar; $x++) $hashStr .= (imagecolorat($imgBox, $x, $y) != 0xF6F6F6)? '1': '0'; $tempchar = $hashDict[$hashStr]; if ($tempchar==' ') break; print($tempchar); } /*header('Content-type: image/png'); imagepng($imgOCR); */ //var_dump($hashDict); imagedestroy($imgDict); imagedestroy($imgOCR); imagedestroy($imgBox); ?> 


Plano B. Senha do twitter


Com o prompt vvsvic , estou fornecendo uma implementação simples de um script alternativo para recuperar uma senha de um twitter do VPNBook (https://twitter.com/vpnbook/)
 <?php function url_get_html($url) { //  cURL $ch = curl_init(); //  url      curl_setopt($ch, CURLOPT_URL, $url); //        string curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //   $output = curl_exec($ch); //  cURL curl_close($ch); //   return $output; } $homepage = url_get_html('https://twitter.com/vpnbook'); preg_match('/Password: ([^<]+)/', $homepage, $matches); // Print the entire match result // var_dump($matches); print($matches[1]) // print_r($matches); ?> 


Script Mikrotik VPNBook


O script deve ser chamado a cada minuto no sheduler. O script monitora o status da conexão PPTP e, após a desconexão, chama todo o procedimento para solicitar uma nova senha, para que o Mikrotik não “tente inundar as tentativas de abrir a conexão por várias horas com a senha errada, e a reconexão seja feita em 1 minuto. Ele também monitora os erros de erro na busca e no arquivo para determinar com mais precisão que uma senha foi recebida.

 # VPNBookScript v2 :global VPNBookpIfName "pptp-out1" :global VPNBookServerAddresses {"euro217.vpnbook.com";"euro214.vpnbook.com";"us1.vpnbook.com";"us2.vpnbook.com";"ca1.vpnbook.com";"de233.vpnbook.com";"fr1.vpnbook.com"} #:if ([:typeof $VPNBookServerAddresses] != "array") do={ # :set VPNBookServerAddresses {"euro217.vpnbook.com";"euro214.vpnbook.com";"us1.vpnbook.com";"us2.vpnbook.com";"ca1.vpnbook.com";"de233.vpnbook.com"} #} :global VPNBookErr false :global VPNBookPassFile "VPNBookPass.txt" :global VPNBookPass :global VPNBookRun #:global TToken "4.....................2" #:global TChatId "2342432...9" :global VPNBookServerIndex :if ([:typeof $VPNBookServerIndex] != "num") do={:set VPNBookServerIndex 0} :if ([/interface pptp-client get $VPNBookpIfName running]) do={ :set VPNBookRun true } else { :if (!$VPNBookRun) do={ :set VPNBookServerIndex ($VPNBookServerIndex + 1) :if ($VPNBookServerIndex>=[:len $VPNBookServerAddresses]) do={:set VPNBookServerIndex 0} } else { :set VPNBookRun false } :if (![/interface pptp-client get $VPNBookpIfName disabled]) do={/interface pptp-client set $VPNBookpIfName disabled=yes} :do {/tool fetch url="http://server/vpnbookpass.php" dst-path=$VPNBookPassFile} on-error={:set VPNBookErr true} :delay 2 :do {:set VPNBookPass [/file get $VPNBookPassFile contents]} on-error={:set VPNBookErr true} :if (!$VPNBookErr) do={ :if ([/interface pptp-client get $VPNBookpIfName password] != $VPNBookPass) do={/interface pptp-client set $VPNBookpIfName password=$VPNBookPass} :if ([/interface pptp-client get $VPNBookpIfName connect-to] != $VPNBookServerAddresses->$VPNBookServerIndex) do={/interface pptp-client set $VPNBookpIfName connect-to=($VPNBookServerAddresses->$VPNBookServerIndex)} :log info ("VPNBook: Attempt to connect to: ".($VPNBookServerAddresses->$VPNBookServerIndex).". Password: $VPNBookPass") # /tool fetch url=("https://api.telegram.org/bot$TToken/sendmessage\?chat_id=$TChatId&text=VPNBook: Attempt to connect to: ".($VPNBookServerAddresses->$VPNBookServerIndex).". Password: $VPNBookPass") keep-result=no /interface pptp-client set $VPNBookpIfName disabled=no } } 

Também recomendo adicionar a desconexão da interface PPTP para desconexão (evento on-down) no perfil PPP, para que a reconexão não seja inundada, mesmo dentro de 1 minuto.

Assim, o script principal dentro de 1 minuto, no caso de recebimento bem-sucedido de uma nova senha, aumentará a conexão pptp-out1.

 add change-tcp-mss=yes name=VPNBook on-down=\ ":if (![/interface pptp-client get pptp-out1 disabled]) do={\r\ \n /interface pptp-client set pptp-out1 disabled=yes\r\ \n}" only-one=yes use-compression=yes use-encryption=required use-ipv6=no use-mpls=no use-upnp=no 

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


All Articles