Умный ботнет Николай «GorluM» Андреев Хакер, номер #076, стр. 076-112-3 Объясню. У меня есть массив элементов BotnetService: typedef BOOL (WINAPI *ServiceParser) (PSTR szString); typedef struct _Service { char szName[128]; ServiceParser spFunc; } BotnetService; В структуре: szName – имя сервиса (команды), а spFunc – это указатель на функцию-парсер сервиса. Когда скрипт парсится, первое слово в строке проверяется на присутсвие в массиве имен сервисов. Если оно там есть, то с помощью GetBotnetService возвращается функция-парсер для команды с таким именем, а затем запускается с параметром – строкой аргументов. По-русски вышесказанное звучит так: бот проверяет, знает ли команду, написанную в строке, и если знает – выполняет ее. Чтобы бот «понимал» новую команду, нужно внести соответствующую новую запись (имя команды и адрес функции) в массив. Для удобства это действие я засунул в функцию RegisterBotnetService. Она найдет пустое место в массиве и аккуратно запихнет в него данные о сервисе. Использовать ее очень легко, к примеру, регистрация команды load (о ее реализации - ниже) выглядит вот так: RegisterBotnetService("load", LoadServiceParser); На случай, если захочется убить или поменять сервис, я также ввел функцию UnregisterBotnetService. Ключевым моментом в понимании работы сервисной системы бота является понятие «функция-парсер». У некоторых моих приятелей оно вызывает какое-то странное выражение лица и почесывание в затылке. Попытаюсь объяснить, что же это такое. Когда бот встречает «знакомую» команду в скрипте ему надо выполнить некоторые действия. Увидев, к примеру, “message”, бот должен вызвать функцию MessageBox с определенными параметрами. Увидев “load”,- должен скачать и запустить модуль. И так далее. Все эти действия надо оформить в функцию, которую я окрестил функцией-парсером. Сложность понимания, видимо, тут заключатся в двух вещах. 1) Парсеру передается строка. Что это за строка? Это аргументы! Это то, что идет в скрипте вслед за именем команды. В случае с “message” – это просто выводимое сообщение. 2) Как GetBotnetService возвращает функцию? Разве можно возвращать функцией функцию? Еще как можно! Когда в Си речь идет о функции, имеется в виду ее адрес. Вот и в массиве лежат, и GetBotnetService’ом возвращаются как раз адреса, а не сами функции. Хотя свойствами они обладают теми же, к примеру, можно их «запускать». Чем я, собственно, и занимаюсь в этой строке: GetBotnetService(temp)(command) Первые скобки – аргументы функции поиска сервиса, вторые – аргумент для возвращенной функции-парсера. Модули и команда load Ради чего был весь этот сыр-бор с сервисами? Исключительно ради плагинности ;). Модуль может обучить ботнет новой команде, только если в ядре бота есть нормальная сервисная система. Ее мы реализовали. Осталось понять, что такое модули, и как их подгружать к ботнету. Итак, модуль, он же плагин – это, как принято «у взрослых» DLL, динамически подгружаемая библиотека. В ней должен содержаться код, обучающий ботнет новым командам, имя сервиса и функция-парсер. Чтобы код не обломался и сделал все, что от него требуется, ему надо объяснить, где находятся функции для работы с массивом сервисов (они ведь в ядре бота, модуль о них ничего не знает). Самый простой способ это сделать – просто передать библиотеке адреса функций в параметрах некой экспортируемой функции. В ней надо сохранить адреса для дальнейшего использования и зарегистрировать (если это планировалось) новый сервис. В коде такая функция выглядит очень просто: |