![](https://habrastorage.org/files/5ff/316/0af/5ff3160afa964a19b572ee245ef01ecb.png)
この記事は、前のトピックの続きです。 あなたが尋ねると、私は公開します。
最初に:最初の記事のコードがSilkRoadのキャプチャを本当に無効にしたことに非常に驚きました。 人々は本当に暗いインターネットに興味を持つようになり、ご存知のように、SillRoad 2.0は最初の友人の閉鎖後に登場しました(2番目の友人も最近閉鎖されましたが)。 猫の下でキャプチャをハッキングすることについて話します。
シルクロードvs. SilkRoad 2.0
Silk Road 2では、キャプチャを入力する必要はありません。 登録にのみ必要です。 おそらく他の場所で必要になりますが、私は1ページだけでそれを見ました。
以前の記事でクラックしたキャプチャは、ExpressionEngineと呼ばれるPHP CMSで作成されたことがわかりました。
SilkRoad 2.0は、simple-captchaと呼ばれるRails用のプラグインを使用します。 元の(?)ブランチは 2008年以降サポートされていませんが、それ以降、 いくつかのフォークは深刻な進歩を遂げています。 興味のあるサイトでどれが使用されているかわかりませんが、 このオプションはテストのために選択されました。
簡単に言うと、キャプチャSRとSR2は似ていませんが、SR2のバージョンも簡単です。 SR2は、ソリューションを取得するすべての操作が可逆的であるため、機械学習なしで高い確率(99%+)で解決される可能性があります。
初見
CAPTCHAはかなり良さそうです。
![](http://habrastorage.org/files/1c3/784/2ae/1c37842ae7264ff8b8ebd1bc161b409d.jpg)
![](http://habrastorage.org/files/ad5/7a3/381/ad57a338121e4af9a5f9327c63ef9389.jpg)
![](http://habrastorage.org/files/ab7/8e9/40e/ab78e940eed54feabc5702c1afded783.jpg)
![](http://habrastorage.org/files/4cb/615/cbf/4cb615cbf2fe49aa83db7c2a329c5260.jpg)
![](http://habrastorage.org/files/90f/f60/a11/90ff60a116e04f19bc237198987fa282.jpg)
いくつかの事実:
- 背景なし;
- 5文字、
/\A[AZ]{5}\z/
; - 「単語」ではなく、辞書を使ったトリックもありません。
- 一行の情報
- SRとは異なり、文字は単に回転または反転するだけでなく、傾斜します。
すべてのスキューは同じように見えるので、よく見てみましょう。
反りますよね?
画像の名前から判断すると、スクリプトは「simple_captcha」などと呼ばれていました。 ソースコードを取得する必要がありましたが、問題の解決策は1週間ではなく、数時間でした。 変換の90%はImageMagickの曲率にすぎないため、captchaアルゴリズムを検索するのは非合理的です。 それにもかかわらず、多くの例がありますが、動作の原理を知らないため、タスクは複雑です。
したがって、 ここを簡単に見て 、すぐにImageMagick操作を見てみましょう。
params = ImageHelpers.image_params(SimpleCaptcha.image_style).dup params << "-size #{SimpleCaptcha.image_size}" params << "-wave #{amplitude}x#{frequency}" params << "-gravity \"Center\"" params << "-pointsize #{SimpleCaptcha.point_size}" params << "-implode 0.2"
ご覧のとおり、この操作は非常にロールバックです。
-implode 0.2
操作を使用していますか?
-implode -0.2
ましょう!
for i in * ; do convert "$i" -implode -0.2 "$i-exploded.png"; done
そして、行われた作業の結果を見てください。
オリジナル | ロールバック |
---|---|
![]() | ![]() |
![]() | ![]() |
![]() | ![]() |
![]() | ![]() |
![]() | ![]() |
implode
がランダムなパラメーターで実行される場合でも、いくつかのオプションを試して、バイナリ検索を使用して、どちらが最適かを判断できます。
波に乗る
これで、y軸に沿ってテキストが作成されました。 はい、それだけに歪みがあります。
今すぐやめて、最初の記事のコードでこれらの問題の山を簡単に解決できると言うことができますが、100%成功するために何かを変えてみましょう。
ここを見てください :
def distortion(key='low') key = key == 'random' ? DISTORTIONS[rand(DISTORTIONS.length)] : DISTORTIONS.include?(key) ? key : 'low' case key.to_s when 'low' then return [0 + rand(2), 80 + rand(20)] when 'medium' then return [2 + rand(2), 50 + rand(20)] when 'high' then return [4 + rand(2), 30 + rand(20)] end end
ランダムに生成された2つのパラメーターが
-wave
演算子で振幅と周波数として使用されます。 ImageMagickの指示から判断すると、波の開始(x軸に沿って)は常にゼロです。
これらの2つのパラメーターとバイナリ検索に基づいて、兵士が編成されているのと同じ方法でこれらの文字を作成できます。
2つの数値を見つけるのは非常に簡単なので、このスニペットを見逃してすぐに進みます。
セグメンテーションの改善(特徴抽出)
このキャプチャは、文字間のスペースが同じではないという点でSR1キャプチャとは異なることに注意してください。 カーニングが関与しているかのような感覚。 この例の
XCUTJ
で
T
と
J
間のスペースを見て
XCUTJ
。
![](http://habrastorage.org/files/be8/5f2/ec7/be85f2ec7e4d48b5a0cd0330768b8c21.png)
最初の記事で使用した方法は、垂直方向のギャップのみを検索するため、今は正常に失敗しています。 すべてのケースの約50%で間違ったソリューションが得られます。 より明確なアルゴリズムが必要です。
すべてを超えて:移動する正方形
このアルゴリズムはオブジェクトを分割できます。 (これは、かなり前に書いたRubyとC ++の例を示しています。)
フィリップ・スパイズは、私が今まで見た中で私たちにとって最良かつ最も適切な例を作成しました。 私は彼のアニメーションを撮りました:
![](http://habrastorage.org/files/8f7/8ba/bd6/8f78babd61d543559c1bb29324136c66.gif)
一番下の行は、正方形が最初に遭遇したオブジェクトに沿って移動し、見つかったポイントを含む配列を返すことです。 これをDouglas Pookerアルゴリズムのようなものと組み合わせると、ポリゴンが得られます。 ( そして、ここに別のプロジェクトでのこのアルゴリズムのアプリケーションがあります 。)
問題は、他の方法を使用せずに、見つかった文字をすぐに削除する必要があることです。
したがって、シンボルを削除して、移動二乗アルゴリズムが再起動されたときに、削除されたシンボルに続く別のシンボルが見つかるようにします。 または、見つかったオブジェクトの座標を記録できます。 次回は「彼の後ろで」検索を開始しますが、これは実装がより困難です。
これは、ライブラリなしでは非常に困難です。 ところで、Rubyでのピクセル単位の操作は非常に(非常に、非常に)遅くなります。 もっと簡単な方法を探しましょう。
塗りつぶし方法
よりスマート、高速、簡単になります。
- 画像を複製します。
- 文字の「内側」にある最初の黒いピクセルを見つけます。
- 作業領域で見えないように白で塗りつぶします。
- オリジナルと、文字が削除された画像の違いを見つけます。
- すべての文字が検出されるまで繰り返します。
次のようになります。
def each_extracted_object(im) return enum_for(__method__, im) unless block_given? loop do xy = first_black_pixel(im) break if xy.nil? # Save the original copy = im.clone # Erase it from our working image im = im.color_floodfill(xy[0], xy[1], 'white') # Exclusion to get the difference, trim and yield copy.composite!(im, 0, 0, Magick::ExclusionCompositeOp) copy = copy.negate.trim('white') # This stuff creates a bit of garbage GC.start yield copy end end
段階的な視覚的変換を検討してください。
アクション | 例 |
---|---|
元の画像(簡単にするためにモノクロ) | ![]() |
左側にある最初のピクセルを白色で塗りつぶします | ![]() |
元の文字と消去された文字を含む画像の違いを見つける | ![]() |
ロールバック | ![]() |
2番目のステップの結果は作業を継続するイメージであり、4番目のステップの結果は孤立したシンボルです。
これはすべて比較的良い速度で行われます。
y軸に沿った1つの直線上に2つのオブジェクトを埋める場合、このメソッドは機能しないことに注意してください。 例については、上記の
T
および
J
画像を参照してください。
一致パターン
SR1キャプチャでは、文字を背景から分離するために、フィルターを使用する必要があります。 回った
![](http://habrastorage.org/files/fb2/f2e/acd/fb2f2eacd4d54662a4c2c805e00b2b81.jpg)
![](http://habrastorage.org/files/9cd/476/cf4/9cd476cf49f846038489d5a5b2bea108.png)
このようなキャプチャを使用して、美しい文字のセットを取得しました。 40個のキャプチャから情報を収集し、次のセットを取得しました。
![](http://habrastorage.org/files/64f/e6f/22d/64fe6f22de6d4839bc12d31922414c0c.png)
たとえば、文字Mを取得し、その透明度を残りすべてのM:
1 / number_of_m_examples
と比較することによって取得されました。
ニューラルネットワークを使用する代わりに、以前に取得したセットと一致する(波を考慮に入れる)最大数のシンボルを見つけるだけです。
def font_match(im, candidate) score = 0 (0...FONT_HEIGHT).each do |y| (0...FONT_WIDTH).each do |x| if black?(im.pixel_color(x, y)) == black?(candidate.pixel_color(x, y)) score += 1 end end end return score.to_f / (FONT_WIDTH * FONT_HEIGHT) end
0.96 ** 5
キャプチャの約81%が合格しました。
比較のために、40の例と3時間のトレーニングで、ニューラルネットワークは45%だけを破りました。
まとめると
品質の悪いキャプチャや低品質のキャプチャは簡単です。 SR1に関する記事の一部のスニペットを使用して、この無関係なキャプチャは3時間で無効になりました。 よりスマートな作業を行うと、解決可能性の割合は95を超えると確信しています。
他のアプリケーション、つまりRubyのsimple_captcha gemで動作するアプリケーションをハックするために使用できるため、スクリプトコード全体を公開したくありません。
また、2014年のキャプチャの有用性についても興味があります。 私は、$ 1で最大1,000個のキャプチャをTorネットワークで解決できると聞きました。
それにもかかわらず、私はキャプチャについて非常に多くを学んだので、私は人生のためにこの知識を十分に持っています:)
ilusha_sergeevichによる一連の記事のアイデアをありがとう