読者です 読者をやめる 読者になる 読者になる

How to 消されない広告の作り方

ブラウザ JavaScript HTML

数年ぶりに Proxomitron を導入して、相変わらず素敵なツールだったので今後の Proxomitroner のために現代の Web ページでどのように広告が表示されているかについて記す。

最も単純な広告

a タグで表示。

<a href="http://sample-ad.com/">絶対儲かる株100選</a>

進化系 v1

単純な a タグで広告をベタ貼りしたのでは単純なフィルタで消されてしまう。
よって、JavaScript で広告を出力させる方法を取る。

<script type="text/javascript">
docment.write('<a href="http://sample-ad.com/">絶対儲かる株100選</a>');
</script>

進化系 v2

v1 もまた簡単なテキストマッチングによって消されてしまうので、外部スクリプトに分ける。

sample-ad.js

docment.write('<a href="http://sample-ad.com/">絶対儲かる株100選</a>');

webページ

<script type="text/javascript" src="sample-ad.js"></script>

進化系 v3

v2 に対して広告キラーやフィルタは「<script type="text/javascript" src="sample-ad.js"></script> を無効にする」という処理を行う。
これをかいくぐるため、クライアントがダウンロードした時点のソースでは <script type=〜〜 </script> を記載せず、スクリプトを動的にロードするためのスクリプトを書く。

sample-ad.js

docment.write('<a href="http://sample-ad.com/">絶対儲かる株100選</a>');

webページ

<script type="text/javascript">
    document.write('<script type="text/javascript" src="sample-ad.js"></script>');
</script>

進化系 v4

v3 の時点である程度の広告キラーをかいくぐってしまうが、まだ引っかかる場合がある。
document.write で script タグを出力するのは広告くらいしかありえないので、
「script タグを含むタグを出力するスクリプトを全て無効にする」というフィルタに引っかかる場合だ。

これを回避するため、以下のようにして単純な正規表現には引っかからないよう誤魔化す。

<script type="text/javascript">
    document.write('<scr' + 'ipt type="text/javascript" src="sample-ad.js">'+'</scr' + 'ipt>');
</script>

これで一見スクリプト中に document.write で script タグを出力するようには見えなくなり、正規表現にマッチせず広告が出力される。

進化系 v4 亜種

unescape することもしばしば。

<script type="text/javascript">
    document.write(unescape("%3Cscript") + ' type="text/javascript" src="sample-ad.js">'+'</scr' + 'ipt>');
</script>

進化系 v4 亜種2

write がダメなら create.

<script type="text/javascript">
    var s = document.createElement('scr'+'ipt');
    s.src = "sample-ad.js";
    document.body.appendChild( s );
</script>

進化系 v5

現代の広告はたいてい v4, v4 亜種程度で収まっているが、質の悪い v5 が存在する。
それは、あえて script タグの文法を間違って記述することでフィルタを回避し、かつブラウザの解釈で文法ミスを自動的に補完する場合。
例えば以下のコードは script の閉じタグが完全に閉じておらず、文法ミスだ。

<script type="text/javascript" src="sample-ad.js"></script

しかし通常の広告フィルタは のような閉じタグがあることを前提としているので、文法ミスに対しては無力である。

進化系 v6

上記 v2 〜 v5 まで、広告用の JavaScript ファイルを生成して読み込ませていた。
Adblock のような JavaScript レベルでの広告カットではこれで十分だが、Proxomitron は条件にマッチしたリソースへのコネクションを切ることが出来る。つまり、sample-ad.js というスクリプトをダウンロードしないというフィルタを書けば上記のものは全て対応できることになる。
(ただしこのコネクションフィルタは特定のスクリプトを弾くような使い方は非効率なのであまり行わない。ファイル名を変えるだけで太刀打ちできなくなる。)

よって、広告用の JavaScript はフィルタされる可能性があるのでここで奥義を使う。
それは、そのサイトのコンテンツの JavaScript と同じファイルにすることである。
例えば、jQuery.js 内に広告用の JavaScript を書いたとして、jQuery.js に対するコネクションをフィルタするわけにはいかない。ページの閲覧どころではなくなるからだ。


理論的には JavaScript コード内の広告出力に関する部分のみカットできれば良いわけだが、フィルタ界のキング Proxomitron でもそのようなフィルタは一般的ではない。誤爆の可能性が大きいからだ。

しかしながら現実にはこの手法の広告はあまり一般的ではない。サイトオーナーが広告を入れる手間がかかってしまうためだ。v2 のように script タグ一行入れるのならサイトオーナーも楽で、広告主としても案内が楽である。v6 のような苦労をして広告を表示したところで、それは通常に比べて高度な広告フィルタを入れているユーザー分のみ多く表示できるというメリットしかない。それはメリットがあまりに少ないので、現実的には広まっておらず、たいていは v4 までである。


まとめ

なぜか document.write( '

[Patterns]
Name = "kill scr ipt ad"
Active = TRUE
Bounds = "<script\s*</script>"
Limit = 2048
Match = "*("
        "('<scr' \+ 'ipt)"
        "|("<scr" \+ "ipt)"
        "|(createElement\('script'\))"
        "|(write\('<scr'\))"
        "|unescape("%3Cscript")"
        ")*"
Replace = "<!-- scr ipt ad killed -->"

Proxomitron の良いところは、フィルタしてしまえばスクリプトをダウンロードしたり実行する処理が減るので、ブラウジングが軽くなること。特に、広告が非常に多いエロサイトは自分向けにカスタマイズすれば超快適でサクサク、ムラムラなブラウジングを行うことができる。