개요
광고는 때로는 우리를 짜증나게 할 때도 있다.
일부 불법 스트리밍 사이트에 있는 광고나, 혹은 다른 광고들이 달갑지 않을 때가 있다.
혹은 주소의 정체를 보이고 싶지않아서, 해석하기 어렵게 난독화를 하는 스크립트도 있다.
따라서 오늘 새벽내내 스크립트들을 여러가지 확인해 보았다.
오늘의 스크립트
1) Fuck Adblock
Fuck Adblock 은 광고차단 스크립트 혹은 부가프로그램인 Adblock 계열이 감지되면 차단하는 스크립트다.
1 |
<script type="text/javascript" src="/vendor/fuckadblock/fuckadblock.js"></script> |
위와 같은형식으로 스크립트를 불러오면 작동을 한다. 물론 스크립트 실행을 위한 값들에 대해서는 직접 추가해야 되지만.
하지만 되게 특이하였다.
1 2 |
//js/ads.js 자바스크립트 구동 내용 var canRunAds=true; |
1 2 |
//js/ads.exoclick.com.js 자바스크립트 구동 내용 localStorage.setItem('canrunads','true'); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<script type="text/javascript" src="/js/ads.js"></script> //상단의 var canRunAds=true; 만 적힌 스크립트를 불러오는 자바스크립트 경로 <script type="text/javascript" src="/js/ads.exoclick.com.js"></script> //상단의 localStorage 가 적힌 스크립트르 불러오는 자바스크립트 경로 <script type="text/javascript">localStorage.setItem('canrunads', 'false');</script> <script type="text/javascript"> if (localStorage.getItem('canrunads') == 'true') { } else { $(document).ready(function(){ document.body.parentNode.removeChild(document.body); alert("Adblock Detected"); }); } </script> |
js/ads.js 에서 canrunads 값이 true 로 기본값이며 값이 true 가 유지면 그대로 스크립트를 나가지만, 이 값이 adblock 계열등에 의해(즉, ads.js 라는 자바스크립트가 실제 광고가 아님에도 차단)차단이 되어 undefined가 되면 false 로 나가서 body 부분을 제거하는 초강수를 두었다.
차단 계열은 광고 블록하는 계열의 스크립트가 ads 라는 단어를 인식할 때 해당 내용을 아예 클라이언트 단에서 차단하는것을 역으로 이용한 것이다.
실제 광고성 내용의 스크립트가 포함된게 아니라, 일부러 광고 차단 프로그램에 의해 감지하라고 내용물을 집어넣은 것이기 때문에 해당 부분만 예외처리로 허용하면 쉽게 우회할 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
<script type="text/javascript"> var adBlockDetected = function(){ var e = document.body; e.parentNode.removeChild(e); alert("AdBlock Detected"); }; var adBlockNotDetected = function(){ }; (function(){ if (window.canRunAds === undefined){ (function(){ var e = document.body; e.parentNode.removeChild(e); alert("AdBlock Detected"); })(); } })(); (function(){ if(typeof fuckAdBlock === 'undefined') (function(){ var e = document.body; e.parentNode.removeChild(e); alert("AdBlock Detected"); })(); else { fuckAdBlock.onDetected(adBlockDetected); fuckAdBlock.onNotDetected(adBlockNotDetected); fuckAdBlock.on(true, adBlockDetected); fuckAdBlock.on(false, adBlockNotDetected); fuckAdBlock.on(true, adBlockDetected).onNotDetected(adBlockNotDetected); } fuckAdBlock.setOption('checkOnLoad', false); fuckAdBlock.setOption({ debug: false, checkOnLoad: false, resetOnEnd: false }); })(); </script> |
내가 알아본 사이트는 스크립트를 4개정도로 심어놓아 대부분의 Adblock 계열을 body 부분을 삭제하는것으로 보인다.
이것을 뚫기 위해서 부단히 노력을 했었다.
2) 단축URL 계열 307 redirect?
1 2 3 4 5 6 7 8 9 10 11 12 |
<a class="ads-link" href="http://s*.*t/st/d1063a012ad******751aac24ff20be7/https://a****d.com/episode/******" onclick="return move(event, this);">바로가기</a> <script type="text/javascript"> var move = function(e, target){ e.preventDefault(); var href = target.getAttribute('href'); location.href = href; return false; }; </script> |
onclick 을 할 경우 return move 값에 대해서 변동을 주는것으로 보인다.
3) base64 encode 계열 video 소스 난독화?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
<video id="video" poster="https://cdn3.a****d.com/uZi7uqC******siTRY0Gkx3zE5GCbxfB/cju407zK******N74D2ZGqEGAQFEulHe.jpg" itemprop="video" itemscope itemtype="http://schema.org/VideoObject" controls> <meta itemprop="name" content="******"> <meta itemprop="description" content="******"> <meta itemprop="url" content="******"> <meta itemprop="thumbnail" content="https://cdn3.a****d.com/uZi7uqC******siTRY0Gkx3zE5GCbxfB/cju407zK******N74D2ZGqEGAQFEulHe.jpg"> <meta itemprop="thumbnailUrl" content="https://cdn3.a****d.com/uZi7uqC******siTRY0Gkx3zE5GCbxfB/cju407zK******N74D2ZGqEGAQFEulHe.jpg"> <meta itemprop="uploadDate" content="2016-12-22 12:05:33.746982 +0000 +0000"> <source type="video/mp4"></source> <script type="text/javascript"> var decrypt = function(encoded){ var decoded = forge.util.decode64(encoded); var buffer = forge.util.createBuffer(decoded); var key = forge.util.createBuffer('1234567890123456', 'utf8'); var iv = forge.util.createBuffer(); var ciphertext = forge.util.createBuffer(); for (var i = 0; i < 16; i++) iv.putByte(buffer.getByte(i)); for (var i = 0, len = buffer.length(); i < len; i++) ciphertext.putByte(buffer.getByte(i)); var cipher = forge.aes.createDecryptionCipher(key, 'CFB'); cipher.start(iv); cipher.update(ciphertext); cipher.finish(); return cipher.output.getBytes(); }; var loadVideo = function() { var token = decrypt("mVeTfsgulhXIfd0pmPt9sXwEWRjA2JsRzkn04dyDjWg="); document.cookie = "token=" + token + ";path=/video"; var videoID = 'xmrmURptNgKyVonDZcOsDm7Q7LS0bO57L9gj1lvL0\/tp\x2b2xfFcz60m\/0\/trSprl48\x2bMayjD7vBNJkn28hg3qPFVPPXC\/XS9oveXf5gIjw\x2bHrfuQXsuaNaEpm9UE1HH3k5t7Tu4M\x2b5vE8rj4K7A=='; var element = document.getElementsByTagName('source')[0]; var video = element.parentNode; if (element.src) return; video.ondrag = function() { return false; }; video.ondragend = function() { return false; }; video.ondragstart = function() { return false; }; video.oncontextmenu = function() { return false; }; element.setAttribute('src', '/video?id=' + encodeURIComponent(videoID) + '&ts=' + Date.now()); video.load(); }; var unloadVideo = function() { document.cookie = "token=;path=/"; var videoID = 'xmrmURptNgKyVonDZcOsDm7Q7LS0bO57L9gj1lvL0\/tp\x2b2xfFcz60m\/0\/trSprl48\x2bMayjD7vBNJkn28hg3qPFVPPXC\/XS9oveXf5gIjw\x2bHrfuQXsuaNaEpm9UE1HH3k5t7Tu4M\x2b5vE8rj4K7A=='; var element = document.getElementsByTagName('source')[0]; var video = element.parentNode; element.setAttribute('src', ''); video.pause(); }; var showFacebookLikePromotion = function() { var target = document.getElementById('facebook-like-promotion'); target.style.display = 'block'; }; var hideFacebookLikePromotion = function() { var target = document.getElementById('facebook-like-promotion'); target.style.display = 'none'; }; var showFacebookSharePromotion = function() { var target = document.getElementById('facebook-share-promotion'); target.style.display = 'block'; }; var hideFacebookSharePromotion = function() { var target = document.getElementById('facebook-share-promotion'); target.style.display = 'none'; }; var shareEpisode = function() { FB.ui( { method: 'share', href: 'https://a****d.com/episode/******', }, function(response) { if (response && !response.error_message) { hideFacebookSharePromotion(); } else { showFacebookSharePromotion(); } } ); }; (function(){ loadVideo(); })(); (function(){ if (!window.localStorage) return; var pathname = window.location.pathname; var paths = pathname.split('/'); var episodeID = paths[paths.length - 1]; localStorage.setItem('episode_id', episodeID); })(); (function(){ var closeMobile = document.getElementById('episode-video-ad-close-mobile'); var closeWeb = document.getElementById('episode-video-ad-close-web'); closeMobile.onclick = function() { var target = closeMobile.parentElement.parentElement; target.parentElement.removeChild(target); }; closeWeb.onclick = function() { var target = closeWeb.parentElement.parentElement; target.parentElement.removeChild(target); }; })(); (function(){ var like = localStorage.getItem('like-anigod'); if (like != '1') { showFacebookLikePromotion(); } else { showFacebookSharePromotion(); } })(); $(function() { $('img.lazy').lazyload({placeholder: 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=='}); }); </script> |
비디오 URL 주소를 보이지 않게 하기 위해 base64 로 인코딩을 하고 source 값에 URL을 넣는것으로 보이고 있다.
4) googlevideo.com 주소 파싱?
위 스크립트는 약 2~30분 주기로 인코딩된 내용이 바뀐다. 즉, 구글드라이브 등으로 저장된 영상의 주소를 시간마다 파싱해와서 그걸 적용하는 방식인데, 어떻게 감지를 하는지에 대해서 검색을 해봐야 할 듯 하다.