AdBlockBlock-広告ブロッカーをバイパスします。 方法1

地元の紳士の神聖な意志に違反する何かに従事することは、彼らが彼らの周りに見たいだけのコンテンツであるということは、もちろん、恩知らずで軍隊的に危険なことです。 しかし、広告ブロッカーと広告システムの間の軍拡競争は避けられないので、それについて話してください。 現在、カットオフトラフィックの総量が約1%になると、すべてがやや緩慢になりますが、広告から受け取るお金が30%未満のサイトオーナーを既に探しています。 広告ネットワークは相互に通信を開始し、仕様を交換しています。このテーマについては、すでにイスラエルのスタートアップが何らかの形で存在しています。 これまでのところ、ロシアのセグメントのすべてが、「広告を無効にしている-これにより開発が妨げられている」という形式の推奨告知や、そのようなユーザーの存在の事実を無視しています。 私は言わなければならない、 それはすべてそのままにしておきます。



ここでは、最小限の操作性の証明モードのみで、URLパターンにより、最も一般的なタイプの広告ブロッカーをバイパスします。 メソッドは以下をサポートする必要があります。





結果を達成するために、パブリッシャーのサーバーと広告主の間の一種のプロキシを介して、広告ネットワークのすべてのURLをマスクします。 この方法はリソースの観点から最も安価ではありません。広告主にとっては潜在的に危険です。クリックやコンバージョンによるトラフィックの品質を評価せずに詐欺の原因となることはできません。サイト運営者にとっては-Googleが禁止されている場合、サイト全体が禁止されます。 したがって、それらの間には信頼の一定のしきい値が必要ですが、これらはすべて別個の問題です。 はい、すべての偶然または言及はランダムであり、手に入れたものを取りました。



そのため、広告ブロッカーを検出した人を対象としたすべてのサイト呼び出しが必要です。

ads.*.ru/228129/prepareCode?pp=g&ps=bugf&p2=ezfl&pct=a&plp=a&pli=a&pop=a'









たとえば、サイト固有のコンテンツと区別できないローカルに置き換えます。



/meduza/2015/09/28/shapitorbFgFQ4Y7_Z3jaPSRix09Pn5VyrnV5Pcki64JcXvjIyzlgYXerh3yMMgY8DB5vleYAkS_gbRiHDSyQHU7QscAd38-1tKyYnnLjLSlpHq6aJ4sEo









明確にするために、必要なものから始めます。



1.広告タグを取得し、最初のエントリポイント(広告タグ自体のエントリポイント)を手動で暗号化します



 <!-- : 990x90js--> <!--: < >--> <script type="text/javascript"> <!-- (function(){ //var link = 'http://ads.XXXXXX.ru/228129/prepareCode?pp=g&ps=bugf&p2=ezfl&pct=a&plp=a&pli=a&pop=a', var link = '/meduza/2015/09/28/shapitorbFgFQ4Y7_Z3jaPSRix09Pn5VyrnV5Pcki64JcXvjIyzlgYXerh3yMMgY8DB5vleYAkS_gbRiHDSyQHU7QscAd38-1tKyYnnLjLSlpHq6aJ4sEo', params = 'phone'; new AXXXBanner(link, params).createBanner(); })(); //--> </script>
      
      





2.サーバー設定(この場合はnginx)を少し拡張し、特別なモードでそのようなURLの処理を開始し、要求処理をスクリプトに渡します:



  location /meduza/2015/09/28/shapito { set $prefix "http://localhost:9090/meduza/2015/09/28/shapito"; rewrite shapito(.*)$ /adbb.php?query=$1&url_mask_prefix=$prefix&ua=$http_user_agent&remote_addr=$remote_addr; }
      
      





それだけです-その後、広告が表示されます。



どのように機能しますか?



リトリート、資金の選択
Luaですべてのロジックを記述したかったのですが、nginxを再構築するのは面倒で、PHPはサイトの所有者により近い可能性があるため、それを使用しました。 簡単なコードは概念実証のために書かれており、2ページで、最後に添付された任意の言語で複製できます。 mbcryptとcurlに依存しています。



仕事のアルゴリズム。



1.渡された文字列を構成のキーで復号化し、宛先URLを取得します



2.そこからドメインを取得し、暗号化します



ads.XXXXXX.ru -> pPM9l7raWppVawqO









3.このキーにより、送信されたCookieを調べ、フォームの値を見つけます。



niFJ2HLxzm27hCLnQUvcmLx62sEU-worI4tjmSAfqxNSMR6DSZ279lampNh_CN2jlu7FXaVk0WRVt-HMxy4vdm0uEncngawC6RvcKBwRXrT0wIi0icl4BvSXPJzH99C_5-mTmneEISfz









そして、インストールのためにこのサーバーから送信された元のCookieを受け取ったら、暗号化を解除します。



4. URLにクリックマーカーが含まれている場合、他には何もせず、302リダイレクトを指定して終了します。



5.それ以外の場合は、Cookie、元のユーザーUser-Agent、およびX-Forwarded-Forヘッダーの実際のIPを渡して、宛先URLにリクエストを行います。



6.サーバーからの応答を分析します。



5.1。 Set-Cookieが送信された場合-それらを再パックし(キーは暗号化されたドメイン、値は呼び出しの結果からの暗号化されたSet-Cookieです)、それらを設定すると、次のようになります



Set-Cookie:oI5upmClXJaq6DY4QWT5g5ZsvQ=niFJ3pLNsqSh0x19ux1HB-3XQiMb3XDhuJC5Byrefm_xOIDJBlZ2FL5q2zvyVtPcNOimtTk-lfoY; expires=Mon, 28-Dec-2015 08:23:57 GMT; Max-Age=7776000









5.2。 content-typeにテキストやJavaScript(画像、gifピクセルなど)が含まれていない場合は、そのままのコンテンツを提供し、キャッシングを好みに合わせて設定します(ただし、しない方が良いです)。 そして出かける



5.3。 他のすべてのコンテンツタイプについては、パターンに従ってURLの応答本文を調べ、それぞれを暗号化し、サーバーから送信されたプレフィックスを使用して、呼び出しを偽装、つまりフォームの場所に置き換えます



 object_1986381203 += '<a href="http://ads.XXXXX.ru/228129/goLink?pr=gleurtb&p5=dcxnh&p1=bohgi&p2=ezfl" target="_blank"><img src="http://content.XXXXX.ru/150924/XXXX/507850/1421973.jpg" width="990" height="90" alt="" border=0></a>';
      
      





このように与えられます:



 object_1986381203 += '<a href="/meduza/2015/09/28/shapitorbFgFQ4Y7_Z3jaPSRix09Pn5VyrnV5P" target="_blank"><img src="/meduza/2015/09/28/shapitorbFgFQ4Y7_Z3jaPSRix09Pn5VyrnV5Pcki64JcXvjIyzlgYXerh3yMMgY8DB5vleYA" width="990" height="90" alt="" border=0></a>';
      
      





変更されたコンテンツを提供して終了します。



6.ブラウザー自体が必要な呼び出しを行い、それぞれに対してステップ1からのすべてが完了します



スクリプト構成セクション



 $CONF = array( 'mask_urls' => array( 'prefix' => '/meduza/2015/09/28/shapito', //default, will be overriden by `url_mask_prefix` 'url_search_patterns' => array( '@https?://[^\\\'\"\n\r\?]+@i', ), ), 'redirect_if_contains' => array( '/click', '/reference', '/link', '/goLink' ), 'encrypt' => array ( 'iv' => '2uV17Dil', 'key' => 'JbaSyaXwD46qIlKdt8mJ4', 'cipher' => MCRYPT_GOST, 'mode' => MCRYPT_MODE_CFB ), 'cookie' => array( 'expire' => 90*24*60*60, ), 'url_call' => array(), );
      
      





繰り返しになりますが、これはコンセプトです-本番環境で使用できません サーバーから匿名プロキシを作成します



adbb.php
 <?php $CONF = array( 'mask_urls' => array( 'prefix' => '/meduza/2015/09/28/shapito', //default could be taken from `url_ 'url_search_patterns' => array( '@https?://[^\\\'\"\n\r\?]+@i', ), ), 'redirect_if_contains' => array( '/click', '/reference', '/link', '/goLink' ), 'encrypt' => array ( 'iv' => '2uV17Dil', 'key' => 'JbaSyaXwD46qIlKdt8mJ4', 'cipher' => MCRYPT_GOST, 'mode' => MCRYPT_MODE_CFB ), 'cookie' => array( 'expire' => 90*24*60*60, ), 'url_call' => array(), ); require_once __DIR__."/adbb_functions.php"; if ( !array_key_exists('query', $_REQUEST) or !$query = $_REQUEST['query']) return; adbb_debug_log('Request params', $_REQUEST); $extra_query = ''; if (($delpos = strpos($query, '&')) !== false) { adbb_debug_log('Extra parameters passed, getting encypted part only. @ position ', $delpos); $extra_query = substr($query, $delpos); adbb_debug_log('Extra query ', $extra_query); $query = substr($query, 0, $delpos); adbb_debug_log('Encrypted query after cut ', $query); } adbb_debug_log('We should have successfully decrypted url with the key for all further logic, decrypting...'); if ( !$url = adbb_decrypt($query, $CONF['encrypt']) ) { adbb_debug_log('Failed. Exiting'); return; } adbb_debug_log('Decrypted URL', $url); if (array_key_exists('url_mask_prefix', $_REQUEST)) { adbb_debug_log('Overriding initial url_mask_prefix ['.$CONF['mask_urls']['prefix'].'] to', $_REQUEST['url_mask_prefix']); $CONF['mask_urls']['prefix'] = $_REQUEST['url_mask_prefix']; } $extra_args = $_REQUEST; unset($extra_args['query'], $extra_args['ua'], $extra_args['remote_addr'], $extra_args['url_mask_prefix']); $url_to_call = $url . (strpos($url, '?') === false ? '?' : '&' ) . http_build_query($extra_args).'&'.$extra_query; adbb_debug_log('Looking for cookies to send to remote host...'); $domain_cookies = ''; $parse = parse_url($url_to_call); $domain_to_call = $parse['host']; if ($domain_to_call) { $domain_cookie_key = adbb_encrypt($domain_to_call, $CONF['encrypt']); adbb_debug_log('Will look for cookies for domain ['.$domain_to_call.'], key', $domain_cookie_key); if (isset($_COOKIE) and array_key_exists($domain_cookie_key, $_COOKIE) and $_COOKIE[$domain_cookie_key]) { adbb_debug_log('Found something, will try to decrypt cookie value ', $_COOKIE[$domain_cookie_key]); if ($json_encoded_cookies = adbb_decrypt($_COOKIE[$domain_cookie_key], $CONF['encrypt']) and $cookies = @json_decode($json_encoded_cookies) ) { adbb_debug_log('Going to send cookies decrypted', $cookies); $domain_cookies = implode('; ', $cookies); } } } adbb_debug_log('Checking if redirect is needed...'); foreach ($CONF['redirect_if_contains'] as $needle) { if (strpos($url_to_call, $needle) !== false ) { $url_to_call .= '&cookies='.urlencode($domain_cookies); adbb_debug_log('URL contains '.$needle.' going to redirect to ', $url_to_call); header('Location: '.$url_to_call); exit; } } adbb_debug_log('About to call remote URL ', $url_to_call); adbb_debug_log('With User-Agent ', $_REQUEST['ua']); adbb_debug_log('With X-Forwarded-For ', $_REQUEST['remote_addr']); adbb_debug_log('With Cookie ', $domain_cookies); $result = adbb_call_url( $url_to_call, '', $_REQUEST['ua'], array( 'X-Forwarded-For' => $_REQUEST['remote_addr'], 'Cookie' => $domain_cookies ) ); if ($result) { adbb_debug_log('Call successfull.'); $info = $result['info']; $header = $result['header']; $content = $result['content']; adbb_debug_log('Remote response info', $info); adbb_debug_log('Remote response headers', $info); $parse = parse_url($url); $domain = $parse['host']; if (array_key_exists('Set-Cookie', $header[count($header)-1])) { adbb_debug_log('Found Set-Cookie in response, taking last one'); $domain_set_cookies = $header[count($header)-1]['Set-Cookie']; $domain_cookies = adbb_translate_cookie_values($domain_set_cookies); adbb_debug_log('Translated domain cookies', $domain_cookies); $json_encoded_cookies = json_encode($domain_cookies); adbb_debug_log('Json encoded cookies', $json_encoded_cookies); $encrypted_cookies_domain = adbb_encrypt( $domain, $CONF['encrypt'] ) ; $encrypted_cookies_values = adbb_encrypt( $json_encoded_cookies, $CONF['encrypt'] ) ; adbb_debug_log('About to set encrypted cookie for domain ['.$domain.'] as ['.$encrypted_cookies_domain.'] with value ', $encrypted_cookies_values); setcookie($encrypted_cookies_domain, $encrypted_cookies_values, time()+$CONF['cookie']['expire']); } if (strpos($info['content_type'], 'text') === false and strpos($info['content_type'], 'javascript') === false ) { adbb_debug_log('Non-text content type '.$info['content_type'].', passing as is. Cache headers not implemented'); header('Content-Type: '.$info['content_type']); echo $content; } else { adbb_debug_log('Initial content in remote response', $content); $new_content = adbb_mask_urls($content, $CONF['mask_urls'], $CONF['encrypt']); echo $new_content; } }
      
      







adbb_functions.php
 <?php function adbb_encrypt($data, $encrypt_conf) { $iv = $encrypt_conf['iv']; return rtrim(strtr( base64_encode(mcrypt_encrypt($encrypt_conf['cipher'], $encrypt_conf['key'], $data, $encrypt_conf['mode'],$iv)), '+/', '-_'), '='); } function adbb_decrypt($data, $encrypt_conf) { $encrypted = base64_decode(str_pad(strtr( $data, '-_', '+/'), strlen( $data ) % 4, '=', STR_PAD_RIGHT)); return mcrypt_decrypt( $encrypt_conf['cipher'], $encrypt_conf['key'], $encrypted, $encrypt_conf['mode'], $encrypt_conf['iv'] ); } function adbb_translate_cookie_values($set_cookies) { $keys = array(); foreach ($set_cookies as $sc) { if ($pos = strpos($sc, ';')) { $keys[] = substr($sc, 0, $pos); } else { $keys[] = $sc; } } return $keys; } function adbb_get_headers_from_curl_response($headerContent) { $headers = array(); // Split the string on every "double" new line. $arrRequests = explode("\r\n\r\n", $headerContent); // Loop of response headers. The "count() -1" is to //avoid an empty row for the extra line break before the body of the response. for ($index = 0; $index < count($arrRequests) -1; $index++) { foreach (explode("\r\n", $arrRequests[$index]) as $i => $line) { if ($i === 0) $headers[$index]['http_code'] = $line; else { list ($key, $value) = explode(': ', $line); if (array_key_exists($key, $headers[$index])) { if (is_array($headers[$index][$key])) { $headers[$index][$key][] = $value; } else { $t = $headers[$index][$key]; $headers[$index][$key] = array( $t ); $headers[$index][$key][] = $value; } } else { $headers[$index][$key] = $value; } } } } return $headers; } function adbb_call_url($url, $cookie, $ua, $headers) { $ch = curl_init(); $curlopt_headers = array(); foreach ($headers as $k => $v) $curlopt_headers[] = $k.': '.$v; $options = array( CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true, CURLOPT_FOLLOWLOCATION => true, CURLOPT_USERAGENT => $ua, CURLOPT_CONNECTTIMEOUT => 5, CURLOPT_TIMEOUT => 5, CURLOPT_MAXREDIRS => 5, CURLOPT_SSL_VERIFYHOST => 0, CURLOPT_COOKIE => $cookie, CURLOPT_HTTPHEADER => $curlopt_headers, CURLOPT_VERBOSE => 1, CURLOPT_HEADER => 1, ); curl_setopt_array($ch, $options); $response = curl_exec($ch); if (!$response) return false; $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE); $header = adbb_get_headers_from_curl_response(substr($response, 0, $header_size)); $content = substr($response, $header_size); $info = curl_getinfo($ch); return array( 'header' => $header, 'content' => $content, 'info' => $info ); } function adbb_mask_urls($content, $mask_conf, $encrypt_conf) { $prefix = $mask_conf['prefix']; $url_search_patterns = $mask_conf['url_search_patterns']; foreach ($url_search_patterns as $pattern) { $matches = array(); if (preg_match_all($pattern, $content, $matches)) { adbb_debug_log('Url matches ',$matches); foreach ($matches[0] as $m) { $encrypted_url = adbb_encrypt($m, $encrypt_conf); $content = str_replace($m, $prefix.$encrypted_url, $content); } } } return $content; } function adbb_debug_log($message, $obj = false) { // $s = $message.($obj ? ' ( '.(is_string($obj) ? $obj : var_export($obj,true) ) . ' )' : '' )."\n"; // static $f = null; // if (!$f and $f = @fopen("/tmp/adbb_tmp_log".date("Ymd"),"a+")) { // fputs($f, "== New call =="); // } // if ($f) { // fputs($f, $s); // } //echo $s ; }
      
      







プライマリログインリンク自体を取得するには、同じ構成で実行します



 adbb_encrypt('http://ads.XXX.ru/XXXX/prepareCode?pp=g&ps=bugf&p2', $CONF['encrypt']);
      
      







ご清聴ありがとうございました。



All Articles