This commit is contained in:
DavidXanatos 2021-07-30 15:54:14 +02:00
parent f8534d56da
commit d6e300f7bf
2 changed files with 124 additions and 32 deletions

View File

@ -16,6 +16,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- fixed issue with fake admin and some nsi installers [#1052](https://github.com/sandboxie-plus/Sandboxie/issues/1052)
- fixed more issued with FileDispositionInformation behavioure, which resulted in bogus file deletion handling
- fixed issue with checking WFP status
- fixed issue WFP failing to initialize at boot

View File

@ -98,6 +98,10 @@ typedef struct _WFP_PROCESS {
// Functions
//---------------------------------------------------------------------------
BOOLEAN WFP_Install_Callbacks(void);
void WFP_Uninstall_Callbacks(void);
NTSTATUS WFP_RegisterSubLayer();
NTSTATUS WFP_RegisterCallout(const GUID* calloutKey, const GUID* applicableLayer, UINT32* callout_id, UINT64* filter_id);
@ -110,6 +114,9 @@ ULONG Process_GetTraceFlag(PROCESS *proc, const WCHAR *setting);;
#pragma alloc_text (INIT, WFP_Init)
#endif // ALLOC_PRAGMA
void WFP_state_changed(
_Inout_ void* context,
_In_ FWPM_SERVICE_STATE newState);
/* The "classifyFn" callout function for this Callout.
For more information about a Callout's classifyFn, see:
@ -156,6 +163,12 @@ void GetNetwork5TupleIndexesForLayer(
// Variables
//---------------------------------------------------------------------------
BOOLEAN WFP_Enabled = FALSE;
PERESOURCE WFP_InitLock = NULL;
static HANDLE WFP_state_handle = NULL;
// Global handle to the WFP Base Filter Engine
static HANDLE WFP_engine_handle = NULL;
@ -206,9 +219,12 @@ _FX VOID WFP_Free(void* pool, void* ptr)
_FX BOOLEAN WFP_Init(void)
{
if (!Conf_Get_Boolean(NULL, L"NetworkEnableWFP", 0, FALSE))
WFP_Enabled = Conf_Get_Boolean(NULL, L"NetworkEnableWFP", 0, FALSE);
if (!WFP_Enabled)
return TRUE;
DbgPrint("Sbie WFP enabled\r\n");
map_init(&WFP_Processes, NULL);
WFP_Processes.func_malloc = &WFP_Alloc;
WFP_Processes.func_free = &WFP_Free;
@ -216,88 +232,142 @@ _FX BOOLEAN WFP_Init(void)
KeInitializeSpinLock(&WFP_MapLock);
if (!Mem_GetLockResource(&WFP_InitLock, TRUE))
return FALSE;
NTSTATUS status = FwpmBfeStateSubscribeChanges((void*)Api_DeviceObject, WFP_state_changed, NULL, &WFP_state_handle);
if (!NT_SUCCESS(status)) {
DbgPrint("Sbie WFP failed to install state change callback\r\n");
return FALSE;
}
if (FwpmBfeStateGet() == FWPM_SERVICE_RUNNING)
WFP_Install_Callbacks();
else
DbgPrint("Sbie WFP is not ready\r\n");
return TRUE;
}
//---------------------------------------------------------------------------
// WFP_state_changed
//---------------------------------------------------------------------------
_FX void WFP_state_changed(_Inout_ void* context, _In_ FWPM_SERVICE_STATE newState)
{
if (newState == FWPM_SERVICE_STOP_PENDING)
WFP_Uninstall_Callbacks();
else if (newState == FWPM_SERVICE_RUNNING)
WFP_Install_Callbacks();
}
//---------------------------------------------------------------------------
// WFP_Install_Callbacks
//---------------------------------------------------------------------------
_FX BOOLEAN WFP_Install_Callbacks(void)
{
ExAcquireResourceSharedLite(WFP_InitLock, TRUE);
if (WFP_engine_handle != NULL) {
ExReleaseResourceLite(WFP_InitLock);
return TRUE; // already initialized
}
NTSTATUS status = STATUS_SUCCESS;
DWORD stage = 0;
FWPM_SESSION wdf_session = { 0 };
BOOLEAN in_transaction = FALSE;
BOOLEAN callout_registered = FALSE;
// Begin a transaction to the FilterEngine. You must register objects (filter, callouts, sublayers)
//to the filter engine in the context of a 'transaction'
wdf_session.flags = FWPM_SESSION_FLAG_DYNAMIC; // <-- Automatically destroys all filters and removes all callouts after this wdf_session ends
status = FwpmEngineOpen(NULL, RPC_C_AUTHN_WINNT, NULL, &wdf_session, &WFP_engine_handle);
if (!NT_SUCCESS(status)) goto Exit;
stage = 0x10; if (!NT_SUCCESS(status)) goto Exit;
status = FwpmTransactionBegin(WFP_engine_handle, 0);
if (!NT_SUCCESS(status)) goto Exit;
stage = 0x20; if (!NT_SUCCESS(status)) goto Exit;
in_transaction = TRUE;
// Register a new sublayer to the filter engine
status = WFP_RegisterSubLayer();
if (!NT_SUCCESS(status)) goto Exit;
stage = 0x30; if (!NT_SUCCESS(status)) goto Exit;
//status = WFP_RegisterCallout(&WPF_CALLOUT_GUID_V4, &FWPM_LAYER_ALE_RESOURCE_ASSIGNMENT_V4, &WFP_callout_id_v4, &WFP_filter_id_v4);
//if (!NT_SUCCESS(status)) goto Exit;
//status = WFP_RegisterCallout(&WPF_CALLOUT_GUID_V6, &FWPM_LAYER_ALE_RESOURCE_ASSIGNMENT_V6, &WFP_callout_id_v6, &WFP_filter_id_v6);
//if (!NT_SUCCESS(status)) goto Exit;
status = WFP_RegisterCallout(&WPF_SEND_CALLOUT_GUID_V4, &FWPM_LAYER_ALE_AUTH_CONNECT_V4, &WFP_send_callout_id_v4, &WFP_send_filter_id_v4);
if (!NT_SUCCESS(status)) goto Exit;
stage = 0x41; if (!NT_SUCCESS(status)) goto Exit;
callout_registered = TRUE;
status = WFP_RegisterCallout(&WPF_SEND_CALLOUT_GUID_V6, &FWPM_LAYER_ALE_AUTH_CONNECT_V6, &WFP_send_callout_id_v6, &WFP_send_filter_id_v6);
if (!NT_SUCCESS(status)) goto Exit;
stage = 0x42; if (!NT_SUCCESS(status)) goto Exit;
status = WFP_RegisterCallout(&WPF_RECV_CALLOUT_GUID_V4, &FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4, &WFP_recv_callout_id_v4, &WFP_recv_filter_id_v4);
if (!NT_SUCCESS(status)) goto Exit;
stage = 0x43; if (!NT_SUCCESS(status)) goto Exit;
status = WFP_RegisterCallout(&WPF_RECV_CALLOUT_GUID_V6, &FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6, &WFP_recv_callout_id_v6, &WFP_recv_filter_id_v6);
if (!NT_SUCCESS(status)) goto Exit;
stage = 0x44; if (!NT_SUCCESS(status)) goto Exit;
// note: we could also setup FWPM_LAYER_ALE_AUTH_LISTEN_V4 but since we block all accepts we dont have to
// Commit transaction to the Filter Engine
status = FwpmTransactionCommit(WFP_engine_handle);
if (!NT_SUCCESS(status)) goto Exit;
stage = 0x50; if (!NT_SUCCESS(status)) goto Exit;
in_transaction = FALSE;
// Cleanup and handle any errors
Exit:
if (!NT_SUCCESS(status)){
//DbgPrint("WFP initialization failed, status 0x%08x\r\n", status);
if (!NT_SUCCESS(status)) {
DbgPrint("Sbie WFP initialization failed, stage %02x, status 0x%08x\r\n", stage, status);
if (in_transaction == TRUE){
if (in_transaction == TRUE) {
FwpmTransactionAbort(WFP_engine_handle);
_Analysis_assume_lock_not_held_(WFP_engine_handle); // Potential leak if "FwpmTransactionAbort" fails
}
if (WFP_engine_handle){
FwpmEngineClose(WFP_engine_handle);
WFP_engine_handle = NULL;
}
if (callout_registered) {
FwpsCalloutUnregisterById(WFP_send_callout_id_v4);
FwpsCalloutUnregisterById(WFP_send_callout_id_v6);
FwpsCalloutUnregisterById(WFP_recv_callout_id_v4);
FwpsCalloutUnregisterById(WFP_recv_callout_id_v6);
}
if (WFP_engine_handle) {
FwpmEngineClose(WFP_engine_handle);
WFP_engine_handle = NULL;
}
ExReleaseResourceLite(WFP_InitLock);
return FALSE;
}
//DbgPrint("--- WFP initialized successfully ---\r\n");
DbgPrint("Sbie WFP initialized successfully\r\n");
ExReleaseResourceLite(WFP_InitLock);
return TRUE;
}
//---------------------------------------------------------------------------
// WFP_Unload
// WFP_Uninstall_Callbacks
//---------------------------------------------------------------------------
_FX void WFP_Unload(void)
_FX void WFP_Uninstall_Callbacks(void)
{
ExAcquireResourceSharedLite(WFP_InitLock, TRUE);
if (WFP_engine_handle == NULL) {
ExReleaseResourceLite(WFP_InitLock);
return; // not initialized
}
NTSTATUS status = STATUS_SUCCESS;
UNICODE_STRING symlink = { 0 };
if (WFP_engine_handle == NULL)
return;
//status = FwpsCalloutUnregisterById(WFP_callout_id_v4);
//if (!NT_SUCCESS(status)) DbgPrint("Failed to unregister callout, status: 0x%08x\r\n", status);
//status = FwpsCalloutUnregisterById(WFP_callout_id_v6);
@ -312,14 +382,32 @@ _FX void WFP_Unload(void)
//if (!NT_SUCCESS(status)) DbgPrint("Failed to unregister callout, status: 0x%08x\r\n", status);
// Close handle to the WFP Filter Engine
if (WFP_engine_handle){
if (WFP_engine_handle) {
FwpmEngineClose(WFP_engine_handle);
WFP_engine_handle = NULL;
}
//DbgPrint("--- WFP uninitialized ---\r\n");
DbgPrint("Sbie WFP uninitialized\r\n");
ExReleaseResourceLite(WFP_InitLock);
}
//---------------------------------------------------------------------------
// WFP_Unload
//---------------------------------------------------------------------------
_FX void WFP_Unload(void)
{
if (!WFP_Enabled)
return; // nothing to do
map_deinit(&WFP_Processes);
if (WFP_state_handle != NULL)
FwpmBfeStateUnsubscribeChanges(WFP_state_handle);
WFP_Uninstall_Callbacks();
}
@ -468,9 +556,12 @@ BOOLEAN WFP_LoadRules(LIST* NetFwRules, PROCESS* proc)
BOOLEAN WFP_InitProcess(PROCESS* proc)
{
if (WFP_engine_handle == NULL)
if (!WFP_Enabled)
return TRUE; // nothing to do
if (WFP_engine_handle == NULL)
return FALSE; // WFP was not ready report failure, cancel process creation
BOOLEAN ok = TRUE;
KIRQL irql;
@ -512,8 +603,8 @@ finish:
BOOLEAN WFP_UpdateProcess(PROCESS* proc)
{
if (WFP_engine_handle == NULL)
return TRUE; // feature disabled all ok
if (!WFP_Enabled)
return TRUE; // nothing to do
BOOLEAN ok = FALSE;
KIRQL irql;
@ -581,8 +672,8 @@ BOOLEAN WFP_UpdateProcess(PROCESS* proc)
void WFP_DeleteProcess(PROCESS* proc)
{
if (WFP_engine_handle == NULL)
return; // nothing to go
if (!WFP_Enabled)
return; // nothing to do
KIRQL irql;
WFP_PROCESS* wfp_proc;