NTSTATUS WallRegisterCallouts() { NTSTATUS status = STATUS_SUCCESS; BOOLEAN bInTransaction = FALSE; BOOLEAN bEngineOpened = FALSE; FWPM_SESSION session = {0}; session.flags = FWPM_SESSION_FLAG_DYNAMIC; //开启WFP引擎 status = FwpmEngineOpen( NULL, RPC_C_AUTHN_WINNT, NULL, &session, &gEngineHandle ); if( !NT_SUCCESS(status)) goto exit; bEngineOpened = TRUE; //确认过滤权限 status = FwpmTransactionBegin( gEngineHandle,0 ); if( !NT_SUCCESS(status)) goto exit; bInTransaction = TRUE; //注册回调函数 status = RegisterCalloutForLayer( &FWPM_LAYER_ALE_AUTH_CONNECT_V4, &GUID_ALE_AUTH_CONNECT_CALLOUT_V4, WallALEConnectClassify, WallNotifyFn, WallFlowDeleteFn, &gAleConnectCalloutId, &gAleConnectFilterId); if( !NT_SUCCESS(status)) { DbgPrint("RegisterCalloutForLayer-FWPM_LAYER_ALE_AUTH_CONNECT_V4 failed!\n"); goto exit; } //确认所有内容并提交,让回调函数正式发挥作用 status = FwpmTransactionCommit(gEngineHandle ); if( !NT_SUCCESS(status)) goto exit; bInTransaction = FALSE; exit: if( !NT_SUCCESS(status)) { if( bInTransaction) { FwpmTransactionAbort( gEngineHandle ); } if( bEngineOpened ) { FwpmEngineClose( gEngineHandle ); gEngineHandle = 0; } } return status; }
DWORD NetHashProtection::AddCallouts() { FWPM_CALLOUT callout; DWORD result; FWPM_DISPLAY_DATA displayData; HANDLE engineHandle = NULL; FWPM_SESSION session; RtlZeroMemory(&session, sizeof(FWPM_SESSION)); session.displayData.name = L"Monitor Non-Dynamic Session"; session.displayData.description = L"For Adding callouts"; printf("Opening Filtering Engine\n"); result = FwpmEngineOpen( NULL, RPC_C_AUTHN_WINNT, NULL, &session, &engineHandle ); if (NO_ERROR != result) { goto cleanup; } printf("Starting Transaction for adding callouts\n"); result = FwpmTransactionBegin(engineHandle, 0); if (NO_ERROR != result) { goto abort; } printf("Successfully started the Transaction\n"); RtlZeroMemory(&callout, sizeof(FWPM_CALLOUT)); displayData.description = MONITOR_FLOW_ESTABLISHED_CALLOUT_DESCRIPTION; displayData.name = MONITOR_FLOW_ESTABLISHED_CALLOUT_NAME; callout.calloutKey = HASH_MONITOR_FLOW_ESTABLISHED_CALLOUT_V4; callout.displayData = displayData; callout.applicableLayer = FWPM_LAYER_ALE_FLOW_ESTABLISHED_V4; callout.flags = FWPM_CALLOUT_FLAG_PERSISTENT; // Make this a persistent callout. printf("Adding Persistent Flow Established callout through the Filtering Engine\n"); result = FwpmCalloutAdd(engineHandle, &callout, NULL, NULL); if (NO_ERROR != result) { goto abort; } printf("Successfully Added Persistent Flow Established callout.\n"); printf("Committing Transaction\n"); result = FwpmTransactionCommit(engineHandle); if (NO_ERROR == result) { printf("Successfully Committed Transaction.\n"); } goto cleanup; abort: printf("Aborting Transaction\n"); result = FwpmTransactionAbort(engineHandle); if (NO_ERROR == result) { printf("Successfully Aborted Transaction.\n"); } cleanup: if (engineHandle) { FwpmEngineClose(engineHandle); } return result; }
DWORD NetHashProtection::MonitorAppAddFilters(IN HANDLE engineHandle) { DWORD result = NO_ERROR; FWPM_SUBLAYER monitorSubLayer; FWPM_FILTER filter; FWPM_FILTER_CONDITION filterConditions[3]; // We only need two for this call tcp / udp -- maybe icmp tunel can bypass this :) -- RtlZeroMemory(&monitorSubLayer, sizeof(FWPM_SUBLAYER)); monitorSubLayer.subLayerKey = HASH_MONITOR_SUBLAYER; monitorSubLayer.displayData.name = L"HASH Monitor Sub layer"; monitorSubLayer.displayData.description = L"HASH Monitor Sub layer"; monitorSubLayer.flags = 0; // We don't really mind what the order of invocation is. monitorSubLayer.weight = 0; printf("Starting Transaction\n"); result = FwpmTransactionBegin(engineHandle, 0); if (NO_ERROR != result) { goto abort; } printf("Successfully Started Transaction\n"); printf("Adding Sublayer\n"); result = FwpmSubLayerAdd(engineHandle, &monitorSubLayer, NULL); if (NO_ERROR != result) { goto abort; } printf("Sucessfully added Sublayer\n"); RtlZeroMemory(&filter, sizeof(FWPM_FILTER)); filter.layerKey = FWPM_LAYER_ALE_FLOW_ESTABLISHED_V4; filter.displayData.name = L"Flow established filter."; filter.displayData.description = L"Sets up flow for traffic that we are interested in."; filter.action.type = FWP_ACTION_CALLOUT_TERMINATING; // We're only doing inspection. filter.action.calloutKey = HASH_MONITOR_FLOW_ESTABLISHED_CALLOUT_V4; filter.filterCondition = filterConditions; filter.subLayerKey = monitorSubLayer.subLayerKey; filter.weight.type = FWP_EMPTY; // auto-weight. filter.numFilterConditions = 3; RtlZeroMemory(filterConditions, sizeof(filterConditions)); filterConditions[0].fieldKey = FWPM_CONDITION_IP_PROTOCOL; filterConditions[0].matchType = FWP_MATCH_EQUAL; filterConditions[0].conditionValue.type = FWP_UINT8; filterConditions[0].conditionValue.uint8 = IPPROTO_UDP; filterConditions[1].fieldKey = FWPM_CONDITION_IP_PROTOCOL; filterConditions[1].matchType = FWP_MATCH_EQUAL; filterConditions[1].conditionValue.type = FWP_UINT8; filterConditions[1].conditionValue.uint8 = IPPROTO_TCP; filterConditions[2].fieldKey = FWPM_CONDITION_IP_PROTOCOL; filterConditions[2].matchType = FWP_MATCH_EQUAL; filterConditions[2].conditionValue.type = FWP_UINT8; filterConditions[2].conditionValue.uint8 = IPPROTO_ICMP; printf("Adding Flow Established Filter\n"); result = FwpmFilterAdd(engineHandle, &filter, NULL, NULL); if (NO_ERROR != result) { goto abort; } printf("Successfully added Flow Established filter\n"); printf("Committing Transaction\n"); result = FwpmTransactionCommit(engineHandle); if (NO_ERROR == result) { printf("Successfully Committed Transaction\n"); } goto cleanup; abort: printf("Aborting Transaction\n"); result = FwpmTransactionAbort(engineHandle); if (NO_ERROR == result) { printf("Successfully Aborted Transaction\n"); } cleanup: return result; }
DWORD NetHashProtection::RemoveCallouts() { DWORD result; HANDLE engineHandle = NULL; FWPM_SESSION session; RtlZeroMemory(&session, sizeof(FWPM_SESSION)); session.displayData.name = L" Monitor Non-Dynamic Session"; session.displayData.description = L"For Adding callouts"; printf("Opening Filtering Engine\n"); result = FwpmEngineOpen( NULL, RPC_C_AUTHN_WINNT, NULL, &session, &engineHandle ); if (NO_ERROR != result) { goto cleanup; } printf("Starting Transaction for Removing callouts\n"); result = FwpmTransactionBegin(engineHandle, 0); if (NO_ERROR != result) { goto abort; } printf("Successfully started the Transaction\n"); printf("Deleting Flow Established callout\n"); result = FwpmCalloutDeleteByKey(engineHandle, &HASH_MONITOR_FLOW_ESTABLISHED_CALLOUT_V4); if (NO_ERROR != result) { goto abort; } printf("Successfully Deleted Flow Established callout\n"); printf("Deleting Stream callout\n"); printf("Committing Transaction\n"); result = FwpmTransactionCommit(engineHandle); if (NO_ERROR == result) { printf("Successfully Committed Transaction.\n"); } goto cleanup; abort: printf("Aborting Transaction\n"); result = FwpmTransactionAbort(engineHandle); if (NO_ERROR == result) { printf("Successfully Aborted Transaction.\n"); } cleanup: if (engineHandle) { FwpmEngineClose(engineHandle); } return result; }
DWORD MonitorAppAddFilters( _In_ HANDLE engineHandle, _In_ FWP_BYTE_BLOB* applicationPath) /*++ Routine Description: Adds the required sublayer, filters and callouts to the Windows Filtering Platform (WFP). Arguments: [in] HANDLE engineHandle - Handle to the base Filtering engine [in] FWP_BYTE_BLOB* applicationPath - full path to the application including the NULL terminator and size also including the NULL the terminator [in] CALLOUTS* callouts - The callouts that need to be added. Return Value: NO_ERROR or a specific result --*/ { DWORD result = NO_ERROR; FWPM_SUBLAYER monitorSubLayer; FWPM_FILTER filter; FWPM_FILTER_CONDITION filterConditions[2]; // We only need two for this call. RtlZeroMemory(&monitorSubLayer, sizeof(FWPM_SUBLAYER)); monitorSubLayer.subLayerKey = MONITOR_SAMPLE_SUBLAYER; monitorSubLayer.displayData.name = L"Monitor Sample Sub layer"; monitorSubLayer.displayData.description = L"Monitor Sample Sub layer"; monitorSubLayer.flags = 0; // We don't really mind what the order of invocation is. monitorSubLayer.weight = 0; printf("Starting Transaction\n"); result = FwpmTransactionBegin(engineHandle, 0); if (NO_ERROR != result) { goto abort; } printf("Successfully Started Transaction\n"); printf("Adding Sublayer\n"); result = FwpmSubLayerAdd(engineHandle, &monitorSubLayer, NULL); if (NO_ERROR != result) { goto abort; } printf("Sucessfully added Sublayer\n"); RtlZeroMemory(&filter, sizeof(FWPM_FILTER)); filter.layerKey = FWPM_LAYER_ALE_FLOW_ESTABLISHED_V4; filter.displayData.name = L"Flow established filter."; filter.displayData.description = L"Sets up flow for traffic that we are interested in."; filter.action.type = FWP_ACTION_CALLOUT_INSPECTION; // We're only doing inspection. filter.action.calloutKey = MONITOR_SAMPLE_FLOW_ESTABLISHED_CALLOUT_V4; filter.filterCondition = filterConditions; filter.subLayerKey = monitorSubLayer.subLayerKey; filter.weight.type = FWP_EMPTY; // auto-weight. filter.numFilterConditions = 2; RtlZeroMemory(filterConditions, sizeof(filterConditions)); // // Add the application path to the filter conditions. // filterConditions[0].fieldKey = FWPM_CONDITION_ALE_APP_ID; filterConditions[0].matchType = FWP_MATCH_EQUAL; filterConditions[0].conditionValue.type = FWP_BYTE_BLOB_TYPE; filterConditions[0].conditionValue.byteBlob = applicationPath; // // For the purposes of this sample, we will monitor TCP traffic only. // filterConditions[1].fieldKey = FWPM_CONDITION_IP_PROTOCOL; filterConditions[1].matchType = FWP_MATCH_EQUAL; filterConditions[1].conditionValue.type = FWP_UINT8; filterConditions[1].conditionValue.uint8 = IPPROTO_TCP; printf("Adding Flow Established Filter\n"); result = FwpmFilterAdd(engineHandle, &filter, NULL, NULL); if (NO_ERROR != result) { goto abort; } printf("Successfully added Flow Established filter\n"); RtlZeroMemory(&filter, sizeof(FWPM_FILTER)); filter.layerKey = FWPM_LAYER_STREAM_V4; filter.action.type = FWP_ACTION_CALLOUT_INSPECTION; // We're only doing inspection. filter.action.calloutKey = MONITOR_SAMPLE_STREAM_CALLOUT_V4; filter.subLayerKey = monitorSubLayer.subLayerKey; filter.weight.type = FWP_EMPTY; // auto-weight. filter.numFilterConditions = 0; RtlZeroMemory(filterConditions, sizeof(filterConditions)); filter.filterCondition = filterConditions; filter.displayData.name = L"Stream Layer Filter"; filter.displayData.description = L"Monitors TCP traffic."; printf("Adding Stream Filter\n"); result = FwpmFilterAdd(engineHandle, &filter, NULL, NULL); if (NO_ERROR != result) { goto abort; } printf("Successfully added Stream filter\n"); printf("Committing Transaction\n"); result = FwpmTransactionCommit(engineHandle); if (NO_ERROR == result) { printf("Successfully Committed Transaction\n"); } goto cleanup; abort: printf("Aborting Transaction\n"); result = FwpmTransactionAbort(engineHandle); if (NO_ERROR == result) { printf("Successfully Aborted Transaction\n"); } cleanup: return result; }
DWORD MonitorAppRemoveCallouts() /*++ Routine Description: Sets the kernel callout ID's through the Monitor Sample device Arguments: [in] HANDLE monitorDevice - Monitor Sample device [in] CALLOUTS* callouts - Callout structure with ID's set [in] DWORD size - Size of the callout structure. Return Value: NO_ERROR or a specific DeviceIoControl result. --*/ { DWORD result; HANDLE engineHandle = NULL; FWPM_SESSION session; RtlZeroMemory(&session, sizeof(FWPM_SESSION)); session.displayData.name = L"Monitor Sample Non-Dynamic Session"; session.displayData.description = L"For Adding callouts"; printf("Opening Filtering Engine\n"); result = FwpmEngineOpen( NULL, RPC_C_AUTHN_WINNT, NULL, &session, &engineHandle ); if (NO_ERROR != result) { goto cleanup; } printf("Starting Transaction for Removing callouts\n"); result = FwpmTransactionBegin(engineHandle, 0); if (NO_ERROR != result) { goto abort; } printf("Successfully started the Transaction\n"); printf("Deleting Flow Established callout\n"); result = FwpmCalloutDeleteByKey(engineHandle, &MONITOR_SAMPLE_FLOW_ESTABLISHED_CALLOUT_V4); if (NO_ERROR != result) { goto abort; } printf("Successfully Deleted Flow Established callout\n"); printf("Deleting Stream callout\n"); result = FwpmCalloutDeleteByKey(engineHandle, &MONITOR_SAMPLE_STREAM_CALLOUT_V4); if (NO_ERROR != result) { goto abort; } printf("Successfully Deleted Stream callout\n"); printf("Committing Transaction\n"); result = FwpmTransactionCommit(engineHandle); if (NO_ERROR == result) { printf("Successfully Committed Transaction.\n"); } goto cleanup; abort: printf("Aborting Transaction\n"); result = FwpmTransactionAbort(engineHandle); if (NO_ERROR == result) { printf("Successfully Aborted Transaction.\n"); } cleanup: if (engineHandle) { FwpmEngineClose(engineHandle); } return result; }
DWORD MonitorAppAddCallouts() /*++ Routine Description: Adds the callouts during installation Arguments: [in] PCWSTR AppPath - The path to the application to monitor. Return Value: NO_ERROR or a specific FWP result. --*/ { FWPM_CALLOUT callout; DWORD result; FWPM_DISPLAY_DATA displayData; HANDLE engineHandle = NULL; FWPM_SESSION session; RtlZeroMemory(&session, sizeof(FWPM_SESSION)); session.displayData.name = L"Monitor Sample Non-Dynamic Session"; session.displayData.description = L"For Adding callouts"; printf("Opening Filtering Engine\n"); result = FwpmEngineOpen( NULL, RPC_C_AUTHN_WINNT, NULL, &session, &engineHandle ); if (NO_ERROR != result) { goto cleanup; } printf("Starting Transaction for adding callouts\n"); result = FwpmTransactionBegin(engineHandle, 0); if (NO_ERROR != result) { goto abort; } printf("Successfully started the Transaction\n"); RtlZeroMemory(&callout, sizeof(FWPM_CALLOUT)); displayData.description = MONITOR_FLOW_ESTABLISHED_CALLOUT_DESCRIPTION; displayData.name = MONITOR_FLOW_ESTABLISHED_CALLOUT_NAME; callout.calloutKey = MONITOR_SAMPLE_FLOW_ESTABLISHED_CALLOUT_V4; callout.displayData = displayData; callout.applicableLayer = FWPM_LAYER_ALE_FLOW_ESTABLISHED_V4; callout.flags = FWPM_CALLOUT_FLAG_PERSISTENT; // Make this a persistent callout. printf("Adding Persistent Flow Established callout through the Filtering Engine\n"); result = FwpmCalloutAdd(engineHandle, &callout, NULL, NULL); if (NO_ERROR != result) { goto abort; } printf("Successfully Added Persistent Flow Established callout.\n"); RtlZeroMemory(&callout, sizeof(FWPM_CALLOUT)); displayData.description = MONITOR_STREAM_CALLOUT_DESCRIPTION; displayData.name = MONITOR_STREAM_CALLOUT_DESCRIPTION; callout.calloutKey = MONITOR_SAMPLE_STREAM_CALLOUT_V4; callout.displayData = displayData; callout.applicableLayer = FWPM_LAYER_STREAM_V4; callout.flags = FWPM_CALLOUT_FLAG_PERSISTENT; // Make this a persistent callout. printf("Adding Persistent Stream callout through the Filtering Engine\n"); result = FwpmCalloutAdd(engineHandle, &callout, NULL, NULL); if (NO_ERROR != result) { goto abort; } printf("Successfully Added Persistent Stream callout.\n"); printf("Committing Transaction\n"); result = FwpmTransactionCommit(engineHandle); if (NO_ERROR == result) { printf("Successfully Committed Transaction.\n"); } goto cleanup; abort: printf("Aborting Transaction\n"); result = FwpmTransactionAbort(engineHandle); if (NO_ERROR == result) { printf("Successfully Aborted Transaction.\n"); } cleanup: if (engineHandle) { FwpmEngineClose(engineHandle); } return result; }
NTSTATUS StreamEditRegisterCallout( const STREAM_EDITOR* streamEditor, _Inout_ void* deviceObject ) /* ++ This function registers dynamic callouts and filters that intercept TCP traffic at WFP FWPM_LAYER_STREAM_V4 and FWPM_LAYER_STREAM_V6 layer. Callouts and filters will be removed during DriverUnload. -- */ { NTSTATUS status = STATUS_SUCCESS; BOOLEAN engineOpened = FALSE; BOOLEAN inTransaction = FALSE; FWPM_SESSION session = {0}; UNREFERENCED_PARAMETER(streamEditor); session.flags = FWPM_SESSION_FLAG_DYNAMIC; status = FwpmEngineOpen( NULL, RPC_C_AUTHN_WINNT, NULL, &session, &gEngineHandle ); if (!NT_SUCCESS(status)) { goto Exit; } engineOpened = TRUE; status = FwpmTransactionBegin(gEngineHandle, 0); if (!NT_SUCCESS(status)) { goto Exit; } inTransaction = TRUE; status = RegisterCalloutForLayer( &FWPM_LAYER_STREAM_V4, &STREAM_EDITOR_STREAM_CALLOUT_V4, deviceObject, &gCalloutIdV4 ); if (!NT_SUCCESS(status)) { goto Exit; } status = RegisterCalloutForLayer( &FWPM_LAYER_STREAM_V6, &STREAM_EDITOR_STREAM_CALLOUT_V6, deviceObject, &gCalloutIdV6 ); if (!NT_SUCCESS(status)) { goto Exit; } status = FwpmTransactionCommit(gEngineHandle); if (!NT_SUCCESS(status)) { goto Exit; } inTransaction = FALSE; Exit: if (!NT_SUCCESS(status)) { if (inTransaction) { NTSTATUS abortStatus; abortStatus = FwpmTransactionAbort(gEngineHandle); _Analysis_assume_(NT_SUCCESS(abortStatus)); } if (engineOpened) { FwpmEngineClose(gEngineHandle); gEngineHandle = NULL; } } return status; }