В этой статье я хочу рассмотреть некоторые приемы написания BackDoor-ов для Windows
XP. Давайте сначала сформулируем минимальные требования к нашему "боевому" бэкдору:
1) автозагрузка при каждом старте системы;
2) невидимость в списке процесов;
3) небольшой размер бинарника;
Основные функции, такие как возможность работы с файловой системой,
процессами, учетными записями пользователей и т.д., должны присутствовать в зависимости от потребностей. Рассмотрим все по
порядку.
Большинство троянов, вирусов и прочей живности прописывает себя на автозагрузку в ключе
"HKLM\SOFTWARE\Microsoft\ Windows\CurrentVersion\Run", а "левые" записи в этом месте сразу вызывают подозрения (ну конечно если владелец компа не слепой
🙂 Я опишу способ автозагрузки который дает нам сразу несколько
преимуществ. Насколько мне известно, похожий способ использовался трояном Donald's Dick для Win2k. Откройте
следующий ключ реестра: "HKLM\SOFTWARE\Microsoft\Windows NT\
CurrentVersion\Winlogon\Notify". Так вот тут хранятся записи о загружаемых вместе с процессом winlogon.exe библиотеках. Никто нам не мешает подгрузить ему свой бэкдор! Единственное "НО": он должен быть оформлен в виде библиотеки DLL. Создаем подключ с произвольным именем (например "My_Backdoor" ;). Далее создаем в нем строковое значение с именем "DLLName" и прописываем туда путь к нашему бэкдору. Далее мы можем создавать следующие строковые значения: "Startup", "Shutdown", "StartShell", "Logon", "Logoff", и т.д. (остальные Вы можете узнать просмотрев существующие ключи и проверить их назначение
экспериментально). Каждое из них ставит в соответствие некоторому событию в системе функцию из подгружаемой библиотеки. Например, если в нашей DLL реализована функция OnLogon и мы создадим значение Logon="OnLogon", то при каждом входе пользователя в систему winlogon.exe будет загружать нашу библиотеку и выполнять функцию OnLogon! А теперь сюрприз: winlogon имеет права SYSTEM, а это значит что наш код выполниться с аналогичными правами!
%) Более того, наш бэкдор не будет светится в списке
процессов (конечно его можно увидеть с помощью специальных
программ типа PrcView, но с winlogon загружается еще туева куча разных библиотек...:). Я думаю
вы уже представили принцип работы нашего творения. Мы создаем библиотеку в которой реализуем функции
инсталляции, инициализации и завершения работы бэкдора (возможно и другие). К примеру, функция инициализации создаст сокет ожидающий
соединения с клиентом и уйдет в бесконечный
цикл обработки его команд. Такой бэкдор может быть
инсталлирован следующим образом: если функция отвечающая за установку бэкдора называется Install, то нужно выполнить команду "rundll32.exe
backdoor.dll, Install" (разумеется для этого надо иметь соответствующие права на машине жертвы).
Теперь поговорим о сокращении размера бинарника. Согласитесь, бэкдор в 1МБ это - некрасиво:) Весь код следует писать на чистом WinAPI без всяких MFC и стандартных библиотек! Первое что надо сделать это переопределить точку входа в DLL (Далее имеется ввиду что мы работаем в Microsoft Visual Studio 2003. Для других версий расположение описываемых опций может быть иным). Ее стандартное определение выглядит следующим образом:
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);
а мы сделаем, например, так:
BOOL WINAPI My_DllMain(void);
Далее с свойствах проекта заходим в Linker->Advanced и задаем значение опции "Entry Point" равным "My_DllMain". Таким образом мы избавились от лишнего стандартного кода, который заботливо добавляет компилятор
😉 Далее пошаманим над секциями PE: в опции "Merge Sections" запишем ".rdata=.text", что
объединит данные секции в одну и тем самым уменьшит размер бинарника. Также стоит
поиграться с опциями отвечающими за оптимизацию.
Итак мы добились соответствия нашим минимальным требованием. Теперь стоит поговорить об основных функциях. Самый простой и в то же время удобный и мощный способ управлять удаленной машиной - консоль. С ее помощью Вы можете делать с системой что угодно.
Мы можем запустить cmd.exe (поскольку имеем права SYSTEM) с перенаправлением ввода/вывода прямо на сокет
соединения с клиентом. Но тут есть одна проблема: трафик будет передаваться в открытом виде что не есть
good 🙂 Но выход есть! Мы перенаправим ввод и вывод cmd.exe в безымянные pipe-ы и будем работать через них. Теперь мы, например, можем читать вывод из пайпа блоками, шифровать его и отправлять клиенту порциями. Правда теперь мы не сможем работать с БО с помощью telnet-а и придется писать свой клиент, ведь
кто-то должен расшифровывать трафик! Я рекомендую использовать алгоритм шифрования RC4 + CRC32 для проверки
целостности данных, поскольку оба реализуются довольно быстро и легко. Далее представлена функция запуска cmd.exe с перенаправлением вывода и ввода в пайпы.
typedef struct {HANDLE hRead; HANDLE hWrite;} PIPE;
PIPE input, output;
PROCESS_INFORMATION pi;
void shell_init(void)
{
SECURITY_ATTRIBUTES sa;
STARTUPINFO si;
/* устанавливает атрибуты безопасности */
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;
/* создаем пайпы */
CreatePipe(&input.hRead, &input.hWrite, &sa, 0);
CreatePipe(&output.hRead, &output.hWrite, &sa, 0);
/* заполняем структуру для вызова CreateProcess()
*/
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; // используем все последующие атрибуты
si.wShowWindow = SW_HIDE; // прячем окно
процесса
si.hStdInput = input.hRead; // перенаправляем ввод
si.hStdOutput = output.hWrite; // перенаправляем вывод
si.hStdError = output.hWrite; // перенаправляем вывод ошибок
/* запускаем cmd.exe */
CreateProcess(NULL, "cmd.exe", NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);
}
Теперь управлять вводом и выводом можно с помощью функций WriteFile и ReadFile соответственно. Чтобы завершить созданный
процесс, надо вызвать функции TerminateProcess(pi.hProcess, 0) и CloseHandle для pi.hProcess, pi.hThread, input.hRead, input.hWrite, output.hRead и output.hWrite.
Также стоит продумать алгоритм аутентификации клиента при подключении к
БД, ведь будет неприятно если кто-то еще случайно попользуется
вашим "черным ходом":) Пароль доступа можно задать статически при компиляции бэкдора в виде хэш-суммы, например
полуученой с помощью алгоритма MD5 (просто так проще чем писать код отвечающий за установку и смену пароля
:)) А сама аутентификация может проходить сравнением хэшей паролей с использованием криптографии с открытым ключем - дело вкуса и зависит от степени ленивости
🙂
Вот в общем-то и все. При написании БД следует помнить, что чем больше
друзей будут им потом пользоваться, тем больше вероятность того, что он окажется в базах антивирей
🙂 Также свое творение следует хорошо отлаживать и тестировать, чтобы в момент когда админ
поломанной тачки будет смотреть свежие фотки с xxx.com не вылетело окошко о недопустимой ошибке
%)))
Если будут вопросы пишите на bi0s_0x269@yahoo.com