Vous n'êtes pas identifié(e).

  • Contributions :
  • Vos boîtes de messages privés sont vides.

🟣 Tuto - ruby - another captcha resolver (image inside)


#1 2014-11-29 12:39:43

Mention conquering_lion
🥉 Grade : Scout

Auxiliaire10likes
Inscription : 2013-05-23
Messages : 275
Likes : 16

Tuto - ruby - another captcha resolver (image inside)

hello

bon, devant mon échec cuisant à bypasser le système de captcha du forum (pour l'instant niark niark niark), je suis allé me défouler ailleurs .. sur une captcha image pour changer !

la bête se trouve ici => http://demo.visualcaptcha.net/

et histoire de changer encore un peu (le changement c'est toujours bon), je me suis dis que j'allais utiliser, non pas un réseau de neurones supervisé, mais une machine à vecteur de support (AKA SVM)..

kezako me direz-vous ??
grosso modo, ca cherche le meilleur hyperplan pour séparer les données

page avec schéma bien parlant => https://www.igvita.com/2008/01/07/suppo … m-in-ruby/

pari réussi .. j'ai dû mettre 3-4 heures en tout (en trois fois) et ce matin, j'ai bouclé le bouzin .. et je vous donne l'intégralité du code (sympa hein !)

un module ruby, trois classes,
- une pour scraper les images et se faire sa BDD
- une pour entrainer le SVM
- et la dernière pour test grandeur nature (connexion à la page, récup du mot à trouver, scrape et analyse des images, et click sur les boutons qui vont bien)


#!/usr/bin/env ruby
# encoding: UTF-8

require 'time'
require 'date'
require 'fileutils'
require 'open-uri'
require 'headless'
require 'selenium/webdriver'
require 'watir-webdriver'
require 'watir-get-image-content'
require 'RMagick'
require 'chunky_png'
require 'cgi'
require 'libsvm'

module Decode_Visual_Captcha
  class ScrapePicto
    START_URL = "http://demo.visualcaptcha.net/"
   
    def initialize
      make_agent
    end

    def finalize
      kill
    end
   
    def aleat
      r = Random.new
      return r.rand(15..75)
    end

    def parse_request(string)
      out = []
      params = CGI.parse(string)
      params.each_pair do |key,value|
        out << value
      end
      return out.join
    end

    def click_refresh
      @b.image(:src => "img/refresh.png").click
    end
   
   
    def get_word
      label = @b.p(:class => "visualCaptcha-explanation").strong.text
      return label
    end
   
    def save_img index, label, img_dest,img_src
      new_nm = "images/" << label << "_" << img_dest << "_" << index << ".png"

      begin
        image = img_src.to_png_base64
        File.open(new_nm, 'wb') do |file|
          file.write(Base64.decode64(image))
        end      
      rescue Exception => e
        puts e.message
      end
    end
   
    def parse_page label
      begin
        @b.divs(:class =>"img").each do |img|
          index = img.img.attribute_value('data-index')
          nm = parse_request(img.img.src)
          save_img index, label, nm, img.img
        end
      rescue Exception => e
        puts e.message
      end
      return true
    end

    def run
      begin
        @b.goto START_URL
        sleep 3
        100.times do
          puts "hop"
          label = get_word
          parse_page label
          click_refresh
          sleep 3
        end
      rescue Exception => e
        #puts e.message
      ensure
        finalize
      end
      return true
    end

=begin doc
partie private
=end    
    private
    def make_agent
      @headless = Headless.new
      @headless.start  
      Selenium::WebDriver::Firefox.path = '/home/digital/firefox31/firefox/firefox'
      @b = Watir::Browser.new :firefox
    end  
   
    def kill
      @b.close
      @headless.destroy  
    end
  end

###############################  
###############################
  class TestSvm
    START_URL = "http://demo.visualcaptcha.net/"
   
    def initialize
      make_agent
    end

    def finalize
      kill
    end
   
    def parse_request(string)
      out = []
      params = CGI.parse(string)
      params.each_pair do |key,value|
        out << value
      end
      return out.join
    end
   
    def parse_nm string
      tab = string.split(".")
      tmp_tab = tab[0].split("_")
      index = tmp_tab[2]
      return index
    end

    def split_name string
      res = string.split("_")
      label = res[0]
      return label
    end

    def click_refresh
      @b.image(:src => "img/refresh.png").click
    end

    def click my_index
      begin
        @b.divs(:class =>"img").each do |img|
          index = img.img.attribute_value('data-index')
          if index == my_index
          then
            img.click
          end
        end
        @b.button(:name => "submit-bt").click
        sleep 3
      rescue Exception => e
        puts e.message
      end
    end
       
    def get_word
      label = @b.p(:class => "visualCaptcha-explanation").strong.text
      return label
    end
   
    def save_img index, label, img_dest,img_src
      new_nm = "work_svm/" << label << "_" << img_dest << "_" << index << ".png"

      begin
        image = img_src.to_png_base64
        File.open(new_nm, 'wb') do |file|
          file.write(Base64.decode64(image))
        end      
      rescue Exception => e
        puts e.message
      end
    end

    def check
      ls = []
      Dir['train_svm/*.png'].each do |file|  
        obj = split_name File.basename(file)
        ls << obj
      end
      return ls.uniq          
    end
   
    def vector(img)
      out = []
      image = Magick::Image.read(img).first
      image.each_pixel do |pixel, c, r|
        out << (pixel.intensity > 0 ? 1 : 0)
      end
      return out        
    end    

    def resolve_captcha label
      words = check
      ind = []
      model = Libsvm::Model.load("visual_captcha.svm")    
      Dir['work_svm/*.png'].each do |file|  
        input = vector(file)
        index = parse_nm File.basename(file)
        pred = model.predict(Libsvm::Node.features(input))
        if
          label == words[pred]
        then
          ind = index
        end
      end
      return ind        
    end
       
    def parse_page label
      begin
        @b.divs(:class =>"img").each do |img|
          index = img.img.attribute_value('data-index')
          nm = parse_request(img.img.src)
          save_img index, label, nm, img.img
        end
      rescue Exception => e
        puts e.message
      end
      return true
    end

    def run
      begin
        @b.goto START_URL
        sleep 3
        1.times do
          label = get_word
          parse_page label
          res = resolve_captcha label
          click res
        end
      rescue Exception => e
        #puts e.message
      ensure
        finalize
      end
      return true
    end

=begin doc
partie private
=end    
    private
    def make_agent
      #@headless = Headless.new
      #@headless.start  
      Selenium::WebDriver::Firefox.path = '/home/digital/firefox31/firefox/firefox'
      @b = Watir::Browser.new :firefox
    end  
   
    def kill
      @b.close
      #@headless.destroy  
    end  
 
  end
###############################  
###############################

  class TrainSvm
=begin doc
partie image
=end
    def split_name string
      res = string.split("_")
      label = res[0]
      return label
    end
   
    def vector(img)
      out = []
      image = Magick::Image.read(img).first
      image.each_pixel do |pixel, c, r|
        out << (pixel.intensity > 0 ? 1 : 0)
      end
      return out        
    end

    def check
      ls = []
      Dir['train_svm/*.png'].each do |file|  
        obj = split_name File.basename(file)
        ls << obj
      end
      return ls.uniq          
    end

    def normalize vec
      s = Math.sqrt(vec.map{|x|x*x}.inject{|x,y|x+y})
      vec.map{|x| x/s}
    end
     
=begin doc
partie SOM
=end
    def som
      alpha = ('a'..'z').to_a + ('0'..'9').to_a  
      example_test = []
      captcha_out = []
      Dir['images/*.png'].each do |file|  
        vec = vector(file)
        obj = split_name File.basename(file)
      end      
    end  

=begin doc
partie SVM
=end
    def svm words
      alphahash = Hash[words.map.with_index.to_a]  # "a"=>0,"b"=>1,"c"=>2 ..
      puts alphahash
      examples, outputs = [], []

=begin doc
partie train
=end
      problem = Libsvm::Problem.new
      parameter = Libsvm::SvmParameter.new
      parameter.cache_size = 1 # in megabytes
      parameter.eps = 0.001
      parameter.c = 10

      Dir['train_svm/*.png'].each do |file|  
        vec = vector(file)
        obj = split_name File.basename(file)
        examples << vec.flatten
        outputs << alphahash[obj]
      end      

      vectors = examples.map {|ary| Libsvm::Node.features(ary) }
      labels = outputs
      problem.set_examples(labels, vectors)
 
      model = Libsvm::Model.train(problem, parameter)

=begin doc
partie test
=end
      Dir['test_svm/*.png'].each do |file|  
        input = vector(file)
        obj = split_name File.basename(file)
        pred = model.predict(Libsvm::Node.features(input))
        puts "#{obj} : Predicted #{words[pred]}"
      end  
      model.save("visual_captcha.svm")
    end      
  end
end

  def main_test
    include Decode_Visual_Captcha
    bot = TestSvm.new
    bot.run
  end

  def main_vector
    include Decode_Visual_Captcha
    bot = TrainSvm.new
    words = bot.check
    bot.svm words
  end

  def main_scrap
    include Decode_Visual_Captcha
    bot = ScrapePicto.new
    bot.run
  end
 
  def main
    #main_scrap
    #main_vector
    #main_test
  end

main
 

enjoy smile

edit :

à noter plusieurs choses :
- le code est fait à l'arrache, ya surement moyen d'optimiser le tout
- le SVM peut servir à catégoriser du texte, dans le lien que j'ai filé, ils s'en servent pour la détection du spam

c'est tout je crois big_smile

Dernière modification par conquering_lion (2014-11-29 12:41:14)

0
J'aime ❤️

🔴 Hors ligne

#2 2014-12-01 15:10:04

Mention Automate
🥉 Grade : Scout

AuxiliaireMembre Hospitalier
Inscription : 2014-03-27
Messages : 313
Likes : 0

Re : Tuto - ruby - another captcha resolver (image inside)

Tu utilises ces scripts en "production" pour casser les captchas que tes scripts rencontrent ?

0
J'aime ❤️

🔴 Hors ligne

#3 2014-12-01 19:18:19

Mention conquering_lion
🥉 Grade : Scout

Auxiliaire10likes
Inscription : 2013-05-23
Messages : 275
Likes : 16

Re : Tuto - ruby - another captcha resolver (image inside)

hello

non non, du tout, c'est plus le challenge technique qui m'amuse
au pire je pourrais toujours fourrer tous mes tests dans un mémoire de doctorat en IA un de ces 4, du style "les captchas ne seront jamais sures"

pour ce test, le coté intéressant était de voir le comportement d'un SVM (que je n'avais jamais utilisé avant, et à peine vu en cours de fac) sur de l'image .. deux nouveautés pour moi

je pense que je vais tester les captchas sous forme de petits jeux où il faut replacer correctement les éléments mouvants .. ca peut être pas mal big_smile

edit :

c'est aussi un plaisir de coder en ruby, donc doublement sympa smile

Dernière modification par conquering_lion (2014-12-01 19:32:26)

0
J'aime ❤️

🔴 Hors ligne

#4 2014-12-02 23:21:25

Mention Automate
🥉 Grade : Scout

AuxiliaireMembre Hospitalier
Inscription : 2014-03-27
Messages : 313
Likes : 0

Re : Tuto - ruby - another captcha resolver (image inside)

C'est sur que ce genre de challenge est toujours sympa !

Je dis ça parce que ton captcha solver audio, ça pourrait vraiment être une tuerie si on pouvait se câbler dessus !

Pour moi ce genre de dev, ça vaut mieux que juste de l'amusement smile

0
J'aime ❤️

🔴 Hors ligne

#5 2014-12-07 10:13:17

Mention conquering_lion
🥉 Grade : Scout

Auxiliaire10likes
Inscription : 2013-05-23
Messages : 275
Likes : 16

Re : Tuto - ruby - another captcha resolver (image inside)

j'y songe, j'y songe .. smile

0
J'aime ❤️

🔴 Hors ligne

Pied de page des forums