之前的文档中,描写了如何对WFP防火墙进行操作[链接在此],这篇文档中,描述如何获取WFP防火墙进行阻断的操作记录。
阻断日志即防火墙返回FWP_ACTION_BLOCK动作的记录信息,读取流程大体上分为:创建枚举句柄、执行枚举、释放枚举句柄简单的三步。
创建枚举句柄
DWORD FwpmNetEventCreateEnumHandle0(
HANDLE engineHandle,
const FWPM_NET_EVENT_ENUM_TEMPLATE0 *enumTemplate,
HANDLE *enumHandle
);
执行枚举操作
DWORD FwpmNetEventEnum0(
HANDLE engineHandle,
HANDLE enumHandle,
UINT32 numEntriesRequested,
FWPM_NET_EVENT0 ***entries,
UINT32 *numEntriesReturned
);
释放枚举句柄
DWORD FwpmNetEventDestroyEnumHandle0(
HANDLE engineHandle,
HANDLE enumHandle
);
相关函数1:启用防火墙事件采集
默认防火墙事件采集就是处于开启状态,因此不调用这个函数在大多数系统上可以正常进行事件读取。但是也发现过某些系统需要调用后才可以进行事件读取,建议还是增加此函数的调用
DWORD FwpmEngineSetOption0(
HANDLE engineHandle,
FWPM_ENGINE_OPTION option,
const FWP_VALUE0 *newValue
);
参考代码
void enumDemoCode()
{
FWPM_SESSION0 session = { 0 };
ZeroMemory(&session, sizeof(session));
session.displayData.name = demoSession;
session.txnWaitTimeoutInMSec = INFINITE;
session.flags = FWPM_SESSION_FLAG_DYNAMIC;
HANDLE hEngine = NULL;
DWORD dwResult = FwpmEngineOpen0(NULL, RPC_C_AUTHN_DEFAULT, NULL, &session, &hEngine);
if (dwResult != ERROR_SUCCESS || hEngine == NULL)
{
std::cout << "FwpmEngineOpen0 Failed. ec:" << GetLastError() << std::endl;
return;
}
FWP_VALUE0 inValue = {FWP_EMPTY};
inValue.type = FWP_UINT32;
inValue.uint32 = 1;
FwpmEngineSetOption0(hEngine, FWPM_ENGINE_COLLECT_NET_EVENTS, &inValue);
FWPM_NET_EVENT_ENUM_TEMPLATE0 enumTemplate = {0};
SYSTEMTIME nowSystemTime;
ZeroMemory(&nowSystemTime, sizeof(nowSystemTime));
GetLocalTime(&nowSystemTime);
FILETIME nowFileTime;
ZeroMemory(&nowFileTime, sizeof(nowFileTime));
if (SystemTimeToFileTime(&nowSystemTime, &nowFileTime))
{
enumTemplate.endTime.dwLowDateTime = nowFileTime.dwLowDateTime;
enumTemplate.endTime.dwHighDateTime = nowFileTime.dwHighDateTime;
}
enumTemplate.startTime.dwHighDateTime = 0;
enumTemplate.startTime.dwLowDateTime = 0;
enumTemplate.numFilterConditions = 0;
HANDLE hEnumHandle = NULL;
dwResult = FwpmNetEventCreateEnumHandle0(hEngine, &enumTemplate, &hEnumHandle);
if (dwResult != ERROR_SUCCESS || hEnumHandle == NULL)
{
std::cout << "Create Enum Handle Failed, ec:" << GetLastError() << std::endl;
FwpmEngineClose0(hEngine);
hEngine = NULL;
return;
}
FWPM_NET_EVENT0** netEvents = NULL;
UINT32 uEventNumber = 0;
dwResult = FwpmNetEventEnum0(hEngine, hEnumHandle, INFINITE, &netEvents, &uEventNumber);
if (uEventNumber > 0)
{
for (int eventPos = 0; eventPos < uEventNumber; eventPos++)
{
FWPM_NET_EVENT0* sigEvent = netEvents[eventPos];
if (sigEvent->type != FWPM_NET_EVENT_TYPE_CLASSIFY_DROP)
{
continue;
}
if (sigEvent->header.ipVersion == FWP_IP_VERSION_V4)
{
std::wstring wstrLocalIp = ip2str(sigEvent->header.localAddrV4);
std::wstring wstrRemoteIp = ip2str(sigEvent->header.remoteAddrV4);
std::wstring wstrProtocol;
switch (sigEvent->header.ipProtocol)
{
case 1:
wstrProtocol = L"ICMP";
break;
case 6:
wstrProtocol = L"TCP";
break;
case 17:
wstrProtocol = L"UDP";
break;
default:
wstrProtocol = L"Other:";
wstrProtocol.append(std::to_wstring(sigEvent->header.ipProtocol));
break;
}
std::wcout << wstrLocalIp << "[" << sigEvent->header.localPort << "] ==> " << wstrRemoteIp << "[" << sigEvent->header.remotePort << "] protocol:" << wstrProtocol << std::endl;
}
}
}
if (netEvents)
{
FwpmFreeMemory0((void**)&netEvents);
netEvents = NULL;
}
if (hEnumHandle)
{
FwpmNetEventDestroyEnumHandle0(hEngine, hEnumHandle);
hEnumHandle = NULL;
}
if (hEngine)
{
FwpmEngineClose0(hEngine);
hEngine = NULL;
}
return;
}
使用事件订阅的方式在防火墙中读取日志,只需要开启和取消事件订阅即可
启动事件订阅
DWORD FwpmNetEventSubscribe0(
HANDLE engineHandle,
const FWPM_NET_EVENT_SUBSCRIPTION0 *subscription,
FWPM_NET_EVENT_CALLBACK0 callback,
void *context,
HANDLE *eventsHandle
);
取消事件订阅
DWORD FwpmNetEventUnsubscribe0(
HANDLE engineHandle,
HANDLE eventsHandle
);
回调函数定义
void CALLBACK FuncFwpmNetEventCallback0(
PVOID FwContext,
FWPM_NET_EVENT1* FwEvent
)
参考代码
void CALLBACK FuncFwpmNetEventCallback0(_Inout_ PVOID FwContext, _In_ const FWPM_NET_EVENT1* FwEvent)
{
if (FwEvent == NULL)
{
return;
}
if (FwEvent->header.ipVersion == FWP_IP_VERSION_V4)
{
std::wstring wstrLocalIp = ip2str(FwEvent->header.localAddrV4);
std::wstring wstrRemoteIp = ip2str(FwEvent->header.remoteAddrV4);
std::wstring wstrProtocol;
switch (FwEvent->header.ipProtocol)
{
case 1:
wstrProtocol = L"ICMP";
break;
case 6:
wstrProtocol = L"TCP";
break;
case 17:
wstrProtocol = L"UDP";
break;
default:
wstrProtocol = L"Other:";
wstrProtocol.append(std::to_wstring(FwEvent->header.ipProtocol));
break;
}
std::wcout << wstrLocalIp << "[" << FwEvent->header.localPort << "] ==> " << wstrRemoteIp << "[" << FwEvent->header.remotePort << "] protocol:" << wstrProtocol << std::endl;
}
return;
}
void subscribeEvents()
{
FWPM_SESSION0 session = { 0 };
ZeroMemory(&session, sizeof(session));
session.displayData.name = demoSession;
session.txnWaitTimeoutInMSec = INFINITE;
session.flags = FWPM_SESSION_FLAG_DYNAMIC;
HANDLE hEngine = NULL;
DWORD dwResult = FwpmEngineOpen0(NULL, RPC_C_AUTHN_DEFAULT, NULL, &session, &hEngine);
if (dwResult != ERROR_SUCCESS || hEngine == NULL)
{
std::cout << "FwpmEngineOpen0 Failed. ec:" << GetLastError() << std::endl;
return;
}
FWP_VALUE0 inValue = { FWP_EMPTY };
inValue.type = FWP_UINT32;
inValue.uint32 = 1;
FwpmEngineSetOption0(hEngine, FWPM_ENGINE_COLLECT_NET_EVENTS, &inValue);
HANDLE hSubScribeHandle = NULL;
FWPM_NET_EVENT_ENUM_TEMPLATE0 eventTemplate = { 0 };
eventTemplate.numFilterConditions = 0;
FWPM_NET_EVENT_SUBSCRIPTION0 subscription = { 0 };
subscription.enumTemplate = &eventTemplate;
subscription.sessionKey = session.sessionKey;
FwpmNetEventSubscribe0(hEngine, &subscription, FuncFwpmNetEventCallback0, NULL, &hSubScribeHandle);
std::cout << "Event Subscribe Started....." << std::endl;
getchar();
FwpmNetEventUnsubscribe0(hEngine, hSubScribeHandle);
if (hEngine)
{
FwpmEngineClose0(hEngine);
hEngine = NULL;
}
}