「captcha」を含む日記 RSS

はてなキーワード: captchaとは

2011-09-02

CAPTCHAと、その認証自動化するシステムは最終的にどっちが勝つ?

CAPTCHAめんどいので、それをアウトソースするシステムを考える→今度はCAPTCHAをする側に立って、そのシステムを無効化する方法を考える→今度はその方法が通用しないようなCAPTCHAを考える→・・・

とやっていって、最後にはどっちが勝つだろうか。

2011-03-09

2011年版】Wordpressお薦めプラグインまとめのまとめ+ソーシャルプラグイン

これからWordpressを始める方、あるいは始めている方が

Wordpressプラグインを探す際に便利になるかな、と思いまとめてみました


2010年以降のみのまとめ及びエントリーに絞っています。



(1)基本的なプラグイン

(2)SEOこだわり派プラグイン

(3)仕事系お役立ちプラグイン

(4)中級者から上級者向けのマニアックプラグイン

(5)ソーシャルプラグインの紹介記事




(1)基本的なプラグイン

2011年版!絶対にインストールしたWordPressプラグイン45個|Vanilla Rock

http://vanilla-rock.com/blog/wordpress/45-absolutely-install-wordpress-plugin/

ある程度、基本的なものからメジャーなものまで揃っています。

Wordpressを始めた人が最初に見ておくと、何かと便利かと思います。





WordPressブログを作ったら入れるべき27個のプラグイン|AUTHORITY SITE

http://www.authority-site.com/2010/04/wordpress/27-wordpress-plugin.html

記事内やサイドバー内で、PHPを扱うことができるものなどの紹介。





使用中のおすすめWordPressプラグイン15個 | Webクリエイターボックス

http://www.webcreatorbox.com/tech/recommended-wordpress-plugin/

フォーム用キャプチャプラグインReally Simple CAPTCHAや、

管理画面に行かなくてもタイトルや本文、カテゴリー名などを編集できるFront-end Editorなどの紹介。





WordPressプラグイン 必須なものから便利なちょっとしたものまで(Webデザインレシピ

http://webdesignrecipes.com/my-favorite-wordpress-plugins/

記事中の画像を1枚だけ取得してサムネイル表示してくれるPost Thumb Revisitedや、

携帯電話から記事を投稿できるKtai Entryなどの紹介。





(2)SEOこだわり派プラグイン

あまり知られていないかもなSEO関連のWordPressプラグイン集:phpspot開発日誌

http://phpspot.org/blog/archives/2011/03/seowordpress_1.html

かなりマニアックSEOに関するまとめです検索対策にこだわりたい方向けです





(3)仕事系お役立ちプラグイン

クライアントに頼まれやすい機能を補えるWordPressプラグインいろいろ-かちびと.net

http://kachibito.net/wordpress/plugins-for-commercial.html

アップロードした画像を一括で記事内に挿入できる、File Galleryや、

管理画面TOPメモを加えるQuickNotes on WP Dashboardなどの紹介。





特集記事や新着記事を見栄えよくスライドショーしてくれるWordPressプラグインまとめ « Web制作覚え書き

http://webdevtoolsoboegaki.wordpress.com/2010/06/22/%E7%89%B9%E9%9B%86%E8%A8%98%

E4%BA%8B%E3%82%84%E6%96%B0%E7%9D%80%E8%A8%98%E4%BA%8B%E3%82%92%E8%A6%8B%E6%A0%84%

E3%81%88%E3%82%88%E3%81%8F%E3%82%B9%E3%83%A9%E3%82%A4%E3%83%89%E3%82%B7%E3%83%A7%E3%83%BC/

イメージをフェードイン・アウトしてくれるプラグインWordPress Content Slideなどの紹介。

URLが長いので繋げてアクセスするか、記事名で検索するかしてください)





WordPressサイトを構築した際に活用したプラグイン5個+α - id:HolyGrailid:HoryGrailの区別がつかない日記

http://d.hatena.ne.jp/HolyGrail/20110228/1298889864

会員登録時に必要な項目を追加する、Cimy User Extra Fieldsなどの紹介。



(4)中級者から上級者向けのマニアックプラグイン

WordPress 3.0対応のとっても便利なプラグイン集|コリス

http://coliss.com/articles/blog/wordpress/plugin/best-plugins-for-wordpress-3.html

管理画面のメニューに好きなアイテムを追加できるFavorites Menu Manager

や、投稿編集ページにカスタムフィールドHTMLを挿入できるInsertMeta ShortCodeなどの紹介。





(5)ソーシャルプラグインの紹介記事


WP Social Bookmarking Light | NINXIT-BLOG

http://www.ninxit.com/blog/2010/06/13/wp-social-bookmarking-light/

はてぶ、FacebookTwitter他、表示させたいものは各々で選択可





WordPressTwitterコメントシステムプラグインリリース!– [Mu]ムジログ

http://musilog.net/webdesign/wordpress/twitter-anyware-comment-system.php

みんなのTwitterからの言及コメントを表示できます





RTしてくれたTwitterの呟きがコメント欄に全文表示されるプラグインBackType Connect”がとても良い!

[WordPress] [Twitter] [net] | No Second Life

http://www.ttcbn.net/no_second_life/archives/1144

1つ上のと同じような機能です、お好みでどうぞ。




WordPresプラグインTwitter tools」のバージョンアップ版のインストールと設定、使い方を日本語解説!:WordPressアマモ

http://www.amamoba.com/wordpress/twitter-tools2.html

記事の投稿と同時に、Twitterポストするタイププラグイン

2010-09-14

好きな人名前 その2

http://anond.hatelabo.jp/20100907085547 の続きなんだけど、

自分名前を調べるときに、人間じゃないとわからない質問に答える、

いわゆるCAPTCHAを設ければロボットによるクロールがなくなるから、

実用的になるんじゃないかなと思ったり。

でも画像認証以外の良いCAPTCHAが思いつかない。

サイト利用者が質問を出し合って、その質問が人間が答えたものか判断する、

って仕組みを考えたけど面倒かもと思ったけど、メールのやりとりみたいで楽しいかもと思ったり。

その宛先が好きな人ならなおさら。



漏れ好きな人名前を叫びたいんだよ!

2010-05-09

http://anond.hatelabo.jp/20100509163408

マジレスすると、技術的な問題はほぼない。

検索ブックマークBOTrobots.txtメタタグで避けることが出きるし、CAPTCHAなぞなぞ認証のような形のアクセス制限も広く運用されている。

必要なのは腐女子ニーズを把握し、必要な技術を選択し、または適切な選択肢を用意し、魅力をアピールしてその界隈でメジャーにしつつ、何らかの方法で利益に結びつける事。

つまり、ビジネス的な問題。

2010-02-13

何これバカにしてんのか

Twitter登録時のCAPTCHAがいみわかんねぇんだけど

単語が二つ出てきてその二つとも入力してるのに一向に認証が通らない

意味わからん

ちゃんとしたCAPTCHA作れやボケ

 

 

しかも下の注意書きには

「2つの文字を見つけて入力してください」?

どういう事だ単語じゃなくて文字入れるのか?

2009-08-17

亡くなった人のはてなダイアリー

アンテナで上がってきたので何かなと思ったら

コメント欄エロサイト広告コメントがついてた



http://d.hatena.ne.jp/yskszk/



なんだか知人の墓が荒らされたようで切ない



はてなCAPTCHAを破るプログラムは30分あれば書ける

http://d.hatena.ne.jp/yaneurao/20090802



こんな風に指摘されてるんだから

早くはてなも対応してくれればいいのに

このごろのはてなは本当にさえないなぁ

2009-02-04

ぼくのかんがえた CAPTCHA

  1. しなもんとかそれっぽいわんこ3Dデータを作る。
  2. おすわりとかふせとかちんちんとかそんなポーズを取らせる。
  3. 光源とかカメラの位置をある程度ランダムにして、レンダリング
  4. それを表示させて、入力欄に「ちんちん」とかポーズ名を書いてもらう。
  5. できれば「けんけん」とか「たってる」とかそういう表記揺れもフォローする。もしくは「おすわり、ふせ、ちんちん、あなほり、じゃんぷのいずれかのポーズを取っています。」みたいな解説文をプラスする。

はてなアンケートCAPTCHA がせめてわんこだったら和んだのにと思ってそっからずるずる。

ポリゴンものについてあんまよく知らないんだけど、現状でもまだ PCハッスルしないとレンダリングできないものなのかな。八年前に買った携帯ポリゴンもの表示できたから、今はそんなハッスルしなくてもいいかも、とかチラッと思ったんだけど。

2008-11-08

SEO業者に発注した話。

はじめてSEOを専門業者に発注した。

http://anond.hatelabo.jp/20081107171440

この話を読んで、そう言えば俺もSEO業者に頼んだ事あったなあと思い出した。

費用数万円。3-4年前の話。いろんなブログで紹介してあるポピュラーな業者だった。

当時はどこにも検索順位の保証とかは無かった。


<当時受けたサービス概要>

・バックリンクを増やす

いろんなバックリンクを増やしてくれるというのが、サービスメインだった。

例えば、中規模や大規模の検索エンジンディレクトリとか。

果ては国内や海外のいろんな掲示板勝手に書き込みしてくれるというものまであった。

(国内は試さなかった。海外を試したらスパムメールがたくさん来ただけだった。)

考えたら、同じサービスを受けているヤツらはたくさんいるわけで、そういうヤツらと差別化できるわけないよなと思った。

Googleの「link:」検索で検索しても、そういうバックリンクは一つも出てこなかった。Googleではまず間違いなく評価されていないだろう。ヤフーではトップページダウンペナルティ対象になるかもしれない。ずっとペナルティが解ける事は無かった。

はっきり言ってこういうバックリンクに頼るより、良いサイトを作って、SBMで多くのブクマを集めた方がよっぽど上位表示されるような気がする。


SEOツール

ツールを使えるとかいうのもあったなあ。

リンク切れが無いか調べるものから、キーワードごとの検索順位を見るもの。

Googleクロールしてもらうようにするのに、URLを登録するツールなんてのもあったなあ。昔はGoogleに登録するのにCAPTCHAとかも無かった。

今考えると、Googleサイトマップを作って設置し、ウェブマスターツールを使った方がよっぽど高機能。

こういうサービスで金を取られていた頃が懐かしいくらいだ。


サイト診断

サイト診断をしてもらったのだが、今考えると、金返せ、と言いたくなる内容だった。

サイトのヘッダー部分の画像を変えた方が良いですよ」

Googleページランクを確認した方が良いですよ」

こんなもんだぞ。これってSEO業者のコンサルティングなの?

今こういう返事が来たら、さすがに金返せというよ。だけど、たぶんいろんなサービスみの値段だから返金とか無理なんだろうね。

あの頃は若くて無知だった。

せめて、「独自ドメインを取得して下さい」というところからアドバイスを始めて、「サイトHTML構造をこういう風に変えた方が良い」とか、メタタグアドバイスとか、そのくらいの事は余裕で指摘して欲しかった。

出来れば、「キーワードのdensityは何%くらいが良い」とかも指摘して欲しかった。

Googleで好かれるhタグの使い方」、「Yahoo!で好かれるhタグの使い方」とかも教えて欲しかった。

それくらいの事が出来ない業者はダメだな。


数万円をいろんなサイトで使ったから、かなりに金額になった。

元増田より使ってるかもしれない。

悪い事は言わんから、効果なかったらあきらめた方が良いかも。追加で金払ったりするのはやめた方が良いよ。

時間がかかりますとか平気で言ってくる業者は実力が無いんだろうなと思う。

今は上位に表示されなければ金は取らないというところにしか頼む気にはなれないなあ。

2008-10-19

YourFileHostの動画をなんとかする

YourFileHostのCAPTCHA画像をなんとかするの続きの続き。

まぁ、なんというか、一応できたので張ってみる。微妙な出来栄えだけど。

decaptcha.rbと同じディレクトリに置いて適当に動かしてみてください。

どっかにいいRSSがないかなぁ。。。

しかし、CAPTCHA画像を相手にしてた時の方が楽しかったなぁ。。。

あと、添削とかいろいろ歓迎です。

追記

なぜか&が&に置き換えられてるみたいなので、適当に&に読み替えてください。

download.rb

#!/usr/local/bin/ruby
$LOAD_PATH << File::dirname(File::expand_path($0))
require 'rubygems'
require 'rss'
require 'mechanize'
require 'decaptcha'
# require 'ruby-debug'
# require 'pp'

DESTDIR = 'files'
TMPDIR = '/tmp'

class Downloader
  COOKIE_URI = 'http://www.yourfilehost.com/media.php?cat=video&amp;file=%s'
  DOWNLOAD_URI =
    'http://www.yourfilehost.com/downloadlink.php?cat=video&amp;file=%s&amp;adult=1'
  VERBOSE = false
  DEBUG = false
  
  def self.fetch(file, destdir)
    puts "Fetching file: #{file}"

    destfile = destdir + '/' + file
    if test(?e, destfile) then
      puts '  - Already exists. skip'
      puts
      return nil
    end
  
    #
    # Initialize Mech
    #
    mech = WWW::Mechanize.new
    mech.user_agent_alias = 'Windows IE 6'
    mech.max_history = 3
    mech.open_timeout = 15
    mech.read_timeout = 3
  
    #
    # get cookie
    #
    uri = COOKIE_URI % file
    page = mech.get(uri)
  
    #
    # Challenge against CAPTCHA
    #
    uri = DOWNLOAD_URI % file
    page = mech.get(uri)
  
    for i in 0...3
      captcha_path = (page/'img[@height="38"]').attr(:src)
      captcha_uri = 'http://www.yourfilehost.com/%s' % captcha_path
      gif = mech.get_file(captcha_uri)
      open("#{TMPDIR}/captcha.gif", 'w') {|fd| fd.write(gif) }
      mech.back
  
      code = DeCAPTCHA.decode("#{TMPDIR}/captcha.gif")
      File.unlink("#{TMPDIR}/captcha.gif")
      if code.nil? then
        puts '  - CAPTCHA decode failed. retry' if VERBOSE
        next
      end
  
      form = mech.page.forms.first
      form.verify = code
      page = mech.submit(form)
  
      break unless page.links.empty?
    end
  
    if page.links.empty? then
      puts '  - Failed 3 times.  Try another one.'
      puts
      return nil
    end
  
    #
    # download
    #
    puts "  - Downloading: #{page.links.first.href}" if DEBUG
    retry_count = 0
    video = nil
    begin
      video = page.links.first.click
    rescue Timeout::Error => evar
      retry_count += 1
      if retry_count < 5 then
        puts "  * Timedout, retry" if VERBOSE
        retry
      end
      raise evar
    end

    unless video.instance_of?(WWW::Mechanize::File) then
      if DEBUG then
        puts "  - Something wrong while downloading. skip."
        puts
      end
      return nil
    end
    video.save(destfile)

    return destfile
  end
end



#
# main
#
[DESTDIR, TMPDIR].each do |dir|
  if !test(?d, dir) or !test(?w, dir) then
    puts "#{dir}: Directory not exists or cannot write."
    exit
  end
end

files = []


# collect URIs from RSS
RSS_URI = [
  ['http://www.yourfilehost.com/make-rss.php?range=day&amp;af=off',
    lambda {|rss| rss.items.map {|x| x.link }},
  ],
]
RSS_URI.each do |uri, preprocessor|
  rss = RSS::Parser.parse(uri)
  uris = preprocessor.call(rss) #=> Array of URI of YourFileHost

  uris.map {|x| /file=([^&amp;]*)/.match(x).to_a[1] }.each do |file|
    # next if file !~ /\.wmv/  # uncomment it if you need only wmv
    files << file
  end
end
files.uniq!


# download
files.each do |file|
  begin
    Downloader.fetch(file, DESTDIR)
  rescue SystemCallError, Timeout::Error => evar
    puts "  - error (#{evar.to_s}). skip."
    puts
  end
end
__END__

2008-10-17

http://anond.hatelabo.jp/20081006220009

YourFileHostのCAPTCHA画像をなんとかするの続き。

その後、適当にいじったら、手元環境で1枚あたり25秒くらい→だいたい2.5秒くらいで判別できるようになった。このくらいなら使えるかな。

速度向上に一番効いたのは、Token#importで画像を比較しているところの修正。他は細かい手直し。

使い方は前のやつと変わってません。

あと、テストに100枚くらいCAPTCHA画像食わせてみたけど、とりあえず全部正しく判定できた。

動作確認用のスクリプト (run.rb)

カレントディレクトリ以下にある*.gifCAPTCHA画像ファイル適当に判別するスクリプト。動作確認用にどうぞ。

後述のdecaptcha.rbと同じディレクトリ適当に置いてchmod +xしてね。

#!/usr/local/bin/ruby
$LOAD_PATH << File::dirname(File::expand_path($0))
require 'decaptcha'

STDOUT.sync = true

Dir.glob('*.gif').sort.each do |file|
  correct = File::basename(file, '.*')
  puts "Processing file: #{file}"
  start_time = Time.now
  ret = DeCAPTCHA.decode(file)
  elapsed = Time.now - start_time

  puts "  Result: #{ret} (=> #{(correct == ret) ? "Ok" : "Fail"})"
  puts "  Elapsed time: #{elapsed}"
  puts
end

コード (decaptcha.rb)

#!/usr/local/bin/ruby
require 'rubygems'
require 'gd2'
require 'pp'

#
#= CAPTCHA画像解析モジュール
# CAPTCHA画像ファイルを食わすとあら不思議Stringが出てくるよ。
# YourFileHostのやつに対応。
#
#== Usage
# decoded_str = DeCAPTCHA.decode("some_captcha_image.gif")  #=> String
# 失敗したらnilが返る。
#
module DeCAPTCHA
  DEBUG = false

  #=== CAPTCHA画像デコード
  # file::    画像ファイル名のパス
  # method::  未指定でよい。男は細かい事を気にするな。
  # returns:: CAPTCHA画像解析結果(String) or nil (デコード失敗時)
  def self.decode(file, method = DeCAPTCHA::Site::YourFileHost)
    return method.new(file).decode
  end



  #= CAPTCHA画像デコードクラス
  # このクラスサブクラスはimport, tokenize, stream_parseメソッドの
  # 実装を含む必要がある。
  class Site
    def initialize(file = nil)
      @pix = nil
      self.import(file) unless file.nil?
    end
    def decode
      return stream_parse(tokenize())
    end
  end

  #= YourFileHostのCAPTCHA画像を解析するクラス
  class Site::YourFileHost < Site
    def import(file)
      @pix = PixelMatrix.new.import(file)
      return self
    end

    # importしたイメージ(PixelMatrix)から、文字と思わしきパターンを
    # 抽出して上下マージンを切り取ってArrayにして返す。
    # returns:: Array of PixelMatrix
    def tokenize
      ret = []
      state = :initial
      for x in 0...@pix.width
        case state
        when :initial
          if !@pix.vline_blank?(x) then
            state = :tokenize
            pixel = PixelMatrix.new(0, 0, true)
            ret << pixel
            redo
          end
        when :tokenize
          if @pix.vline_blank?(x) then
            state = :initial
            next
          end
          x0 = pixel.width
          for y in 0...@pix.height
            pixel[x0, y] = @pix[x, y]
          end
        else
          raise 'NOTREACHED'
        end
      end

      ret.map! {|token| Token.new.import(token.cutoff_vmargin!) }
    end


    # PixelMatrixのArrayを受け取り、数字を判別。
    # tokens:: Array of PixelMatrix
    # returns:: String (判別結果)
    def stream_parse(tokens)
      rs = tokens.map {|x| x.guess.to_s }.join('')
      if rs.length != 4 then
        rs = nil
        if DEBUG then
          puts '- guess failed. dumping guess result of each token:'
          tokens.each_index do |i|
            print "##{i}:#{tokens[i].guess} "
            pp tokens[i].candidate
          end
          puts
        end
      end
      return rs
    end

    class Token
      @@digits = nil
      attr_accessor :candidate

      def initialize
        if @@digits.nil? then
          # 文字画像サンプルを作っておく
          @@digits = DIGITS_ASSOC.map {|digit|
            PixelMatrix.new(0, 0, true).import_array(digit) }
        end

        @candidate = Hash.new
      end

      # PixelMatrixを受け取り、文字画像サンプルと比較して
      # 一致率を計算しておく。
      # pixel:: PixelMatrix
      # returns:: self
      def import(pixel)
        @@digits.each_index do |i|
          digit = @@digits[i]

          if (digit.width - pixel.width).abs   > 4 or
             (digit.height - pixel.height).abs > 4 then
            @candidate[i] = -1  # サイズが違いすぎな場合、一致させない
            next
          end

          correct_bits = 0
          enlarged_width  = [digit.width,  pixel.width ].max
          enlarged_height = [digit.height, pixel.height].max
          for y in 0...enlarged_height
            dy = (y.to_f / digit.height * enlarged_height).to_i
            py = (y.to_f / pixel.height * enlarged_height).to_i
            for x in 0...enlarged_width
              dx = (x.to_f / digit.width * enlarged_width).to_i
              px = (x.to_f / pixel.width * enlarged_width).to_i
              correct_bits += 1 if digit[dx, dy] == pixel[px, py]
            end
          end

          @candidate[i] = correct_bits * 100 /
                          (enlarged_width * enlarged_height)
        end

        return self
      end

      # importのときの比較結果をもとに文字を推測
      # returns:: Fixnum or nil(失敗時)
      def guess
        digit, ratio = @candidate.sort {|a, b| a.last <=> b.last}.last
        digit = nil if ratio < 0 or ratio < 65
        return digit
      end
    end
  end


  #= 画素マトリックスクラス
  # 画像ファイルを食わせると、各ピクセル(画素)を2値(black(1) or white(0))に
  # 変換して、内部で保持する。
  # 以後、Matrixクラスのような感じで個々の画素アクセスできる。
  class PixelMatrix
    BLACK = 1
    WHITE = 0

    attr_accessor :width
    attr_accessor :height

    # width::  幅
    # height:: 高さ
    # is_flexible:: 自動的に伸張するか
    def initialize(width = 0, height = 0, is_flexible = false)
      @matrix = Hash.new {|hash, key| hash[key] = Hash.new(WHITE)}
      @width, @height, @flexible = width, height, is_flexible
    end

    # file:: 画像ファイル名のパス
    # brightness_threshold:: 画素を黒とみなす閾値 (0 - 255, default: 0x40)
    # returns:: self (DeCAPTCHA::PixelMatrix)
    def import(file, brightness_threshold = 0x40)
      gd = GD2::Image.import(file)
      @width, @height = gd.width, gd.height

      self.each_with_axis do |x, y|
        color = gd[x, y]
        greyscale = (color.red + color.green + color.blue) / 3
        self[x, y] = (greyscale > brightness_threshold) ?
          WHITE :
          BLACK
      end
      return self
    end

    def import_array(array)
      array.each_with_index do |str, y|
        str.split('').each_with_index do |c, x|
          self[x, y] = c.to_i
        end
      end
      return self
    end

    # PixelMatrixを画像ファイルとしてexport
    # file:: 新たに作る画像ファイル名のパス
    def export(file)
      gd = GD2::Image::IndexedColor.new(@width, @height)
      gd.palette << GD2::Color::WHITE
      gd.palette << GD2::Color::BLACK
      self.each_with_axis do |x, y|
        gd[x, y] = {
          WHITE => GD2::Color::WHITE,
          BLACK => GD2::Color::BLACK,
        }[self[x, y]]
      end
      gd.export(file)
      return self
    end

    # 指定された位置の画素を返す。
    # returns:: PixelMatrix::BLACK(1) or WHITE(0)
    def [](x, y)
      if !@flexible and !in_range?(x, y) then
        raise RangeError
      end
      return WHITE if !@matrix.has_key?(y)  # XXX: for optimize
      return @matrix[y][x]
    end

    # 画素に値を設定。
    # returns:: PixelMatrix::BLACK(1) or WHITE(0)
    def []=(x, y, val)
      unless in_range?(x, y) then
        raise RangeError unless @flexible
        @width  = (x >= @width)  ? x + 1 : @width
        @height = (y >= @height) ? y + 1 : @height
      end

      @matrix[y][x] = val
    end

    def in_range?(x, y)
      ((0...@width) === x and (0...@height) === y)
    end

    # 指定された軸をもとに画素を走査し、Arrayに変換。
    # 例えば、to_a(:vertical, 10) とすると、x == 10 な列を取り出して
    # Arrayにして返す。
    #
    # axis:: 軸を指定 (:vertical または :horizontal)
    # pos:: 位置を指定。_axis_で指定した軸と直交する軸における位置を指定。
    def to_a(axis, pos)
      {:vertical => lambda {
        (0...@height).map {|y| self[pos, y]}
       },
       :horizontal => lambda {
        (0...@width).map  {|x| self[x, pos]}
       },
      }[axis].call
    end

    # returns:: Array
    def hline(y)
      self.to_a(:horizontal, y)
    end

    # returns:: Array
    def vline(x)
      self.to_a(:vertical, x)
    end

    # X軸方向に画素を走査。
    # y:: どの位置で走査するか
    # returns:: 指定された軸の上にドットが存在: false, 無い: true
    def hline_blank?(y)
      return true if @matrix.has_key?(y) == false # XXX: for optimize
      for x in 0...@width
        return false if self[x, y] == BLACK
      end
      return true
    end

    # Y軸方向に画素を走査。
    # x:: どの位置で走査するか
    # returns:: 指定された軸の上にドットが存在: false, 無い: true
    def vline_blank?(x)
      for y in 0...@height
        return false if self[x, y] == BLACK
      end
      return true
    end

    # 上下のマージン削除した新しいPixelMatrixを返す。
    # returns:: PixelMatrix
    def cutoff_vmargin
      pixel = PixelMatrix.new(0, 0, true)
      head = 0
      tail = self.height - 1

      head.upto(tail) do |y|
        if !self.hline_blank?(y) then
          head = y
          break
        end
      end
      tail.downto(head) do |y|
        if !self.hline_blank?(y) then
          tail = y
          break
        end
      end

      head.upto(tail) do |y|
        0.upto(self.width - 1) do |x|
          pixel[x, y - head] = self[x, y]
        end
      end

      return pixel
    end
    
    # 自身の上下のマージン削除する。cutoff_vmarginの破壊版。
    # 速度稼ぎのために直接@matrixを触ったり、すこしずるをしている。
    # 効率は、ほんの少しだけ速くなったような誤差の範囲のような感じ。
    # returns:: self (PixelMatrix)
    def cutoff_vmargin!
      head = 0
      tail = self.height - 1

      head.upto(tail) do |y|
        if !self.hline_blank?(y) then
          head = y
          break
        end
      end
      tail.downto(head) do |y|
        if !self.hline_blank?(y) then
          tail = y
          break
        end
        @matrix.delete(y) if @matrix.has_key?(y)  # XXX
      end

      if head > 0 then
        head.upto(tail) do |y|
          next if !@matrix.has_key?(y)            # XXX
          @matrix[y - head] = @matrix.delete(y)   # XXX
        end
      end
      self.height = tail - head + 1

      return self
    end
    
    def each_with_axis
      for x in 0...@width
        for y in 0...@height
          yield(x, y)
        end
      end
    end
  end
end

class DeCAPTCHA::Site::YourFileHost::Token
DIGITS_ASSOC = [
  # 0
  ["00000000011111110000000000",
   "00000001111111111110000000",
   "00000011111000001111000000",
   "00001111111100010011110000",
   "00011111100000110000111000",
   "00111111000000100001111000",
   "00111111110001000001111100",
   "01111111000010000011111110",
   "01111100000110000111111110",
   "01111111000100000111111110",
   "11111100001000001111111111",
   "11100000001000011111111111",
   "11111000010000011111111111",
   "11111000110000111111111111",
   "10000000100001111111111111",
   "01100001000001111111111110",
   "01100010000011111111111110",
   "01100010000111111111111110",
   "00111100000111111111111100",
   "00011100001111111111111000",
   "00001100011111111111111000",
   "00001111111111111111100000",
   "00000011111111111111000000",
   "00000000111111111100000000"],
  # 1
  ["00001",
   "00111",
   "11111",
   "11111",
   "10001",
   "00001",
   "00001",
   "00001",
   "00001",
   "00001",
   "00001",
   "00001",
   "00001",
   "00001",
   "00001",
   "00001",
   "00001",
   "00001",
   "00001",
   "00001"],
  # 2
  ["0000011111111110000000",
   "0001111111111111000000",
   "0011110000000010000000",
   "0110000000000100000000",
   "1100000000001100011110",
   "1000000000001000001111",
   "1000000000010000000111",
   "1000000000110001111111",
   "1000000000100001111111",
   "1000000001000000011111",
   "0100000011000001111111",
   "0011000010000111111110",
   "0011000110000001111110",
   "0000001100000111111100",
   "0000001000011111110000",
   "0000011000000111100000",
   "0000110000000000000000",
   "0000111111111111111111",
   "0001111111111111111110",
   "0011111111111111111100",
   "0011111111111111111100",
   "0111111111111111111000",
   "0111111111111111110000"],
  # 3
  ["000000011111111110000000",
   "000001111111111111100000",
   "000011100000011111111000",
   "000111000000111111111000",
   "000110000001111111111100",
   "000100000001111111111100",
   "000100000011111111111100",
   "000110000111111111111000",
   "000010000111111111111000",
   "000000001111111111100000",
   "000000011111111111000000",
   "000000011111111110000000",
   "000000000000001100000000",
   "000000000000011100011100",
   "000000000000111000111110",
   "000000000000110000001110",
   "000000000001110001111111",
   "110000000011100011111111",
   "111000000111000000111110",
   "011100000110001111111100",
   "001111001110000111111000",
   "000011111100000011100000",
   "000000011000111000000000"],
  # 4
  ["0000000000011",
   "0000000000011",
   "0000000000111",
   "0000000001111",
   "0000000001111",
   "0000000011111",
   "0000000111111",
   "0000000110111",
   "0000001100111",
   "0000011100111",
   "0000011000111",
   "0000110000111",
   "0001110000111",
   "0001100000111",
   "0011000000111",
   "0111000000111",
   "0111111111111",
   "1111111111111",
   "0000000000111",
   "0000000000111",
   "0000000000111",
   "0000000000111",
   "0000000000111"],
  # 5
  ["000000001111111111111110",
   "000000011111111111111100",
   "000000111111111111111100",
   "000000111111111111111000",
   "000001111111111111110000",
   "000011100000000000000000",
   "000011011111111110000000",
   "000111111111111111000000",
   "001111100000000111000000",
   "001110000000000110001100",
   "000000000000000100011110",
   "000000000000001100000110",
   "000000000000011000011111",
   "000000000000011001111111",
   "000000000000110000011111",
   "000000000001100000111111",
   "110000000001100111111110",
   "011000000011000001111110",
   "011100000110000011111100",
   "001111000110011111111000",
   "000111111100001111110000",
   "000001111100000011000000",
   "000000001000011000000000"],
  # 6
  ["000000000000000110000000",
   "000000010001111111111000",
   "000001110000011100111100",
   "000011100000011000001000",
   "000111000011111000000000",
   "001111000001110000000000",
   "001110000000111100000000",
   "011110001111111111100000",
   "011100000111000011110000",
   "011000000010000001111000",
   "011000011110000011111100",
   "010000111100000111111110",
   "100000001000000111111110",
   "100001111000001111111111",
   "000011110000011111111111",
   "000000100000011111111111",
   "000011100000111111111111",
   "001111000001111111111110",
   "000010000001111111111110",
   "001110000011111111111100",
   "000111000111111111111000",
   "000011111111111111110000",
   "000000111111111111000000",
   "000000000111111000000000"],
  # 7
  ["0011111111111110001111",
   "0011111111111100000011",
   "0111111111111000000110",
   "1111111111111000111100",
   "1111111111110000001100",
   "0000000000000000011000",
   "0000000000000011111000",
   "0000000011000000110000",
   "0000001110000011100000",
   "0000011110001111100000",
   "0000111100000011000000",
   "0001111000000110000000",
   "0001111000111110000000",
   "0011110000001100000000",
   "0011110000001000000000",
   "0011100011111000000000",
   "0011000001110000000000",
   "0001000000110000000000",
   "0000000111100000000000",
   "0000000111000000000000",
   "0000000011000000000000",
   "0000001110000000000000",
   "0000001100000000000000"],
  # 8
  ["0000000111111111110000000",
   "0000011111111111111100000",
   "0000001111100000011110000",
   "0000000001110000000111000",
   "0011000011111000000011100",
   "0011100001111100000011100",
   "0011110000001110000011100",
   "0001111000011111000111000",
   "0000111100000111101110000",
   "0000011110000001111100000",
   "0000001111000011111110000",
   "0000111111110000011111000",
   "0011110011111000001111100",
   "0111100001111100011111100",
   "0111000000111110000111110",
   "1111000000011111000000111",
   "1111000000001111100011111",
   "1111000000000011111000010",
   "0111100000000001111100000",
   "0011110000000000111110000",
   "0001111110000001111110000",
   "0000011111111111111000000",
   "0000000011111110000000000"],
  # 9
  ["000000111111111110000000",
   "000001111111111111100000",
   "000111111111111001111000",
   "001111111111110000010000",
   "011111111111110000010000",
   "011111111111100000100000",
   "011111111111000001100000",
   "111111111110000001000111",
   "111111111110000010000001",
   "111111111100000110000111",
   "011111111000000100011111",
   "011111111000001000001111",
   "001111110000011000011111",
   "001111100000010001111110",
   "000111110000100000011110",
   "000001111111100000111110",
   "000000011111000111111100",
   "000000000010000001111100",
   "000000000110000001111000",
   "000100001100011111110000",
   "000111001100001111100000",
   "000011111000001111000000",
   "000000010000110000000000"],
]
end
__END__

2008-10-06

YourFileHostのCAPTCHA画像をなんとかする

破ろうぜ!CAPTCHA画像♪(うっうーん)

そんなわけで、みんな大好きなYourFileHostだけども、最近みてみたら、なんかCAPTCHA認証がついているわけじゃないですか。

でもこれってさーCAPTCHAといっても見るからに危ういというか、見れば見るほど簡単に破れてしまいそうな気がして、どうにもむずがゆいアンニュイな気分になってしまうわけです。

そんで、このたび適当にいじってみたところ、それなりに推測できるコードが書けたので、ここに張ってみますね。

やってることは単純で、こんな感じ

  1. CAPTCHA画像ファイルをよみこむ
  2. ピクセルごとにグレイスケールにして、それで2値にする
  3. この時点でじゃまな背景が消えて、文字の形がわかってしまうわけです
  4. 縦軸に点がないところで切って、文字ごとにばらばらにする
  5. 文字画像のサンプルと比較して、一致率が高いものを採用

使い方は、こんな感じで

require 'decaptcha.rb'
captcha_string = DeCAPTCHA.decode(filename)
if !captcha_string.nil? then
  # 判別成功時の処理
else
  # 判別失敗時の処理。失敗することもあるのでよしなに。
end

あ、Ruby/GD2入れといてね。sudo gem install gd2とかで入ります。多分。

判別率はそこそこ良い感じになったんだけども、富豪プログラミングがたたってか、いかんせん遅いです。

手元だと1枚判別するのに20秒くらいかかることもある。

そんなわけで誰かチューニングしてくれるとうれしい。

追記

実行速度を上げた改良版はこっちにうpしました。以下のコードは参考程度に。

コード (decaptcha.rb)

#!/usr/local/bin/ruby
require 'rubygems'
require 'gd2'
require 'pp'

#
#= CAPTCHA画像解析モジュール
# CAPTCHA画像ファイルを食わすとあら不思議Stringが出てくるよ。
# YourFileHostのやつに対応。
#
#== Usage
# decoded_str = DeCAPTCHA.decode("some_captcha_image.gif")  #=> String
# 失敗したらnilが返る。
#
module DeCAPTCHA
  DEBUG = false

  #=== CAPTCHA画像デコード
  # file::    画像ファイル名のパス
  # method::  未指定でよい。男は細かい事を気にするな。
  # returns:: CAPTCHA画像解析結果(String) or nil (デコード失敗時)
  def self.decode(file, method = DeCAPTCHA::Site::YourFileHost)
    return method.new(file).decode
  end



  #= CAPTCHA画像デコードクラス
  # このクラスサブクラスはimport, tokenize, stream_parseメソッドの
  # 実装を含む必要がある。
  class Site
    def initialize(file = nil)
      @pix = nil
      self.import(file) unless file.nil?
    end
    def decode
      return stream_parse(tokenize())
    end
  end

  #= YourFileHostのCAPTCHA画像を解析するクラス
  class Site::YourFileHost < Site
    def import(file)
      @pix = PixelMatrix.new.import(file)
      return self
    end

    # importしたイメージ(PixelMatrix)から、文字と思わしきパターンを
    # 抽出して上下マージンを切り取ってArrayにして返す。
    # returns:: Array of PixelMatrix
    def tokenize
      getter, tokenizer = lambda {|queue|
        [ lambda { return queue },
          lambda {|x, pixel|
            if pixel.nil? then
              x, pixel = tokenizer.call(x, PixelMatrix.new(0, 0, true))
              queue << pixel
              return x
            end
  
            if !@pix.in_range?(x, 0) or @pix.vline_blank?(x) then
              return [x, pixel]
            end
            x0 = pixel.width
            @pix.vline(x).inject(0) do |y, color|
              pixel[x0, y] = color
              y + 1
            end
            return tokenizer.call(x + 1, pixel)
          }
        ]
      }.call([])

      x = 0
      while (x < @pix.width)
        x = @pix.vline_blank?(x) ?
          x + 1 :
          tokenizer.call(x, nil)
      end

      getter.call.map do |token|
        # Token.new.import(token.cutoff_vmargin.shrink)
        Token.new.import(token.cutoff_vmargin)
      end
    end

    # PixelMatrixのArrayを受け取り、数字を判別。
    # tokens:: Array of PixelMatrix
    # returns:: String (判別結果)
    def stream_parse(tokens)
      r = []
      tokens.inject(nil) do |prev, cur|
        r << cur.guess
      end

      rs = r.map {|x| x.to_s}.join('')
      if rs.length != 4 then
        if DEBUG then
          puts '- guess failed. dumping guess result of each token:'
          tokens.each_index do |i|
            print "##{i}: "
            pp tokens[i].candidate
          end
          puts
        end
        return nil
      end
      return rs
    end

    class Token
      @@digits = nil
      attr_accessor :candidate

      def initialize
        if @@digits.nil? then
          # 文字画像サンプルを作っておく
          @@digits = DIGITS_ASSOC.map {|assoc|
            PixelMatrix.new(0, 0, true).import_assoc(assoc) }
        end

        @candidate = Hash.new
      end

      # PixelMatrixを受け取り、文字画像サンプルと比較して
      # 一致率を計算しておく。
      # pixel:: PixelMatrix
      # returns:: self
      def import(pixel)
        gcd = lambda {|a, b|
          a, b = [b, a] if a < b
          return a if b == 0
          r = a % b
          return gcd.call(b, r)
        }
        lcm = lambda {|a, b| a * b / gcd.call(a, b) }
        mul_to_lcm = lambda {|a, b|
          g = gcd.call(a, b)
          [b / g, a / g]
        }

        0.upto(@@digits.size - 1) do |i|
          if (@@digits[i].width - pixel.width).abs   > 4 or
             (@@digits[i].height - pixel.height).abs > 4 then
            @candidate[i] = -1  # 比較対象とサイズが違いすぎ
            next
          end

          mul_ax, mul_bx = mul_to_lcm.call(@@digits[i].width,  pixel.width)
          mul_ay, mul_by = mul_to_lcm.call(@@digits[i].height, pixel.height)
          enlarged_width  = @@digits[i].width  * mul_ax
          enlarged_height = @@digits[i].height * mul_ay

          # 文字画像サンプルと比較対象画像のサイズをあわせる
          # 幅・高さをそれぞれ適当整数倍して、最小公倍数に合わせて比較
          # (めんどうだから)
          correct_bits = 0
          (0...enlarged_width).each do |x|
            (0...enlarged_height).each do |y|
              if @@digits[i][x/mul_ax, y/mul_ay] ==
                 pixel[x/mul_bx, y/mul_by] then
                correct_bits += 1
              end
            end
          end
          
          @candidate[i] = correct_bits * 100 /
                          (enlarged_width * enlarged_height)
        end

        return self
      end

      # importのときの比較結果をもとに文字を推測
      # returns:: Fixnum or nil(失敗時)
      def guess
        digit, ratio = @candidate.sort {|a, b| a.last <=> b.last}.last
        digit = nil if ratio < 0 or ratio < 80
        return digit
      end
    end
  end


  #= 画素マトリックスクラス
  # 画像ファイルを食わせると、各ピクセル(画素)を2値(black(1) or white(0))に
  # 変換して、内部で保持する。
  # 以後、Matrixクラスのような感じで個々の画素アクセスできる。
  class PixelMatrix
    BLACK = 1
    WHITE = 0

    attr_accessor :width
    attr_accessor :height

    # width::  幅
    # height:: 高さ
    # is_flexible:: 自動的に伸張するか
    def initialize(width = 0, height = 0, is_flexible = false)
      @matrix = Hash.new {|hash, key| hash[key] = Hash.new(WHITE)}
      @width, @height, @flexible = width, height, is_flexible
    end

    # file:: 画像ファイル名のパス
    # brightness_threshold:: 画素を黒とみなす閾値 (0 - 255, default: 0x40)
    # returns:: self (DeCAPTCHA::PixelMatrix)
    def import(file, brightness_threshold = 0x40)
      gd = GD2::Image.import(file)
      @width, @height = gd.width, gd.height

      self.each_with_axis do |x, y|
        color = gd[x, y]
        greyscale = (color.red + color.green + color.blue) / 3
        self[x, y] = (greyscale > brightness_threshold) ?
          WHITE :
          BLACK
      end
      return self
    end

    # reverse function of to_assoc
    def import_assoc(assoc)
      assoc.inject(0) do |y, columns|
        columns.inject(0) do |x, color|
          self[x, y] = color
          x + 1
        end
        y + 1
      end
      return self
    end

    # PixelMatrixを画像ファイルとしてexport
    # file:: 新たに作る画像ファイル名のパス
    def export(file)
      gd = GD2::Image::IndexedColor.new(@width, @height)
      gd.palette << GD2::Color::WHITE
      gd.palette << GD2::Color::BLACK
      self.each_with_axis do |x, y|
        gd[x, y] = {
          WHITE => GD2::Color::WHITE,
          BLACK => GD2::Color::BLACK,
        }[self[x, y]]
      end
      gd.export(file)
      return self
    end

    def to_assoc
      (0...@height).map do |y|
        (0...@width).map do |x|
          self[x, y]
        end
      end
    end

    # 指定された位置の画素を返す。
    # returns:: PixelMatrix::BLACK(1) or WHITE(0)
    def [](x, y)
      if !@flexible and !in_range?(x, y) then
        raise RangeError
      end
      return @matrix[y][x]
    end

    # 画素に値を設定。
    # returns:: PixelMatrix::BLACK(1) or WHITE(0)
    def []=(x, y, val)
      unless in_range?(x, y) then
        raise RangeError unless @flexible
        @width  = (x >= @width)  ? x + 1 : @width
        @height = (y >= @height) ? y + 1 : @height
      end

      @matrix[y][x] = val
    end

    def in_range?(x, y)
      ((0...@width) === x and (0...@height) === y)
    end

    # 指定された軸をもとに画素を走査し、Arrayに変換。
    # 例えば、to_a(:vertical, 10) とすると、x == 10 な列を取り出して
    # Arrayにして返す。
    #
    # axis:: 軸を指定 (:vertical または :horizontal)
    # pos:: 位置を指定。_axis_で指定した軸と直交する軸における位置を指定。
    def to_a(axis, pos)
      {:vertical => lambda {
        (0...@height).map {|y| self[pos, y]}
       },
       :horizontal => lambda {
        (0...@width).map  {|x| self[x, pos]}
       },
      }[axis].call
    end

    # returns:: Array
    def hline(y)
      self.to_a(:horizontal, y)
    end

    # returns:: Array
    def vline(x)
      self.to_a(:vertical, x)
    end

    # X軸方向に画素を走査。
    # y:: どの位置で走査するか
    # returns:: 指定された軸の上にドットが存在: false, 無い: true
    def hline_blank?(y)
      hline(y).find {|color| color == BLACK }.nil? ?
        true : false
    end

    # Y軸方向に画素を走査。
    # x:: どの位置で走査するか
    # returns:: 指定された軸の上にドットが存在: false, 無い: true
    def vline_blank?(x)
      vline(x).find {|color| color == BLACK }.nil? ?
        true : false
    end

    # 上下のマージン削除した新しいPixelMatrixを返す。
    # returns:: PixelMatrix
    def cutoff_vmargin
      pixel = PixelMatrix.new(0, 0, true)
      head = 0.upto(self.height - 1) do |y|
        break(y) if !self.hline_blank?(y)
      end
      tail = (self.height - 1).downto(0) do |y|
        break(y) if !self.hline_blank?(y)
      end

      head.upto(tail) do |y|
        y0 = pixel.height
        self.hline(y).inject(0) do |x, color|
          pixel[x, y0] = color
          x + 1
        end
      end

      return pixel
    end
    
    def each_with_axis
      (0...@width).each {|x|
        (0...@height).each {|y|
          yield(x, y)}}
    end
  end
end

class DeCAPTCHA::Site::YourFileHost::Token
DIGITS_ASSOC = [
# 0
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0],
 [0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0],
 [0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0],
 [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0],
 [0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0],
 [0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0],
 [0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0],
 [1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
 [1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
 [1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
 [1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
 [1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
 [0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
 [0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
 [0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
 [0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
 [0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
 [0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
 [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]
],
# 1
[[0, 0, 0, 0, 1],
 [0, 0, 1, 1, 1],
 [1, 1, 1, 1, 1],
 [1, 1, 1, 1, 1],
 [1, 0, 0, 0, 1],
 [0, 0, 0, 0, 1],
 [0, 0, 0, 0, 1],
 [0, 0, 0, 0, 1],
 [0, 0, 0, 0, 1],
 [0, 0, 0, 0, 1],
 [0, 0, 0, 0, 1],
 [0, 0, 0, 0, 1],
 [0, 0, 0, 0, 1],
 [0, 0, 0, 0, 1],
 [0, 0, 0, 0, 1],
 [0, 0, 0, 0, 1],
 [0, 0, 0, 0, 1],
 [0, 0, 0, 0, 1],
 [0, 0, 0, 0, 1],
 [0, 0, 0, 0, 1]],
# 2
[[0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
 [0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
 [0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
 [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0],
 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1],
 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1],
 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1],
 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1],
 [1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1],
 [0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1],
 [0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0],
 [0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0],
 [0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0],
 [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
 [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
 [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
 [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
 [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
 [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0]],
# 3
[[0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
 [0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
 [0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
 [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
 [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
 [0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
 [0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1],
 [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1],
 [1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0],
 [0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
 [0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0],
 [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
# 4
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1],
 [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1],
 [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1],
 [0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1],
 [0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1],
 [0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1],
 [0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1],
 [0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1],
 [0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1],
 [0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1],
 [0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1],
 [0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1],
 [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1]],
# 5
[[0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
 [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
 [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
 [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
 [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
 [0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
 [0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0],
 [0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1],
 [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0],
 [0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0],
 [0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
 [0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
 [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
# 6
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
 [0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0],
 [0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0],
 [0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
 [0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0],
 [0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0],
 [0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
 [0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0],
 [1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0],
 [1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
 [0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
 [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
 [0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
 [0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
 [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
 [0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
 [0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
 [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
# 7
[[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1],
 [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1],
 [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0],
 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0],
 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
# 8
[[0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0],
 [0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0],
 [0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0],
 [0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0],
 [0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0],
 [0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
 [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
 [0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0],
 [0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
 [0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0],
 [1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1],
 [1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1],
 [1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0],
 [0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
 [0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0],
 [0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
# 9
[[0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
 [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0],
 [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
 [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
 [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
 [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0],
 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1],
 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1],
 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1],
 [0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1],
 [0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1],
 [0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1],
 [0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0],
 [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0],
 [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0],
 [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0],
 [0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
 [0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
]
end


__END__
Dir.glob('*.gif').each do |file|
  puts "Processing file: #{file}"
  p DeCAPTCHA.decode(file)
end

__END__

2008-05-27

http://anond.hatelabo.jp/20080527030326

「作ってみた」的なへたれものしかないからだな。ちゃんとしたサービスを作れよ。

WebAPI を公開しろよ。日本語の文章を打ち込むようなものを作れよ。

http://www.google.co.jp/search?&q=%E6%97%A5%E6%9C%AC%E8%AA%9E+captcha

なんで日本語 captcha を誰も作らないの?日本人しか対象にしていないサイトは複数あると思うし、

日本語にすれば大分 captcha 破りの難易度はあがると思うのだけど。

日本ウェブ屋さんは馬鹿ばかりかよ。

2007-05-30

http://anond.hatelabo.jp/20070530010836

大概理解した。管理の甘いサーバサーバサイドスクリプトでのっとり、それが出来なきゃindex.htmlおいてのっとり表示orフィッシング、最悪○○.txtや○○.jpghtmlおいてクライアントサイドスクリプト嫌がらせorトロイつーとこですか。

どうも、その「ずるずるのアップローダー」はターゲットらしい。いろいろやられてる所が散見されました。

やっぱりIEのおせっかい仕様ガンだなぁ。firefoxだとcontent-typeを無視しないから、画像として表示しようとして、表示できなくて終わりだけど、IEだと中身がHTMLだとHTMLとして解釈しちゃうんだよな。

根本対策は、いったん画像コンバートしてから保存するようにして、画像として処理できないデータは破棄するしかないのかな。GDとかImageMagicで1.0倍に変換とかしたらうまくいったりしないのかな?あとはアップロード時にはCAPTCHA使うとか。

でも、その「ずるずるあっぷろだ」をやめて、世界的にはマイナー、ただしユーザはそこそこいるアップローダにしたら、とりあえず大丈夫な気がする。

この攻撃、のっとったサーバボットネットか何かから、手当たり次第に特定環境機械的に攻めてるだけじゃないかな?だから、狙われないマイナーな奴使うのも一つの手だと思うよ。

何はともあれサイト復旧がんばってください。

- 転職ならen
- 派遣ならen
 
1ページ中1ページ目を表示(合計:14件)