- Аудит подключения платформы фильтрации Audit Filtering Platform Connection
- Платформа фильтрации Windows — Windows Filtering Platform
- СОДЕРЖАНИЕ
- Составные части
- Диагностика
- Исправление
- Краткий обзор Windows Filtering Platform
- WFP изнутри: Исследуем внутренности Windows Filtering Platform
- Содержание статьи
- Методика исследования
- От Vista к Windows 7
- Заключение
Аудит подключения платформы фильтрации Audit Filtering Platform Connection
Относится к: Applies to
- Windows 10 Windows 10
- Windows Server 2016 Windows Server 2016
Подключение платформы фильтрации аудита определяет, генерирует ли операционная система события аудита, если подключение разрешено или заблокировано платформой фильтрации Windows. Audit Filtering Platform Connection determines whether the operating system generates audit events when connections are allowed or blocked by the Windows Filtering Platform.
Платформа фильтрации Windows (WFP) позволяет независимым поставщикам программного обеспечения (ISVs) фильтровать и изменять пакеты TCP/IP, отслеживать или авторизовать подключения, фильтровать трафик, защищенный протоколом Интернета (IPsec) и фильтровать удаленные вызовы процедур (RPCs). Windows Filtering Platform (WFP) enables independent software vendors (ISVs) to filter and modify TCP/IP packets, monitor or authorize connections, filter Internet Protocol security (IPsec)-protected traffic, and filter remote procedure calls (RPCs).
В этом подкатегории содержатся события платформы фильтрации Windows о заблокированных и разрешенных подключениях, заблокированных и разрешенных привязках портов, заблокированных и разрешенных действиях прослушивания порта и заблокированных для приемов входящих подключений. This subcategory contains Windows Filtering Platform events about blocked and allowed connections, blocked and allowed port bindings, blocked and allowed port listening actions, and blocked to accept incoming connections applications.
Объем событий: High. Event volume: High.
Тип компьютера Computer Type | Общий успех General Success | Общий сбой General Failure | Более сильный успех Stronger Success | Более сильный сбой Stronger Failure | Комментарии Comments |
---|---|---|---|---|---|
Контроллер домена Domain Controller | Нет No | Да Yes | IF IF | Да Yes | Аудит успешности для этой подкатегории обычно создает очень большой объем событий, например одно событие для каждого подключения к системе. Success auditing for this subcategory typically generates a very high volume of events, for example, one event for every connection that was made to the system. Гораздо важнее аудит событий сбоя (например, заблокированных подключений). It is much more important to audit Failure events (blocked connections, for example). Рекомендации по использованию и анализу собранной информации см. в разделах Рекомендации по мониторингу безопасности. For recommendations for using and analyzing the collected information, see the Security Monitoring Recommendations sections. IF . Включить аудит успешности в случае необходимости отслеживать успешные исходящие или входящие подключения к неоправданым IP-адресам на компьютерах или устройствах с высоким значением. IF — Enable Success audit in case you need to monitor successful outbound or inbound connections to and from untrusted IP addresses on high value computers or devices. |
Сервер участника Member Server | Нет No | Да Yes | IF IF | Да Yes | Аудит успешности для этой подкатегории обычно создает очень большой объем событий, например одно событие для каждого подключения к системе. Success auditing for this subcategory typically generates a very high volume of events, for example, one event for every connection that was made to the system. Гораздо важнее аудит событий сбоя (например, заблокированных подключений). It is much more important to audit Failure events (blocked connections, for example). Рекомендации по использованию и анализу собранной информации см. в разделах Рекомендации по мониторингу безопасности. For recommendations for using and analyzing the collected information, see the Security Monitoring Recommendations sections. IF . Включить аудит успешности в случае необходимости отслеживать успешные исходящие или входящие подключения к неоправданым IP-адресам на компьютерах или устройствах с высоким значением. IF — Enable Success audit in case you need to monitor successful outbound or inbound connections to and from untrusted IP addresses on high value computers or devices. |
Workstation Workstation | Нет No | Да Yes | IF IF | Да Yes | Аудит успешности для этой подкатегории обычно создает очень большой объем событий, например одно событие для каждого подключения к системе. Success auditing for this subcategory typically generates a very high volume of events, for example, one event for every connection that was made to the system. Гораздо важнее аудит событий сбоя (например, заблокированных подключений). It is much more important to audit Failure events (blocked connections, for example). Рекомендации по использованию и анализу собранной информации см. в разделах Рекомендации по мониторингу безопасности. For recommendations for using and analyzing the collected information, see the Security Monitoring Recommendations sections. IF . Включить аудит успешности в случае необходимости отслеживать успешные исходящие или входящие подключения к неоправданым IP-адресам на компьютерах или устройствах с высоким значением. IF — Enable Success audit in case you need to monitor successful outbound or inbound connections to and from untrusted IP addresses on high value computers or devices. |
Список событий: Events List:
5031(F). Служба брандмауэра Windows заблокировала прием входящих подключений в сети. 5031(F): The Windows Firewall Service blocked an application from accepting incoming connections on the network.
5150(-): Платформа фильтрации Windows заблокировала пакет. 5150(-): The Windows Filtering Platform blocked a packet.
5151(-): Более строгий фильтр платформы фильтрации Windows заблокировал пакет. 5151(-): A more restrictive Windows Filtering Platform filter has blocked a packet.
5154(S). Платформа фильтрации Windows разрешила приложению или службе прослушивать в порту для входящих подключений. 5154(S): The Windows Filtering Platform has permitted an application or service to listen on a port for incoming connections.
5155(F): Платформа фильтрации Windows заблокировала прослушивание приложения или службы в порту для входящих подключений. 5155(F): The Windows Filtering Platform has blocked an application or service from listening on a port for incoming connections.
5156(S): Платформа фильтрации Windows разрешила подключение. 5156(S): The Windows Filtering Platform has permitted a connection.
5157(F): Платформа фильтрации Windows заблокировала подключение. 5157(F): The Windows Filtering Platform has blocked a connection.
5158(S). Платформа фильтрации Windows разрешила привязку к локальному порту. 5158(S): The Windows Filtering Platform has permitted a bind to a local port.
5159(F): Платформа фильтрации Windows заблокировала привязку к локальному порту. 5159(F): The Windows Filtering Platform has blocked a bind to a local port.
Платформа фильтрации Windows — Windows Filtering Platform
Платформа фильтрации Windows (WFP) — это набор системных служб в Windows Vista и более поздних версиях, которые позволяют программному обеспечению Windows обрабатывать и фильтровать сетевой трафик. Microsoft планировала использовать WFP для брандмауэров , программного обеспечения для защиты от вредоносных программ и приложений родительского контроля . Кроме того, WFP используется для реализации NAT и для хранения конфигурации политики IPSec.
WFP использует стек TCP / IP нового поколения Windows Vista . Он предоставляет такие функции, как интегрированная связь и логика обработки для каждого приложения. Начиная с Windows 8 и Windows Server 2012, WFP позволяет фильтровать на втором уровне пакета TCP / IP .
СОДЕРЖАНИЕ
Составные части
Платформа фильтрации включает в себя следующие компоненты:
- Прокладки , которые раскрывают внутреннюю структуру пакета как свойства. Для протоколов на разных уровнях существуют разные прокладки . WFP поставляется с набором регулировочных шайб; пользователи могут регистрировать прокладки для других протоколов с помощью API. В комплект шайб входят:
- Прокладка Application Layer Enforcement (ALE)
- Прокладка модуля транспортного уровня (TLM)
- Прокладка модуля сетевого уровня (NLM)
- Прокладка среды выполнения RPC
- Прокладка протокола управляющих сообщений Интернета (ICMP)
- Регулировочная шайба
- Фильтрование двигателя , который охватывает оба режим ядра и пользовательский режим , обеспечивая основные возможности фильтрации. Он сопоставляет данные в пакете — как показано с помощью прокладок — с правилами фильтрации и либо блокирует, либо разрешает пакет. Выноска (смотри ниже) может реализовывать любое другое действие по мере необходимости. Фильтры работают для каждого приложения. Чтобы смягчить конфликты между фильтрами, им присваиваются веса (приоритеты) и они сгруппированы в подслои , которые также имеют веса. Фильтры и выноски могут быть связаны с поставщиками, которым можно дать имя и описание, и которые по существу связаны с конкретным приложением или услугой.
- Базовый механизм фильтрации , модуль, который управляет механизмом фильтрации. Он принимает правила фильтрации и обеспечивает соблюдение модели безопасности приложения. Он также ведет статистику по WFP и регистрирует его состояние.
- Callout , функция обратного вызова , предоставляемая драйвером фильтрации. Драйверы фильтрации предоставляют возможности фильтрации, отличные от блокировки / разрешения по умолчанию. Администраторы указывают функцию выноски во время регистрации правила фильтрации. Когда фильтр совпадает, система вызывает выноску, которая обрабатывает указанное действие.
Диагностика
Начиная с Windows 7 , команда netsh может диагностировать внутреннее состояние WFP.
Исправление
Microsoft выпустила три внеполосных исправления для WPF в Windows Vista и Windows 7 для решения проблем, которые могли вызвать утечку памяти, потерю связи во время сеанса подключения к удаленному рабочему столу или синий экран смерти . Позже эти исправления были объединены в один пакет.
Краткий обзор Windows Filtering Platform
Здесь я постараюсь дать небольшой обзор WFP, а также затронуть некоторые
технические моменты. Без каких-либо претензий на полноту, точность и т.д.
WFP расшифровывается как Windows Filtering Platform, платформа фильтрации Windows.
Внимание ! Не путать с технологией WPF из .NET !
WFP — это универсальная технология фильтрации сети, охватывающая все основные
уровни, от транспортного (TCP/UDP) до канального (Ethernet), и дающая разработчикам
массу интересных возможностей.
До WFP разработчики фаерволов, спам-фильтров, родконтролей и других программ
такого плана были вынуждены использовать сложные, разрозненные, а часто просто
недокументированные способы, которые во многих отношениях не давали нужного
эффекта или требовали высокой квалификации и учета многочисленных деталей, с
которыми то и дело возникали проблемы при переносе на другие версии Windows.
Пример таких технологий — TDI, LSP, NDIS, а также старые Filter-Hook Drivers и
Firewall-Hook Drivers. В WFP многие типовые проблемы этих технологий были учтены,
некоторые решения вообще не имеют аналогов, либо тяжелореализуемы в TDI/LSP/NDIS.
Сама технология имеет достаточно простую и понятную объектную модель, хорошо
документирована и при желании ее может освоить человек весьма средней квалификации.
Добавлю, что WFP — единственная на сегодняшний день технология, позволяющая
полноценно фильтровать трафик от modern-приложений на Windows 8 и выше.
И не только. Например, TDI и LSP в настоящее время уже не справляются даже с
Internet Explorer 11 на Windows 7. Поэтому при выборе технологии для нового проекта
следует в первую очередь рассматривать WFP, и только потом (если есть причины,
например совместимость с XP или отсутствие каких-то важных функций WFP на
целевых версиях Windows) другие.
Появилась в Windows Vista, с тех пор постепенно развивается и дополняется.
В Windows 7 появилась возможность фильтрации на уровне Ethernet, возможность
делать редиректы соединений (как исходящих, так и входящих), а также разные
вспомогательные функции, например для своевременной очистки ресурсов.
В Windows 8 появилось то, чего так долго ждали некоторые разработчики —
возможность многократно перекидывать соединение с одного прокси на другой.
Раньше из-за отсутствия этой возможности было почти нереальным иметь в системе,
к примеру, параллельно работающий фаервол и какой-нибудь спам-фильтр от
разных производителей. Есть и другие изменения, все они описаны в MSDN.
Лично для меня ложкой дегтя в WFP является то, что наиболее «вкусные» вещи в
ней появились только в Windows 7 — Windows 8 и для того, чтобы сделать
коммерческий продукт, реально совместимый со всей современной линейкой Windows,
не списывая со счетов XP и Vista, все равно приходится использовать TDI/LSP
вместе с WFP. Также я замечал, что документация местами недостаточно детальная, а
кое-где содержит ошибки. В итоге приходилось иногда закапываться надолго в
отладчик, чтобы узнать, в чем дело. И в WFP, как и в любой технологии, есть
недочеты и даже ошибки. Сам я с ними на практике не сталкивался, но не раз
слышал о проблемах с Teredo, например, в результате чего система выпадает в
синий экран (BSOD).
Документация и исходники.
Главный источник информации по WFP — конечно же, MSDN.
Обращаю внимание, что WFP имеет функции как в kernel mode, так и в user mode,
поэтому одну часть документации следует искать в разделе о программировании
драйверов, а вторую — в разделе «network programming» из WinAPI:
Аналогично, исходники примеров для WFP есть как в Windows SDK Samples (diagevents и
msnfilter) и в Windows Driver Kit Samples (ddproxy, inspect, msnmntr и stmedit).
Вероятно, на MSDN Gallery можно найти и другие исходники, а где-нибудь на codeproject,
sourceforge и других опенсорсных хостингах — исходники проектов с использованием WFP.
В следующей части: Архитектура WFP, объектная модель, принципы работы.
WFP изнутри: Исследуем внутренности Windows Filtering Platform
Содержание статьи
Механизм WFP, появившийся в Windows Vista, уже активно используется разработчиками защит (различных файерволов и антивирусов). Действительно, предоставляемый набор ядерных функций успешно справляется со своими обязанностями по упрощению жизни девелоперам. Но сегодня мы не будем говорить о разработке ядерных фильтров трафика при помощи WFP, а обсудим вопрос обхода этих фильтров.
Методика исследования
Сначала немного определимся с определениями. Callout в терминологии WFP — это набор функций для фильтрации трафика. У нас есть три функции, составляющие callout: classifyFn, notifyFn, flowDeleteFn (см. структуру FWPS_CALLOUT). Интереснее всего classifyFn (классифицирующая функция): она, собственно, и решает, что делать с соединением/пакетом — разрешить или запретить. notifyFn просто уведомляет (как можно понять из названия) о создании и удалении фильтра. Фильтр — это набор условий фильтрации. Когда мы вызываем функцию FwpsCalloutRegister, и нам возвращают 32-битный идентификатор коллаута.
Далее я не буду останавливаться на определениях, элементарные вещи ты сможешь вычитать в доках, ссылки на которые найдешь на боковых сносках. Еще одно замечание — для удаленной отладки используем WinDbg, гостевая система — Windows Vista x64, дизассемблер — Ida Pro, символы для дебаггера корректны. Перезагрузить их (символы) можно командой .reload /s /n. Для того, чтобы успешно исследовать внутреннее устройство WFP, нужно выработать определенный подход. В нашем случае довольно удобно написать свой callout (а точнее, драйвер, содержащий callout). Затем расставить брейки на функции нашего коллаута и посмотреть в окно Call Stack (в WinDbg вызывается или одноименным пунктом меню), дабы выяснить, откуда происходит вызов наших функций. И вот, останавливаемся в первый раз на нотифицирующей функции. Call Stack.
ipsblock!FlNotify ;-> наша нотифицирующая функция
NETIO!FeNotifyFilter+0x3a
NETIO!HandleFilterFree+0x1f
NETIO!DeleteFilterFromIndex+0x22b
NETIO! ?? ::FNODOBFM::`string’+0x6f03
NETIO!IoctlKfdCommitTransaction+0x39
Ага, понятно. Непосредственный вызов происходит из функции FeNotifyFilter. Теперь посмотрим, что там:
fffffa60 00bac100 sub rsp,20h
fffffa60 00bac104 mov rbx,rdx
fffffa60 00bac107 mov rdi,rcx
fffffa60 00bac10a lea rdx,[rsp+38h]
fffffa60 00bac10f mov ecx,dword ptr [rbx+2Ch]
fffffa60 00bac112 mov esi,r8d
fffffa60 00bac115 call
NETIO!FeGetRefCallout (fffffa60 00ba3060)
fffffa60 00bac11a mov r8,rbx
fffffa60 00bac11d mov rbx,qword ptr [rsp+38h]
; предположительно адрес объектаколлаута
fffffa60 00bac122 mov rdx,rdi
fffffa60 00bac125 mov ecx,esi
fffffa60 00bac127 call qword ptr [rbx+10h]
; вызов ipsblock!FlNotify
fffffa60 00bac12a test eax,eax
Продолжим наши исследования. Брякаемся на нашей классифицирующей функции (FlClassify). Колстек при вызове:
ipsblock!FlClassify ;-> наша функция
NETIO!ArbitrateAndEnforce+0x3b0
NETIO!KfdClassify+0x8f1
tcpip!WfpAleClassify+0x47
tcpip! ?? ::FNODOBFM::’string’+0x178d3
tcpip!WfpAleAuthorizeConnect+0x2ef
tcpip!TcpCreateAndConnectTcbWorkQueueRoutin e+0x4a2
tcpip!TcpCreateAndConnectTcb+0x48a
tdx!TdxConnectConnection+0x4e6
tdx!TdxTdiDispatchInternalDeviceControl+0x158
Посмотрим код NETIO!ArbitrateAndEnforce (в листинге оставлено только самое важное). Двойной щелчок по строке в окне вызовов переносит нас в недра дизассемблерного кода.
fffffa60 00b9e9ef add rbp,rbp
fffffa60 00b9e9f2 lock xadd dword ptr
[r12+rbp*8+80h],eax
fffffa60 00b9e9fc cmp qword ptr [r12+80h],r9
fffffa60 00b9ea04 jne NETIO! ??
::FNODOBFM::’string’+0x6719
fffffa60 00b9ea0a mov rax,qword ptr [NETIO!gWfpGlobal]
fffffa60 00b9ea11 cmp ebx,dword ptr [rax+970h] ; max count
fffffa60 00b9ea17 jae NETIO! ??
::FNODOBFM::’string’+0x6785
fffffa60 00b9ea1d imul rbx,rbx,38h
fffffa60 00b9ea21 add rbx,qword ptr [rax+978h]
// add callout base
fffffa60 00b9ea28 cmp dword ptr [rbx],0
// ненулевой callout?
fffffa60 00b9ea2b je NETIO! ??
::FNODOBFM::’string’+0x6785
.
fffffa60 00b9eacb lea rax,[rsp+78h]
fffffa60 00b9ead0 mov rdx,r15
fffffa60 00b9ead3 mov qword ptr [rsp+28h], rax
fffffa60 00b9ead8 mov qword ptr [rsp+20h], r12
fffffa60 00b9eadd call qword ptr [rbx+8]
Попробуем собрать воедино то, что видим в этом и предыдущем листинге. Очевидно, что значительную роль в получении адреса нужного callout играет переменная NETIO!gWfpGlobal — это основа для получения всех остальных нужных данных. Сначала значение в ebx сравнивается с некоторым значением.
Чтобы узнать, что лежит в ebx на момент вызова, я поставил брейк на сравнение по адресу fffffa60`00b9ea11. И как ты думаешь, что я увидел? Помнишь, я упоминал про то, что при регистрации callout нам возвращается его 32-битный идентификатор? Так вот, в момент сравнения как раз он и находится в ebx. Ага, теперь-то ясно, что в dword ptr [rax+970h] — это максимальное число коллаутов в системе (в моей — 0x11e). В ebx у нас индекс коллаута, потом выполняется определение адреса структуры коллаута, размер которой (судя по инструкции imul rbx,rbx,38h) равен 0x38 байт. По адресу qword ptr [rax+978h] находится база всех коллаутов (то есть адрес начала буфера для объекто-коллаутов).
Теперь для вывода инфы об установленных в системе коллаутах можно написать свою функцию. В качестве аргумента она принимает значение переменной gWfpGlobal (узнается адрес командой dq poi(netio!gWfpGlobal) в WinDbg).
typedef struct _FW_CALLOUT_OBJECT
<
ULONG64 uFlag;
ULONG64 uClassifyFunction;
ULONG64 uNotifyFunction;
ULONG64 uFlowDeleteFunction;
//ULONG64 uReserved[3];
>FW_CALLOUT_OBJECT,*PFW_CALLOUT_OBJECT;
#define CALLOUT_OBJECT_SIZE 0x38
.
VOID PrintCallouts6(ULONG64 gWfpGlobal)
<
ULONG uMaxCount;
ULONG64 uCalloutBase;
PFW_CALLOUT_OBJECT pCurrentCallout;
// база коллаутов
uCalloutBase = *(PULONG64)(gWfpGlobal+0x978);
// получаем максимальное число коллаутов
uMaxCount = *(PULONG)(gWfpGlobal + 0x970);
CHAR ModuleName[10]=<0>;
FLOUT(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, «Max id count %dn», uMaxCount);
for(int i=0;i uFlag)
<
FLOUT(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, «Current callout 0x%I64Xn», pCurrentCallout);
FLOUT(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, » Notify routine 0x%I64Xn Classify routine 0x%I64Xn Flow delete function 0x%I64Xn», pCurrentCallout->uNotifyFunction, pCurrentCallout->uClassifyFunction, pCurrentCallout->uFlowDeleteFunction);
// получаем имя модуля, которому принадлежит нотифицирующая функция
GetModuleName(ModuleName, 8, pCurrentCallout->uClassifyFunction);
FLOUT(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, » Module name = %sn», ModuleName);
RtlZeroMemory(ModuleName,sizeof(ModuleName));
>
>
>
Код достаточно прокомментирован, да и не сложный вовсе. Для удобства чтения кода я объявил структуру FW_CALLOUT_ OBJECT. GetModuleName — это моя функция, ищущая имя модуля по адресу внутри него. Использует пресловутую ZwQuerySystemInformation(. SystemModuleInformation. ) и, думаю, большинство читателей так или иначе представляет, как энумить модули таким способом :).
Имея такую важную инфу, как адреса классифицирующих функций, можно делать все, что угодно. Например, перехватить их. Кстати, проверить, что мы все сделали правильно, можно, «не отходя от кассы», прямо тут же, в WinDbg, командой u адрес.
Notify routine 0xFFFFFA6000E113B0
Classify routine 0xFFFFFA6000E35070
Flow delete function 0x0
Module name = tcpip.sys
.
kd> u 0xFFFFFA6000E113B0 ;-> мы действительно имеем дело с нотифицирующей функцией драйвера tcpip.sys?
tcpip!IPSecAleConnectCalloutNotify:
fffffa60 00e113b0 33c0 xor eax,eax
kd> u 0xFFFFFA6000E35070 ;-> мы действительно имеем дело с классифицирующей функцией драйвера tcpip.sys?
tcpip!IPSecInboundTransportFilterCalloutClassifyV4:
fffffa60 00e35070 488bc4 mov rax,rsp
Теперь можно с уверенностью сказать, что все верно.
От Vista к Windows 7
Что касается Windows 7, которая до сего времени совсем не упоминалась, то здесь все проще (но по-другому!). И вообще, WFP был несколько изменен и дополнен. Там есть внутренняя функция netio!ProcessCallout:
.text:000000000001C680 ProcessCallout proc near
; CODE XREF: ArbitrateAndEnforce+2A457
.
.text:000000000001C71D mov rax, cs:gWfpGlobal
.text:000000000001C724 cmp ebx, [rax+548h]
// max count
.text:000000000001C72A jnb loc_2D270
.text:000000000001C730 mov rdi, rbx
.text:000000000001C733 shl rdi, 6 // callout size
.text:000000000001C737 add rdi, [rax+550h]
// callout base
.text:000000000001C73E cmp [rdi+4], esi
.text:000000000001C741 jz loc_2D270
.
.text:000000000001C7E6 mov r10, [rdi+10h]
.text:000000000001C7EA mov rbx, qword ptr
[rsp+118h+arg_30.LockState]
.text:000000000001C7F2 mov r8, [rsp+118h+arg_18]
.text:000000000001C7FA mov rcx, [rsp+118h+arg_8]
.text:000000000001C802 mov rdx, rbp
.text:000000000001C805 cmp [rdi], esi
.text:000000000001C807 jz loc_2D56F
.text:000000000001C80D mov [rsp+118h+var_E8], rbx
.text:000000000001C812 mov r9, r13
.text:000000000001C815 mov [rsp+118h+var_F0], r14
.text:000000000001C81A mov [rsp+118h+var_F8], rax
.text:000000000001C81F call r10 // Classifyfn
Как видно из листинга выше, gWfpGlobal играет такую же важную роль в функционировании WFP Win7, как и в Vista. Однако структуры теперь 0x40 (shl rdi, 6, что эквивалентно * 2^6), изменилось смещение callout base ([rax+550h]) и других полей. Так что enum случая Win7 я оставляю for fun увлеченному читателю :). А также в netio есть функция GetCalloutEntry, которая подтверждает сказанное выше:
.text:000000000001CE30 GetCalloutEntry proc near
; CODE XREF: FeGetRefCallout+2057
; FeGetCalloutFlowDelete+28 .
.text:000000000001CE30
.text:000000000001CE30 ; FUNCTION CHUNK AT
.text:0000000000028954 SIZE 0000000B BYTES
.text:000000000001CE30
.text:000000000001CE30 mov rax, cs:gWfpGlobal
.text:000000000001CE37 cmp ecx, [rax+548h]
// max count
.text:000000000001CE3D jnb loc_28954
.text:000000000001CE43 mov rax, [rax+550h]
// callout base
.text:000000000001CE4A mov ecx, ecx
.text:000000000001CE4C shl rcx, 6
// callout object size
.text:000000000001CE50 add rcx, rax
.text:000000000001CE53 mov [rdx], rcx
.text:000000000001CE56 cmp dword ptr [rcx+4], 0
.text:000000000001CE5A jz loc_28954
.text:000000000001CE60 rep retn
.text:000000000001CE60 GetCalloutEntry endp
Заключение
Конечно, такой монстр, как WFP, требует гораздо более глубокого исследования. Я рассмотрел только некоторые интересные моменты функционирования WFP, но это далеко не все. Освоиться с программированием WFP тебе поможет WDK, а с его внутренним устройством — стандартный инструментарий реверсера.