Obsługa recaptcha (Prośba do Olesio)

0

Witam, mam problem jak w temacie - chcę móc obsłużyć dowolną recaptchę (tak, chodzi o TEN konkretny system) za pomocą delphi. Oczywiście nie mam zamiaru jej odczytywać/hackować (choć posiadając dobry OCR -jest to możliwe ;P), ale o to bym mógł w moim programie wyświetlić dany obrazek oraz okienko, w które to użytkownik wpisze zawartość danego obrazka. Potem oczywiście muszę przesłać to pod odpowiedni adres.

Niestety jeżeli chodzi o java script (a w nim napisana jest recaptcha) to ja ani be ani me, więc potrzebuję pomocy...

Skierowałem prośbę do Olesia, bo w innym temacie zamieścił link do źródła programu, który (mam nadzieję) powinien pomóc w moim problemie. Niestety link wygasł.

Oto ten temat:
http://4programmers.net/Forum/656722?h=captcha#id656722

0

Jeżeli chodzi o recaptche konkretnie, to o ile się orientuje nie wymaga JavaScruptu trzeba tylko
pobrać odpowiednie dane, w odpowiedni sposób. Mi pomógł to zrobić MisiekD podsyłajac kiedyś
przykładowe źródłó oczywiście z wykorzystaniem preferowanego przez nas Synapse. Pod linkiem
poniżej znajduje się kod programu, który bez problemów skompilujesz. Loguje się on na jeden z
serwisów torentowych, który wykorzystuje właśnie ReCaptcha. Są na nim jeszcze dostepne free
konta, także możesz założyć i przetestować lub przeanalizować sobie kod źródłowy i dostosować
do innego serwisu. Myślę, że kod jest na tyle przejrzysty, że dojdziesz dzięki niemu jak obsłużyć
ReCaptche. Link do źródeł: http://www.speedyshare.com/files/24497887/login_to_pb.rar i już
kończę tę odpowiedź, bo znowu się trochę rozpisałem, a i tamten kod z wątku, do którego linka
podałeś też obsługuje Captche, ale inną, która jest na stronie bramki sms Orange. I podesłałem
go wtedy pytającej osobie, bo chodziło o pokazanie Gifa - załadowanego ze strony internetowej.

0

Wprawdzie to prośba do Olesio ale pozwolę sobie udzielić kilku wskazówek (nie chce mi się kodzić zresztą nie będę pozbawiał Cię tej przyjemności).

Po pierwsze analiza kodu HTML strony dajmy na to http://www.google.com/recaptcha/demo/
od razu widać fragment:

<script type="text/javascript" src="//www.google.com/recaptcha/api/challenge?k=6Ld4iQsAAAAAAM3nfX_K0vXaUudl2Gk0lpTF3REf"></script>

to oczywiście adres skryptu który musisz pobrać a później sparsować (najlepiej za pomocą wyrażeń regularnych) masz np. :

var RecaptchaState = {
    site : '6Ld4iQsAAAAAAM3nfX_K0vXaUudl2Gk0lpTF3REf',
    challenge : '03AHJ_VutSw5uY5m-U2Tp8WVgqR1cWqcuFbxBZ7yWeIzeAa5GKD3K1DgjON_4B_cAEeAynK0mcdB9i1k1O7tC7InP7BH9AxRHcANnZZXWy4PzR0nRh7DxKyT1Yd_rlvpX-0_PNtuHTDS9VJBYINr_OPbq9zNNy9wtgkA',
    is_incorrect : false,
    programming_error : '',
    error_message : '',
    server : 'http://www.google.com/recaptcha/api/',
    timeout : 18000
};

document.write('<scr'+'ipt type="text/javascript" s'+'rc="' + RecaptchaState.server + 'js/recaptcha.js"></scr'+'ipt>');

Z tego zawsze musisz wyciągnąć sobie wartość challenge i server (server nie koniecznie gdyż można założyć, że jest stały i wpisać na stałe na stronach wykorzystujących ten system nie spotkałem innego niż http://api.recaptcha.net/) Przykładowy adres obrazka to:

http://www.google.com/recaptcha/api/image?c=03AHJ_VutSw5uY5m-U2Tp8WVgqR1cWqcuFbxBZ7yWeIzeAa5GKD3K1DgjON_4B_cAEeAynK0mcdB9i1k1O7tC7InP7BH9AxRHcANnZZXWy4PzR0nRh7DxKyT1Yd_rlvpX-0_PNtuHTDS9VJBYINr_OPbq9zNNy9wtgkA

Jak widać to server + image?c= + challenge więc wystarczy zwyczajnie pobrąć (np. do TMemoryStream) obrazek i go wyświetlić.
Do serwera metodą POST (prócz zwyczajnych pół jakiegoś tam formularza) wysyłasz:
recaptcha_challenge_field - tu jako wartość podstawiasz pobrany wcześniej challenge
recaptcha_response_field - a tu przepisany przez użytkownika tekst z obrazka (spację między wyrazami zmieniasz na + )
No to by było na tyle żadna filozofia. ;-)

EDIT// Widzę że Olesio zapodał już gotowca

0

Dokładnie jak kAzek pisze. Tylko zamiast wyrażeń regularnych, które oczywiście można uzyć.
Do prostego parsowania tekstu z pomiędzy dwoch różnych znaczników wystarczy taka funckja,
której używa mój gotowiec. Funkcję napisal MisiekD i sie ona sprawdza. Natomiast w gotowcu,
do którego podałem linka - adres serwera captchy wpisany jest na stałe, ale można go pobrąć
w taki sposób jak kAzek napisał. I myślę, że moje źródło pomoże Tobie Crow zrozumieć ideę.

function TMainForm.Parse(StrBegin, StrEnd, Str : string) : string;
var
  B, E : integer;
begin
  Result := '';
  if StrBegin = '' then
  begin
    B := 1;
  end
  else
  begin
    B := Pos(StrBegin, Str);
  end;
  if B > 0 then
  begin
    Str := Copy(Str, B + Length(StrBegin), MaxInt);
    if StrEnd = '' then
    begin
      E := Length(Str) + 1;
    end
    else
    begin
      E := Pos(StrEnd, Str);
    end;
    if E > 0 then
    begin
      Result := Copy(Str, 1, E - 1);
    end;
  end;
end;
0

Po pierwsze - dzięki za odpowiedź, wam obydwu.

Niestety części nie rozumiem, a to co rozumiem... nie działa.

Wchodzę na tą stronkę:
http://www.google.com/recaptcha/demo/

Wyświetla się pusta strona z samą Recaptchą.

Potem wyświetlam źródło strony i dostaję coś takiego:

<html><head></head> 
<body><style type="text/css"> 
    body {
      font-family: Helvetica, sans-serif;
      color: #000000;
      font-size: 12px;
      border: none;
      background-color: transparent;
    }
    </style> 
 
<form method="POST" action=""><div><br> 
<br></div> 
 
 
<script type="text/javascript"> 
        var RecaptchaOptions = {
           
           theme: "red",
           
           lang: "en"
        };
        </script> 
<script type="text/javascript" src="//www.google.com/recaptcha/api/challenge?k=6Ld4iQsAAAAAAM3nfX_K0vXaUudl2Gk0lpTF3REf"></script> 
<noscript><iframe src="//www.google.com/recaptcha/api/noscript?k=6Ld4iQsAAAAAAM3nfX_K0vXaUudl2Gk0lpTF3REf" height="300" width="500" frameborder="0"></iframe><br> 
<textarea name="recaptcha_challenge_field" rows="3" cols="40"> 
           </textarea> 
<input type="hidden" name="recaptcha_response_field" value="manual_challenge"></noscript> 
<script type="text/javascript"> 
          window.onload = function() {
              Recaptcha.focus_response_field();
          }
        </script> 
<table cellspacing="0" cellpadding="4" border="0" style="font-family: Helvetica, sans-serif; color: #000000; font-size: 12px;"><tr><td><div><input type="submit" name="Button1" value="Submit"></div></td> 
<td><b style="line-height: 18px;">The words above come from scanned books. <br> By typing them, you help to digitize old texts.</b></td></tr></table></form></body></html>

Otwieram:

//www.google.com/recaptcha/api/challengek=6Ld4iQsAAAAAAM3nfX_K0vXaUudl2Gk0lpTF3REf

i faktycznie otrzymuję zgodnie z oczekiwaniem, coś takiego:

var RecaptchaState = {
    site : '6Ld4iQsAAAAAAM3nfX_K0vXaUudl2Gk0lpTF3REf',
    challenge : '03AHJ_VutMe3w0SdlBAwlEnhEnwl4yCJgj553JksXz9kD1MtNR4wbtBh74qesSfyZ6KSE9DuM99yLu_dD76XfwpY8mkUVYUo1ysUkZUfI3E7blo-fSZsLxyHDQRXJzac8hHwyRxxVlAduDBSKJcYX2kMolJSczHH03tw',
    is_incorrect : false,
    programming_error : '',
    error_message : '',
    server : 'http://www.google.com/recaptcha/api/',
    timeout : 18000
};

document.write('<scr'+'ipt type="text/javascript" s'+'rc="' + RecaptchaState.server + 'js/recaptcha.js"></scr'+'ipt>');

gdy staram się odczytać obrazek, biorę server + image?c= + challenge, czyli w tym wypadku:

http://www.google.com/recaptcha/api/image?c=03AHJ_VutMe3w0SdlBAwlEnhEnwl4yCJgj553JksXz9kD1MtNR4wbtBh74qesSfyZ6KSE9DuM99yLu_dD76XfwpY8mkUVYUo1ysUkZUfI3E7blo-fSZsLxyHDQRXJzac8hHwyRxxVlAduDBSKJcYX2kMolJSczHH03tw

Obrazek się pokazuje (fajnie), ale niestety inny niż ten który widnieje w recaptcha...

A czego nie rozumiem? Nie wiem jak mam konkretnie wysłać, i gdzie, kiedy to:

recaptcha_challenge_field
recaptcha_response_field

PS. Może dało by się to zrobić za pomocą kodu HTML? Bo ja i tak używam WebBrowsera do komunikacji ze stronką, więc w obsłudze captchy też się może przydać ;P

0

Fakt obrazek jest inny (nie wnikam dlaczego) ale walidacja poprawności kodu zadziała :)
Nie wiem co tam nakodziłeś więc jak jeszcze czegoś nie rozumiesz to daj kod.
Tymczasem ja daję kolejny przykład tym razem w Indy (Olesio już dawał przykład z użyciem Synapse).

unit uMain;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, IdAntiFreezeBase, IdAntiFreeze, IdBaseComponent,
  IdComponent, IdTCPConnection, IdTCPClient, IdHTTP, jpeg, RegExpr;


const
  USER_AGENT = 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT ' +
    '5.1; pl; rv:1.9.2.10) Gecko/20100914 Firefox/3.6.10 ( .NET CLR 3.5.30729)';
  CAPTCHA_URL = 'http://www.google.com/recaptcha/demo/';
  CAPTCHA_API_URL = 'http://www.google.com/recaptcha/api/image?c=';
type
  TfrmMain = class(TForm)
    imgCaptcha: TImage;
    btnGet: TButton;
    edCaptcha: TEdit;
    btnSend: TButton;
    IdHTTP: TIdHTTP;
    IdAntiFreeze: TIdAntiFreeze;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure btnGetClick(Sender: TObject);
    procedure btnSendClick(Sender: TObject);
  private
    { Private declarations }
    RegEx: TRegExpr;
    inStr, outStr: string;
    challenge: string;
  public
    { Public declarations }
  end;

var
  frmMain: TfrmMain;

implementation

{$R *.dfm}


procedure TfrmMain.FormCreate(Sender: TObject);
begin
  btnSend.Enabled:=False;
  IdHttp.HandleRedirects:= True;
  IdHttp.Request.UserAgent:= USER_AGENT;
  RegEx:= TRegExpr.Create;
end;

procedure TfrmMain.FormDestroy(Sender: TObject);
begin
  RegEx.Free;
end;

procedure TfrmMain.btnGetClick(Sender: TObject);
var
  jpg: TJpegImage;
  ms: TMemoryStream;
begin
  outStr:= IdHTTP.Get(CAPTCHA_URL);
  RegEx.Expression:= '<script type="text\/javascript" src="([^"]{1,})"';
  if RegEx.Exec(outStr) then
  begin
    inStr:= RegEx.Match[1];
    inStr:= StringReplace(inStr, '//', 'http://', [rfReplaceAll]);
    outStr:= IdHTTP.Get(inStr);
    RegEx.Expression:= 'challenge[\x20]{0,}\:[\x20]{0,}\x27([^\x27]{1,})\x27';
    if not RegEx.Exec(outStr) then
    begin
      ShowMessage('Bład pobierania challenge');
      exit;
    end;
    challenge:= RegEx.Match[1];
    inStr:= CAPTCHA_API_URL + challenge;
    ms:= TMemoryStream.Create;
    try
    IdHTTP.Get(inStr, ms);
    jpg:= TJpegImage.Create;
    try
    ms.Position:= 0;
    jpg.LoadFromStream(ms);
    imgCaptcha.Picture.Bitmap.Assign(jpg);
    finally
    jpg.Free;
    end;
    finally
    ms.Free;
    end;
  end
  else
    ShowMessage('Bład pobierania adresu skryptu');
  btnGet.Enabled:= not btnGet.Enabled;
  btnSend.Enabled:= not btnSend.Enabled;
end;

procedure TfrmMain.btnSendClick(Sender: TObject);
var
  sl: TStringList;
  recaptcha_response_field: string;
begin
  recaptcha_response_field:= edCaptcha.Text;
  recaptcha_response_field:= StringReplace(recaptcha_response_field, ' ', '+', [rfReplaceAll]);
  sl:= TStringList.Create;
  try
  sl.Add('recaptcha_challenge_field=' + challenge);
  sl.Add('recaptcha_response_field=' + recaptcha_response_field);
  sl.Add('Button1=Submit');
  outStr:= IdHTTP.Post(CAPTCHA_URL, sl);
  RegEx.Expression:= 'Correct\!';
  if RegEx.Exec(outStr) then
    ShowMessage('Kod prawidłowy :)')
  else
    ShowMessage('Kod nieprawidłowy!');
  finally
  sl.Free;
  end;
  btnGet.Enabled:= not btnGet.Enabled;
  btnSend.Enabled:= not btnSend.Enabled;
end;

end.

EDIT// Masz gotowy projekt demo (wraz z plikiem exe wiec bez problemu możesz sprawdzić czy działa).
EDIT2//Aktualizacja linka
http://www.speedyshare.com/files/27789532/ReCaptcha_Demo.rar

0

Klasa w C# (Może komuś się przyda. Sam kiedyś szukałem.). FormLoginCaptcha to jakieś okienko, do którego wczytujesz obrazek i wpisujesz wyświetlony kod. WebHelper to klasa dziedzicząca po WebClient (dodanie ciastek etc.), tylko ulepszona przeze mnie. Klasa powinna działać na wszystkich stronach, na których występuje ReCaptcha. Z tego co wiem, to ReCaptchy nie da się złamać.

namespace Dupa
{
    using System.Drawing;
    using System.IO;
    using System.Text.RegularExpressions;

    public class ReCaptcha
    {
        FormLoginCaptcha formCaptcha;
        private string siteSource = string.Empty;
        private string siteBriefDescription = string.Empty;
        private WebHelper webHelper = new WebHelper(true);

        private const string ChallengeUrl = "http://www.google.com/recaptcha/api/challenge?k=";
        private const string ImageUrl = "http://www.google.com/recaptcha/api/image?c=";

        public string Challenge { get; set; }

        public ReCaptcha(string siteSource, string siteBriefDescription)
        {
            this.siteSource = siteSource;
            this.siteBriefDescription = siteBriefDescription;
        }

        public string GetReCaptchaResponse()
        {
            if (string.IsNullOrEmpty(siteSource)) return null;

            // Sprawdź czy trzeba rozwiązać ReCaptche
            bool isReCaptchaAvailable = (siteSource.Contains("recaptcha_response_field") && siteSource.Contains("recaptcha_challenge_field"));
            string recaptchaResponseField;

            if (isReCaptchaAvailable)
            {
                // Wyłuskaj klucz publiczny
                string publicKey = Regex.Match(siteSource, "challenge\\?k=(?<publicKey>[^\"']+)").Groups["publicKey"].Value.Trim();
                if (string.IsNullOrEmpty(publicKey)) return null;

                string recaptchaSrc = webHelper.DownloadStuff(ChallengeUrl + publicKey);

                // Wyłuskaj kod 'challenge', który posłuży do wczytania obrazka
                string recaptchaChallengeField = Challenge = Regex.Match(recaptchaSrc, "challenge : '(?<challenge>[^']+)',").Groups["challenge"].Value.Trim();
                if (string.IsNullOrEmpty(recaptchaChallengeField)) return null;

                string recaptchaImageUrl = ImageUrl + recaptchaChallengeField;

                // Pobierz obrazek
                Image recaptchaImage = Image.FromStream(new MemoryStream(webHelper.DownloadData(recaptchaImageUrl)));
                if (recaptchaImage.Width == 0) return null;

                FormLoginCaptcha captchaForm = new FormLoginCaptcha(recaptchaImage, siteBriefDescription);
                captchaForm.ShowDialog();
                recaptchaResponseField = captchaForm.GetCaptchaText();
            }
            else return null;

            return recaptchaResponseField;
        }
    }
}
0
olesio napisał(a):

Jeżeli chodzi o recaptche konkretnie, to o ile się orientuje nie wymaga JavaScruptu trzeba tylko
pobrać odpowiednie dane, w odpowiedni sposób. Mi pomógł to zrobić MisiekD podsyłajac kiedyś
przykładowe źródłó oczywiście z wykorzystaniem preferowanego przez nas Synapse. Pod linkiem
poniżej znajduje się kod programu, który bez problemów skompilujesz. Loguje się on na jeden z
serwisów torentowych, który wykorzystuje właśnie ReCaptcha. Są na nim jeszcze dostepne free
konta, także możesz założyć i przetestować lub przeanalizować sobie kod źródłowy i dostosować
do innego serwisu. Myślę, że kod jest na tyle przejrzysty, że dojdziesz dzięki niemu jak obsłużyć
ReCaptche. Link do źródeł: http://www.speedyshare.com/files/24497887/login_to_pb.rar i już
kończę tę odpowiedź, bo znowu się trochę rozpisałem, a i tamten kod z wątku, do którego linka
podałeś też obsługuje Captche, ale inną, która jest na stronie bramki sms Orange. I podesłałem
go wtedy pytającej osobie, bo chodziło o pokazanie Gifa - załadowanego ze strony internetowej.

misiekd to złodziej oszukał mnie wział kase, nie przesłał projektu, od tego czasu nie ma go na tym forum pod nickiem misiekd, prawdopodobnie jest ale pod innym.

0

jaki ORC niby odczytuje dobrze captchę google? Testowałem różne OCRY i żaden nie radził sobie z nią nawet w 50%, a jednen OCR był typowo pod captchę robiony i płatny jest, ale on też sobie z google captcha nie radzi, co najwyżej radził sobie z jakąś biedną captchą z innych serwisów, gdzie napisy są dość proste. Wymień zatem OCR, który odczyta poprawnie captchę, może być to program nawet, taki, który strony zeskanowane czyta, nawet płatny 1 mln złotych, przetestuję.

0
oioiioio napisał(a):

jaki ORC niby odczytuje dobrze captchę google? Testowałem różne OCRY i żaden nie radził sobie z nią nawet w 50%, a jednen OCR był typowo pod captchę robiony i płatny jest, ale on też sobie z google captcha nie radzi, co najwyżej radził sobie z jakąś biedną captchą z innych serwisów, gdzie napisy są dość proste. Wymień zatem OCR, który odczyta poprawnie captchę, może być to program nawet, taki, który strony zeskanowane czyta, nawet płatny 1 mln złotych, przetestuję.

Nigdy nie widziałem takiego OCR'a.

0

Cześć i czołem, odgrzewam kotleta - no ale.
Podany przykład w tym temacie dawien dawno wszyłem do aplikacji logującej się na pewną stronę i czytającej obecny stan pewnego wskaźnika (lekka automatyzacja, żeby zaoszczędzić kilka sekund, ponieważ później trzeba się przeklikać w głąb strony. Działało toto do wczoraj/przedwczoraj/maxtydzień. Prawdopodobnie google coś pomieniło w skrypcie, gdyż w chwili obecnej wyświetlają mi się tylko "hard" Captche czyli te z którymi ludzie sobie nie radzą typu :
user image
Defakto w tym momencie niestety czasem i kilka minut mi zejdzie aż mi się uda przejść ten test na człowieczeństwo. Próbuję i próbuję zrozumieć ten javascript od nich ale ni jak mi nie idzie.

Jest ktoś w stanie zerknąć w skrypt i podpowiedzieć co, gdzie i jak z wyświetlaniem tej kapczy ?

PSt: W przeglądarce pokazują mi się pięknie obrazki z cyferkami domów, także to kwestia javascriptu

0

Teraz taka jest captcha dla przeglądarek nieobsługujących JS (a więc Synapse czy Indy też) aby wyświetlić "zwykłą" musiałbyś zrozumieć ten skrypt http://www.google.com/recaptcha/api/js/recaptcha.js (a właściwie jego część odpowiedzialną za wygenerowanie linku do obrazka) i napisać jego odpowiednik w Delphi. Jak dla mnie jest to raczej nie do ogarnięcia, bo nie dość że nie jestem jakiś super biegły w JS to kod nawet nie jest sformatowany. Czyli masz 3 wyjścia:

  1. Pogodzić się z tym :P
  2. Jakimś cudem jednak przeanalizować ten kod i coś wykombinować... (już mnie głowa boli)
  3. Użyć IE (lub czegoś innego np. Gecko) jako silnika
1

@kAzek - sformatowanie tego kodu to pryszcz (patrz załącznik), jednak kod jest dosyć długi (ponad 3k LoC) i mocno zobfuskowany, więc jego analiza może zająć sporo czasu...

0

A nie umie może ktoś obsługiwać debuggera js ? Ja próbuje zaprzęgnąć firebuga do współpracy, ale toto też mi na razie nie idzie. Może wieczorem grubiej przysiądę, ale może ktoś już to przerabiał i szybko prześledzi kod ?

1 użytkowników online, w tym zalogowanych: 0, gości: 1