PHP – Curl & Captchas II

        De volta com o assunto de manipular os captchas com o Curl. Lembram que no primeiro POST eu havia falado que se não fosse possivel burlar o captcha ao menos poderiamos copia-lo e valida-lo em nosso sistema? Então mostrei como era possivel copia-lo e valida-lo em nosso sistema, e agora quero mostrar como é possivel burlar o captcha.
        Certamente isso não é possivel em 100% dos casos, talvez em 20 ou 30%. Tudo depende de como o sistema para geração de captcha funciona.
O exemplo que usaremos hoje é no site da Secretaria da Fazenda do Estado do Rio Grande do Sul, veja o link aqui. O governo do estado dispoe de uma ficha de registro de contribuintes (pessoa juridica) que é consultada por CNPJ ou inscrição estadual.
        Agora que ja sabemos para que serve e o que faz, vamos ao codigo. Observe bem o que o sistema do governo faz:
        Tela 1 – Voce deve digitar o CNPJ / IE para acessar a ficha.
        Tela 2 – Voce deve digitar os caracteres do captcha.
        Tela 3 – Mostra a ficha do contribuinte do CNPJ / IE em questão.

        Legal! Mas vamos nos aprofundar um pouquinho mais e ver quem são os responsaveis que isso tudo aconteça. Vamos por partes!

Tela 1.
- Vejam com atenção os inputs a serem enviados via post no form:
        SEQ = 1
        LOCAL = SINTEGRA
        cgcmf = (cnpj digitado pelo usuario)
        cgcte = (ie digitado pelo usuario)
- Essas informações são enviadas via post para “http://sintegra.sefaz.rs.gov.br/sef_root/inf/SEF_entrada_sintegra_completa_1.asp?Menu=Nao”.

Tela 2.
- É gerada pelo link acima.
- Veja que interessante a propriedade scr da imagem, “../../includeNovo/GeraImagemVerificacao.asp”, não é uma imagem.
- Envia via post as seguintes variaveis:
MsgUsuario = (os caracteres do captcha digitado pelo usuatio)
btOK= Avançar
- Essas informações são enviadas via post para “http://sintegra.sefaz.rs.gov.br/sef_root/inf/SEF_entrada_sintegra_completa_3.asp?origem=&amb=&consulta=Direta&Menu=Nao&dtDataConsulta=”.

Tela 3.
- É gerada pelo link acima.
- Não tem nemhuma ação.

Dica
        Quando vamos usar CURL em uma pagina que vai fazer autenticação de qualquer especie, sempre armazene os cookies de seção usando CURLOPT_COOKIEJAR. Nunca sabemos quando o sistema vai precisar ler ou gravar esse tipo de cookies.

        Agora que já está tudo explicado vamos aos codigos. Vai ser mais facil explicar como fazer os macetes com o codigo ja na tela.
Vamos fazer tudo em um mesmo arquivo todo o codigo junto. Salve-o como “curl.php”.
Lembram da função “recebe_imagem” que usamos no post anterior? Vamos usa-la novamente. Aí vai a função.

        function recebe_imagem($url, $arquivo, $cookief="", $cookiej="") {
$ch = curl_init ($url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
                if(!empty($cookief)) {
        curl_setopt($ch, CURLOPT_COOKIEFILE, $cookief);
        }
                if(!empty($cookiej)) {
        curl_setopt($ch, CURLOPT_COOKIEJAR, $cookiej);
        }
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_BINARYTRANSFER,1);
$data=curl_exec($ch);
curl_close ($ch);
$fp = fopen($arquivo,'w');
fwrite($fp, $data);
fclose($fp);
return $arquivo;
}

Vamos usar tambem uma outra função simples de apoio.

        function between($beg, $end, $str, $i=0, $p="S") {
$a = explode($beg, $str, 2);
$b = explode($end, $a[1]);
$return = $p == "S" ? $beg . $b[$i] . $end : $b[$i];
return $return;
}

20-25. Entenderam? ela serve simplesmente para pegar o conteudo de uma string entre dois delimitadores. Voces vão ver.

Agora vamos criar uma outra função que só mostra o formulario.

        function ConsultaSintegraForm()	{
echo "
"; echo "Digite o CNPJ"; echo ""; echo " "; echo ""; echo "OU digite a inscrição estadual"; echo ""; echo " "; echo ""; echo ""; echo " "; echo "
"; echo ""; echo "Repare que não tem o captcha para digitar! Vamos pular ele? Será!?"; }

26-41. Sem explicação para isso.

Lembram que na explicação “Tela1″ no começo do post vimos que eram necessario 4 inputs? SEQ, LOCAL, cgcmf e cgcte? Mas os dois primeiros nunca mudam, então neste formulario só queremos o conteudo dinamico.

Agora vamos ao monstro! Fiz uma função que faz a consulta. Vou coloca-la por partes com fins de didaticos.

        function ConsultaSintegra($cnpj, $ie)	{
$post="SEQ=1&LOCAL=SINTEGRA&cgcmf=$cnpj&cgcte=$ie";
$ch = curl_init("http://sintegra.sefaz.rs.gov.br/sef_root/inf/SEF_entrada_sintegra_completa_1.asp?Menu=Nao");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, "sintegra.txt");
$output = curl_exec($ch);
curl_close($ch);

42. A função tem dois parametros $cnpj e $ie.
43. Criamos uma variavel com os valores dos 4 inputs necessarios.
44. Inicia uma seção CURL para a url passada por parametro.
45. Avisa ao CURL que vamos enviar dados via post.
46. Diz para o CURL onde estão os dados que vamos enviar.
47. Pede para o CURL salvar o retorno em uma variavel.
48. Avisa ao CURL que pode seguir qualquer redirecionamento.
49. Salva os cookies de seção no arquivo “sintegra.txt”.
50. Executa a seção CURL e guarda o retorno em $output.
51. Finaliza a seção CURL.

Até aqui beleza. Ja tinhamos visto praticamente a mesma coisa no post anterior. Agora o negócio esquenta!

$ch = curl_init("http://sintegra.sefaz.rs.gov.br/Include/GeraImagemVerificacao.asp");curl_setopt($ch, CURLOPT_COOKIEFILE, "sintegra.txt");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$senha=curl_exec($ch);
curl_close ($ch);

52. Inicia uma seção CURL para a url passada por parametro.
53. Le o cookie de seção que gravamos anteriormente (linha 50).
54. Pede para o CURL salvar o retorno em uma variavel.
55. Encerra a seção CURL.

Por que fizemos isso? O script “GeraImagemVerificacao.asp” só serve para uma coisa, para verificar se os cookies de seção estão gravados com os devidos valores e provavelmente deve conferir se existe a variavel “cgcmf” ou “cgcte” que enviamos via post anteriormente. Após ele fazer essas verificações o “GeraImagemVerificacao.asp” redireciona para outro script. Mas observe que nós não pedimos para o CURL seguir os redirecionamentos com a opção “CURLOPT_FOLLOWLOCATION”. O redirecionamento é para o script “webcod.cgi”, veja um exemplo da url completa do redirecionamento: “http://www.sefaz.rs.gov.br/cgi-bin/webcod.cgi?figura=876r”. O que tem de interessante aí? O codigo do captcha! huahauahuahuahua! Agora então temos em uma variavel o codigo do captcha, só temos que cortar algumas partes para pega-la.

Observação:
O script “GeraImagemVerificacao.asp” é responsavel pelas verificações dos cookies de seção. Se tudo estiver ok ele vai gravar um outro cookie de seção com os valores do captcha.
O script “webcod.cgi” simplesmente é responsavel por gerar a imagem do captcha com os valores que ele recebe por parametro em “figura”.

$senha=explode("?", $senha);
$senha=explode('"', $senha[1]);
$senha=explode('=', $senha[0]);
$senha=$senha[1];

56-59. Cortamos tudo até ficarmos só com o captcha.

Agora vamos acessar o script “GeraImagemVerificacao.asp” a fim de que ele salve os cookies de seção. Vamos usar para isso a função “recebe_imagem”.

recebe_imagem("http://sintegra.sefaz.rs.gov.br/Include/GeraImagemVerificacao.asp",
                      "ImgSintegra.png",
                      "sintegra.txt",
                      "Imgsintegra.txt");

Certo? E agora? Agora ja temos a faca e o queijo na mão, é só cortar e mandar ver. Então finalmente o fim da função.

$post="MsgUsuario=".$senha."&btOK= Avançar ";
$ch = curl_init("http://sintegra.sefaz.rs.gov.br/sef_root/inf/SEF_entrada_sintegra_completa_3.asp?origem=&amb=&consulta=Direta&Menu=Nao&dtDataConsulta=");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_COOKIEFILE, "Imgsintegra.txt");
curl_setopt($ch, CURLOPT_COOKIEJAR, "sintegra.txt");
$output = curl_exec($ch);
curl_close ($ch);
echo $output;
}

64. Criamos uma variavel com o valor do captcha e mais uma variavel.
65. Inicia uma seção CURL para a url passada por parametro.
66. Avisa ao CURL que vamos enviar dados via post.
67. Diz para o CURL onde estão os dados que vamos enviar.
68. Pede para o CURL salvar o retorno em uma variavel.
69. Avisa ao CURL que pode seguir qualquer redirecionamento.
70. Le o cookie de seção salvo pela função “recebe_imagem”.
71. Salva o cookie de seção no arquivo “sintegra.txt”.
72. Executa a seção CURL e guarda o retorno em $output.
73. Finaliza a seção CURL.
74. Mostra o resultado.
75. Termina a função.

É para dar certo! Vamos tornar o script usavel.

       if(isset($_POST['cnpj']) OR isset($_POST['ie'])) {
ConsultaSintegra($_POST['cnpj'], $_POST['ie']);
}
       else {
ConsultaSintegraForm();
}

Pronto, salve tudo entre as tags do php e acesse-o, use este cnpj para testar 05385071000173. Deu certo? Uhuuuu! legal né?!

até a próxima,

This entry was posted in PHP and tagged , , , , . Bookmark the permalink.

25 Responses to PHP – Curl & Captchas II

  1. dr_gori says:

    Muito bom! ótimo tutorial

  2. Ricardo Amorim says:

    Bryan, estou interessado no seu trabalho. Por favor entre em contato via email para conversarmos.

  3. Claudio Costa says:

    Brian, como posso tirar algumas duvidas com vc? Me responda por favor e se possivel via email.

  4. walter says:

    bryan, preciso fazer consulta a pagina do sintegra de todos os estados mais detalhes do que preciso, me envia um e-mail, preciso de um orcamento.

  5. Romulo Avila says:

    Bryan,

    Bom dia,

    Achei este codigo muito interessante, como posso entrar em contato com voce?

    Att.

    Romulo

  6. Mauro says:

    Salve!
    Podes me dizer se é possível fazer isso com o site http://www.tjrs.jus.br usando o curl?Até não me importo de digitar o captcha.

  7. Mauro Cassano says:

    Brian,
    Gostaria de tirar algumas dúvidas com vc.
    Por favor, se vc tiver disponibilidade podemos falar por email.

    Obrigado

  8. Mauro Cassano says:

    Salbe Brian!!
    Podes me dizer se ha algo errado com meu código?

    captcha

    cnpj

    CURLS.PHP******************

  9. bryan says:

    Mauro: Sim é possivel fazer com o TJRS sem problemas.

  10. Jean says:

    Meu otimo exemplo, agora vou tentar quebra o capctha do dataprev, ´para consulta de credito de aposentado e automatizar a busca

  11. Rodrigo says:

    Kra…
    parabens pelos 2 post sobre Captcha….
    Consegui fazer o primeiro….o segundo deu erro….
    bom…..mas é seguinte…..tem como….separar os dados que é retornado da receita federal…separar numa array….ou até mesmo em variaveis?
    me retorna no e-mail
    valew

  12. Olá Bryan, cheguei no seu site enquanto fazia exatamente a mesma coisa!
    Gostaria de saber se você fez a captura de algum outro estado do Sintegra, eu implementei várias, mas estou com problemas com o sintegra de SP e PR…
    o código que eu fiz funciona, mas apenas localmente.

    você poderia me dar uma ajuda? mande um email se puder.

    obrigado,
    miguel

  13. alysson vinicius says:

    Brayn , muito bom seu post, mas quando a url é https não é possível acessar o endereço por exemplo:
    https://pagamento.serpro.gov.br/sicalcweb/UF.asp?AP=P&Person=N&TipTributo=2&FormaPagto=1

    estou tentando acessar a pagina da receita para consulta de cnpj e transmissão de dados, mas nao é possivel

    sera que estou fazendo aldo de errado, porque com outro exemplo funciona beleza.

  14. breno souza says:

    Funcionou bem mas como me livro do timeout de aproximadamente 1 minuto do site da receita? resumindo preciso redigitar o captcha a cada um minuto.

    abraços

  15. I think that to get the http://www.lowest-rate-loans.com from banks you must have a good motivation. But, one time I have got a bank loan, just because I wanted to buy a car.

  16. Felipe says:

    Preciso de contato seu urgente.
    Obrigado.

  17. Thiago Gervasi says:

    Opa, eu estou usando a Curl do TCL/TK e não do PHP, porém não muda muuuito, graças a você consegui passar pelo CAPTCHA :)
    Porém, ele nem sempre funciona. A cada 3 vezes que eu rodo em média uma ele falha. Você sabe oque poderia ser?? Eu acho que foi algum erro com os cookies mas não tenho certeza, pois monitorei eles e vi que as vezes ele permanece o mesmo (e é justamente nessas ocasiões que da erro) ficaria muito grato se você me ajudasse xD.

    Obrigado

    Thiago Gervasi Eggert
    InfoCont Sistemas Integrados

  18. Thiago Gervasi says:

    Resolvi, o problema realmente estava nos cookies.
    Oque eu fiz para resolver foi antes de buscar o captcha, receber os cookies da página principal (só para curiosidade ou para caso outra pessoa perguntar xD)

    Mas parabéns cara ótimo tópico, eternamente grato.


    Thiago Gervasi Eggert
    InfoCont Sistemas Integrados

  19. Cristiano R says:

    bryan, preciso de sua ajuda e de seus serviços, coisa rapida se puder entrar em contato:

  20. Cristiano R says:

    bryan, preciso de seus serviços, coisa rapida por favor entre em contato: ctrlucas@hotmail.com

  21. sidnei says:

    Bom Dia Pessoal;

    to precisando de um codigo igual, mas parece que esse já nao funciona, acredito que a receita deva ter mudado algo, por acaso vcoes nao tem um atual funcionando.

    att.

  22. Alisson says:

    Amigo Bryan, preciso de seus serviços no desenvolvimetno de um sistema. Podemos negociar um valor pelo serviço …me envie email para adrconsultoria@hotmail.com…aguardo.

  23. nati says:

    ooi Bryan será que tem algum codigo pra mim usar na votação no site do bebe hipoglos ?

  24. Maxi says:

    Bryan, estou interessado no seu trabalho. Por favor entre em contato via email para conversarmos.maxi.arlem@hotmail.com

  25. Maxi says:

    Bryan, estou interessado no seu trabalho. Por favor entre em contato via email para conversarmos.

    maxi.arlem@hotmail.com

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>