В этой статье я хочу рассмотреть некоторые приемы написания 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, π);
}
Теперь управлять вводом и выводом можно с помощью функций
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
|