В настоящее время набирает популярность способ шифрования javascript на сайтах с помощью вложенных команд eval. Недавно я столкнулся с таким шифрованием на файловом хостинге mediafire.com. Шифрование было необычное, меня это заинтересовало и я решил понять, насколько хорошо данный метод работает.
Сайт mediafire.com позволяет скачивать файлы без каптчи и при этом, с недавнего времени, стал достаточно успешно защищаться от всевозможных автоматических роботов. Делает он это с помощью встроенного генератора кода javascript. Причем, код каждый раз создается новый, что затрудняет его эмуляцию автоматическими средствами.
В этой статье я расскажу о том, как можно очень легко обойти такую защиту без глубокого анализа шифрованного кода и создать автоматический скрипт загрузки файлов с mediafire.com.
Для начала покажу как выглядит такой код:
Как видно из примера, код шифруется. Также при каждом обращении к странице, код меняется: изменяются коды шифрования (XOR), изменяется вложенность eval, изменяются названия переменных и функций.
Код вызывает одну из N функций (генерируются в html), которая в свою очередь включает на экране один из N блоков (тоже генерируются в html) и показывает его на экране. Потом, загружается дополнительный скрипт (тоже шифрованный), который записывает во все блоки ссылки на псевдо-правильный путь к загрузке файла и только в один их этих блоков записывает правильный путь.
Итак, нам надо решить задачу автоматической загрузки файлов с такой
системы.
Составим план действий.
1. Загрузить главную страницу, расшифровать и определить какая именно из N функций вызывается и в какой именно из N блоков она включает (узнать ключ)
2. Загрузить файл со ссылками по ключу, расшифровать и определить какая из N ссылок реальная (определить по ключу)
3. Скачать файл
Честно говоря, идею с разбором кода и метода шифрования я отмел сразу, так как код постоянно меняется смысла в этом нет никакого. Поэтому я предлагаю вашему вниманию другой способ, а именно эмуляция некоторых функций браузера.
Решать эту задачу будем с привлечением подручных средств: spidermonkey.
Установим spidermonkey в систему (в моем примере FreeBSD):
Самая большая проблема, с которой я столкнулся, это то, что заранее неизвестно куда именно исполняемый код будет сохранять ссылки и какую именно функцию он будет вызывать. Для того, чтобы не разбирать сам код, я создал некоторое подобие функции getElementById(), функция используется для загрузки значений в конкретный элемент HTML. Сделал я это вот так:
Сам код, в неизменном виде вставляется внутрь этой обертки и исполняется. Если код вызывает функию getElementById(), мой код выведет на экран все, что сохранится в innerHTML.
Таким образом, без изменения кода, появляется возможность определять что и куда сохраняет скрипт.
И в заключении предлагаю вам ознакомиться с работающим примером загрузки файлов с ресурса mediafire.com:
Сайт mediafire.com позволяет скачивать файлы без каптчи и при этом, с недавнего времени, стал достаточно успешно защищаться от всевозможных автоматических роботов. Делает он это с помощью встроенного генератора кода javascript. Причем, код каждый раз создается новый, что затрудняет его эмуляцию автоматическими средствами.
В этой статье я расскажу о том, как можно очень легко обойти такую защиту без глубокого анализа шифрованного кода и создать автоматический скрипт загрузки файлов с mediafire.com.
Для начала покажу как выглядит такой код:
Copy Source | Copy HTML
- var h5u='';
- var ybb=unescape('rev%24l%7Djg9%23%23%3Frev%24swhsp4l9qjawgeta%2C%23%213Bl%213F%216%3Da4c0%2A%2A6%213Bl%<<<тут был длинный код шифрованных символов>>>Z%3D--%3Fareh%2Cl%7Djg-%3F');
- for(i=0;i<1324;i++)h5u=h5u+(String.fromCharCode(ybb.charCodeAt(i)^4));
- eval(h5u);
Как видно из примера, код шифруется. Также при каждом обращении к странице, код меняется: изменяются коды шифрования (XOR), изменяется вложенность eval, изменяются названия переменных и функций.
Код вызывает одну из N функций (генерируются в html), которая в свою очередь включает на экране один из N блоков (тоже генерируются в html) и показывает его на экране. Потом, загружается дополнительный скрипт (тоже шифрованный), который записывает во все блоки ссылки на псевдо-правильный путь к загрузке файла и только в один их этих блоков записывает правильный путь.
Итак, нам надо решить задачу автоматической загрузки файлов с такой
системы.
Составим план действий.
1. Загрузить главную страницу, расшифровать и определить какая именно из N функций вызывается и в какой именно из N блоков она включает (узнать ключ)
2. Загрузить файл со ссылками по ключу, расшифровать и определить какая из N ссылок реальная (определить по ключу)
3. Скачать файл
Честно говоря, идею с разбором кода и метода шифрования я отмел сразу, так как код постоянно меняется смысла в этом нет никакого. Поэтому я предлагаю вашему вниманию другой способ, а именно эмуляция некоторых функций браузера.
Решать эту задачу будем с привлечением подручных средств: spidermonkey.
Установим spidermonkey в систему (в моем примере FreeBSD):
cd /usr/ports/lang/spidermonkey
make install clean
Самая большая проблема, с которой я столкнулся, это то, что заранее неизвестно куда именно исполняемый код будет сохранять ссылки и какую именно функцию он будет вызывать. Для того, чтобы не разбирать сам код, я создал некоторое подобие функции getElementById(), функция используется для загрузки значений в конкретный элемент HTML. Сделал я это вот так:
Copy Source | Copy HTML
- var element = new Object();
- element.innerHTML = "";
- var parent = new Object();
- parent.document = new Object();
- parent.document.getElementById = functiontheGetElementByID(x) {
- print("HTML:" + element.innerHTML);
- print("\n");
- print("ELEMENT:" + x + ":");
- return element;
- };
-
- // INSERT CODE HERE
-
- print("HTML:" + element.innerHTML);
Сам код, в неизменном виде вставляется внутрь этой обертки и исполняется. Если код вызывает функию getElementById(), мой код выведет на экран все, что сохранится в innerHTML.
Таким образом, без изменения кода, появляется возможность определять что и куда сохраняет скрипт.
И в заключении предлагаю вам ознакомиться с работающим примером загрузки файлов с ресурса mediafire.com:
Copy Source | Copy HTML
- /*<br/> * Copyright (C) AIG<br/> * aignospam at gmail.com<br/> *<br/> * Redistribution and use in source and binary forms, with or without<br/> * modification, are permitted provided that the following conditions<br/> * are met:<br/> * 1. Redistributions of source code must retain the above copyright<br/> * notice, this list of conditions and the following disclaimer.<br/> * 2. Redistributions in binary form must reproduce the above copyright<br/> * notice, this list of conditions and the following disclaimer in the<br/> * documentation and/or other materials provided with the distribution.<br/> *<br/> * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND<br/> * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE<br/> * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE<br/> * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE<br/> * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL<br/> * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS<br/> * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)<br/> * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT<br/> * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY<br/> * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF<br/> * SUCH DAMAGE.<br/> */
-
- function jsDecode($code)
- {
- $fh = fopen('./code.js', 'w');
- fwrite($fh, 'var element = new Object();element.innerHTML = "";');
- fwrite($fh, 'var parent = new Object();parent.document = new Object();');
- fwrite($fh, 'parent.document.getElementById = function theGetElementByID(x) {print("HTML:" + element.innerHTML);print("\n");print("ELEMENT:" + x + ":");return element;};');
- fwrite($fh, $code);
- fwrite($fh, 'print("HTML:" + element.innerHTML);');
- fclose($fh);
- return `js ./code.js 2>&1`;
- }
-
- function downloadMediafire($url)
- {
- $cookie_file = './cookie.mediafire.txt';
- @unlink($cookie_file);
-
- $user_agent = "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)";
-
- $ch = curl_init($url);
- curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
- curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
- curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
- curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_file);
- curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie_file);
- $result_parent = curl_exec($ch);
-
- $referer = $url;
-
- // search all functions
- if (!preg_match_all("/function\s+([a-z0-9]+)\(qk\,pk\,r\)/", $result_parent, $match_function_names)) {
- print "unable to find generated functions\n";
- print $result_parent;
- return false;
- }
-
- $code_header = '';
- foreach ($match_function_names[1] as $function_name) {
- $code_header .= 'function ';
- $code_header .= $function_name;
- $code_header .= '(qk,pk,r)';
- $code_header .= '{print("KEY:" + qk + ":" + pk + ":" + r + ":" + "' . $function_name . '" + ":");};';
- }
-
- if (!preg_match('/Eo\(\);(.*?eval.*?)if/', $result_parent, $match_code)) {
- print "unable to find key code\n";
- print $result_parent;
- return false;
- }
-
- // decode eval functions...
- $code = jsDecode($code_header . $match_code[1]);
-
- if (!preg_match('/KEY:(.*?):(.*?):(.*?):(.*?):/', $code, $match_key)) {
- print $code;
- return false;
- }
-
- $qk = $match_key[1];
- $pk = $match_key[2];
- $r = $match_key[3];
-
- $valid_function_name = $match_key[4];
-
- // search for visible element...
- if (!preg_match('/function ' . $valid_function_name . '\(.*?document.getElementById\(\'(.{32})\'\)/', $result_parent, $match_id)) {
- print $result_parent;
- return false;
- }
-
- $element_id = $match_id[1];
-
- $url = 'http://www.mediafire.com/dynamic/download.php?qk=' . $qk . '&pk=' . $pk . '&r=' . $r;
-
- print "URL=$url\n";
-
- curl_setopt($ch, CURLOPT_URL, $url);
- curl_setopt($ch, CURLOPT_REFERER, $referer);
- $result_fetch = curl_exec($ch);
- curl_close($ch);
-
- if (!preg_match('/(var\s+et\s*=\s*15.*?)function/', $result_fetch, $match_header)) {
- print "unable to find link header\n";
- print $result_fetch;
- return false;
- }
-
- $code_header = $match_header[1];
-
- if (!preg_match('/case\s+15:(.*?)break;/', $result_fetch, $match_code)) {
- print "unable to find link code\n";
- print $result_fetch;
- return false;
- }
-
- // decode eval functions...
- $code = jsDecode($code_header . $match_code[1]);
-
- if (!preg_match('/' . $element_id . '.*?href="http:\/\/([^"]+)"/', $code, $match_url)) {
- print "unable to find element url\n";
- print $code;
- return false;
- }
-
- $file_url = $match_url[1];
-
- print "URL=$file_url\n";
-
- $file = basename($file_url);
- $url = "http://$file_url";
-
- if (file_exists($file)) {
- return true;
- }
-
- $fp = fopen($file, 'w');
-
- $ch = curl_init($url);
- curl_setopt($ch,CURLOPT_RETURNTRANSFER, 1);
- curl_setopt($ch,CURLOPT_USERAGENT, $user_agent);
- curl_setopt($ch,CURLOPT_FOLLOWLOCATION,1);
- curl_setopt($ch,CURLOPT_COOKIEJAR, $cookie_file);
- curl_setopt($ch,CURLOPT_COOKIEFILE, $cookie_file);
- curl_setopt($ch,CURLOPT_REFERER, $referer);
- curl_setopt($ch, CURLOPT_FILE, $fp);
- $result = curl_exec($ch);
- $info = curl_getinfo($ch);
- curl_close($ch);
-
- fclose($fp);
-
- if ($info['http_code'] != 200) {
- print_r($info);
- return false;
- }
-
- return true;
- }
-