Fast OCR, um ein VPNBook-Passwort zu erhalten. PHP + Mikrotik

Vor kurzem hat VPNBook begonnen, ein Kennwort anstelle von einfachem Text als Bild zu veröffentlichen. "Nun, wie so", dachte ich und suchte nach Wegen, um dieses Problem zu lösen. Wir erkennen das "Bild" Passwort VPNBook in PHP. Und natürlich ein Drehbuch für Mikrotik.

Ich habe lange Zeit einen automatischen kostenlosen PPTP-VPN-Tunnel von VPNBook.com auf meinem Router (Mikrotik) eingerichtet und ihn bis vor kurzem erfolgreich verwendet. Ich werde nicht auf Details eingehen , sie werden im Artikel " Konfigurieren des automatischen Empfangs eines Passworts für VPN auf Mikrotik " beschrieben. Vor dem Problem konnte das Kennwort für das VPNBook einfach wie folgt aus der HTML-Seite extrahiert werden:

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

Und in jüngerer Zeit ist das Passwort ein "Bild" geworden. Und der erste Gedanke war die optische Texterkennung. Ich fing an, Online- und Offline-OCR-Dienste auszuprobieren, die das Passwort erkennen konnten. Ich grüße Winand , mit dem wir zu diesem Thema korrespondiert haben. Im Allgemeinen war die letzte OCR, mit der ich mich herumgetrieben habe, Tesseract, der das Passwort sofort festlegte, jedoch mit Fehlern. Aber ihm können neue Schriften beigebracht werden, was ich tun wollte. Als ich eine Schriftart aufnahm, die wie eine „Bildschrift“ aussah, kam mir die Idee, dass es etwas Einfaches war, obwohl es wie ein Teminal von Windows oder eine Terminus-Schrift von Linux aussah. Und voila - es stellte sich heraus, dass es sich nur um eine integrierte PHP-Schriftart mit der Nummer (Größe) 5 handelt. Als Nächstes habe ich OCR aufgegeben und ein PHP-Skript geschrieben, das im generierten Wörterbuch nach Zeichen des Kennworts "Bild" sucht. Ein Wörterbuch besteht aus einer Reihe von Bildern möglicher Kennwortzeichen derselben Farbe und Größe. Die Suche erfolgt durch übereinstimmende Bilder. Hier ist so ein einfaches Reverse Engineering. Ich gehe davon aus, dass die aktuelle Version des Images auf dem VPNBook aufgrund seiner Primitivität nicht lange halten wird.

Vpnbook.php-Skript


Sprite gibt eine Passwortzeichenfolge zurück.

 <?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. Passwort von Twitter


Mit der Eingabeaufforderung vvsvic biete ich eine einfache Implementierung eines alternativen Skripts zum Abrufen eines Kennworts von einem VPNBook-Twitter an (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); ?> 


Mikrotik VPNBook-Skript


Das Skript muss jede Minute vom Sheduler aufgerufen werden. Das Skript überwacht den Status der PPTP-Verbindung und ruft beim Trennen die gesamte Prozedur zum Anfordern eines neuen Kennworts auf, sodass Mikrotik nicht versucht, die Verbindung für mehrere Stunden mit dem falschen Kennwort zu öffnen, und die erneute Verbindung erfolgt in 1 Minute. Es überwacht auch Fehler beim Abrufen und Abrufen von Dateien, um genauer festzustellen, ob ein Kennwort empfangen wurde.

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

Ich empfehle außerdem, die Trennung der PPTP-Schnittstelle für die Trennung (On-Down-Ereignis) im PPP-Profil hinzuzufügen, damit die erneute Verbindung auch innerhalb von 1 Minute überhaupt nicht überflutet wird.

Dementsprechend wird das Hauptskript innerhalb von 1 Minute bei erfolgreichem Empfang eines neuen Passworts die pptp-out1-Verbindung herstellen.

 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/de420373/


All Articles