mirror of
https://github.com/henrypp/simplewall.git
synced 2026-10-22 19:12:58 -05:00
962 lines
31 KiB
C++
962 lines
31 KiB
C++
// simplewall
|
|
// Copyright (c) 2016-2020 Henry++
|
|
|
|
#include "global.hpp"
|
|
|
|
PR_STRING _app_getlogviewer ()
|
|
{
|
|
LPCWSTR result = _r_config_getstring (L"LogViewer", LOG_VIEWER_DEFAULT);
|
|
|
|
if (_r_str_isempty (result))
|
|
return _r_path_expand (LOG_VIEWER_DEFAULT);
|
|
|
|
return _r_path_expand (result);
|
|
}
|
|
|
|
VOID _app_loginit (BOOLEAN is_install)
|
|
{
|
|
// dropped packets logging (win7+)
|
|
if (!config.hnetevent)
|
|
return;
|
|
|
|
// reset log handle
|
|
SAFE_DELETE_HANDLE (config.hlogfile);
|
|
|
|
if (!is_install || !_r_config_getboolean (L"IsLogEnabled", FALSE))
|
|
return; // already closed or not enabled
|
|
|
|
PR_STRING logPath = _r_path_expand (_r_config_getstring (L"LogPath", LOG_PATH_DEFAULT));
|
|
|
|
if (!logPath)
|
|
return;
|
|
|
|
config.hlogfile = CreateFile (logPath->Buffer, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
|
|
if (_r_fs_isvalidhandle (config.hlogfile))
|
|
{
|
|
if (GetLastError () != ERROR_ALREADY_EXISTS)
|
|
{
|
|
ULONG written;
|
|
BYTE bom[] = {0xFF, 0xFE};
|
|
|
|
WriteFile (config.hlogfile, bom, sizeof (bom), &written, NULL); // write utf-16 le byte order mask
|
|
}
|
|
else
|
|
{
|
|
_r_fs_setpos (config.hlogfile, 0, FILE_END);
|
|
}
|
|
|
|
_r_obj_dereference (logPath);
|
|
}
|
|
}
|
|
|
|
VOID _app_logwrite (PITEM_LOG ptr_log)
|
|
{
|
|
PR_STRING path = NULL;
|
|
WCHAR dateString[256];
|
|
PR_STRING localAddressString;
|
|
PR_STRING localPortString;
|
|
PR_STRING remoteAddressString;
|
|
PR_STRING remotePortString;
|
|
PR_STRING directionString;
|
|
PR_STRING buffer;
|
|
|
|
// parse path
|
|
{
|
|
PITEM_APP ptr_app = _app_getappitem (ptr_log->app_hash);
|
|
|
|
if (ptr_app)
|
|
{
|
|
if (ptr_app->type == DataAppUWP || ptr_app->type == DataAppService)
|
|
{
|
|
if (!_r_str_isempty (ptr_app->real_path))
|
|
{
|
|
path = _r_obj_reference (ptr_app->real_path);
|
|
}
|
|
else if (!_r_str_isempty (ptr_app->display_name))
|
|
{
|
|
path = _r_obj_reference (ptr_app->display_name);
|
|
}
|
|
}
|
|
else if (!_r_str_isempty (ptr_app->original_path))
|
|
{
|
|
path = _r_obj_reference (ptr_app->original_path);
|
|
}
|
|
|
|
_r_obj_dereference (ptr_app);
|
|
}
|
|
}
|
|
|
|
_r_format_dateex (dateString, RTL_NUMBER_OF (dateString), ptr_log->timestamp, FDTF_SHORTDATE | FDTF_SHORTTIME);
|
|
|
|
localAddressString = _app_formataddress (ptr_log->af, 0, &ptr_log->local_addr, 0, FMTADDR_RESOLVE_HOST);
|
|
remoteAddressString = _app_formataddress (ptr_log->af, 0, &ptr_log->remote_addr, 0, FMTADDR_RESOLVE_HOST);
|
|
|
|
localPortString = _app_formatport (ptr_log->local_port, TRUE);
|
|
remotePortString = _app_formatport (ptr_log->remote_port, TRUE);
|
|
|
|
directionString = _app_getdirectionname (ptr_log->direction, ptr_log->is_loopback, FALSE);
|
|
|
|
buffer = _r_format_string (SZ_LOG_BODY,
|
|
dateString,
|
|
_r_obj_getstringordefault (ptr_log->username, SZ_EMPTY),
|
|
_r_obj_getstringordefault (path, SZ_EMPTY),
|
|
_r_obj_getstringordefault (localAddressString, SZ_EMPTY),
|
|
_r_obj_getstringordefault (localPortString, SZ_EMPTY),
|
|
_r_obj_getstringordefault (remoteAddressString, SZ_EMPTY),
|
|
_r_obj_getstringordefault (remotePortString, SZ_EMPTY),
|
|
_app_getprotoname (ptr_log->protocol, ptr_log->af, SZ_UNKNOWN),
|
|
_r_obj_getstringorempty (ptr_log->provider_name),
|
|
_r_obj_getstringorempty (ptr_log->filter_name),
|
|
ptr_log->filter_id,
|
|
_r_obj_getstringordefault (directionString, SZ_EMPTY),
|
|
(ptr_log->is_allow ? SZ_STATE_ALLOW : SZ_STATE_BLOCK)
|
|
);
|
|
|
|
if (_app_logislimitreached ())
|
|
_app_logclear ();
|
|
|
|
ULONG written;
|
|
|
|
if (_r_fs_size (config.hlogfile) == 2)
|
|
WriteFile (config.hlogfile, SZ_LOG_TITLE, (ULONG)(_r_str_length (SZ_LOG_TITLE) * sizeof (WCHAR)), &written, NULL); // adds csv header
|
|
|
|
WriteFile (config.hlogfile, buffer->Buffer, (ULONG)buffer->Length, &written, NULL);
|
|
|
|
SAFE_DELETE_REFERENCE (localAddressString);
|
|
SAFE_DELETE_REFERENCE (localPortString);
|
|
SAFE_DELETE_REFERENCE (remoteAddressString);
|
|
SAFE_DELETE_REFERENCE (remotePortString);
|
|
SAFE_DELETE_REFERENCE (directionString);
|
|
SAFE_DELETE_REFERENCE (path);
|
|
|
|
_r_obj_dereference (buffer);
|
|
}
|
|
|
|
BOOLEAN _app_logisexists (HWND hwnd, PITEM_LOG ptr_log_new)
|
|
{
|
|
BOOLEAN is_duplicate_found = FALSE;
|
|
|
|
for (auto it = log_arr.begin (); it != log_arr.end (); ++it)
|
|
{
|
|
if (!*it)
|
|
continue;
|
|
|
|
PITEM_LOG ptr_log = (PITEM_LOG)_r_obj_reference (*it);
|
|
|
|
if (
|
|
ptr_log->is_allow == ptr_log_new->is_allow &&
|
|
ptr_log->af == ptr_log_new->af &&
|
|
ptr_log->direction == ptr_log_new->direction &&
|
|
ptr_log->protocol == ptr_log_new->protocol &&
|
|
ptr_log->remote_port == ptr_log_new->remote_port &&
|
|
ptr_log->local_port == ptr_log_new->local_port
|
|
)
|
|
{
|
|
if (ptr_log->af == AF_INET)
|
|
{
|
|
if (
|
|
ptr_log->remote_addr.S_un.S_addr == ptr_log_new->remote_addr.S_un.S_addr &&
|
|
ptr_log->local_addr.S_un.S_addr == ptr_log_new->local_addr.S_un.S_addr
|
|
)
|
|
{
|
|
is_duplicate_found = TRUE;
|
|
}
|
|
}
|
|
else if (ptr_log->af == AF_INET6)
|
|
{
|
|
if (
|
|
RtlEqualMemory (ptr_log->remote_addr6.u.Byte, ptr_log_new->remote_addr6.u.Byte, FWP_V6_ADDR_SIZE) &&
|
|
RtlEqualMemory (ptr_log->local_addr6.u.Byte, ptr_log_new->local_addr6.u.Byte, FWP_V6_ADDR_SIZE)
|
|
)
|
|
{
|
|
is_duplicate_found = TRUE;
|
|
}
|
|
}
|
|
|
|
if (is_duplicate_found)
|
|
{
|
|
ptr_log_new->timestamp = ptr_log->timestamp; // upd date
|
|
_r_obj_dereference (ptr_log);
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
_r_obj_dereference (ptr_log);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
VOID _app_logwrite_ui (HWND hwnd, PITEM_LOG ptr_log)
|
|
{
|
|
INT listview_id;
|
|
SIZE_T index;
|
|
INT icon_id;
|
|
INT item_id;
|
|
PR_STRING nameString;
|
|
PR_STRING localAddressString;
|
|
PR_STRING localPortString;
|
|
PR_STRING remoteAddressString;
|
|
PR_STRING remotePortString;
|
|
PR_STRING directionString;
|
|
|
|
if (_app_logisexists (hwnd, ptr_log))
|
|
return;
|
|
|
|
listview_id = IDC_LOG;
|
|
index = log_arr.size ();
|
|
|
|
log_arr.emplace_back ((PITEM_LOG)_r_obj_reference (ptr_log));
|
|
|
|
icon_id = (INT)_app_getappinfo (ptr_log->app_hash, InfoIconId);
|
|
|
|
if (!icon_id)
|
|
icon_id = config.icon_id;
|
|
|
|
nameString = (PR_STRING)_app_getappinfo (ptr_log->app_hash, InfoName);
|
|
|
|
if (!nameString && !_r_str_isempty (ptr_log->path))
|
|
nameString = _r_obj_reference (ptr_log->path);
|
|
|
|
localAddressString = _app_formataddress (ptr_log->af, 0, &ptr_log->local_addr, 0, 0);
|
|
remoteAddressString = _app_formataddress (ptr_log->af, 0, &ptr_log->remote_addr, 0, 0);
|
|
|
|
localPortString = _app_formatport (ptr_log->local_port, TRUE);
|
|
remotePortString = _app_formatport (ptr_log->remote_port, TRUE);
|
|
|
|
directionString = _app_getdirectionname (ptr_log->direction, ptr_log->is_loopback, FALSE);
|
|
|
|
item_id = _r_listview_getitemcount (hwnd, listview_id, FALSE);
|
|
|
|
_r_listview_additemex (hwnd, listview_id, item_id, 0, _r_obj_getstringordefault (nameString, SZ_EMPTY), icon_id, I_GROUPIDNONE, index);
|
|
_r_listview_setitem (hwnd, listview_id, item_id, 1, _r_obj_getstringordefault (localAddressString, SZ_EMPTY));
|
|
_r_listview_setitem (hwnd, listview_id, item_id, 3, _r_obj_getstringordefault (remoteAddressString, SZ_EMPTY));
|
|
_r_listview_setitem (hwnd, listview_id, item_id, 5, _app_getprotoname (ptr_log->protocol, ptr_log->af, SZ_EMPTY));
|
|
|
|
if (localPortString)
|
|
_r_listview_setitem (hwnd, listview_id, item_id, 2, _r_obj_getstringorempty (localPortString));
|
|
|
|
if (remotePortString)
|
|
_r_listview_setitem (hwnd, listview_id, item_id, 4, _r_obj_getstringorempty (remotePortString));
|
|
|
|
_r_listview_setitem (hwnd, listview_id, item_id, 6, _r_obj_getstringordefault (ptr_log->filter_name, SZ_EMPTY));
|
|
_r_listview_setitem (hwnd, listview_id, item_id, 7, _r_obj_getstringorempty (directionString));
|
|
_r_listview_setitem (hwnd, listview_id, item_id, 8, ptr_log->is_allow ? SZ_STATE_ALLOW : SZ_STATE_BLOCK);
|
|
|
|
SAFE_DELETE_REFERENCE (nameString);
|
|
SAFE_DELETE_REFERENCE (localAddressString);
|
|
SAFE_DELETE_REFERENCE (remoteAddressString);
|
|
SAFE_DELETE_REFERENCE (localPortString);
|
|
SAFE_DELETE_REFERENCE (remotePortString);
|
|
SAFE_DELETE_REFERENCE (directionString);
|
|
|
|
if (listview_id == (INT)_r_tab_getlparam (hwnd, IDC_TAB, INVALID_INT))
|
|
{
|
|
_app_listviewresize (hwnd, listview_id, FALSE);
|
|
_app_listviewsort (hwnd, listview_id, INVALID_INT, FALSE);
|
|
}
|
|
}
|
|
|
|
BOOLEAN _app_logislimitreached ()
|
|
{
|
|
ULONG limit = _r_config_getulong (L"LogSizeLimitKb", LOG_SIZE_LIMIT_DEFAULT);
|
|
|
|
if (!limit || !_r_fs_isvalidhandle (config.hlogfile))
|
|
return FALSE;
|
|
|
|
return (_r_fs_size (config.hlogfile) >= (_r_calc_kilobytes2bytes (LONG64, limit)));
|
|
}
|
|
|
|
VOID _app_logclear ()
|
|
{
|
|
if (_r_fs_isvalidhandle (config.hlogfile))
|
|
{
|
|
_r_fs_setpos (config.hlogfile, 2, FILE_BEGIN);
|
|
|
|
SetEndOfFile (config.hlogfile);
|
|
|
|
FlushFileBuffers (config.hlogfile);
|
|
}
|
|
else
|
|
{
|
|
PR_STRING logPath = _r_path_expand (_r_config_getstring (L"LogPath", LOG_PATH_DEFAULT));
|
|
|
|
if (logPath)
|
|
{
|
|
_r_fs_remove (logPath->Buffer, _R_FLAG_REMOVE_FORCE);
|
|
_r_obj_dereference (logPath);
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID _app_logclear_ui (HWND hwnd)
|
|
{
|
|
SendDlgItemMessage (hwnd, IDC_LOG, LVM_DELETEALLITEMS, 0, 0);
|
|
//SendDlgItemMessage (hwnd, IDC_LOG, LVM_SETITEMCOUNT, 0, 0);
|
|
|
|
_app_freelogobjects_vec (&log_arr);
|
|
}
|
|
|
|
VOID _wfp_logsubscribe (HANDLE hengine)
|
|
{
|
|
if (config.hnetevent)
|
|
return; // already subscribed
|
|
|
|
HMODULE hlib = LoadLibraryEx (L"fwpuclnt.dll", NULL, LOAD_LIBRARY_SEARCH_USER_DIRS | LOAD_LIBRARY_SEARCH_SYSTEM32);
|
|
|
|
if (hlib)
|
|
{
|
|
typedef ULONG (WINAPI *FWPMNES4)(HANDLE engineHandle, const FWPM_NET_EVENT_SUBSCRIPTION0* subscription, FWPM_NET_EVENT_CALLBACK4 callback, void* context, HANDLE* eventsHandle); // win10rs5+
|
|
typedef ULONG (WINAPI *FWPMNES3)(HANDLE engineHandle, const FWPM_NET_EVENT_SUBSCRIPTION0* subscription, FWPM_NET_EVENT_CALLBACK3 callback, void* context, HANDLE* eventsHandle); // win10rs4+
|
|
typedef ULONG (WINAPI *FWPMNES2)(HANDLE engineHandle, const FWPM_NET_EVENT_SUBSCRIPTION0* subscription, FWPM_NET_EVENT_CALLBACK2 callback, void* context, HANDLE* eventsHandle); // win10rs1+
|
|
typedef ULONG (WINAPI *FWPMNES1)(HANDLE engineHandle, const FWPM_NET_EVENT_SUBSCRIPTION0* subscription, FWPM_NET_EVENT_CALLBACK1 callback, void* context, HANDLE* eventsHandle); // win8+
|
|
typedef ULONG (WINAPI *FWPMNES0)(HANDLE engineHandle, const FWPM_NET_EVENT_SUBSCRIPTION0* subscription, FWPM_NET_EVENT_CALLBACK0 callback, void* context, HANDLE* eventsHandle); // win7+
|
|
|
|
const FWPMNES4 _FwpmNetEventSubscribe4 = (FWPMNES4)GetProcAddress (hlib, "FwpmNetEventSubscribe4");
|
|
const FWPMNES3 _FwpmNetEventSubscribe3 = (FWPMNES3)GetProcAddress (hlib, "FwpmNetEventSubscribe3");
|
|
const FWPMNES2 _FwpmNetEventSubscribe2 = (FWPMNES2)GetProcAddress (hlib, "FwpmNetEventSubscribe2");
|
|
const FWPMNES1 _FwpmNetEventSubscribe1 = (FWPMNES1)GetProcAddress (hlib, "FwpmNetEventSubscribe1");
|
|
const FWPMNES0 _FwpmNetEventSubscribe0 = (FWPMNES0)GetProcAddress (hlib, "FwpmNetEventSubscribe0");
|
|
|
|
if (_FwpmNetEventSubscribe4 || _FwpmNetEventSubscribe3 || _FwpmNetEventSubscribe2 || _FwpmNetEventSubscribe1 || _FwpmNetEventSubscribe0)
|
|
{
|
|
FWPM_NET_EVENT_SUBSCRIPTION subscription;
|
|
FWPM_NET_EVENT_ENUM_TEMPLATE enum_template;
|
|
|
|
RtlSecureZeroMemory (&subscription, sizeof (subscription));
|
|
RtlSecureZeroMemory (&enum_template, sizeof (enum_template));
|
|
|
|
//enum_template.numFilterConditions = 0; // get events for all conditions
|
|
|
|
subscription.enumTemplate = &enum_template;
|
|
|
|
ULONG code;
|
|
|
|
if (_FwpmNetEventSubscribe4)
|
|
code = _FwpmNetEventSubscribe4 (hengine, &subscription, &_wfp_logcallback4, NULL, &config.hnetevent); // win10rs5+
|
|
|
|
else if (_FwpmNetEventSubscribe3)
|
|
code = _FwpmNetEventSubscribe3 (hengine, &subscription, &_wfp_logcallback3, NULL, &config.hnetevent); // win10rs4+
|
|
|
|
else if (_FwpmNetEventSubscribe2)
|
|
code = _FwpmNetEventSubscribe2 (hengine, &subscription, &_wfp_logcallback2, NULL, &config.hnetevent); // win10rs1+
|
|
|
|
else if (_FwpmNetEventSubscribe1)
|
|
code = _FwpmNetEventSubscribe1 (hengine, &subscription, &_wfp_logcallback1, NULL, &config.hnetevent); // win8+
|
|
|
|
else if (_FwpmNetEventSubscribe0)
|
|
code = _FwpmNetEventSubscribe0 (hengine, &subscription, &_wfp_logcallback0, NULL, &config.hnetevent); // win7+
|
|
|
|
else
|
|
code = ERROR_INVALID_FUNCTION;
|
|
|
|
if (code != ERROR_SUCCESS)
|
|
{
|
|
_r_logerror (0, L"FwpmNetEventSubscribe", code, NULL);
|
|
}
|
|
else
|
|
{
|
|
_app_loginit (TRUE); // create log file
|
|
}
|
|
}
|
|
|
|
FreeLibrary (hlib);
|
|
}
|
|
}
|
|
|
|
VOID _wfp_logunsubscribe (HANDLE hengine)
|
|
{
|
|
if (config.hnetevent)
|
|
{
|
|
_app_loginit (FALSE); // destroy log file handle if present
|
|
|
|
ULONG code = FwpmNetEventUnsubscribe (hengine, config.hnetevent);
|
|
|
|
if (code == ERROR_SUCCESS)
|
|
config.hnetevent = NULL;
|
|
}
|
|
}
|
|
|
|
VOID CALLBACK _wfp_logcallback (UINT32 flags, FILETIME const* pft, UINT8 const* app_id, SID* package_id, SID* user_id, UINT8 proto, FWP_IP_VERSION ipver, UINT32 remote_addr4, FWP_BYTE_ARRAY16 const* remote_addr6, UINT16 remote_port, UINT32 local_addr4, FWP_BYTE_ARRAY16 const* local_addr6, UINT16 local_port, UINT16 layer_id, UINT64 filter_id, UINT32 direction, BOOLEAN is_allow, BOOLEAN is_loopback)
|
|
{
|
|
HANDLE hengine = _wfp_getenginehandle ();
|
|
|
|
if (!hengine || !filter_id || !layer_id || _wfp_isfiltersapplying () || (is_allow && _r_config_getboolean (L"IsExcludeClassifyAllow", TRUE)))
|
|
return;
|
|
|
|
// set allowed directions
|
|
switch (direction)
|
|
{
|
|
case FWP_DIRECTION_IN:
|
|
case FWP_DIRECTION_INBOUND:
|
|
case FWP_DIRECTION_OUT:
|
|
case FWP_DIRECTION_OUTBOUND:
|
|
{
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
// do not parse when tcp connection has been established, or when non-tcp traffic has been authorized
|
|
{
|
|
FWPM_LAYER *layer = NULL;
|
|
|
|
if (FwpmLayerGetById (hengine, layer_id, &layer) == ERROR_SUCCESS && layer)
|
|
{
|
|
if (RtlEqualMemory (&layer->layerKey, &FWPM_LAYER_ALE_FLOW_ESTABLISHED_V4, sizeof (GUID)) || RtlEqualMemory (&layer->layerKey, &FWPM_LAYER_ALE_FLOW_ESTABLISHED_V6, sizeof (GUID)))
|
|
{
|
|
FwpmFreeMemory ((PVOID*)&layer);
|
|
return;
|
|
}
|
|
else if (RtlEqualMemory (&layer->layerKey, &FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4, sizeof (GUID)) || RtlEqualMemory (&layer->layerKey, &FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6, sizeof (GUID)))
|
|
{
|
|
direction = FWP_DIRECTION_INBOUND; // HACK!!! (issue #581)
|
|
}
|
|
|
|
FwpmFreeMemory ((PVOID*)&layer);
|
|
}
|
|
}
|
|
|
|
// get filter information
|
|
BOOLEAN is_myprovider = FALSE;
|
|
|
|
PR_STRING filterName = NULL;
|
|
PR_STRING providerName = NULL;
|
|
|
|
UINT8 filter_weight = 0;
|
|
|
|
{
|
|
FWPM_FILTER *ptr_filter = NULL;
|
|
FWPM_PROVIDER *ptr_provider = NULL;
|
|
|
|
if (FwpmFilterGetById (hengine, filter_id, &ptr_filter) == ERROR_SUCCESS && ptr_filter)
|
|
{
|
|
if (!_r_str_isempty (ptr_filter->displayData.description))
|
|
filterName = _r_obj_createstring (ptr_filter->displayData.description);
|
|
|
|
else if (!_r_str_isempty (ptr_filter->displayData.name))
|
|
filterName = _r_obj_createstring (ptr_filter->displayData.name);
|
|
|
|
if (ptr_filter->weight.type == FWP_UINT8)
|
|
filter_weight = ptr_filter->weight.uint8;
|
|
|
|
if (ptr_filter->providerKey)
|
|
{
|
|
if (RtlEqualMemory (ptr_filter->providerKey, &GUID_WfpProvider, sizeof (GUID)))
|
|
is_myprovider = TRUE;
|
|
|
|
if (FwpmProviderGetByKey (hengine, ptr_filter->providerKey, &ptr_provider) == ERROR_SUCCESS && ptr_provider)
|
|
{
|
|
if (!_r_str_isempty (ptr_provider->displayData.name))
|
|
providerName = _r_obj_createstring (ptr_provider->displayData.name);
|
|
|
|
else if (!_r_str_isempty (ptr_provider->displayData.description))
|
|
providerName = _r_obj_createstring (ptr_provider->displayData.description);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (ptr_filter)
|
|
FwpmFreeMemory ((PVOID*)&ptr_filter);
|
|
|
|
if (ptr_provider)
|
|
FwpmFreeMemory ((PVOID*)&ptr_provider);
|
|
|
|
// prevent filter "not found" items
|
|
if (!filterName && !providerName)
|
|
return;
|
|
}
|
|
|
|
PITEM_LOG_LISTENTRY ptr_entry = (PITEM_LOG_LISTENTRY)_aligned_malloc (sizeof (ITEM_LOG_LISTENTRY), MEMORY_ALLOCATION_ALIGNMENT);
|
|
|
|
if (!ptr_entry)
|
|
return;
|
|
|
|
PITEM_LOG ptr_log = (PITEM_LOG)_r_obj_allocateex (sizeof (ITEM_LOG), &_app_dereferencelog);
|
|
|
|
// get package id (win8+)
|
|
PR_STRING sidString = NULL;
|
|
|
|
if ((flags & FWPM_NET_EVENT_FLAG_PACKAGE_ID_SET) != 0 && package_id)
|
|
{
|
|
sidString = _r_str_fromsid (package_id);
|
|
|
|
if (sidString)
|
|
{
|
|
if (!_app_item_get (DataAppUWP, _r_str_hash (sidString), NULL, NULL, NULL, NULL))
|
|
_r_obj_clearreference (&sidString);
|
|
}
|
|
}
|
|
|
|
// copy converted nt device path into win32
|
|
if ((flags & FWPM_NET_EVENT_FLAG_PACKAGE_ID_SET) != 0 && sidString)
|
|
{
|
|
_r_obj_movereference (&ptr_log->path, sidString);
|
|
ptr_log->app_hash = _r_str_hash (ptr_log->path);
|
|
|
|
sidString = NULL;
|
|
}
|
|
else if ((flags & FWPM_NET_EVENT_FLAG_APP_ID_SET) != 0 && app_id)
|
|
{
|
|
PR_STRING path = _r_path_dospathfromnt ((LPCWSTR)app_id);
|
|
|
|
if (path)
|
|
{
|
|
_r_obj_movereference (&ptr_log->path, path);
|
|
ptr_log->app_hash = _r_str_hash (ptr_log->path);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ptr_log->app_hash = 0;
|
|
}
|
|
|
|
if (sidString)
|
|
_r_obj_clearreference (&sidString);
|
|
|
|
// copy date and time
|
|
if (pft)
|
|
ptr_log->timestamp = _r_unixtime_from_filetime (pft);
|
|
|
|
// get username information
|
|
if ((flags & FWPM_NET_EVENT_FLAG_USER_ID_SET) != 0 && user_id)
|
|
ptr_log->username = _r_sys_getusernamefromsid (user_id);
|
|
|
|
// indicates the direction of the packet transmission
|
|
switch (direction)
|
|
{
|
|
case FWP_DIRECTION_IN:
|
|
case FWP_DIRECTION_INBOUND:
|
|
{
|
|
ptr_log->direction = FWP_DIRECTION_INBOUND;
|
|
break;
|
|
}
|
|
|
|
case FWP_DIRECTION_OUT:
|
|
case FWP_DIRECTION_OUTBOUND:
|
|
{
|
|
ptr_log->direction = FWP_DIRECTION_OUTBOUND;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// destination
|
|
if ((flags & FWPM_NET_EVENT_FLAG_IP_VERSION_SET) != 0)
|
|
{
|
|
if (ipver == FWP_IP_VERSION_V4)
|
|
{
|
|
ptr_log->af = AF_INET;
|
|
|
|
// remote address
|
|
if ((flags & FWPM_NET_EVENT_FLAG_REMOTE_ADDR_SET) != 0 && remote_addr4)
|
|
ptr_log->remote_addr.S_un.S_addr = _r_byteswap_ulong (remote_addr4);
|
|
|
|
// local address
|
|
if ((flags & FWPM_NET_EVENT_FLAG_LOCAL_ADDR_SET) != 0 && local_addr4)
|
|
ptr_log->local_addr.S_un.S_addr = _r_byteswap_ulong (local_addr4);
|
|
}
|
|
else if (ipver == FWP_IP_VERSION_V6)
|
|
{
|
|
ptr_log->af = AF_INET6;
|
|
|
|
// remote address
|
|
if ((flags & FWPM_NET_EVENT_FLAG_REMOTE_ADDR_SET) != 0 && remote_addr6)
|
|
RtlCopyMemory (ptr_log->remote_addr6.u.Byte, remote_addr6->byteArray16, FWP_V6_ADDR_SIZE);
|
|
|
|
// local address
|
|
if ((flags & FWPM_NET_EVENT_FLAG_LOCAL_ADDR_SET) != 0 && local_addr6)
|
|
RtlCopyMemory (ptr_log->local_addr6.u.Byte, local_addr6->byteArray16, FWP_V6_ADDR_SIZE);
|
|
}
|
|
|
|
if ((flags & FWPM_NET_EVENT_FLAG_REMOTE_PORT_SET) != 0 && remote_port)
|
|
ptr_log->remote_port = remote_port;
|
|
|
|
if ((flags & FWPM_NET_EVENT_FLAG_LOCAL_PORT_SET) != 0 && local_port)
|
|
ptr_log->local_port = local_port;
|
|
}
|
|
|
|
// protocol
|
|
if ((flags & FWPM_NET_EVENT_FLAG_IP_PROTOCOL_SET) != 0)
|
|
ptr_log->protocol = proto;
|
|
|
|
// indicates FWPM_NET_EVENT_TYPE_CLASSIFY_ALLOW state
|
|
ptr_log->is_allow = is_allow;
|
|
|
|
// indicates whether the packet originated from (or was heading to) the loopback adapter
|
|
ptr_log->is_loopback = is_loopback;
|
|
|
|
// set filter information
|
|
ptr_log->filter_id = filter_id;
|
|
|
|
ptr_log->is_myprovider = is_myprovider;
|
|
|
|
_r_obj_movereference (&ptr_log->filter_name, filterName);
|
|
_r_obj_movereference (&ptr_log->provider_name, providerName);
|
|
|
|
ptr_log->is_blocklist = (filter_weight == FILTER_WEIGHT_BLOCKLIST);
|
|
ptr_log->is_system = (filter_weight == FILTER_WEIGHT_HIGHEST) || (filter_weight == FILTER_WEIGHT_HIGHEST_IMPORTANT);
|
|
ptr_log->is_custom = (filter_weight == FILTER_WEIGHT_CUSTOM) || (filter_weight == FILTER_WEIGHT_CUSTOM_BLOCK);
|
|
|
|
// push into a slist
|
|
{
|
|
ptr_entry->Body = ptr_log;
|
|
|
|
RtlInterlockedPushEntrySList (&log_stack.ListHead, &ptr_entry->ListEntry);
|
|
InterlockedIncrement (&log_stack.item_count);
|
|
|
|
// check if thread has been terminated
|
|
LONG thread_count = InterlockedCompareExchange (&log_stack.thread_count, 0, 0);
|
|
|
|
if (!thread_count || !_r_fastlock_islocked (&lock_logthread))
|
|
{
|
|
_app_freethreadpool (&threads_pool);
|
|
|
|
HANDLE hthread = _r_sys_createthreadex (&LogThread, _r_app_gethwnd (), TRUE, THREAD_PRIORITY_HIGHEST);
|
|
|
|
if (hthread)
|
|
{
|
|
InterlockedIncrement (&log_stack.thread_count);
|
|
|
|
threads_pool.emplace_back (hthread);
|
|
|
|
NtResumeThread (hthread, NULL);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// win7+ callback
|
|
VOID CALLBACK _wfp_logcallback0 (PVOID pContext, const FWPM_NET_EVENT1* pEvent)
|
|
{
|
|
UINT16 layer_id;
|
|
UINT64 filter_id;
|
|
UINT32 direction;
|
|
BOOLEAN is_loopback;
|
|
|
|
if (pEvent->type == FWPM_NET_EVENT_TYPE_CLASSIFY_DROP && pEvent->classifyDrop)
|
|
{
|
|
layer_id = pEvent->classifyDrop->layerId;
|
|
filter_id = pEvent->classifyDrop->filterId;
|
|
direction = pEvent->classifyDrop->msFwpDirection;
|
|
is_loopback = !!pEvent->classifyDrop->isLoopback;
|
|
}
|
|
else if (pEvent->type == FWPM_NET_EVENT_TYPE_IPSEC_KERNEL_DROP && pEvent->ipsecDrop)
|
|
{
|
|
layer_id = pEvent->ipsecDrop->layerId;
|
|
filter_id = pEvent->ipsecDrop->filterId;
|
|
direction = pEvent->ipsecDrop->direction;
|
|
is_loopback = FALSE;
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
|
|
_wfp_logcallback (pEvent->header.flags, &pEvent->header.timeStamp, pEvent->header.appId.data, NULL, pEvent->header.userId, pEvent->header.ipProtocol, pEvent->header.ipVersion, pEvent->header.remoteAddrV4, &pEvent->header.remoteAddrV6, pEvent->header.remotePort, pEvent->header.localAddrV4, &pEvent->header.localAddrV6, pEvent->header.localPort, layer_id, filter_id, direction, FALSE, is_loopback);
|
|
}
|
|
|
|
// win8+ callback
|
|
VOID CALLBACK _wfp_logcallback1 (PVOID pContext, const FWPM_NET_EVENT2* pEvent)
|
|
{
|
|
UINT16 layer_id;
|
|
UINT64 filter_id;
|
|
UINT32 direction;
|
|
|
|
BOOLEAN is_loopback;
|
|
BOOLEAN is_allow = FALSE;
|
|
|
|
if (pEvent->type == FWPM_NET_EVENT_TYPE_CLASSIFY_DROP && pEvent->classifyDrop)
|
|
{
|
|
layer_id = pEvent->classifyDrop->layerId;
|
|
filter_id = pEvent->classifyDrop->filterId;
|
|
direction = pEvent->classifyDrop->msFwpDirection;
|
|
is_loopback = !!pEvent->classifyDrop->isLoopback;
|
|
}
|
|
else if (pEvent->type == FWPM_NET_EVENT_TYPE_IPSEC_KERNEL_DROP && pEvent->ipsecDrop)
|
|
{
|
|
layer_id = pEvent->ipsecDrop->layerId;
|
|
filter_id = pEvent->ipsecDrop->filterId;
|
|
direction = pEvent->ipsecDrop->direction;
|
|
is_loopback = FALSE;
|
|
}
|
|
else if (pEvent->type == FWPM_NET_EVENT_TYPE_CLASSIFY_ALLOW && pEvent->classifyAllow)
|
|
{
|
|
layer_id = pEvent->classifyAllow->layerId;
|
|
filter_id = pEvent->classifyAllow->filterId;
|
|
direction = pEvent->classifyAllow->msFwpDirection;
|
|
is_loopback = !!pEvent->classifyAllow->isLoopback;
|
|
|
|
is_allow = TRUE;
|
|
}
|
|
else if (pEvent->type == FWPM_NET_EVENT_TYPE_CLASSIFY_DROP_MAC && pEvent->classifyDropMac)
|
|
{
|
|
layer_id = pEvent->classifyDropMac->layerId;
|
|
filter_id = pEvent->classifyDropMac->filterId;
|
|
direction = pEvent->classifyDropMac->msFwpDirection;
|
|
is_loopback = !!pEvent->classifyDropMac->isLoopback;
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
|
|
_wfp_logcallback (pEvent->header.flags, &pEvent->header.timeStamp, pEvent->header.appId.data, pEvent->header.packageSid, pEvent->header.userId, pEvent->header.ipProtocol, pEvent->header.ipVersion, pEvent->header.remoteAddrV4, &pEvent->header.remoteAddrV6, pEvent->header.remotePort, pEvent->header.localAddrV4, &pEvent->header.localAddrV6, pEvent->header.localPort, layer_id, filter_id, direction, is_allow, is_loopback);
|
|
}
|
|
|
|
// win10rs1+ callback
|
|
VOID CALLBACK _wfp_logcallback2 (PVOID pContext, const FWPM_NET_EVENT3* pEvent)
|
|
{
|
|
UINT16 layer_id;
|
|
UINT64 filter_id;
|
|
UINT32 direction;
|
|
|
|
BOOLEAN is_loopback;
|
|
BOOLEAN is_allow = FALSE;
|
|
|
|
if (pEvent->type == FWPM_NET_EVENT_TYPE_CLASSIFY_DROP && pEvent->classifyDrop)
|
|
{
|
|
layer_id = pEvent->classifyDrop->layerId;
|
|
filter_id = pEvent->classifyDrop->filterId;
|
|
direction = pEvent->classifyDrop->msFwpDirection;
|
|
is_loopback = !!pEvent->classifyDrop->isLoopback;
|
|
}
|
|
else if (pEvent->type == FWPM_NET_EVENT_TYPE_IPSEC_KERNEL_DROP && pEvent->ipsecDrop)
|
|
{
|
|
layer_id = pEvent->ipsecDrop->layerId;
|
|
filter_id = pEvent->ipsecDrop->filterId;
|
|
direction = pEvent->ipsecDrop->direction;
|
|
is_loopback = FALSE;
|
|
}
|
|
else if (pEvent->type == FWPM_NET_EVENT_TYPE_CLASSIFY_ALLOW && pEvent->classifyAllow)
|
|
{
|
|
layer_id = pEvent->classifyAllow->layerId;
|
|
filter_id = pEvent->classifyAllow->filterId;
|
|
direction = pEvent->classifyAllow->msFwpDirection;
|
|
is_loopback = !!pEvent->classifyAllow->isLoopback;
|
|
|
|
is_allow = TRUE;
|
|
}
|
|
else if (pEvent->type == FWPM_NET_EVENT_TYPE_CLASSIFY_DROP_MAC && pEvent->classifyDropMac)
|
|
{
|
|
layer_id = pEvent->classifyDropMac->layerId;
|
|
filter_id = pEvent->classifyDropMac->filterId;
|
|
direction = pEvent->classifyDropMac->msFwpDirection;
|
|
is_loopback = !!pEvent->classifyDropMac->isLoopback;
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
|
|
_wfp_logcallback (pEvent->header.flags, &pEvent->header.timeStamp, pEvent->header.appId.data, pEvent->header.packageSid, pEvent->header.userId, pEvent->header.ipProtocol, pEvent->header.ipVersion, pEvent->header.remoteAddrV4, &pEvent->header.remoteAddrV6, pEvent->header.remotePort, pEvent->header.localAddrV4, &pEvent->header.localAddrV6, pEvent->header.localPort, layer_id, filter_id, direction, is_allow, is_loopback);
|
|
}
|
|
|
|
// win10rs4+ callback
|
|
VOID CALLBACK _wfp_logcallback3 (PVOID pContext, const FWPM_NET_EVENT4* pEvent)
|
|
{
|
|
UINT16 layer_id;
|
|
UINT64 filter_id;
|
|
UINT32 direction;
|
|
|
|
BOOLEAN is_loopback;
|
|
BOOLEAN is_allow = FALSE;
|
|
|
|
if (pEvent->type == FWPM_NET_EVENT_TYPE_CLASSIFY_DROP && pEvent->classifyDrop)
|
|
{
|
|
layer_id = pEvent->classifyDrop->layerId;
|
|
filter_id = pEvent->classifyDrop->filterId;
|
|
direction = pEvent->classifyDrop->msFwpDirection;
|
|
is_loopback = !!pEvent->classifyDrop->isLoopback;
|
|
}
|
|
else if (pEvent->type == FWPM_NET_EVENT_TYPE_IPSEC_KERNEL_DROP && pEvent->ipsecDrop)
|
|
{
|
|
layer_id = pEvent->ipsecDrop->layerId;
|
|
filter_id = pEvent->ipsecDrop->filterId;
|
|
direction = pEvent->ipsecDrop->direction;
|
|
is_loopback = FALSE;
|
|
}
|
|
else if (pEvent->type == FWPM_NET_EVENT_TYPE_CLASSIFY_ALLOW && pEvent->classifyAllow)
|
|
{
|
|
layer_id = pEvent->classifyAllow->layerId;
|
|
filter_id = pEvent->classifyAllow->filterId;
|
|
direction = pEvent->classifyAllow->msFwpDirection;
|
|
is_loopback = !!pEvent->classifyAllow->isLoopback;
|
|
|
|
is_allow = TRUE;
|
|
}
|
|
else if (pEvent->type == FWPM_NET_EVENT_TYPE_CLASSIFY_DROP_MAC && pEvent->classifyDropMac)
|
|
{
|
|
layer_id = pEvent->classifyDropMac->layerId;
|
|
filter_id = pEvent->classifyDropMac->filterId;
|
|
direction = pEvent->classifyDropMac->msFwpDirection;
|
|
is_loopback = !!pEvent->classifyDropMac->isLoopback;
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
|
|
_wfp_logcallback (pEvent->header.flags, &pEvent->header.timeStamp, pEvent->header.appId.data, pEvent->header.packageSid, pEvent->header.userId, pEvent->header.ipProtocol, pEvent->header.ipVersion, pEvent->header.remoteAddrV4, &pEvent->header.remoteAddrV6, pEvent->header.remotePort, pEvent->header.localAddrV4, &pEvent->header.localAddrV6, pEvent->header.localPort, layer_id, filter_id, direction, is_allow, is_loopback);
|
|
}
|
|
|
|
// win10rs5+ callback
|
|
VOID CALLBACK _wfp_logcallback4 (PVOID pContext, const FWPM_NET_EVENT5* pEvent)
|
|
{
|
|
UINT16 layer_id;
|
|
UINT64 filter_id;
|
|
UINT32 direction;
|
|
|
|
BOOLEAN is_loopback;
|
|
BOOLEAN is_allow = FALSE;
|
|
|
|
if (pEvent->type == FWPM_NET_EVENT_TYPE_CLASSIFY_DROP && pEvent->classifyDrop)
|
|
{
|
|
layer_id = pEvent->classifyDrop->layerId;
|
|
filter_id = pEvent->classifyDrop->filterId;
|
|
direction = pEvent->classifyDrop->msFwpDirection;
|
|
is_loopback = !!pEvent->classifyDrop->isLoopback;
|
|
}
|
|
else if (pEvent->type == FWPM_NET_EVENT_TYPE_IPSEC_KERNEL_DROP && pEvent->ipsecDrop)
|
|
{
|
|
layer_id = pEvent->ipsecDrop->layerId;
|
|
filter_id = pEvent->ipsecDrop->filterId;
|
|
direction = pEvent->ipsecDrop->direction;
|
|
is_loopback = FALSE;
|
|
}
|
|
else if (pEvent->type == FWPM_NET_EVENT_TYPE_CLASSIFY_ALLOW && pEvent->classifyAllow)
|
|
{
|
|
layer_id = pEvent->classifyAllow->layerId;
|
|
filter_id = pEvent->classifyAllow->filterId;
|
|
direction = pEvent->classifyAllow->msFwpDirection;
|
|
is_loopback = !!pEvent->classifyAllow->isLoopback;
|
|
|
|
is_allow = TRUE;
|
|
}
|
|
else if (pEvent->type == FWPM_NET_EVENT_TYPE_CLASSIFY_DROP_MAC && pEvent->classifyDropMac)
|
|
{
|
|
layer_id = pEvent->classifyDropMac->layerId;
|
|
filter_id = pEvent->classifyDropMac->filterId;
|
|
direction = pEvent->classifyDropMac->msFwpDirection;
|
|
is_loopback = !!pEvent->classifyDropMac->isLoopback;
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
|
|
_wfp_logcallback (pEvent->header.flags, &pEvent->header.timeStamp, pEvent->header.appId.data, pEvent->header.packageSid, pEvent->header.userId, pEvent->header.ipProtocol, pEvent->header.ipVersion, pEvent->header.remoteAddrV4, &pEvent->header.remoteAddrV6, pEvent->header.remotePort, pEvent->header.localAddrV4, &pEvent->header.localAddrV6, pEvent->header.localPort, layer_id, filter_id, direction, is_allow, is_loopback);
|
|
}
|
|
|
|
THREAD_FN LogThread (PVOID lparam)
|
|
{
|
|
HWND hwnd = (HWND)lparam;
|
|
|
|
_r_fastlock_acquireshared (&lock_logthread);
|
|
|
|
while (TRUE)
|
|
{
|
|
PSLIST_ENTRY listEntry = RtlInterlockedPopEntrySList (&log_stack.ListHead);
|
|
|
|
if (!listEntry)
|
|
break;
|
|
|
|
InterlockedDecrement (&log_stack.item_count);
|
|
|
|
PITEM_LOG_LISTENTRY ptr_entry = CONTAINING_RECORD (listEntry, ITEM_LOG_LISTENTRY, ListEntry);
|
|
PITEM_LOG ptr_log = (PITEM_LOG)ptr_entry->Body;
|
|
|
|
_aligned_free (ptr_entry);
|
|
|
|
if (!ptr_log)
|
|
continue;
|
|
|
|
BOOLEAN is_logenabled = _r_config_getboolean (L"IsLogEnabled", FALSE);
|
|
BOOLEAN is_loguienabled = _r_config_getboolean (L"IsLogUiEnabled", FALSE);
|
|
BOOLEAN is_notificationenabled = _r_config_getboolean (L"IsNotificationsEnabled", TRUE);
|
|
|
|
BOOLEAN is_exludestealth = !(ptr_log->is_system && _r_config_getboolean (L"IsExcludeStealth", TRUE));
|
|
|
|
// apps collector
|
|
BOOLEAN is_notexist = ptr_log->app_hash && !_r_str_isempty (ptr_log->path) && !ptr_log->is_allow && !_app_isappfound (ptr_log->app_hash);
|
|
|
|
if (is_notexist)
|
|
{
|
|
_r_fastlock_acquireshared (&lock_logbusy);
|
|
ptr_log->app_hash = _app_addapplication (hwnd, ptr_log->path->Buffer, 0, 0, 0, FALSE, FALSE);
|
|
_r_fastlock_releaseshared (&lock_logbusy);
|
|
|
|
INT app_listview_id = (INT)_app_getappinfo (ptr_log->app_hash, InfoListviewId);
|
|
|
|
if (app_listview_id && app_listview_id == (INT)_r_tab_getlparam (hwnd, IDC_TAB, INVALID_INT))
|
|
{
|
|
_app_listviewsort (hwnd, app_listview_id, INVALID_INT, FALSE);
|
|
_app_refreshstatus (hwnd, app_listview_id);
|
|
}
|
|
|
|
_app_profile_save ();
|
|
}
|
|
|
|
// made network name resolution
|
|
{
|
|
_r_fastlock_acquireshared (&lock_logbusy);
|
|
|
|
PR_STRING addressFormat;
|
|
|
|
addressFormat = _app_formataddress (ptr_log->af, ptr_log->protocol, &ptr_log->remote_addr, 0, FMTADDR_RESOLVE_HOST);
|
|
SAFE_DELETE_REFERENCE (addressFormat);
|
|
|
|
addressFormat = _app_formataddress (ptr_log->af, ptr_log->protocol, &ptr_log->local_addr, 0, FMTADDR_RESOLVE_HOST);
|
|
SAFE_DELETE_REFERENCE (addressFormat);
|
|
|
|
_r_fastlock_releaseshared (&lock_logbusy);
|
|
}
|
|
|
|
if ((is_logenabled || is_loguienabled || is_notificationenabled) && is_exludestealth)
|
|
{
|
|
// write log to a file
|
|
if (is_logenabled)
|
|
_app_logwrite (ptr_log);
|
|
|
|
// only for my own provider
|
|
if (ptr_log->is_myprovider)
|
|
{
|
|
// write log to a ui
|
|
if (is_loguienabled)
|
|
_app_logwrite_ui (hwnd, ptr_log);
|
|
|
|
// display notification
|
|
if (is_notificationenabled && ptr_log->app_hash && !ptr_log->is_allow)
|
|
{
|
|
if (!(ptr_log->is_blocklist && _r_config_getboolean (L"IsExcludeBlocklist", TRUE)) && !(ptr_log->is_custom && _r_config_getboolean (L"IsExcludeCustomRules", TRUE)))
|
|
{
|
|
PITEM_APP ptr_app = _app_getappitem (ptr_log->app_hash);
|
|
|
|
if (ptr_app)
|
|
{
|
|
if (!ptr_app->is_silent)
|
|
_app_notifyadd (config.hnotification, (PITEM_LOG)_r_obj_reference (ptr_log), ptr_app);
|
|
|
|
_r_obj_dereference (ptr_app);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
_r_obj_dereference (ptr_log);
|
|
}
|
|
|
|
_r_fastlock_releaseshared (&lock_logthread);
|
|
|
|
InterlockedDecrement (&log_stack.thread_count);
|
|
|
|
return _r_sys_endthread (ERROR_SUCCESS);
|
|
}
|