
Исследовательский проект по реверс-инжинирингу COM-интерфейсов Центра безопасности Windows для отслеживания регистрации антивирусов через ATL, vtable, WSCAPI и RPC с проверкой в реальном времени через WMI.
OWN-Defender — это исследовательский проект по безопасности Windows, направленный на понимание того, как Центр безопасности Windows (WSC) представляет и управляет антивирусными продуктами безопасности через свои COM-интерфейсы.
Проект начался как исследование поведения, продемонстрированного в DefendNot, но вместо того, чтобы рассматривать существующую реализацию как «чёрный ящик», я использовал её как отправную точку для независимого реверс-инжиниринга и верификации.
Цель этого проекта — понять полный путь выполнения:
COM
↓
CLSID / IID
↓
CoCreateInstance
↓
QueryInterface
↓
ATL Interface Map
↓
vtable
↓
IWscAVStatus4
↓
CWscIsv
↓
WSCAPI.dll
↓
RPC
↓
Центр безопасности Windows
Проект разрабатывался и тестировался в контролируемой исследовательской среде Windows.
Только для исследований / образовательных целей
Этот проект предназначен для исследования внутренностей Windows, реверс-инжиниринга, обучения безопасности и авторизованного тестирования безопасности. Не используйте его для вмешательства в работу программного обеспечения безопасности на системах, которыми вы не владеете или на тестирование которых у вас нет явного разрешения.
Изначальный вопрос был прост:
Как Центр безопасности Windows узнаёт, что антивирусный продукт существует?
Вместо того чтобы останавливаться на публичной документации API, я хотел понять, что происходит под капотом API.
Это привело к нескольким вопросам:
QueryInterface() разрешает интерфейс?__int64 a1 для метода?Register() на самом деле является функцией регистрации AV?Первым шагом была идентификация COM-класса Центра безопасности Windows.
Проект использует COM-класс WSC:
CLSID_WscIsv
F2102C37-90C3-450C-B3F6-92BE1693BDF2
Реализация также содержит логику динамического поиска CLSID в реестре Windows вместо того, чтобы полагаться исключительно на жёстко заданное значение.
Концептуально:
HKLM
└── SOFTWARE
└── Classes
└── CLSID
└── {CLSID}
└── API ISV Центра безопасности Windows
Это дало первую важную взаимосвязь:
Реестр
↓
CLSID
↓
API ISV Центра безопасности Windows
Следующей задачей было определение того, какой COM-интерфейс следует запрашивать.
Проект использует:
IWscAVStatus4
с:
4DCBAFAC-29BA-46B1-80FC-B8BDE3C0AE4D
Один из важных уроков исследования:
Одного имени GUID недостаточно как доказательства.
Я проверил взаимосвязь через реверс-инжиниринг, а не предполагал, что имя интерфейса и GUID верны.
Исследование включало:
QueryInterface_ATL_INTMAP_ENTRYQueryInterfaceОдним из самых полезных шагов реверса было отслеживание реализации:
CComAggObject<CWscIsv>::QueryInterface()
которая в конечном итоге достигает:
ATL::CComObjectRootBase::InternalQueryInterface()
Карта интерфейсов ATL используется для сравнения запрошенного IID с зарегистрированными записями интерфейсов.
Концептуально:
Запрошенный IID
↓
QueryInterface()
↓
InternalQueryInterface()
↓
Карта интерфейсов ATL
↓
Сравнение GUID
↓
Соответствующий интерфейс
↓
Указатель на интерфейс
Это дало независимое доказательство того, что исследуемый GUID действительно соответствовал ожидаемому COM-интерфейсу.
Register()Одной из самых больших проблем реверса было понимание того, почему IDA/Ghidra не всегда отображали сигнатуру метода, которую я ожидал.
Реконструированный интерфейс содержит:
virtual HRESULT __stdcall Register(
BSTR path,
BSTR name,
unsigned int,
unsigned int
) = 0;
Однако декомпилятор мог показывать реализацию так:
_IWscAVStatus4<CWscIsv>::Register(__int64 a1)
Сначала это выглядело несогласованным.
Дальнейшее исследование показало, что представление декомпилятора описывало обёртку/трамплин и лежащий в основе косвенный вызов vtable, а не полную логическую сигнатуру интерфейса.
Это стало важным уроком:
Вывод декомпилятора — это интерпретация машинного кода, а не исходная истина на уровне исходного кода.
Чтобы разрешить эти расхождения, я сравнил:
Определение COM-интерфейса
↓
Расположение vtable
↓
Ассемблер
↓
Обёртка/трамплин
↓
Соглашение о вызове
↓
Фактическая целевая функция
Register()Ещё одним источником путаницы было наличие нескольких функций с такими именами, как:
IWscAVStatus2::Register
IWscAVStatus4::Register
IWscFWStatus2::Register
RegisterAV
Важным осознанием стало то, что похожие имена не означают идентичные интерфейсы.
Например:
AV
↓
IWscAVStatus4
↓
Регистрация AV
в то время как:
Брандмауэр
↓
IWscFWStatus2
↓
Регистрация брандмауэра
Номер интерфейса и окружающая реализация должны были быть проверены, а не выбирать функцию просто потому, что её имя содержало Register.
Это была одна из самых полезных частей исследования, потому что она заставила меня сопоставить:
Интерфейс
+
IID
+
vtable
+
реализация
+
расположение параметров
+
цель вызова
После идентификации правильного интерфейса я проследил операцию регистрации глубже в бинарном файле.
Наблюдаемый путь был приблизительно таким:
IWscAVStatus4::Register()
↓
CWscIsv
↓
RegisterSecurityProductFunction
↓
wscRegisterSecurityProduct()
↓
WSCAPI.dll
↓
s_wscRegisterSecurityProduct()
↓
NdrClientCall3()
↓
RPC
↓
Центр безопасности Windows
Это было особенно важно, потому что сам COM-метод не был финальной операцией.
Вызов в конечном итоге пересекал границу RPC.
Это изменило мой взгляд на архитектуру:
COM
≠
финальная реализация
Вместо этого:
COM
↓
локальная реализация
↓
API WSC
↓
RPC-клиент
↓
компонент Windows
WSCAPI.dllСледующим слоем был WSCAPI.dll.
Путь, восстановленный реверсом, достигал:
wscRegisterSecurityProduct()
которая в конечном итоге вызывала:
s_wscRegisterSecurityProduct()
а затем:
NdrClientCall3()
Это была точка, где исследование переходило от обычного COM-вызова к RPC-инфраструктуре Windows.
Понимание этого слоя помогло объяснить, почему поведение нельзя было полностью понять, глядя только на исходную COM-DLL.
Статический анализ был лишь частью исследования.
После реконструкции соответствующего интерфейса и пути вызовов я создал собственную контролируемую реализацию и сравнил результирующее поведение с Центром безопасности Windows.
Я использовал информацию Центра безопасности Windows / WMI, такую как:
ROOT\SecurityCenter2
AntiVirusProduct
для независимого наблюдения за зарегистрированной информацией о продукте.
Процесс проверки был:
Реверс-инжиниринг
↓
Реконструкция интерфейса
↓
Собственная реализация
↓
Выполнение во время работы
↓
Центр безопасности Windows
↓
Наблюдение через WMI
↓
Сравнение результатов
Это позволило мне убедиться, что выводы статического анализа соответствуют наблюдаемому поведению Windows.
Этот проект научил меня значительно большему, чем просто взаимодействию с одним COM-интерфейсом.
CoCreateInstanceQueryInterfaceWSCAPI.dllNdrClientCall3Самое главное, я научился избегать опоры на единственное доказательство.
Вместо этого:
Символ
↓
Декомпилятор
↓
Ассемблер
↓
GUID
↓
Карта интерфейсов
↓
vtable
↓
Граф вызовов
↓
RPC
↓
Проверка во время выполнения
Каждый слой повышает уверенность в выводе.
Исследовательская реализация состоит из двух основных компонентов.
OWN-Defender
│
├── OWN-Defender.cpp
│ ├── Взаимодействие с COM WSC
│ ├── Обнаружение CLSID
│ ├── Инициализация COM
│ ├── Взаимодействие с IWscAVStatus4
│ ├── Регистрация
│ ├── Обновление статуса
│ └── Очистка
│
└── dllmain.cpp
├── Точка входа DLL
├── Исследовательский загрузчик
├── Контролируемое выполнение
└── Обработка очистки/остановки
Репозиторий намеренно небольшой, чтобы связь между поведением, восстановленным реверсом, и реализацией оставалась легко прослеживаемой.
Этот проект строился вокруг вопросов, а не простого воспроизведения функциональности:
Как WSC идентифицирует COM-класс?
Как IID сопоставляется с интерфейсом?
Как QueryInterface находит интерфейс?
Почему IDA показывает разные сигнатуры функций?
Где находится фактическая vtable?
Какая Register() является реализацией AV?
Что происходит после COM-метода?
Где WSCAPI.dll входит в цепочку вызовов?
Где начинается RPC?
Как можно независимо проверить результат?
Эти вопросы в конечном итоге оказались ценнее, чем сама финальная реализация.
Проект также предоставляет полезную отправную точку для изучения границы безопасности между:
Приложение
↓
COM
↓
Центр безопасности Windows
↓
Информация о провайдере безопасности
Важное различие заключается в том, что регистрация информации о продукте безопасности не автоматически эквивалентна отключению движка Defender или обходу его механизмов защиты.
Поэтому этот проект следует рассматривать в первую очередь как:
Исследование реверс-инжиниринга Центра безопасности Windows / COM
а не как утверждение, что регистрация в WSC сама по себе представляет уязвимость Defender.
Любое влияние на безопасность требует отдельного исследования и проверки.
Это исследование частично вдохновлено работой, продемонстрированной в DefendNot от es3n1n.
Особая благодарность автору за предоставление полезной отправной точки для понимания механизма WSC.
Оригинальный проект: https://github.com/es3n1n/defendnot
Цель этого репозитория — не присвоить оригинальное исследование себе, а задокументировать мой собственный процесс реверс-инжиниринга, независимую реализацию и проверку лежащего в основе поведения Windows.
Этот репозиторий предоставляется для:
Используйте этот проект только на системах, которыми вы владеете или на тестирование которых у вас есть явное разрешение.
Автор не несёт ответственности за неправильное использование, ущерб, потерю данных, вмешательство в работу средств безопасности или несанкционированное развёртывание.
Этот проект лицензирован под GNU General Public License v3.0.
Подробности см. в LICENSE.
Основная цель OWN-Defender — не просто воспроизвести технику регистрации AV.
Она заключается в демонстрации воспроизводимой методологии реверс-инжиниринга:
Найти
↓
Сопоставить
↓
Разобрать
↓
Реконструировать
↓
Проследить
↓
Реализовать
↓
Проверить
То, что началось с вопроса о Центре безопасности Windows, превратилось в более глубокое исследование COM, ATL, сопоставления GUID/IID, vtable, кода, генерируемого компилятором, WSCAPI, RPC и архитектуры безопасности Windows.
Реализация — это результат. Процесс реверс-инжиниринга — это настоящий проект.