Casi OCR para obtener la contraseña de VPNBook. PHP + Mikrotik

Recientemente, VPNBook comenzó a publicar una contraseña en lugar de texto sin formato como imagen. "Bueno, cómo es eso", pensé, y comencé a buscar formas de resolver este problema. Reconocemos la contraseña de "imagen" VPNBook en PHP. Y, por supuesto, un guión para Mikrotik.

Durante mucho tiempo configuré un túnel VPN PPTP gratuito automático desde VPNBook.com en mi enrutador (Mikrotik) y lo usé con éxito hasta hace poco. No entraré en detalles, se describen en el artículo " Configuración de la recepción automática de una contraseña para VPN en Mikrotik ". Antes del problema, la contraseña para el VPNBook podría simplemente extraerse de la página html, por ejemplo, así:

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

Y más recientemente, la contraseña se ha convertido en una "imagen". Y el primer pensamiento fue utilizar el reconocimiento óptico de texto. Comencé a probar los servicios de OCR en línea y sin conexión, que podían reconocer la contraseña. Le envío mis saludos a Winand , con quien mantuvimos correspondencia sobre este tema. En general, el último OCR con el que me metí fue Tesseract, que de inmediato determinó la contraseña, pero con errores. Pero se le pueden enseñar nuevas fuentes, lo que iba a hacer. Cuando tomé una fuente que parecía una "fuente de imagen", surgió la idea de que era algo simple, aunque parecía un terminal de Windows o una fuente terminal de Linux. Y listo, resultó ser solo una fuente PHP integrada con número (tamaño) 5. Luego, abandoné OCR y escribí un script PHP que busca caracteres de la contraseña de "imagen" en el diccionario generado. Un diccionario es un conjunto de imágenes de posibles caracteres de contraseña del mismo color y tamaño. La búsqueda se realiza combinando imágenes. Aquí hay una ingeniería inversa tan simple. Supongo que la versión actual de la imagen en el VPNBook no durará mucho, dada su primitividad.

Script vpnbook.php


Sprite devuelve una cadena de contraseña.

 <?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); ?> 


Plan B. Contraseña de twitter


Con el mensaje vvsvic , proporciono una implementación simple de un script alternativo para recuperar una contraseña de un VPNBook twitter (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 de Mikrotik VPNBook


La secuencia de comandos debe llamarse cada minuto desde el programador. El script monitorea el estado de la conexión PPTP y, tras la desconexión, llama a todo el procedimiento para solicitar una nueva contraseña, por lo que Mikrotik no "inundará los intentos de abrir la conexión durante varias horas con la contraseña incorrecta, y la reconexión se realiza en 1 minuto. También supervisa los errores en caso de error para obtener y obtener el archivo para determinar con mayor precisión que se ha recibido una contraseña.

 # 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 } } 

También recomiendo agregar la desconexión de la interfaz PPTP para desconexión (evento de encendido / apagado) en el perfil PPP para que la reconexión no se inunde en absoluto, incluso en 1 minuto.

En consecuencia, el script principal dentro de 1 minuto en caso de recepción exitosa de una nueva contraseña aumentará la conexión 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/es420373/


All Articles