Показать сообщение отдельно

создание своей nulled CMS на примере DLE
  #1  
Старый 31.05.2008, 22:26
Аватар для SchmeL
SchmeL
Участник форума
Регистрация: 16.06.2007
Сообщений: 104
Провел на форуме:
178647

Репутация: 143
По умолчанию создание своей nulled CMS на примере DLE

На сегодняшний день существует множество популярных коммерческих CMS: DLE , SLAED CMS Pro, bitrix и др. Я не буду сейчас подробно разъяснять чем отличаются коммерческие движки от открытых, скажу лишь только, что поддержка у них намного лучше, да и безопасность тоже - хотя это мое личное мнение. Отдельной стороной стоят нуленые cкрипты. Статус Nulled данные скрипты получают после исключения из их кода защит и систем контроля, оставленных разработчиками, к примеру привязка к домену, запрос ключа регистрации при установке, ограничение времени использования и тп…
Вопрос стоит ли использовать Nulled движки зависит от самого пользователя, если вы хотите безопасный скрипт на неограниченном количестве сайтов - дерзайте. При этом правда потеряется непосредственное обновление с сайта разработчиков, но это не сильно страшно, всегда можно и вручную заплатки ставить или скачать новую зануленую версию. К тому же если вы решите напичкать свой двиг модулями, то обновления затрут их, так что добрая половина пользователей вообще не используют эту функцию, а остальная часть использует лицензию
В последнее время участилось распространение фейковых дистрибутивов, с бекдором внутри. Собственно добрые дядьки нулили нулили, а злые впихивали туда свой код и распространяли на файлообменниках. В принципе, чтобы самому создать Nulled версию - достаточно хорошо знать PHP, ну и плюс пару тройку часов свободного времени и несколько банок пива. А что что делать тем кто плохо знает PHP и не хочет левый "null"? - читать дальше.
Есть еще один способ эффективного понимания процесса нуления. Многие движки распространяются в исходниках, некоторые с закрытыми или шифрованными исходниками ( к примеру DLE Demo).
И так, рассмотрим "чистый" способ создания nulled скриптов на примере DLE 7.0. Для этого лицензию всетаки надо приобрести, чтоб получить открытый код CMS, ну можно также скачать в инете или, что еще лучше спросить у друга, который эту лицензию приобрел (без ключа-то она такое же демо) : еще нужна программа для визуального сравнения текстовых документов на предмет изменений в них - подойдет WinMerge (аналогичные есть и под линь, к примеру KDiff3), собственно сама нуленая версия для сравнения ( использовалась от MID team) и кой-какое знание PHP.
И так, приступим:
Открываем WinMerge - создаем новый проект, в левой стороне указываем папку с "демо" версией DLE (допустим C:\temp\dle\demo\), в правой c нуленой версией от МИДа (C:\temp\dle\nulled\).
Как видно изменений много, но если присмотреться львиная чать изменена не намного, вставлен копирайт от MID. Значительному изменению подверглись только несколько файлов: в папке \upgrade\index.php, addnews.php, dboption.php, functions.inc.php, \engine\inc\init.php, main.php, options.php, updates.php.
Рассмотрим их содержимое более подробней.
1. \upgrade\index.php - тут надо удалить строчку с двумя переменными -
PHP код:
$_D ROOT_DIR$_F ENGINE_DIR
- они не нужны.
2. addnews.php - тут убрать ограничение на добавление новостей (просто удалить этот кусок)

PHP код:
if ($lic_tr) {
    
$row $db->super_query("SELECT COUNT(*) as count FROM " PREFIX "_post");
    
$stats_news $row['count'];
    
$row $db->super_query("SELECT COUNT(*) as count FROM " PREFIX "_comments");
    
$count_comments $row['count'];

    if (
$stats_news 200) die("Licence not Found!");
    if (
$count_comments 500) die("Licence not Found!");

3. dboption.php - убираем условие, отвечающее за привязку к домену
PHP код:
if ($domen_hash == "" OR $domen_hash != $config['key']) {$row $db->super_query("SELECT COUNT(*) as count FROM " PREFIX "_comments");if ($row['count'] > 555) die("\114\151\143\455\156\455\145\40\156\157\164\40\106\157\165\156\144!");} 
4. в functions.inc.php - удаляем переменные $_F, $_D и условие
PHP код:
if(!$_F OR !$_D) exit();
function 
echoheader($image$header_text){
    global 
$PHP_SELF$skin_header$member_db$user_group$_F$_D;

    
$skin_header preg_replace("/{header-text}/"$header_text$skin_header);
    
$skin_header preg_replace("/{user}/"$member_db[2], $skin_header);    
    
$skin_header preg_replace("/{group}/"$user_group[$member_db[1]]['group_name'], $skin_header);    
    if(!
$_F OR !$_D) exit();
    echo 
$skin_header;

Должно получиться следующие
PHP код:
function echoheader($image$header_text){
    global 
$PHP_SELF$skin_header$member_db$user_group;

    
$skin_header preg_replace("/{header-text}/"$header_text$skin_header);
    
$skin_header preg_replace("/{user}/"$member_db[2], $skin_header);    
    
$skin_header preg_replace("/{group}/"$user_group[$member_db[1]]['group_name'], $skin_header);    
    echo 
$skin_header;

5. main.php - изменяем переменную $licence
PHP код:
$licence = ($lic_tr) ? $lang['licence_trial'] : $lang['licence_full']; 
На
PHP код:
$licence "Nulled by NickName"
Далее удаляем условие, когда активируется ключ.
PHP код:
if ($lic_tr) {

echo <<<HTML
<SCRIPT LANGUAGE="JavaScript">
function dle_activation (){

    document.getElementById( 'result_info' ).innerHTML = '
{$lang['nl_sinfo']}';

    var dle_key = ajax.encodeVAR( document.getElementById('sitekey').value );

    var varsString = "dle_key=" + dle_key;

    ajax.setVar("activation", 'yes');

    ajax.requestFile = "
{$config['admin_path']}";
    ajax.element = 'dle-activation';
    ajax.method = 'POST';

    ajax.sendAJAX(varsString);

    return false;
}
</script>
HTML;
       echo
"<br /><table width=\"100%\"align=center><tr><td style='padding:3px; border:1px dashed rgb(190,190,190); background-color:lightyellow;' class=main>
         <div id=\"dle-activation\">
$lang[trial_info]<br /><br /><b>$lang[trial_key]</b><span style=\"padding-left:7px;\"><input class=\"edit\" type=\"text\" size=\"55\" name=\"sitekey\" id=\"sitekey\"> <input class=\"edit\" type=\"button\" onClick=\"dle_activation(); return false;\" value=\"$lang[trial_act]\"></span><div id=\"result_info\" style=\"color:red;\"><br /></div></div>
    </td></tr><tr><td>&nbsp;</td></tr></table>"
;
  } 
6. Ковыряем options.php
Удаляем условие, отвечающее за ограничение на комментарии и новости
PHP код:
if ($lic_tr) {
$row $db->super_query("SELECT COUNT(*) as count FROM " PREFIX "_post");
$stats_news $row['count'];
$row $db->super_query("SELECT COUNT(*) as count FROM " PREFIX "_comments");
$count_comments $row['count'];
if (
$stats_news 501) die("Licence not Found!");
if (
$count_comments 1001) die("Licence not Found!");

7. updates.php - убираем функцию обновления скрипта
заменяем
PHP код:
$data = @file_get_contents("http://www.dle-news.ru/extras/updates.php?version_id=".$_REQUEST['versionid']."&key=".$config['key']);
if (!
strlen($data)) echo $lang['no_update']; else echo $data
на
PHP код:
$data "нельзя - движок нуленый";
echo 
$data
8. и самый большой подводный камень - это init.php. Этот файлик очень хитрожо…в общем зашифрован он. Тестить бум на сервере, копируем весь "мусор" в index.php и будем запускать из браузера (я использовал денвер). Посмотрев теперь index.php по внимательней можно найти строчку
PHP код:
$_D=strrev('edoced_46esab');eval($_D"тут какой-то код"
если ее прочитать задом наперед то получится base64_decoded : вот тут то и начинает попахивать жареным. Копаем дальше… Функция strrev переводит сроку в обратном направлении. Расшифровываем переменную $_D в BASE64 (использовал онлайн дешифратор, таких скриптов куча)- получилось:
PHP код:
$_X=base64_decode($_X);$_X=strtr($_X,'O/bpuw3kM6B2txD1.RoX]lVY >JAEGTfz7K
QH=js}ZqUce8v5nm<[9a4i0CrW{NghdILPySF'
,'iC
vfF>zeSE7P5nqlAt.wWDOmKubdU}=3M{Rkcx92JhLZgX06yrpQTG< VajIB1][Y48sH/oN'
);$_R=ereg_replace('__FILE__',"'".$_F."'",$_X);eval($_R);$_R=0;$_X=0
что видим… переворачивается 'edoced_46esab' слева направо, таким образом получая 'base64_decode', выполняется переменная под eval, собственно это и есть ключ к расшифровке.
Таксь, уже близко - чую запашок горелого, если это не на кухне - тогда скрипт наш скроро сдастся.
Видно, что нешифрованный код будет находиться в переменной $_X, а не в $_R.
Поэтому изменим его: eval($_R); заменим на print base64_encode($_X);
Должно получиться следующее:
PHP код:
$_X=base64_decode($_X);$_X=strtr($_X,'O/bpuw3kM6B2txD1.RoX]lVY >JAEGTfz7K
QH=js}ZqUce8v5nm<[9a4i0CrW{NghdILPySF'
,'iC
vfF>zeSE7P5nqlAt.wWDOmKubdU}=3M{Rkcx92JhLZgX06yrpQTG< VajIB1][Y48sH/oN'
);$_R=ereg_replace('__FILE__',"'".$_F."'",$_X);print base64_encode($_X);$_R=0;$_X=0
Шифруем в BASE64 и вставляем обратно, потом запускаем скрипт из браузера, нам выдаст опять шифровку в BASE64, вставляем ее в декодер и видим примерно тот же исходник которой был до этого, кроме одного но - ключ уже будет другой. Копируем дешифрованный код в наш скрипт полностью все заменяя (возможно придется убрать знак "?>" вначале), далее делаем такие же манипуляции с $_D как и выше, раскодируем - заменяем eval($_R); на print base64_encode($_X); -кодируем, заменяем в файле, запускаем в браузере - нам опять выдает закодированный код - только теперь если его раскодировать получим наш исходник : Вот такая у него мега кул защита…
Если скачать демо версию, то большинство файлов (если не все) там закодированы также, так что если есть энтузиазм и банка пива - дерзайте, возможно превратить demo в полноценную версию (можно написать скрипт, чтоб все это вручную не проделывать), ну или использовать готовый null.

Приступим непосредственно к ковырянию в коде и извлечению ненужных функций.
Удаляем ограничение на новости:
PHP код:
if (($mod != "editnews" AND $mod != "main" AND $mod != "") AND $lic_tr) {

    
$row $db->super_query("SELECT COUNT(*) as count FROM " PREFIX "_post");
    
$stats_news $row['count'];

    
$row $db->super_query("SELECT COUNT(*) as count FROM " PREFIX "_comments");
    
$count_comments $row['count'];

    if (
$stats_news 100msg("info","error"$lang['trial_limit']);
    if (
$count_comments 200msg("info","error"$lang['trial_limit']);


Удаляем ограничения на домен:
PHP код:
$domen_hash explode('.'$_SERVER['HTTP_HOST']);
    
$count_key count($domen_hash) - 1;
    unset (
$domen_hash[$count_key]);
    if (
end($domen_hash) == "com" OR end($domen_hash) == "net"$count_key --;
    
$domen_hash $domen_hash[$count_key-1];
    
$domen_hash md5(md5($domen_hash."780918"));
    
$lic_tr true;

    if (
$domen_hash == $config['key']) $lic_tr false;

if (
$_REQUEST['activation'] == "yes") { dle_activation (convert_unicode($_REQUEST['dle_key']), $domen_hash$config); exit;} 
и Удаляем активацию скрипта на сервере:
PHP код:
function convert_unicode($t, $to = 'windows-1251')
{
        $t = preg_replace( '#%u([0-9A-F]{1,4})#ie', "'&#' . hexdec('\\1') . ';'", $t );
        $t = urldecode ($t);
        $t = @html_entity_decode($t, ENT_NOQUOTES, $to);
        return $t;
}

function send_activation ($query,$others=''){

   $host='dle-news.ru';
   $path='/extras/activate.php';

   $post="POST $path HTTP/1.1\r\nHost: $host\r\nContent-type: application/x-www-form-urlencoded\r\n{$others}User-Agent: Mozilla 4.0\r\nContent-length: ".strlen($query)."\r\nConnection: close\r\n\r\n$query";

   $h=@fsockopen($host,80, $errno, $errstr, 30);

    if (!$h) {
       $r = @file_get_contents("http://".$host.$path."?".$query);
    } 
    else 
    {
         fwrite($h,$post);
    
         for($a=0,$r='';!$a;){
            $b=fread($h,8192);
            $r.=$b;
            $a=(($b=='')?1:0);
         }

         fclose($h);
    }

  if (stristr( $r, "antw:activated" )) return "1";
  if (stristr( $r, "antw:denied" )) return "0";

  return "-1";
}


function dle_activation($key, $domen_hash, $config){

include (ROOT_DIR.'/language/'.$config['langs'].'/adminpanel.lng');
$config['charset'] = ($lang['charset'] != '') ? $lang['charset'] : $config['charset'];

$domain = urlencode(strip_tags ($_SERVER['HTTP_HOST']));
$key  = strip_tags ($key);

$buffer = send_activation ("domain={$domain}&key={$key}&site_key={$domen_hash}&c_id=5411");


switch ($buffer) {

case "-1" :
    $buffer = $lang['trial_act1'];
    break;

case "0" :
    $buffer = $lang['trial_act2'];
    break;

case "1" :
    $config['key'] = $domen_hash;

    $handler = fopen(ENGINE_DIR.'/data/config.php', "w");
    fwrite($handler, "<?PHP \n\n//System Configurations\n\n\$config = array (\n\n");
    
foreach($config as $name => $value)
    {
    
fwrite($handler"'{$name}' => \"{$value}\",\n\n");
    }
    
fwrite($handler");\n\n?>");
    
fclose($handler);

    
$buffer $lang['trial_act3'];
    break;

default:
    
$buffer $lang['trial_act4'];
}

@
header("Content-type: text/css; charset=".$config['charset']);
echo 
$buffer;
die ();
}

extract($_REQUESTEXTR_SKIP);
замечания: вышеописанный способ работает с версией 7.0, для версии 7.2 нужно подправить init.php - там привязка к домену запихана в функцию. еще 2 файла редактировать необязательно - это editnews.php и editusers.php. тут нужно убрать условие также отвечающее за привязку к домену и проверке ключа, в принципе и с этим нормально работает...
PHP код:
if ($domen_hash == "" OR $domen_hash != ........................);} 
но я за чистоту кода

Данный способ позволяет лишний раз убедится в чистоте занулленого движка и по возможности создать свою версию nulled, к тому же приведенный выше способ подойдет наверняка и к другой версии, не думаю что разработчики каждый раз переписывают модули лицензии .
Вся описанная информация предоставляется исключительно к ознакомлению и размышлению. Никакая часть данного материала не может быть использована во вред, в обратном случае, автор не несет какой-либо ответственности за возможный ущерб, причиненный материалами статьи.

спициально для antichat.ru

Последний раз редактировалось SchmeL; 19.08.2008 в 01:53.. Причина: ошибки исправил и подкорректировал для новой версии
 
Ответить с цитированием