/* * Process Hacker Extra Plugins - * Firewall Monitor * * Copyright (C) 2015 dmex * * This file is part of Process Hacker. * * Process Hacker is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Process Hacker is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Process Hacker. If not, see . */ #include "fwmon.h" #define FWP_DIRECTION_IN 0x00003900L #define FWP_DIRECTION_OUT 0x00003901L #define FWP_DIRECTION_FORWARD 0x00003902L PH_CALLBACK_DECLARE(FwItemAddedEvent); PH_CALLBACK_DECLARE(FwItemModifiedEvent); PH_CALLBACK_DECLARE(FwItemRemovedEvent); PH_CALLBACK_DECLARE(FwItemsUpdatedEvent); static PH_CALLBACK_REGISTRATION ProcessesUpdatedCallbackRegistration; static PPH_OBJECT_TYPE FwObjectType = NULL; static HANDLE FwEngineHandle = NULL; static HANDLE FwEventHandle = NULL; static HANDLE FwEnumHandle = NULL; static _FwpmNetEventSubscribe1 FwpmNetEventSubscribe1_I = NULL; static VOID NTAPI FwObjectTypeDeleteProcedure( _In_ PVOID Object, _In_ ULONG Flags ) { PhClearReference(&Object); } PFW_EVENT_ITEM EtCreateFirewallEntryItem( VOID ) { static ULONG itemCount = 0; PFW_EVENT_ITEM diskItem; diskItem = PhCreateObject(sizeof(FW_EVENT_ITEM), FwObjectType); memset(diskItem, 0, sizeof(FW_EVENT_ITEM)); diskItem->Index = itemCount; diskItem->IndexString = PhFormatString(L"%lu", itemCount); itemCount++; return diskItem; } static VOID CALLBACK DropEventCallback( _Inout_ PVOID FwContext, _In_ const FWPM_NET_EVENT* FwEvent ) { PFW_EVENT_ITEM fwEventItem = EtCreateFirewallEntryItem(); SYSTEMTIME systemTime; PhQuerySystemTime(&fwEventItem->AddedTime); PhLargeIntegerToLocalSystemTime(&systemTime, &fwEventItem->AddedTime); fwEventItem->TimeString = PhFormatDateTime(&systemTime); switch (FwEvent->type) { case FWPM_NET_EVENT_TYPE_CLASSIFY_DROP: { FWPM_FILTER* fwFilterItem = NULL; FWPM_LAYER* fwLayerItem = NULL; FWPM_NET_EVENT_CLASSIFY_DROP* fwDropEvent = FwEvent->classifyDrop; PhInitializeStringRef(&fwEventItem->FwRuleActionString, L"DROP"); if (FwpmFilterGetById(FwEngineHandle, fwDropEvent->filterId, &fwFilterItem) == ERROR_SUCCESS) { if (fwFilterItem->displayData.name) { fwEventItem->FwRuleNameString = PhCreateString(fwFilterItem->displayData.name); } if (fwFilterItem->displayData.description) { fwEventItem->FwRuleDescriptionString = PhCreateString(fwFilterItem->displayData.description); } if ((fwFilterItem->action.type & FWP_ACTION_BLOCK) != 0) { } FwpmFreeMemory(&fwFilterItem); } if (FwpmLayerGetById(FwEngineHandle, fwDropEvent->layerId, &fwLayerItem) == ERROR_SUCCESS) { if (fwLayerItem->displayData.name) { fwEventItem->FwRuleLayerNameString = PhCreateString(fwLayerItem->displayData.name); } //fwEventItem->FwRuleLayerDescriptionString = PhCreateString(fwLayerRuleItem->displayData.description); for (UINT32 i = 0; i < fwLayerItem->numFields; i++) { FWPM_FIELD fwRuleField = fwLayerItem->field[i]; // http://msdn.microsoft.com/en-us/library/windows/desktop/aa363996.aspx if (memcmp(fwRuleField.fieldKey, &FWPM_CONDITION_ALE_APP_ID, sizeof(GUID)) == 0) { //The fully qualified device path of the application, as returned by the FwpmGetAppIdFromFileName0 function. // (For example, "\device0\hardiskvolume1\Program Files\Application.exe".) // Data type : FWP_BYTE_BLOB_TYPE //fwDropEvent-> } else if (IsEqualGUID(fwRuleField.fieldKey, &FWPM_CONDITION_ALE_ORIGINAL_APP_ID)) { // The fully qualified device path of the application, such as "\device0\hardiskvolume1\Program Files\Application.exe". // When a connection has been redirected, this will be the identifier of the originating app, // otherwise this will be the same as FWPM_CONDITION_ALE_APP_ID. } else if (IsEqualGUID(fwRuleField.fieldKey, &FWPM_CONDITION_ALE_USER_ID)) { //The identification of the local user. //Data type : FWP_SECURITY_DESCRIPTOR_TYPE } else if (IsEqualGUID(fwRuleField.fieldKey, &FWPM_CONDITION_IP_LOCAL_ADDRESS)) { } else if (IsEqualGUID(fwRuleField.fieldKey, &FWPM_CONDITION_IP_LOCAL_ADDRESS_TYPE)) { //The local IP address type. //Possible values : Any of the following NL_ADDRESS_TYPE enumeration values. //NlatUnspecified //NlatUnicast //NlatAnycast //NlatMulticast //NlatBroadcast //Data type : FWP_UINT8 } else if (IsEqualGUID(fwRuleField.fieldKey, &FWPM_CONDITION_IP_LOCAL_PORT)) { //The local transport protocol port number. //Data type : FWP_UINT16 } //else //{ // PhInitializeStringRef(&fwEventItem->FwRuleModeString, L"UNKNOWN"); //} } FwpmFreeMemory(&fwLayerItem); } if (fwDropEvent->isLoopback) { PhInitializeStringRef(&fwEventItem->DirectionString, L"Loopback"); } else { switch (fwDropEvent->msFwpDirection) { case FWP_DIRECTION_IN: case FWP_DIRECTION_INBOUND: PhInitializeStringRef(&fwEventItem->DirectionString, L"In"); break; case FWP_DIRECTION_OUT: case FWP_DIRECTION_OUTBOUND: PhInitializeStringRef(&fwEventItem->DirectionString, L"Out"); break; case FWP_DIRECTION_FORWARD: PhInitializeStringRef(&fwEventItem->DirectionString, L"Forward"); break; default: PhInitializeStringRef(&fwEventItem->DirectionString, L""); break; } } } break; case FWPM_NET_EVENT_TYPE_CLASSIFY_ALLOW: { FWPM_FILTER* fwFilterItem = NULL; FWPM_LAYER* fwLayerItem = NULL; FWPM_NET_EVENT_CLASSIFY_ALLOW* fwAllowEvent = FwEvent->classifyAllow; PhInitializeStringRef(&fwEventItem->FwRuleActionString, L"ALLOW"); if (FwpmFilterGetById(FwEngineHandle, fwAllowEvent->filterId, &fwFilterItem) == ERROR_SUCCESS) { if (fwFilterItem->displayData.name) { fwEventItem->FwRuleNameString = PhCreateString(fwFilterItem->displayData.name); } if (fwFilterItem->displayData.description) { fwEventItem->FwRuleDescriptionString = PhCreateString(fwFilterItem->displayData.description); } if ((fwFilterItem->action.type & FWP_ACTION_BLOCK) != 0) { } FwpmFreeMemory(&fwFilterItem); } if (FwpmLayerGetById(FwEngineHandle, fwAllowEvent->layerId, &fwLayerItem) == ERROR_SUCCESS) { for (UINT32 i = 0; i < fwLayerItem->numFields; i++) { FWPM_FIELD fwRuleField = fwLayerItem->field[i]; // http://msdn.microsoft.com/en-us/library/windows/desktop/aa363996.aspx if (memcmp(fwRuleField.fieldKey, &FWPM_CONDITION_ALE_APP_ID, sizeof(GUID)) == 0) { //The fully qualified device path of the application, as returned by the FwpmGetAppIdFromFileName0 function. // (For example, "\device0\hardiskvolume1\Program Files\Application.exe".) // Data type : FWP_BYTE_BLOB_TYPE //fwAllowEvent-> } else if (IsEqualGUID(fwRuleField.fieldKey, &FWPM_CONDITION_ALE_ORIGINAL_APP_ID)) { // The fully qualified device path of the application, such as "\device0\hardiskvolume1\Program Files\Application.exe". // When a connection has been redirected, this will be the identifier of the originating app, // otherwise this will be the same as FWPM_CONDITION_ALE_APP_ID. } else if (IsEqualGUID(fwRuleField.fieldKey, &FWPM_CONDITION_ALE_USER_ID)) { //The identification of the local user. //Data type : FWP_SECURITY_DESCRIPTOR_TYPE } else if (IsEqualGUID(fwRuleField.fieldKey, &FWPM_CONDITION_IP_LOCAL_ADDRESS)) { } else if (IsEqualGUID(fwRuleField.fieldKey, &FWPM_CONDITION_IP_LOCAL_ADDRESS_TYPE)) { //The local IP address type. //Possible values : Any of the following NL_ADDRESS_TYPE enumeration values. //NlatUnspecified //NlatUnicast //NlatAnycast //NlatMulticast //NlatBroadcast //Data type : FWP_UINT8 } else if (IsEqualGUID(fwRuleField.fieldKey, &FWPM_CONDITION_IP_LOCAL_PORT)) { //The local transport protocol port number. //Data type : FWP_UINT16 } //else //{ // PhInitializeStringRef(&fwEventItem->FwRuleModeString, L"UNKNOWN"); //} } fwEventItem->FwRuleLayerNameString = PhCreateString(fwLayerItem->displayData.name); //fwEventItem->FwRuleLayerDescriptionString = PhCreateString(fwLayerRuleItem->displayData.description); FwpmFreeMemory(&fwLayerItem); } if (fwAllowEvent->isLoopback) { PhInitializeStringRef(&fwEventItem->DirectionString, L"Loopback"); } else { switch (fwAllowEvent->msFwpDirection) { case FWP_DIRECTION_IN: case FWP_DIRECTION_INBOUND: PhInitializeStringRef(&fwEventItem->DirectionString, L"In"); break; case FWP_DIRECTION_OUT: case FWP_DIRECTION_OUTBOUND: PhInitializeStringRef(&fwEventItem->DirectionString, L"Out"); break; case FWP_DIRECTION_FORWARD: PhInitializeStringRef(&fwEventItem->DirectionString, L"Forward"); break; default: PhInitializeStringRef(&fwEventItem->DirectionString, L""); break; } } } break; case FWPM_NET_EVENT_TYPE_CAPABILITY_DROP: //FWPM_NET_EVENT_CAPABILITY_DROP* fwCapDropEvent = FwEvent->capabilityDrop; PhInitializeStringRef(&fwEventItem->FwRuleActionString, L"CAPABILITY_DROP"); return; case FWPM_NET_EVENT_TYPE_CAPABILITY_ALLOW: //FWPM_NET_EVENT_CAPABILITY_ALLOW* fwCapAllowEvent = FwEvent->capabilityAllow; PhInitializeStringRef(&fwEventItem->FwRuleActionString, L"CAPABILITY_ALLOW"); return; case FWPM_NET_EVENT_TYPE_CLASSIFY_DROP_MAC: //FWPM_NET_EVENT_CLASSIFY_DROP_MAC* fwMacDropEvent = FwEvent->classifyDropMac; PhInitializeStringRef(&fwEventItem->FwRuleActionString, L"CLASSIFY_DROP_MAC"); break; case FWPM_NET_EVENT_TYPE_IPSEC_KERNEL_DROP: //FWPM_NET_EVENT_IPSEC_KERNEL_DROP* fwIpSecDropEvent = FwEvent->ipsecDrop; PhInitializeStringRef(&fwEventItem->FwRuleActionString, L"IPSEC_KERNEL_DROP"); break; case FWPM_NET_EVENT_TYPE_IPSEC_DOSP_DROP: //FWPM_NET_EVENT_IPSEC_DOSP_DROP* fwIpSecDoSDropEvent = FwEvent->idpDrop; PhInitializeStringRef(&fwEventItem->FwRuleActionString, L"IPSEC_DOSP_DROP"); break; case FWPM_NET_EVENT_TYPE_IKEEXT_MM_FAILURE: //FWPM_NET_EVENT_IKEEXT_MM_FAILURE* fwIkeextMMFailureEvent = FwEvent->ikeMmFailure; PhInitializeStringRef(&fwEventItem->FwRuleActionString, L"IKEEXT_MM_FAILURE"); break; case FWPM_NET_EVENT_TYPE_IKEEXT_QM_FAILURE: //FWPM_NET_EVENT_IKEEXT_QM_FAILURE* fwIkeextQMFailureEvent = FwEvent->ikeQmFailure; PhInitializeStringRef(&fwEventItem->FwRuleActionString, L"QM_FAILURE"); break; case FWPM_NET_EVENT_TYPE_IKEEXT_EM_FAILURE: //FWPM_NET_EVENT_IKEEXT_EM_FAILURE* fwIkeextEMFailureEvent = FwEvent->ikeEmFailure; PhInitializeStringRef(&fwEventItem->FwRuleActionString, L"EM_FAILURE"); break; default: PhInitializeStringRef(&fwEventItem->FwRuleActionString, L"unknown"); break; } if ((FwEvent->header.flags & FWPM_NET_EVENT_FLAG_LOCAL_PORT_SET) != 0) { fwEventItem->LocalPort = FwEvent->header.localPort; fwEventItem->LocalPortString = PhFormatString(L"%u", FwEvent->header.localPort); } if ((FwEvent->header.flags & FWPM_NET_EVENT_FLAG_REMOTE_PORT_SET) != 0) { fwEventItem->RemotePort = FwEvent->header.remotePort; fwEventItem->RemotePortString = PhFormatString(L"%u", FwEvent->header.remotePort); } if ((FwEvent->header.flags & FWPM_NET_EVENT_FLAG_IP_VERSION_SET) != 0) { if (FwEvent->header.ipVersion == FWP_IP_VERSION_V4) { if ((FwEvent->header.flags & FWPM_NET_EVENT_FLAG_LOCAL_ADDR_SET) != 0) { //IN_ADDR ipv4Address = { 0 }; //PWSTR ipv4StringTerminator = 0; //WCHAR ipv4AddressString[INET_ADDRSTRLEN] = L""; // //ULONG localAddrV4 = _byteswap_ulong(FwEvent->header.localAddrV4); // //RtlIpv4AddressToString((PIN_ADDR)&localAddrV4, ipv4AddressString); //RtlIpv4StringToAddress(ipv4AddressString, TRUE, &ipv4StringTerminator, &ipv4Address); // //fwEventItem->LocalAddressString = PhFormatString(L"%s", ipv4AddressString); fwEventItem->LocalAddressString = PhFormatString( L"%lu.%lu.%lu.%lu", ((PBYTE)&FwEvent->header.localAddrV4)[3], ((PBYTE)&FwEvent->header.localAddrV4)[2], ((PBYTE)&FwEvent->header.localAddrV4)[1], ((PBYTE)&FwEvent->header.localAddrV4)[0] ); } if ((FwEvent->header.flags & FWPM_NET_EVENT_FLAG_REMOTE_ADDR_SET) != 0) { //IN_ADDR ipv4Address = { 0 }; //PWSTR ipv4StringTerminator = 0; //WCHAR ipv4AddressString[INET_ADDRSTRLEN] = L""; // //ULONG remoteAddrV4 = _byteswap_ulong(FwEvent->header.remoteAddrV4); // //RtlIpv4AddressToString((PIN_ADDR)&remoteAddrV4, ipv4AddressString); //RtlIpv4StringToAddress(ipv4AddressString, TRUE, &ipv4StringTerminator, &ipv4Address); // //fwEventItem->RemoteAddressString = PhFormatString(L"%s", ipv4AddressString); fwEventItem->RemoteAddressString = PhFormatString( L"%lu.%lu.%lu.%lu", ((PBYTE)&FwEvent->header.remoteAddrV4)[3], ((PBYTE)&FwEvent->header.remoteAddrV4)[2], ((PBYTE)&FwEvent->header.remoteAddrV4)[1], ((PBYTE)&FwEvent->header.remoteAddrV4)[0] ); } } else if (FwEvent->header.ipVersion == FWP_IP_VERSION_V6) { if ((FwEvent->header.flags & FWPM_NET_EVENT_FLAG_LOCAL_ADDR_SET) != 0) { IN6_ADDR ipv6Address = { 0 }; PWSTR ipv6StringTerminator = 0; WCHAR ipv6AddressString[INET6_ADDRSTRLEN] = L""; RtlIpv6AddressToString((struct in6_addr*)&FwEvent->header.localAddrV6, ipv6AddressString); RtlIpv6StringToAddress(ipv6AddressString, &ipv6StringTerminator, &ipv6Address); fwEventItem->LocalAddressString = PhFormatString(L"%s", ipv6AddressString); //fwEventItem->LocalAddressString = PhFormatString( // L"%x:%x:%x:%x%x:%x:%x:%x", // ((WORD*)&FwEvent->header.localAddrV6)[7], // ((WORD*)&FwEvent->header.localAddrV6)[6], // ((WORD*)&FwEvent->header.localAddrV6)[5], // ((WORD*)&FwEvent->header.localAddrV6)[4], // ((WORD*)&FwEvent->header.localAddrV6)[3], // ((WORD*)&FwEvent->header.localAddrV6)[2], // ((WORD*)&FwEvent->header.localAddrV6)[1], // ((WORD*)&FwEvent->header.localAddrV6)[0] // ); } if ((FwEvent->header.flags & FWPM_NET_EVENT_FLAG_REMOTE_ADDR_SET) != 0) { WCHAR ipv6AddressString[INET6_ADDRSTRLEN] = L""; PWSTR ipv6StringTerminator = 0; IN6_ADDR ipv6Address = { 0 }; RtlIpv6AddressToString((struct in6_addr*)&FwEvent->header.remoteAddrV6, ipv6AddressString); RtlIpv6StringToAddress(ipv6AddressString, &ipv6StringTerminator, &ipv6Address); fwEventItem->RemoteAddressString = PhFormatString(L"%s", ipv6AddressString); //fwEventItem->RemoteAddressString = PhFormatString( // L"%x:%x:%x:%x%x:%x:%x:%x", // ((WORD*)&FwEvent->header.remoteAddrV6)[7], // ((WORD*)&FwEvent->header.remoteAddrV6)[6], // ((WORD*)&FwEvent->header.remoteAddrV6)[5], // ((WORD*)&FwEvent->header.remoteAddrV6)[4], // ((WORD*)&FwEvent->header.remoteAddrV6)[3], // ((WORD*)&FwEvent->header.remoteAddrV6)[2], // ((WORD*)&FwEvent->header.remoteAddrV6)[1], // ((WORD*)&FwEvent->header.remoteAddrV6)[0] // ); } } else { //FwEvent->header.addressFamily Available when ipVersion is FWP_IP_VERSION_NONE. } } if ((FwEvent->header.flags & FWPM_NET_EVENT_FLAG_APP_ID_SET) != 0) { PPH_STRING fileName = NULL; PPH_STRING resolvedName = NULL; if (FwEvent->header.appId.data && FwEvent->header.appId.size > 0) { fileName = PhCreateStringEx((PWSTR)FwEvent->header.appId.data, (SIZE_T)FwEvent->header.appId.size); resolvedName = PhResolveDevicePrefix(fileName); PhDereferenceObject(fileName); } if (resolvedName) { fwEventItem->ProcessNameString = PhGetFileName(resolvedName); fwEventItem->ProcessBaseString = PhGetBaseName(resolvedName); //FWP_BYTE_BLOB* fwpApplicationByteBlob = NULL; //if (FwpmGetAppIdFromFileName(fileNameString->Buffer, &fwpApplicationByteBlob) == ERROR_SUCCESS) //fwEventItem->ProcessBaseString = PhCreateStringEx(fwpApplicationByteBlob->data, fwpApplicationByteBlob->size); //fwEventItem->Icon = PhGetFileShellIcon(PhGetString(resolvedName), L".exe", FALSE); PhDereferenceObject(resolvedName); } } if ((FwEvent->header.flags & FWPM_NET_EVENT_FLAG_USER_ID_SET) != 0) { if (RtlValidSid(FwEvent->header.userId)) { fwEventItem->UserNameString = PhGetSidFullName(FwEvent->header.userId, TRUE, NULL); } } if ((FwEvent->header.flags & FWPM_NET_EVENT_FLAG_IP_PROTOCOL_SET)) { // The ipProtocol member is set. } if ((FwEvent->header.flags & FWPM_NET_EVENT_FLAG_SCOPE_ID_SET)) { // The scopeId member is set. } if ((FwEvent->header.flags & FWPM_NET_EVENT_FLAG_REAUTH_REASON_SET) != 0) { // Indicates an existing connection was reauthorized. } if ((FwEvent->header.flags & FWPM_NET_EVENT_FLAG_PACKAGE_ID_SET) != 0) { // The packageSid member is set. } switch (FwEvent->header.ipProtocol) { case IPPROTO_HOPOPTS: PhInitializeStringRef(&fwEventItem->ProtocalString, L"HOPOPTS"); break; case IPPROTO_ICMP: PhInitializeStringRef(&fwEventItem->ProtocalString, L"ICMP"); break; case IPPROTO_IGMP: PhInitializeStringRef(&fwEventItem->ProtocalString, L"IGMP"); break; case IPPROTO_GGP: PhInitializeStringRef(&fwEventItem->ProtocalString, L"GGP"); break; case IPPROTO_IPV4: PhInitializeStringRef(&fwEventItem->ProtocalString, L"IPv4"); break; case IPPROTO_ST: PhInitializeStringRef(&fwEventItem->ProtocalString, L"ST"); break; case IPPROTO_TCP: PhInitializeStringRef(&fwEventItem->ProtocalString, L"TCP"); break; case IPPROTO_CBT: PhInitializeStringRef(&fwEventItem->ProtocalString, L"CBT"); break; case IPPROTO_EGP: PhInitializeStringRef(&fwEventItem->ProtocalString, L"EGP"); break; case IPPROTO_IGP: PhInitializeStringRef(&fwEventItem->ProtocalString, L"IGP"); break; case IPPROTO_PUP: PhInitializeStringRef(&fwEventItem->ProtocalString, L"PUP"); break; case IPPROTO_UDP: PhInitializeStringRef(&fwEventItem->ProtocalString, L"UDP"); break; case IPPROTO_IDP: PhInitializeStringRef(&fwEventItem->ProtocalString, L"IDP"); break; case IPPROTO_RDP: PhInitializeStringRef(&fwEventItem->ProtocalString, L"RDP"); break; case IPPROTO_IPV6: PhInitializeStringRef(&fwEventItem->ProtocalString, L"IPv6"); break; case IPPROTO_ROUTING: PhInitializeStringRef(&fwEventItem->ProtocalString, L"ROUTING"); break; case IPPROTO_FRAGMENT: PhInitializeStringRef(&fwEventItem->ProtocalString, L"FRAGMENT"); break; case IPPROTO_ESP: PhInitializeStringRef(&fwEventItem->ProtocalString, L"ESP"); break; case IPPROTO_AH: PhInitializeStringRef(&fwEventItem->ProtocalString, L"AH"); break; case IPPROTO_ICMPV6: PhInitializeStringRef(&fwEventItem->ProtocalString, L"ICMPv6"); break; case IPPROTO_DSTOPTS: PhInitializeStringRef(&fwEventItem->ProtocalString, L"DSTOPTS"); break; case IPPROTO_ND: PhInitializeStringRef(&fwEventItem->ProtocalString, L"ND"); break; case IPPROTO_ICLFXBM: PhInitializeStringRef(&fwEventItem->ProtocalString, L"ICLFXBM"); break; case IPPROTO_PIM: PhInitializeStringRef(&fwEventItem->ProtocalString, L"PIM"); break; case IPPROTO_PGM: PhInitializeStringRef(&fwEventItem->ProtocalString, L"PGM"); break; case IPPROTO_L2TP: PhInitializeStringRef(&fwEventItem->ProtocalString, L"L2TP"); break; case IPPROTO_SCTP: PhInitializeStringRef(&fwEventItem->ProtocalString, L"SCTP"); break; case IPPROTO_RESERVED_IPSEC: PhInitializeStringRef(&fwEventItem->ProtocalString, L"IPSEC"); break; case IPPROTO_RESERVED_IPSECOFFLOAD: PhInitializeStringRef(&fwEventItem->ProtocalString, L"IPSECOFFLOAD"); break; case IPPROTO_RESERVED_WNV: PhInitializeStringRef(&fwEventItem->ProtocalString, L"WNV"); break; case IPPROTO_RAW: case IPPROTO_RESERVED_RAW: PhInitializeStringRef(&fwEventItem->ProtocalString, L"RAW"); break; case IPPROTO_NONE: default: PhInitializeStringRef(&fwEventItem->ProtocalString, L"Unknown"); break; } PhInvokeCallback(&FwItemAddedEvent, fwEventItem); } static VOID NTAPI ProcessesUpdatedCallback( _In_opt_ PVOID Parameter, _In_opt_ PVOID Context ) { static LARGE_INTEGER systemTime; PhQuerySystemTime(&systemTime); for (ULONG i = 0; i < FwNodeList->Count; i++) { PFW_EVENT_NODE node = (PFW_EVENT_NODE)FwNodeList->Items[i]; if (systemTime.QuadPart > (node->EventItem->AddedTime.QuadPart + (60 * PH_TIMEOUT_SEC))) { PhInvokeCallback(&FwItemRemovedEvent, node); } } PhInvokeCallback(&FwItemsUpdatedEvent, NULL); } BOOLEAN StartFwMonitor( VOID ) { FWP_VALUE value = { FWP_EMPTY }; FWPM_SESSION session = { 0 }; FWPM_NET_EVENT_SUBSCRIPTION subscription = { 0 }; FWPM_NET_EVENT_ENUM_TEMPLATE eventTemplate = { 0 }; FwpmNetEventSubscribe1_I = PhGetModuleProcAddress(L"fwpuclnt.dll", "FwpmNetEventSubscribe1"); FwNodeList = PhCreateList(100); FwObjectType = PhCreateObjectType(L"FwObject", 0, FwObjectTypeDeleteProcedure); session.flags = 0; session.displayData.name = L"PhFirewallMonitoringSession"; session.displayData.description = L"Non-Dynamic session for Process Hacker"; // Create a non-dynamic BFE session if (FwpmEngineOpen( NULL, RPC_C_AUTHN_WINNT, NULL, &session, &FwEngineHandle ) != ERROR_SUCCESS) { return FALSE; } value.type = FWP_UINT32; value.uint32 = 1; // Enable collection of NetEvents if (FwpmEngineSetOption( FwEngineHandle, FWPM_ENGINE_COLLECT_NET_EVENTS, &value ) != ERROR_SUCCESS) { return FALSE; } if (WindowsVersion > WINDOWS_7) { value.type = FWP_UINT32; value.uint32 = FWPM_NET_EVENT_KEYWORD_CAPABILITY_DROP | FWPM_NET_EVENT_KEYWORD_CAPABILITY_ALLOW | FWPM_NET_EVENT_KEYWORD_CLASSIFY_ALLOW; // FWPM_NET_EVENT_KEYWORD_INBOUND_MCAST | FWPM_NET_EVENT_KEYWORD_INBOUND_BCAST if (FwpmEngineSetOption( FwEngineHandle, FWPM_ENGINE_NET_EVENT_MATCH_ANY_KEYWORDS, &value ) != ERROR_SUCCESS) { return FALSE; } value.type = FWP_UINT32; value.uint32 = 1; if (FwpmEngineSetOption( FwEngineHandle, FWPM_ENGINE_MONITOR_IPSEC_CONNECTIONS, &value ) != ERROR_SUCCESS) { return FALSE; } } eventTemplate.numFilterConditions = 0; // get events for all conditions subscription.sessionKey = session.sessionKey; subscription.enumTemplate = &eventTemplate; // Subscribe to the events if (FwpmNetEventSubscribe1_I) { if (FwpmNetEventSubscribe1_I( FwEngineHandle, &subscription, DropEventCallback, NULL, &FwEventHandle ) != ERROR_SUCCESS) { return FALSE; } } else { if (FwpmNetEventSubscribe0( FwEngineHandle, &subscription, (FWPM_NET_EVENT_CALLBACK0)DropEventCallback, // TODO: Use correct function. NULL, &FwEventHandle ) != ERROR_SUCCESS) { return FALSE; } } PhRegisterCallback( &PhProcessesUpdatedEvent, ProcessesUpdatedCallback, NULL, &ProcessesUpdatedCallbackRegistration ); return TRUE; } VOID StopFwMonitor( VOID ) { if (FwEventHandle) { FwpmNetEventUnsubscribe(FwEngineHandle, FwEventHandle); FwEventHandle = NULL; } if (FwEngineHandle) { //FWP_VALUE value = { FWP_EMPTY }; //value.type = FWP_UINT32; //value.uint32 = 0; // TODO: return to previous state if other applications require event collection enabled?? // Disable collection of NetEvents //FwpmEngineSetOption(FwEngineHandle, FWPM_ENGINE_COLLECT_NET_EVENTS, &value); FwpmEngineClose(FwEngineHandle); FwEngineHandle = NULL; } }