Files
simplewall/src/helper.cpp
T
2020-08-05 15:40:30 +06:00

3188 lines
69 KiB
C++

// simplewall
// Copyright (c) 2016-2020 Henry++
#include "global.hpp"
VOID NTAPI _app_dereferenceapp (PVOID pdata)
{
PITEM_APP ptr_item = (PITEM_APP)pdata;
SAFE_DELETE_REFERENCE (ptr_item->display_name);
SAFE_DELETE_REFERENCE (ptr_item->real_path);
SAFE_DELETE_REFERENCE (ptr_item->original_path);
SAFE_DELETE_REFERENCE (ptr_item->pnotification);
delete ptr_item->guids;
}
VOID NTAPI _app_dereferenceappshelper (PVOID pdata)
{
PITEM_APP_HELPER ptr_item = (PITEM_APP_HELPER)pdata;
SAFE_DELETE_REFERENCE (ptr_item->display_name);
SAFE_DELETE_REFERENCE (ptr_item->real_path);
SAFE_DELETE_REFERENCE (ptr_item->internal_name);
SAFE_DELETE_MEMORY (ptr_item->pdata);
}
VOID NTAPI _app_dereferencelog (PVOID pdata)
{
PITEM_LOG ptr_item = (PITEM_LOG)pdata;
SAFE_DELETE_REFERENCE (ptr_item->path);
SAFE_DELETE_REFERENCE (ptr_item->provider_name);
SAFE_DELETE_REFERENCE (ptr_item->filter_name);
SAFE_DELETE_REFERENCE (ptr_item->username);
SAFE_DELETE_ICON (ptr_item->hicon);
}
VOID NTAPI _app_dereferencenetwork (PVOID pdata)
{
PITEM_NETWORK ptr_item = (PITEM_NETWORK)pdata;
SAFE_DELETE_REFERENCE (ptr_item->path);
}
VOID NTAPI _app_dereferencerule (PVOID pdata)
{
PITEM_RULE ptr_item = (PITEM_RULE)pdata;
SAFE_DELETE_REFERENCE (ptr_item->name);
SAFE_DELETE_REFERENCE (ptr_item->rule_remote);
SAFE_DELETE_REFERENCE (ptr_item->rule_local);
delete ptr_item->apps;
delete ptr_item->guids;
}
VOID NTAPI _app_dereferenceruleconfig (PVOID pdata)
{
PITEM_RULE_CONFIG ptr_item = (PITEM_RULE_CONFIG)pdata;
SAFE_DELETE_REFERENCE (ptr_item->name);
SAFE_DELETE_REFERENCE (ptr_item->apps);
}
PR_STRING _app_resolveaddress (ADDRESS_FAMILY af, LPCVOID paddr)
{
PR_STRING arpaString = _app_formataddress (af, 0, paddr, 0, FMTADDR_AS_ARPA);
PR_STRING domainString = NULL;
if (arpaString)
{
SIZE_T arpa_hash = _r_str_hash (arpaString);
BOOLEAN is_exists = cache_arpa.find (arpa_hash) != cache_arpa.end ();
if (is_exists)
{
PR_STRING pdata = cache_arpa[arpa_hash];
if (pdata)
domainString = _r_obj_reference (pdata);
}
else
{
cache_arpa[arpa_hash] = NULL;
PDNS_RECORD ppQueryResultsSet = NULL;
DNS_STATUS dnsStatus = DnsQuery (_r_obj_getstring (arpaString), DNS_TYPE_PTR, DNS_QUERY_NO_HOSTS_FILE, NULL, &ppQueryResultsSet, NULL);
if (dnsStatus == DNS_ERROR_RCODE_NO_ERROR)
{
if (ppQueryResultsSet)
{
if (!_r_str_isempty (ppQueryResultsSet->Data.PTR.pNameHost))
{
domainString = _r_obj_createstring (ppQueryResultsSet->Data.PTR.pNameHost);
PR_STRING arpaCacheString = _r_obj_createstring2 (domainString);
_app_freestrings_map (&cache_arpa, MAP_CACHE_MAX);
cache_arpa[arpa_hash] = arpaCacheString;
}
DnsRecordListFree (ppQueryResultsSet, DnsFreeRecordList);
}
}
}
}
SAFE_DELETE_REFERENCE (arpaString);
return domainString;
}
PR_STRING _app_formataddress (ADDRESS_FAMILY af, UINT8 proto, LPCVOID paddr, UINT16 port, DWORD flags)
{
BOOLEAN is_success = FALSE;
WCHAR formatted_address[DNS_MAX_NAME_BUFFER_LENGTH] = {0};
PIN_ADDR p4addr = (PIN_ADDR)paddr;
PIN6_ADDR p6addr = (PIN6_ADDR)paddr;
if ((flags & FMTADDR_AS_ARPA) != 0)
{
if (af == AF_INET)
{
_r_str_appendformat (formatted_address, RTL_NUMBER_OF (formatted_address), L"%hhu.%hhu.%hhu.%hhu.%s", p4addr->s_impno, p4addr->s_lh, p4addr->s_host, p4addr->s_net, DNS_IP4_REVERSE_DOMAIN_STRING_W);
}
else if (af == AF_INET6)
{
for (INT i = sizeof (IN6_ADDR) - 1; i >= 0; i--)
_r_str_appendformat (formatted_address, RTL_NUMBER_OF (formatted_address), L"%hhx.%hhx.", p6addr->s6_addr[i] & 0xF, (p6addr->s6_addr[i] >> 4) & 0xF);
_r_str_append (formatted_address, RTL_NUMBER_OF (formatted_address), DNS_IP6_REVERSE_DOMAIN_STRING_W);
}
is_success = TRUE;
}
else
{
if ((flags & FMTADDR_USE_PROTOCOL) != 0)
{
_r_str_printf (formatted_address, RTL_NUMBER_OF (formatted_address), L"%s://", _app_getprotoname (proto, AF_UNSPEC, SZ_UNKNOWN));
}
WCHAR addr_str[DNS_MAX_NAME_BUFFER_LENGTH] = {0};
if (_app_formatip (af, paddr, addr_str, RTL_NUMBER_OF (addr_str), (flags & FMTADDR_AS_RULE) != 0))
{
if (af == AF_INET6 && port)
{
_r_str_appendformat (formatted_address, RTL_NUMBER_OF (formatted_address), L"[%s]", addr_str);
}
else
{
_r_str_append (formatted_address, RTL_NUMBER_OF (formatted_address), addr_str);
}
is_success = TRUE;
}
if (port && (flags & FMTADDR_USE_PROTOCOL) == 0)
{
_r_str_appendformat (formatted_address, RTL_NUMBER_OF (formatted_address), !_r_str_isempty (formatted_address) ? L":%" TEXT (PRIu16) : L"%" TEXT (PRIu16), port);
is_success = TRUE;
}
}
if ((flags & FMTADDR_RESOLVE_HOST) != 0)
{
if (is_success && _r_config_getboolean (L"IsNetworkResolutionsEnabled", FALSE))
{
SIZE_T addr_hash = _r_str_hash (formatted_address);
BOOLEAN is_exists = cache_hosts.find (addr_hash) != cache_hosts.end ();
if (is_exists)
{
PR_STRING pdata = cache_hosts[addr_hash];
if (pdata)
{
PR_STRING addressString = _r_obj_reference (pdata);
_r_str_appendformat (formatted_address, RTL_NUMBER_OF (formatted_address), L" (%s)", _r_obj_getstring (addressString));
_r_obj_dereference (addressString);
}
}
else
{
cache_hosts[addr_hash] = NULL;
PR_STRING domainString = _app_resolveaddress (af, paddr);
if (domainString)
{
_app_freestrings_map (&cache_hosts, MAP_CACHE_MAX);
_r_str_appendformat (formatted_address, RTL_NUMBER_OF (formatted_address), L" (%s)", _r_obj_getstring (domainString));
_r_obj_movereference (&cache_hosts[addr_hash], domainString);
}
}
}
}
if (is_success)
return _r_obj_createstring (formatted_address);
return NULL;
}
BOOLEAN _app_formatip (ADDRESS_FAMILY af, LPCVOID paddr, LPWSTR out_buffer, ULONG buffer_size, BOOLEAN is_checkempty)
{
PIN_ADDR p4addr;
PIN6_ADDR p6addr;
if (af == AF_INET)
{
p4addr = (PIN_ADDR)paddr;
if (is_checkempty)
{
if (IN4_IS_ADDR_UNSPECIFIED (p4addr))
return FALSE;
}
if (NT_SUCCESS (RtlIpv4AddressToStringEx (p4addr, 0, out_buffer, &buffer_size)))
return TRUE;
}
else if (af == AF_INET6)
{
p6addr = (PIN6_ADDR)paddr;
if (is_checkempty)
{
if (IN6_IS_ADDR_UNSPECIFIED (p6addr))
return FALSE;
}
if (NT_SUCCESS (RtlIpv6AddressToStringEx (p6addr, 0, 0, out_buffer, &buffer_size)))
return TRUE;
}
return FALSE;
}
PR_STRING _app_formatport (UINT16 port, BOOLEAN is_noempty)
{
PR_STRING string;
if (!port)
return NULL;
if (is_noempty)
{
string = _r_format_string (L"%" TEXT (PRIu16), port);
LPCWSTR seviceString = _app_getservicename (port, NULL);
if (seviceString)
_r_string_appendformat (&string, L" (%s)", seviceString);
}
else
{
string = _r_format_string (L"%" TEXT (PRIu16) L" (%s)", port, _app_getservicename (port, SZ_UNKNOWN));
}
return string;
}
VOID _app_freestrings_map (OBJECTS_STRINGS_MAP* ptr_map, SIZE_T max_size)
{
if (max_size && ptr_map->size () <= max_size)
return;
PVOID pdata;
for (auto it = ptr_map->begin (); it != ptr_map->end ();)
{
pdata = it->second;
it = ptr_map->erase (it);
if (pdata)
_r_obj_dereference (pdata);
if (max_size && ptr_map->size () <= max_size)
break;
}
}
VOID _app_freeapps_map (OBJECTS_APP_MAP* ptr_map)
{
PVOID pdata;
for (auto it = ptr_map->begin (); it != ptr_map->end ();)
{
pdata = it->second;
it = ptr_map->erase (it);
if (pdata)
_r_obj_dereference (pdata);
}
}
VOID _app_freeappshelper_map (OBJECTS_APP_HELPER_MAP* ptr_map)
{
PVOID pdata;
for (auto it = ptr_map->begin (); it != ptr_map->end ();)
{
pdata = it->second;
it = ptr_map->erase (it);
if (pdata)
_r_obj_dereference (pdata);
}
}
VOID _app_freerulesconfig_map (OBJECTS_RULE_CONFIG_MAP* ptr_map)
{
PVOID pdata;
for (auto it = ptr_map->begin (); it != ptr_map->end ();)
{
pdata = it->second;
it = ptr_map->erase (it);
if (pdata)
_r_obj_dereference (pdata);
}
}
VOID _app_freeapps_vec (OBJECTS_APP_VECTOR* ptr_vec)
{
PVOID pdata;
for (auto it = ptr_vec->begin (); it != ptr_vec->end ();)
{
pdata = *it;
it = ptr_vec->erase (it);
if (pdata)
_r_obj_dereference (pdata);
}
}
VOID _app_freerules_vec (OBJECTS_RULE_VECTOR* ptr_vec)
{
PVOID pdata;
for (auto it = ptr_vec->begin (); it != ptr_vec->end ();)
{
pdata = *it;
it = ptr_vec->erase (it);
if (pdata)
_r_obj_dereference (pdata);
}
}
VOID _app_freelogobjects_vec (OBJECTS_LOG_VECTOR* ptr_vec)
{
PVOID pdata;
for (auto it = ptr_vec->begin (); it != ptr_vec->end ();)
{
pdata = *it;
it = ptr_vec->erase (it);
if (pdata)
_r_obj_dereference (pdata);
}
}
VOID _app_freethreadpool (THREADS_VEC* ptr_vec)
{
HANDLE hthread;
for (auto it = ptr_vec->begin (); it != ptr_vec->end ();)
{
hthread = *it;
if (_r_fs_isvalidhandle (hthread))
{
if (WaitForSingleObjectEx (hthread, 0, FALSE) != WAIT_OBJECT_0)
{
++it;
continue;
}
CloseHandle (hthread);
}
it = ptr_vec->erase (it);
}
}
VOID _app_freelogstack ()
{
PSLIST_ENTRY listEntry;
PITEM_LOG_LISTENTRY ptr_entry;
while (TRUE)
{
listEntry = RtlInterlockedPopEntrySList (&log_stack.ListHead);
if (!listEntry)
break;
InterlockedDecrement (&log_stack.item_count);
ptr_entry = CONTAINING_RECORD (listEntry, ITEM_LOG_LISTENTRY, ListEntry);
if (ptr_entry->Body)
_r_obj_dereference (ptr_entry->Body);
_aligned_free (ptr_entry);
}
}
VOID _app_getappicon (const PITEM_APP ptr_app, BOOLEAN is_small, PINT picon_id, HICON* picon)
{
BOOLEAN is_iconshidden = _r_config_getboolean (L"IsIconsHidden", FALSE);
if (ptr_app->type == DataAppRegular || ptr_app->type == DataAppService)
{
if (is_iconshidden || !_app_getfileicon (_r_obj_getstring (ptr_app->real_path), is_small, picon_id, picon))
{
if (picon_id)
*picon_id = (ptr_app->type == DataAppService) ? config.icon_service_id : config.icon_id;
if (picon)
*picon = CopyIcon (is_small ? config.hicon_small : config.hicon_large);
}
if (ptr_app->type == DataAppService)
{
if (picon_id && *picon_id == config.icon_id)
*picon_id = config.icon_service_id;
}
}
else if (ptr_app->type == DataAppUWP)
{
if (picon_id)
*picon_id = config.icon_uwp_id;
if (picon)
*picon = CopyIcon (is_small ? config.hicon_uwp : config.hicon_large); // small-only!
}
else
{
if (picon_id)
*picon_id = config.icon_id;
if (picon)
*picon = CopyIcon (is_small ? config.hicon_small : config.hicon_large);
}
}
PR_STRING _app_getdisplayname (SIZE_T app_hash, PITEM_APP ptr_app)
{
PR_STRING string;
if (ptr_app->type == DataAppService)
{
return _r_obj_reference (ptr_app->original_path);
}
if (ptr_app->type == DataAppUWP)
{
if (_app_item_get (ptr_app->type, app_hash, &string, NULL, NULL, NULL))
return string;
}
string = ((app_hash == config.ntoskrnl_hash) ? ptr_app->original_path : ptr_app->real_path);
if (string)
{
if (_r_config_getboolean (L"ShowFilenames", TRUE))
{
return _r_obj_createstring (_r_path_getbasename (_r_obj_getstring (string)));
}
return _r_obj_reference (string);
}
return NULL;
}
BOOLEAN _app_getfileicon (LPCWSTR path, BOOLEAN is_small, PINT picon_id, HICON* picon)
{
if (_r_str_isempty (path))
return FALSE;
BOOLEAN result = FALSE;
SHFILEINFO shfi = {0};
DWORD flags = 0;
if (picon_id)
flags |= SHGFI_SYSICONINDEX;
if (picon)
flags |= SHGFI_ICON;
if (is_small)
flags |= SHGFI_SMALLICON;
if (SHGetFileInfo (path, 0, &shfi, sizeof (shfi), flags))
{
if (picon_id)
*picon_id = shfi.iIcon;
if (picon && shfi.hIcon)
*picon = shfi.hIcon;
result = TRUE;
}
if (!result)
{
if (picon_id)
*picon_id = config.icon_id;
if (picon)
*picon = CopyIcon (is_small ? config.hicon_small : config.hicon_large);
result = TRUE;
}
return result;
}
PR_STRING _app_getsignatureinfo (SIZE_T app_hash, const PITEM_APP ptr_app)
{
if (_r_str_isempty (ptr_app->real_path) || (ptr_app->type != DataAppRegular && ptr_app->type != DataAppService && ptr_app->type != DataAppUWP))
return NULL;
PR_STRING signatureCacheString = NULL;
if (cache_signatures.find (app_hash) != cache_signatures.end ())
{
PR_STRING pdata = cache_signatures.at (app_hash);
if (pdata)
signatureCacheString = _r_obj_reference (pdata);
}
else
{
cache_signatures[app_hash] = NULL;
HANDLE hfile = CreateFile (ptr_app->real_path->Buffer, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
if (_r_fs_isvalidhandle (hfile))
{
GUID WinTrustActionGenericVerifyV2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
WINTRUST_FILE_INFO fileInfo = {0};
fileInfo.cbStruct = sizeof (fileInfo);
fileInfo.pcwszFilePath = ptr_app->real_path->Buffer;
fileInfo.hFile = hfile;
WINTRUST_DATA trustData = {0};
trustData.cbStruct = sizeof (trustData);
trustData.dwUIChoice = WTD_UI_NONE;
trustData.fdwRevocationChecks = WTD_REVOKE_NONE;
trustData.dwProvFlags = WTD_SAFER_FLAG | WTD_CACHE_ONLY_URL_RETRIEVAL;
trustData.dwUnionChoice = WTD_CHOICE_FILE;
trustData.pFile = &fileInfo;
trustData.dwStateAction = WTD_STATEACTION_VERIFY;
LONG status = WinVerifyTrust ((HWND)INVALID_HANDLE_VALUE, &WinTrustActionGenericVerifyV2, &trustData);
if (status == S_OK)
{
PCRYPT_PROVIDER_DATA provData = WTHelperProvDataFromStateData (trustData.hWVTStateData);
if (provData)
{
PCRYPT_PROVIDER_SGNR psProvSigner = WTHelperGetProvSignerFromChain (provData, 0, FALSE, 0);
if (psProvSigner)
{
CRYPT_PROVIDER_CERT* psProvCert = WTHelperGetProvCertFromChain (psProvSigner, 0);
if (psProvCert)
{
DWORD num_chars = CertGetNameString (psProvCert->pCert, CERT_NAME_ATTR_TYPE, 0, szOID_COMMON_NAME, NULL, 0);
if (num_chars)
{
signatureCacheString = _r_obj_createstringex (NULL, num_chars * sizeof (WCHAR));
if (CertGetNameString (psProvCert->pCert, CERT_NAME_ATTR_TYPE, 0, szOID_COMMON_NAME, signatureCacheString->Buffer, num_chars))
{
_app_freestrings_map (&cache_signatures, MAP_CACHE_MAX);
cache_signatures.insert_or_assign (app_hash, _r_obj_reference (signatureCacheString));
}
else
{
_r_obj_clearreference (&signatureCacheString);
}
}
}
}
}
}
trustData.dwStateAction = WTD_STATEACTION_CLOSE;
WinVerifyTrust ((HWND)INVALID_HANDLE_VALUE, &WinTrustActionGenericVerifyV2, &trustData);
CloseHandle (hfile);
}
}
ptr_app->is_signed = !_r_str_isempty (signatureCacheString);
return signatureCacheString;
}
PR_STRING _app_getversioninfo (SIZE_T app_hash, const PITEM_APP ptr_app)
{
if (_r_str_isempty (ptr_app->real_path))
return NULL;
PR_STRING versionCacheString = NULL;
if (cache_versions.find (app_hash) != cache_versions.end ())
{
PR_STRING pdata = cache_versions.at (app_hash);
if (pdata)
versionCacheString = _r_obj_reference (pdata);
}
else
{
cache_versions[app_hash] = NULL;
HINSTANCE hlib = LoadLibraryEx (ptr_app->real_path->Buffer, NULL, LOAD_LIBRARY_AS_IMAGE_RESOURCE | LOAD_LIBRARY_AS_DATAFILE);
if (hlib)
{
HRSRC hres = FindResource (hlib, MAKEINTRESOURCE (VS_VERSION_INFO), RT_VERSION);
if (hres)
{
HGLOBAL hglob = LoadResource (hlib, hres);
if (hglob)
{
PVOID versionInfo = LockResource (hglob);
if (versionInfo)
{
versionCacheString = _r_obj_createstringbuilder ();
PVOID buffer;
ULONG langId;
UINT length;
WCHAR authorEntry[128];
WCHAR descriptionEntry[128];
if (VerQueryValue (versionInfo, L"\\VarFileInfo\\Translation", &buffer, &length) && length == 4)
{
RtlCopyMemory (&langId, buffer, length);
_r_str_printf (authorEntry, RTL_NUMBER_OF (authorEntry), L"\\StringFileInfo\\%02X%02X%02X%02X\\CompanyName", (langId & 0xff00) >> 8, langId & 0xff, (langId & 0xff000000) >> 24, (langId & 0xff0000) >> 16);
_r_str_printf (descriptionEntry, RTL_NUMBER_OF (descriptionEntry), L"\\StringFileInfo\\%02X%02X%02X%02X\\FileDescription", (langId & 0xff00) >> 8, langId & 0xff, (langId & 0xff000000) >> 24, (langId & 0xff0000) >> 16);
}
else
{
_r_str_printf (authorEntry, RTL_NUMBER_OF (authorEntry), L"\\StringFileInfo\\%04X04B0\\CompanyName", GetUserDefaultLangID ());
_r_str_printf (descriptionEntry, RTL_NUMBER_OF (descriptionEntry), L"\\StringFileInfo\\%04X04B0\\FileDescription", GetUserDefaultLangID ());
}
if (VerQueryValue (versionInfo, descriptionEntry, &buffer, &length))
{
_r_string_appendformat (&versionCacheString, SZ_TAB L"%s", buffer);
VS_FIXEDFILEINFO* verInfo;
if (VerQueryValue (versionInfo, L"\\", (PVOID*)&verInfo, &length))
{
_r_string_appendformat (&versionCacheString, L" %d.%d", HIWORD (verInfo->dwFileVersionMS), LOWORD (verInfo->dwFileVersionMS));
if (HIWORD (verInfo->dwFileVersionLS) || LOWORD (verInfo->dwFileVersionLS))
{
_r_string_appendformat (&versionCacheString, L".%d", HIWORD (verInfo->dwFileVersionLS));
if (LOWORD (verInfo->dwFileVersionLS))
_r_string_appendformat (&versionCacheString, L".%d", LOWORD (verInfo->dwFileVersionLS));
}
}
_r_string_append (&versionCacheString, L"\r\n");
}
if (VerQueryValue (versionInfo, authorEntry, &buffer, &length))
{
_r_string_appendformat (&versionCacheString, SZ_TAB L"%s\r\n", buffer);
}
_r_str_trim (versionCacheString, DIVIDER_TRIM);
if (_r_str_isempty (versionCacheString))
{
_r_obj_clearreference (&versionCacheString);
}
else
{
_app_freestrings_map (&cache_versions, MAP_CACHE_MAX);
cache_versions.insert_or_assign (app_hash, _r_obj_reference (versionCacheString));
}
}
FreeResource (hglob);
}
}
FreeLibrary (hlib);
}
}
return versionCacheString;
}
LPCWSTR _app_getservicename (UINT16 port, LPCWSTR default_value)
{
switch (port)
{
case 1:
return L"tcpmux";
case 7:
return L"echo";
case 9:
return L"discard";
case 11:
return L"systat";
case 13:
return L"daytime";
case 20:
return L"ftp-data";
case 21:
return L"ftp";
case 22:
return L"ssh";
case 23:
return L"telnet";
case 25:
return L"smtp";
case 26:
return L"rsftp";
case 37:
return L"time";
case 39:
return L"rlp";
case 42:
return L"nameserver";
case 43:
return L"nicname";
case 48:
return L"auditd";
case 53:
return L"domain";
case 63:
return L"whois++";
case 67:
case 68:
return L"dhcp";
case 69:
return L"tftp";
case 78:
return L"vettcp";
case 79:
case 2003:
return L"finger";
case 80:
return L"http";
case 81:
return L"hosts2-ns";
case 84:
return L"ctf";
case 88:
return L"kerberos-sec";
case 90:
return L"dnsix";
case 92:
return L"npp";
case 93:
return L"dcp";
case 94:
return L"objcall";
case 95:
return L"supdup";
case 101:
return L"hostname";
case 105:
return L"cso";
case 106:
return L"pop3pw";
case 107:
return L"rtelnet";
case 109:
return L"pop2";
case 110:
return L"pop3";
case 111:
return L"rpcbind";
case 112:
return L"mcidas";
case 113:
return L"auth";
case 115:
return L"sftp";
case 118:
return L"sqlserv";
case 119:
return L"nntp";
case 123:
return L"ntp";
case 126:
return L"nxedit";
case 129:
return L"pwdgen";
case 135:
return L"msrpc";
case 136:
return L"profile";
case 137:
return L"netbios-ns";
case 138:
return L"netbios-dgm";
case 139:
return L"netbios-ssn";
case 143:
return L"imap";
case 144:
return L"news";
case 145:
return L"uaac";
case 150:
return L"sql-net";
case 152:
return L"bftp";
case 156:
return L"sqlsrv";
case 159:
return L"nss-routing";
case 160:
return L"sgmp-traps";
case 161:
return L"snmp";
case 162:
return L"snmptrap";
case 169:
return L"send";
case 174:
return L"mailq";
case 175:
return L"vmnet";
case 179:
return L"bgp";
case 182:
return L"audit";
case 185:
return L"remote-kis";
case 186:
return L"kis";
case 194:
case 529:
return L"irc";
case 195:
return L"dn6-nlm-aud";
case 196:
return L"dn6-smm-red";
case 197:
return L"dls";
case 199:
return L"smux";
case 209:
return L"qmtp";
case 245:
return L"link";
case 280:
return L"http-mgmt";
case 322:
return L"rtsps";
case 349:
return L"mftp";
case 389:
return L"ldap";
case 427:
return L"svrloc";
case 443:
return L"https";
case 444:
return L"snpp";
case 445:
return L"microsoft-ds";
case 464:
return L"kerberos";
case 465:
return L"smtps";
case 500:
return L"isakmp";
case 513:
return L"login";
case 514:
return L"shell";
case 515:
return L"printer";
case 524:
return L"ncp";
case 530:
return L"rpc";
case 543:
return L"klogin";
case 544:
return L"kshell";
case 546:
return L"dhcpv6-client";
case 547:
return L"dhcpv6-server";
case 548:
return L"afp";
case 554:
return L"rtsp";
case 565:
return L"whoami";
case 558:
return L"sdnskmp";
case 585:
return L"imap4-ssl";
case 587:
return L"submission";
case 631:
return L"ipp";
case 636:
return L"ldaps";
case 646:
return L"ldp";
case 647:
return L"dhcp-failover";
case 666:
return L"doom"; // khe-khe-khe!
case 847:
return L"dhcp-failover2";
case 861:
return L"owamp-control";
case 862:
return L"twamp-control";
case 873:
return L"rsync";
case 853:
return L"domain-s";
case 989:
return L"ftps-data";
case 990:
return L"ftps";
case 992:
return L"telnets";
case 993:
return L"imaps";
case 994:
return L"ircs";
case 995:
return L"pop3s";
case 1025:
return L"NFS-or-IIS";
case 1027:
return L"IIS";
case 1029:
return L"ms-lsa";
case 1110:
return L"nfsd";
case 1111:
return L"lmsocialserver";
case 1112:
case 1114:
case 4333:
return L"mini-sql";
case 1119:
return L"bnetgame";
case 1120:
return L"bnetfile";
case 1123:
return L"murray";
case 1194:
return L"openvpn";
case 1337:
return L"menandmice-dns";
case 1433:
return L"ms-sql-s";
case 1688:
return L"nsjtp-data";
case 1701:
return L"l2tp";
case 1720:
return L"h323q931";
case 1723:
return L"pptp";
case 1863:
return L"msnp";
case 1900:
case 5000:
return L"upnp";
case 2000:
return L"cisco-sccp";
case 2054:
return L"weblogin";
case 2086:
return L"gnunet";
case 2001:
return L"dc";
case 2121:
return L"ccproxy-ftp";
case 2164:
return L"ddns-v3";
case 2167:
return L"raw-serial";
case 2171:
return L"msfw-storage";
case 2172:
return L"msfw-s-storage";
case 2173:
return L"msfw-replica";
case 2174:
return L"msfw-array";
case 2371:
return L"worldwire";
case 2717:
return L"pn-requester";
case 2869:
return L"icslap";
case 3000:
return L"ppp";
case 3074:
return L"xbox";
case 3128:
return L"squid-http";
case 3306:
return L"mysql";
case 3389:
return L"ms-wbt-server";
case 3407:
return L"ldap-admin";
case 3540:
return L"pnrp-port";
case 3558:
return L"mcp-port";
case 3587:
return L"p2pgroup";
case 3702:
return L"ws-discovery";
case 3713:
return L"tftps";
case 3724:
return L"blizwow";
case 4500:
return L"ipsec-nat-t";
case 4554:
return L"msfrs";
case 4687:
return L"nst";
case 4876:
return L"tritium-can";
case 4899:
return L"radmin";
case 5004:
return L"rtp-data";
case 5005:
return L"rtp";
case 5009:
return L"airport-admin";
case 5051:
return L"ida-agent";
case 5060:
return L"sip";
case 5101:
return L"admdog";
case 5190:
return L"aol";
case 5350:
return L"nat-pmp-status";
case 5351:
return L"nat-pmp";
case 5352:
return L"dns-llq";
case 5353:
return L"mdns";
case 5354:
return L"mdnsresponder";
case 5355:
return L"llmnr";
case 5357:
return L"wsdapi";
case 5358:
return L"wsdapi-s";
case 5362:
return L"serverwsd2";
case 5432:
return L"postgresql";
case 5631:
return L"pcanywheredata";
case 5666:
return L"nrpe";
case 5687:
return L"gog-multiplayer";
case 5800:
return L"vnc-http";
case 5900:
return L"vnc";
case 5938:
return L"teamviewer";
case 6000:
case 6001:
case 6002:
case 6003:
return L"x11";
case 6222:
case 6662: // deprecated!
return L"radmind";
case 6346:
return L"gnutella";
case 6347:
return L"gnutella2";
case 6622:
return L"mcftp";
case 6665:
case 6666:
case 6667:
case 6668:
case 6669:
return L"ircu";
case 6881:
return L"bittorrent-tracker";
case 7070:
return L"realserver";
case 7235:
return L"aspcoordination";
case 8443:
return L"https-alt";
case 8021:
return L"ftp-proxy";
case 8333:
case 18333:
return L"bitcoin";
case 591:
case 8000:
case 8008:
case 8080:
case 8444:
return L"http-alt";
case 8999:
return L"bctp";
case 9418:
return L"git";
case 9800:
return L"webdav";
case 10107:
return L"bctp-server";
case 11371:
return L"hkp";
case 25565:
return L"minecraft";
case 26000:
return L"quake";
case 27015:
return L"halflife";
case 27017:
case 27018:
case 27019:
case 28017:
return L"mongod";
case 27500:
return L"quakeworld";
case 27910:
return L"quake2";
case 27960:
return L"quake3";
case 28240:
return L"siemensgsm";
case 33434:
return L"traceroute";
}
return default_value;
}
LPCWSTR _app_getprotoname (UINT8 proto, ADDRESS_FAMILY af, LPCWSTR default_value)
{
switch (proto)
{
case IPPROTO_HOPOPTS:
return L"hopopt";
case IPPROTO_ICMP:
return L"icmp";
case IPPROTO_IGMP:
return L"igmp";
case IPPROTO_GGP:
return L"ggp";
case IPPROTO_IPV4:
return L"ipv4";
case IPPROTO_ST:
return L"st";
case IPPROTO_TCP:
return ((af == AF_INET6) ? L"tcp6" : L"tcp");
case IPPROTO_CBT:
return L"cbt";
case IPPROTO_EGP:
return L"egp";
case IPPROTO_IGP:
return L"igp";
case IPPROTO_PUP:
return L"pup";
case IPPROTO_UDP:
return ((af == AF_INET6) ? L"udp6" : L"udp");
case IPPROTO_IDP:
return L"xns-idp";
case IPPROTO_RDP:
return L"rdp";
case IPPROTO_IPV6:
return L"ipv6";
case IPPROTO_ROUTING:
return L"ipv6-route";
case IPPROTO_FRAGMENT:
return L"ipv6-frag";
case IPPROTO_ESP:
return L"esp";
case IPPROTO_AH:
return L"ah";
case IPPROTO_ICMPV6:
return L"ipv6-icmp";
case IPPROTO_DSTOPTS:
return L"ipv6-opts";
case IPPROTO_L2TP:
return L"l2tp";
case IPPROTO_SCTP:
return L"sctp";
}
return default_value;
}
LPCWSTR _app_getconnectionstatusname (DWORD state, LPCWSTR default_value)
{
switch (state)
{
case MIB_TCP_STATE_CLOSED:
return L"Closed";
case MIB_TCP_STATE_LISTEN:
return L"Listen";
case MIB_TCP_STATE_SYN_SENT:
return L"SYN sent";
case MIB_TCP_STATE_SYN_RCVD:
return L"SYN received";
case MIB_TCP_STATE_ESTAB:
return L"Established";
case MIB_TCP_STATE_FIN_WAIT1:
return L"FIN wait 1";
case MIB_TCP_STATE_FIN_WAIT2:
return L"FIN wait 2";
case MIB_TCP_STATE_CLOSE_WAIT:
return L"Close wait";
case MIB_TCP_STATE_CLOSING:
return L"Closing";
case MIB_TCP_STATE_LAST_ACK:
return L"Last ACK";
case MIB_TCP_STATE_TIME_WAIT:
return L"Time wait";
case MIB_TCP_STATE_DELETE_TCB:
return L"Delete TCB";
}
return default_value;
}
PR_STRING _app_getdirectionname (FWP_DIRECTION direction, BOOLEAN is_loopback, BOOLEAN is_localized)
{
PR_STRING string;
if (is_localized)
{
if (direction == FWP_DIRECTION_OUTBOUND)
{
string = _r_obj_createstring (_r_locale_getstring (IDS_DIRECTION_1));
}
else if (direction == FWP_DIRECTION_INBOUND)
{
string = _r_obj_createstring (_r_locale_getstring (IDS_DIRECTION_2));
}
else if (direction == FWP_DIRECTION_MAX)
{
string = _r_obj_createstring (_r_locale_getstring (IDS_ANY));
}
else
{
return NULL;
}
if (is_loopback)
{
_r_string_appendformat (&string, L" (%s)", SZ_DIRECTION_LOOPBACK);
}
}
else
{
if (direction == FWP_DIRECTION_OUTBOUND)
{
string = _r_obj_createstring (SZ_DIRECTION_OUT);
}
else if (direction == FWP_DIRECTION_INBOUND)
{
string = _r_obj_createstring (SZ_DIRECTION_IN);
}
else if (direction == FWP_DIRECTION_MAX)
{
string = _r_obj_createstring (SZ_DIRECTION_ANY);
}
else
{
return NULL;
}
if (is_loopback)
{
_r_string_append (&string, L"-" SZ_DIRECTION_LOOPBACK);
}
}
return string;
}
COLORREF _app_getcolorvalue (SIZE_T color_hash)
{
if (!color_hash)
return 0;
for (auto it = colors.begin (); it != colors.end (); ++it)
{
PITEM_COLOR ptr_clr = *it;
if (ptr_clr->hash == color_hash)
return ptr_clr->new_clr ? ptr_clr->new_clr : ptr_clr->default_clr;
}
return 0;
}
PR_STRING _app_getservicenamefromtag (HANDLE hprocess, LPCVOID ptag)
{
PR_STRING serviceNameString = NULL;
HMODULE hlib = GetModuleHandle (L"advapi32.dll");
if (hlib)
{
typedef ULONG (NTAPI* IQTI) (PVOID, SC_SERVICE_TAG_QUERY_TYPE, PSC_SERVICE_TAG_QUERY); // I_QueryTagInformation
const IQTI _I_QueryTagInformation = (IQTI)GetProcAddress (hlib, "I_QueryTagInformation");
if (_I_QueryTagInformation)
{
PSC_SERVICE_TAG_QUERY pnameTag = (PSC_SERVICE_TAG_QUERY)_r_mem_allocatezero (sizeof (SC_SERVICE_TAG_QUERY));
pnameTag->ProcessId = HandleToUlong (hprocess);
pnameTag->ServiceTag = PtrToUlong (ptag);
_I_QueryTagInformation (NULL, ServiceNameFromTagInformation, pnameTag);
if (pnameTag->Buffer)
{
serviceNameString = _r_obj_createstring ((LPCWSTR)pnameTag->Buffer);
LocalFree (pnameTag->Buffer);
}
_r_mem_free (pnameTag);
}
}
return serviceNameString;
}
BOOLEAN _app_isimmersiveprocess (HANDLE hprocess)
{
HMODULE huser32 = GetModuleHandle (L"user32.dll");
if (huser32)
{
typedef BOOL (WINAPI* IIP) (HANDLE); // IsImmersiveProcess
const IIP _IsImmersiveProcess = (IIP)GetProcAddress (huser32, "IsImmersiveProcess");
if (_IsImmersiveProcess)
return !!_IsImmersiveProcess (hprocess);
}
return FALSE;
}
PR_STRING _app_getnetworkpath (DWORD pid, PULONG64 pmodules, PITEM_NETWORK ptr_network)
{
if (pid == PROC_WAITING_PID)
{
ptr_network->app_hash = 0;
ptr_network->icon_id = config.icon_id;
ptr_network->type = DataAppRegular;
return _r_obj_createstring (PROC_WAITING_NAME);
}
else if (pid == PROC_SYSTEM_PID)
{
ptr_network->app_hash = config.ntoskrnl_hash;
ptr_network->icon_id = config.icon_id;
ptr_network->type = DataAppRegular;
return _r_obj_createstring (PROC_SYSTEM_NAME);
}
PR_STRING processName = NULL;
if (pmodules)
{
PR_STRING serviceName = _app_getservicenamefromtag (UlongToHandle (pid), UlongToPtr (*(PULONG)pmodules));
if (serviceName)
{
_r_obj_movereference (&processName, serviceName);
ptr_network->type = DataAppService;
}
}
if (!processName)
{
HANDLE hprocess = OpenProcess (PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid);
if (hprocess)
{
if (_r_sys_isosversiongreaterorequal (WINDOWS_8) && _app_isimmersiveprocess (hprocess))
{
ptr_network->type = DataAppUWP;
}
else
{
ptr_network->type = DataAppRegular;
}
DWORD size = 1024;
processName = _r_obj_createstringex (NULL, size * sizeof (WCHAR));
BOOL is_success = QueryFullProcessImageName (hprocess, 0, processName->Buffer, &size);
// fix for WSL processes (issue #606)
if (!is_success)
{
if (GetLastError () == ERROR_GEN_FAILURE)
{
size = 1024;
QueryFullProcessImageName (hprocess, PROCESS_NAME_NATIVE, processName->Buffer, &size);
is_success = TRUE;
}
}
if (!is_success)
{
SAFE_DELETE_REFERENCE (processName);
}
else
{
_r_string_trimtonullterminator (processName);
}
CloseHandle (hprocess);
}
}
if (processName)
{
SIZE_T app_hash = _r_str_hash (processName);
ptr_network->app_hash = app_hash;
ptr_network->icon_id = (INT)_app_getappinfo (app_hash, InfoIconId);
if (!ptr_network->icon_id)
_app_getfileicon (_r_obj_getstring (processName), TRUE, &ptr_network->icon_id, NULL);
}
else
{
ptr_network->app_hash = 0;
ptr_network->icon_id = config.icon_id;
}
return processName;
}
SIZE_T _app_getnetworkhash (ADDRESS_FAMILY af, DWORD pid, LPCVOID remote_addr, DWORD remote_port, LPCVOID local_addr, DWORD local_port, UINT8 proto, DWORD state)
{
PR_STRING networkString;
WCHAR remoteAddress[LEN_IP_MAX];
WCHAR localAddress[LEN_IP_MAX];
SIZE_T networkHash;
if (remote_addr)
_app_formatip (af, remote_addr, remoteAddress, RTL_NUMBER_OF (remoteAddress), FALSE);
else
*remoteAddress = UNICODE_NULL;
if (local_addr)
_app_formatip (af, local_addr, localAddress, RTL_NUMBER_OF (localAddress), FALSE);
else
*localAddress = UNICODE_NULL;
networkString = _r_format_string (L"%" TEXT (PRIu8) L"_%" TEXT (PR_ULONG) L"_%s_%" TEXT (PR_ULONG) L"_%s_%" TEXT (PR_ULONG) L"_%" TEXT (PRIu8) L"_%" TEXT (PR_ULONG),
af,
pid,
remoteAddress,
remote_port,
localAddress,
local_port,
proto,
state
);
networkHash = _r_str_hash (networkString);
_r_obj_dereference (networkString);
return networkHash;
}
BOOLEAN _app_isvalidconnection (ADDRESS_FAMILY af, LPCVOID paddr)
{
if (af == AF_INET)
{
PIN_ADDR p4addr = (PIN_ADDR)paddr;
return (!IN4_IS_ADDR_UNSPECIFIED (p4addr) &&
!IN4_IS_ADDR_LOOPBACK (p4addr) &&
!IN4_IS_ADDR_LINKLOCAL (p4addr) &&
!IN4_IS_ADDR_MULTICAST (p4addr) &&
!IN4_IS_ADDR_MC_ADMINLOCAL (p4addr) &&
!IN4_IS_ADDR_RFC1918 (p4addr)
);
}
else if (af == AF_INET6)
{
PIN6_ADDR p6addr = (PIN6_ADDR)paddr;
return (!IN6_IS_ADDR_UNSPECIFIED (p6addr) &&
!IN6_IS_ADDR_LOOPBACK (p6addr) &&
!IN6_IS_ADDR_LINKLOCAL (p6addr) &&
!IN6_IS_ADDR_MULTICAST (p6addr) &&
!IN6_IS_ADDR_SITELOCAL (p6addr) &&
!IN6_IS_ADDR_ANYCAST (p6addr)
);
}
return FALSE;
}
VOID _app_generate_connections (OBJECTS_NETWORK_MAP* ptr_map, HASHER_MAP* checker_map)
{
checker_map->clear ();
PITEM_NETWORK ptr_network;
SIZE_T network_hash;
DWORD allocationSize = 0x4000;
PVOID memoryAddress = _r_mem_allocatezero (allocationSize);
DWORD requiredSize = 0;
GetExtendedTcpTable (NULL, &requiredSize, FALSE, AF_INET, TCP_TABLE_OWNER_MODULE_ALL, 0);
if (requiredSize)
{
if (allocationSize < requiredSize)
{
memoryAddress = _r_mem_reallocatezero (memoryAddress, requiredSize);
allocationSize = requiredSize;
}
PMIB_TCPTABLE_OWNER_MODULE tcp4Table = (PMIB_TCPTABLE_OWNER_MODULE)memoryAddress;
if (GetExtendedTcpTable (tcp4Table, &requiredSize, FALSE, AF_INET, TCP_TABLE_OWNER_MODULE_ALL, 0) == NO_ERROR)
{
for (DWORD i = 0; i < tcp4Table->dwNumEntries; i++)
{
IN_ADDR remote_addr = {0};
IN_ADDR local_addr = {0};
remote_addr.S_un.S_addr = tcp4Table->table[i].dwRemoteAddr;
local_addr.S_un.S_addr = tcp4Table->table[i].dwLocalAddr;
network_hash = _app_getnetworkhash (AF_INET, tcp4Table->table[i].dwOwningPid, &remote_addr, tcp4Table->table[i].dwRemotePort, &local_addr, tcp4Table->table[i].dwLocalPort, IPPROTO_TCP, tcp4Table->table[i].dwState);
if (ptr_map->find (network_hash) != ptr_map->end ())
{
checker_map->emplace (network_hash, FALSE);
continue;
}
ptr_network = (PITEM_NETWORK)_r_obj_allocateex (sizeof (ITEM_NETWORK), &_app_dereferencenetwork);
ptr_network->path = _app_getnetworkpath (tcp4Table->table[i].dwOwningPid, tcp4Table->table[i].OwningModuleInfo, ptr_network);
if (!ptr_network->path)
{
_r_obj_dereference (ptr_network);
continue;
}
ptr_network->af = AF_INET;
ptr_network->protocol = IPPROTO_TCP;
ptr_network->remote_addr.S_un.S_addr = tcp4Table->table[i].dwRemoteAddr;
ptr_network->remote_port = _r_byteswap_ushort ((USHORT)tcp4Table->table[i].dwRemotePort);
ptr_network->local_addr.S_un.S_addr = tcp4Table->table[i].dwLocalAddr;
ptr_network->local_port = _r_byteswap_ushort ((USHORT)tcp4Table->table[i].dwLocalPort);
ptr_network->state = tcp4Table->table[i].dwState;
if (tcp4Table->table[i].dwState == MIB_TCP_STATE_ESTAB)
{
if (_app_isvalidconnection (ptr_network->af, &ptr_network->remote_addr) || _app_isvalidconnection (ptr_network->af, &ptr_network->local_addr))
ptr_network->is_connection = TRUE;
}
ptr_map->insert_or_assign (network_hash, ptr_network);
checker_map->emplace (network_hash, TRUE);
}
}
}
requiredSize = 0;
GetExtendedTcpTable (NULL, &requiredSize, FALSE, AF_INET6, TCP_TABLE_OWNER_MODULE_ALL, 0);
if (requiredSize)
{
if (allocationSize < requiredSize)
{
memoryAddress = _r_mem_reallocatezero (memoryAddress, requiredSize);
allocationSize = requiredSize;
}
PMIB_TCP6TABLE_OWNER_MODULE tcp6Table = (PMIB_TCP6TABLE_OWNER_MODULE)memoryAddress;
if (GetExtendedTcpTable (tcp6Table, &requiredSize, FALSE, AF_INET6, TCP_TABLE_OWNER_MODULE_ALL, 0) == NO_ERROR)
{
for (DWORD i = 0; i < tcp6Table->dwNumEntries; i++)
{
network_hash = _app_getnetworkhash (AF_INET6, tcp6Table->table[i].dwOwningPid, tcp6Table->table[i].ucRemoteAddr, tcp6Table->table[i].dwRemotePort, tcp6Table->table[i].ucLocalAddr, tcp6Table->table[i].dwLocalPort, IPPROTO_TCP, tcp6Table->table[i].dwState);
if (ptr_map->find (network_hash) != ptr_map->end ())
{
checker_map->emplace (network_hash, FALSE);
continue;
}
ptr_network = (PITEM_NETWORK)_r_obj_allocateex (sizeof (ITEM_NETWORK), &_app_dereferencenetwork);
ptr_network->path = _app_getnetworkpath (tcp6Table->table[i].dwOwningPid, tcp6Table->table[i].OwningModuleInfo, ptr_network);
if (!ptr_network->path)
{
_r_obj_dereference (ptr_network);
continue;
}
ptr_network->af = AF_INET6;
ptr_network->protocol = IPPROTO_TCP;
RtlCopyMemory (ptr_network->remote_addr6.u.Byte, tcp6Table->table[i].ucRemoteAddr, FWP_V6_ADDR_SIZE);
ptr_network->remote_port = _r_byteswap_ushort ((USHORT)tcp6Table->table[i].dwRemotePort);
RtlCopyMemory (ptr_network->local_addr6.u.Byte, tcp6Table->table[i].ucLocalAddr, FWP_V6_ADDR_SIZE);
ptr_network->local_port = _r_byteswap_ushort ((USHORT)tcp6Table->table[i].dwLocalPort);
ptr_network->state = tcp6Table->table[i].dwState;
if (tcp6Table->table[i].dwState == MIB_TCP_STATE_ESTAB)
{
if (_app_isvalidconnection (ptr_network->af, &ptr_network->remote_addr6) || _app_isvalidconnection (ptr_network->af, &ptr_network->local_addr6))
ptr_network->is_connection = TRUE;
}
ptr_map->insert_or_assign (network_hash, ptr_network);
checker_map->emplace (network_hash, TRUE);
}
}
}
requiredSize = 0;
GetExtendedUdpTable (NULL, &requiredSize, FALSE, AF_INET, UDP_TABLE_OWNER_MODULE, 0);
if (requiredSize)
{
if (allocationSize < requiredSize)
{
memoryAddress = _r_mem_reallocatezero (memoryAddress, requiredSize);
allocationSize = requiredSize;
}
PMIB_UDPTABLE_OWNER_MODULE udp4Table = (PMIB_UDPTABLE_OWNER_MODULE)memoryAddress;
if (GetExtendedUdpTable (udp4Table, &requiredSize, FALSE, AF_INET, UDP_TABLE_OWNER_MODULE, 0) == NO_ERROR)
{
for (DWORD i = 0; i < udp4Table->dwNumEntries; i++)
{
IN_ADDR local_addr = {0};
local_addr.S_un.S_addr = udp4Table->table[i].dwLocalAddr;
network_hash = _app_getnetworkhash (AF_INET, udp4Table->table[i].dwOwningPid, NULL, 0, &local_addr, udp4Table->table[i].dwLocalPort, IPPROTO_UDP, 0);
if (ptr_map->find (network_hash) != ptr_map->end ())
{
checker_map->emplace (network_hash, FALSE);
continue;
}
ptr_network = (PITEM_NETWORK)_r_obj_allocateex (sizeof (ITEM_NETWORK), &_app_dereferencenetwork);
ptr_network->path = _app_getnetworkpath (udp4Table->table[i].dwOwningPid, udp4Table->table[i].OwningModuleInfo, ptr_network);
if (!ptr_network->path)
{
_r_obj_dereference (ptr_network);
continue;
}
ptr_network->af = AF_INET;
ptr_network->protocol = IPPROTO_UDP;
ptr_network->local_addr.S_un.S_addr = udp4Table->table[i].dwLocalAddr;
ptr_network->local_port = _r_byteswap_ushort ((USHORT)udp4Table->table[i].dwLocalPort);
//ptr_network->state = 0;
if (_app_isvalidconnection (ptr_network->af, &ptr_network->local_addr))
ptr_network->is_connection = TRUE;
ptr_map->insert_or_assign (network_hash, ptr_network);
checker_map->emplace (network_hash, TRUE);
}
}
}
requiredSize = 0;
GetExtendedUdpTable (NULL, &requiredSize, FALSE, AF_INET6, UDP_TABLE_OWNER_MODULE, 0);
if (requiredSize)
{
if (allocationSize < requiredSize)
{
memoryAddress = _r_mem_reallocatezero (memoryAddress, requiredSize);
allocationSize = requiredSize;
}
PMIB_UDP6TABLE_OWNER_MODULE udp6Table = (PMIB_UDP6TABLE_OWNER_MODULE)memoryAddress;
if (GetExtendedUdpTable (udp6Table, &requiredSize, FALSE, AF_INET6, UDP_TABLE_OWNER_MODULE, 0) == NO_ERROR)
{
for (DWORD i = 0; i < udp6Table->dwNumEntries; i++)
{
network_hash = _app_getnetworkhash (AF_INET6, udp6Table->table[i].dwOwningPid, NULL, 0, udp6Table->table[i].ucLocalAddr, udp6Table->table[i].dwLocalPort, IPPROTO_UDP, 0);
if (ptr_map->find (network_hash) != ptr_map->end ())
{
checker_map->emplace (network_hash, FALSE);
continue;
}
ptr_network = (PITEM_NETWORK)_r_obj_allocateex (sizeof (ITEM_NETWORK), &_app_dereferencenetwork);
ptr_network->path = _app_getnetworkpath (udp6Table->table[i].dwOwningPid, udp6Table->table[i].OwningModuleInfo, ptr_network);
if (!ptr_network->path)
{
_r_obj_dereference (ptr_network);
continue;
}
ptr_network->af = AF_INET6;
ptr_network->protocol = IPPROTO_UDP;
RtlCopyMemory (ptr_network->local_addr6.u.Byte, udp6Table->table[i].ucLocalAddr, FWP_V6_ADDR_SIZE);
ptr_network->local_port = _r_byteswap_ushort ((USHORT)udp6Table->table[i].dwLocalPort);
//ptr_network->state = 0;
if (_app_isvalidconnection (ptr_network->af, &ptr_network->local_addr6))
ptr_network->is_connection = TRUE;
ptr_map->insert_or_assign (network_hash, ptr_network);
checker_map->emplace (network_hash, TRUE);
}
}
}
if (memoryAddress)
_r_mem_free (memoryAddress);
}
VOID _app_generate_packages ()
{
LSTATUS code;
HKEY hkey;
HKEY hsubkey;
DWORD key_index;
DWORD max_length;
DWORD size;
LPBYTE packageSid;
PR_STRING keyName;
PR_STRING displayName;
PR_STRING packageSidString;
SIZE_T app_hash;
code = RegOpenKeyEx (HKEY_CLASSES_ROOT, L"Local Settings\\Software\\Microsoft\\Windows\\CurrentVersion\\AppModel\\Repository\\Packages", 0, KEY_READ, &hkey);
if (code == ERROR_SUCCESS)
{
max_length = _r_reg_querysubkeylength (hkey);
if (!max_length)
{
RegCloseKey (hkey);
return;
}
keyName = _r_obj_createstringex (NULL, max_length * sizeof (WCHAR));
key_index = 0;
while (TRUE)
{
size = max_length;
if (RegEnumKeyEx (hkey, key_index++, keyName->Buffer, &size, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
break;
_r_string_trimtonullterminator (keyName);
code = RegOpenKeyEx (hkey, keyName->Buffer, 0, KEY_READ, &hsubkey);
if (code == ERROR_SUCCESS)
{
packageSid = _r_reg_querybinary (hsubkey, L"PackageSid");
if (packageSid)
{
if (RtlValidSid (packageSid))
{
packageSidString = _r_str_fromsid (packageSid);
if (packageSidString)
{
app_hash = _r_str_hash (packageSidString);
if (!_app_isapphelperfound (app_hash))
{
displayName = _r_reg_querystring (hsubkey, L"DisplayName");
if (displayName)
{
if (displayName->Buffer[0] == L'@')
{
UINT localizedLength = 256;
PR_STRING localizedName = _r_obj_createstringex (NULL, localizedLength * sizeof (WCHAR));
if (SUCCEEDED (SHLoadIndirectString (displayName->Buffer, localizedName->Buffer, localizedLength, NULL)))
{
_r_string_trimtonullterminator (localizedName);
_r_obj_movereference (&displayName, localizedName);
}
else
{
_r_obj_dereference (localizedName);
}
}
PITEM_APP_HELPER ptr_item = (PITEM_APP_HELPER)_r_obj_allocateex (sizeof (ITEM_APP_HELPER), &_app_dereferenceappshelper);
ptr_item->type = DataAppUWP;
ptr_item->pdata = packageSid;
// query timestamp
ptr_item->timestamp = _r_reg_querytimestamp (hsubkey);
_r_obj_movereference (&ptr_item->display_name, displayName);
_r_obj_movereference (&ptr_item->internal_name, packageSidString);
_r_obj_movereference (&ptr_item->real_path, _r_reg_querystring (hsubkey, L"PackageRootFolder"));
// load additional info from appx manifest
_app_load_appxmanifest (ptr_item);
// clear references
packageSidString = NULL;
packageSid = NULL;
apps_helper[app_hash] = ptr_item;
}
}
if (packageSidString)
_r_obj_clearreference (&packageSidString);
}
}
if (packageSid)
_r_mem_free (packageSid);
}
RegCloseKey (hsubkey);
}
}
_r_obj_dereference (keyName);
RegCloseKey (hkey);
}
}
VOID _app_generate_services ()
{
SC_HANDLE hsvcmgr = OpenSCManager (NULL, NULL, SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE);
if (!hsvcmgr)
return;
static DWORD initialBufferSize = 0x8000;
DWORD returnLength = 0;
DWORD servicesReturned = 0;
DWORD dwServiceType = SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS;
DWORD dwServiceState = SERVICE_STATE_ALL;
// win10+
if (_r_sys_isosversiongreaterorequal (WINDOWS_10))
dwServiceType |= SERVICE_INTERACTIVE_PROCESS | SERVICE_USER_SERVICE | SERVICE_USERSERVICE_INSTANCE;
DWORD bufferSize = initialBufferSize;
PVOID buffer = _r_mem_allocatezero (bufferSize);
if (!EnumServicesStatusEx (hsvcmgr, SC_ENUM_PROCESS_INFO, dwServiceType, dwServiceState, (LPBYTE)buffer, bufferSize, &returnLength, &servicesReturned, NULL, NULL))
{
if (GetLastError () == ERROR_MORE_DATA)
{
// Set the buffer
bufferSize += returnLength;
buffer = _r_mem_reallocatezero (buffer, bufferSize);
// Now query again for services
if (!EnumServicesStatusEx (hsvcmgr, SC_ENUM_PROCESS_INFO, dwServiceType, dwServiceState, (LPBYTE)buffer, bufferSize, &returnLength, &servicesReturned, NULL, NULL))
{
_r_mem_free (buffer);
buffer = NULL;
}
}
else
{
_r_mem_free (buffer);
buffer = NULL;
}
}
// now traverse each service to get information
if (buffer)
{
LPENUM_SERVICE_STATUS_PROCESS service = (LPENUM_SERVICE_STATUS_PROCESS)buffer;
LPENUM_SERVICE_STATUS_PROCESS services = (LPENUM_SERVICE_STATUS_PROCESS)buffer;
for (DWORD i = 0; i < servicesReturned; i++)
{
service = &services[i];
LPCWSTR display_name = service->lpDisplayName;
LPCWSTR service_name = service->lpServiceName;
SIZE_T app_hash = _r_str_hash (service_name);
if (_app_isapphelperfound (app_hash))
continue;
PR_STRING servicePath = NULL;
time_t serviceTimestamp = 0;
HKEY hkey;
WCHAR generalKey[256];
WCHAR parametersKey[256];
_r_str_printf (generalKey, RTL_NUMBER_OF (generalKey), L"System\\CurrentControlSet\\Services\\%s", service_name);
_r_str_printf (parametersKey, RTL_NUMBER_OF (parametersKey), L"System\\CurrentControlSet\\Services\\%s\\Parameters", service_name);
// query "ServiceDll" path
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, parametersKey, 0, KEY_READ, &hkey) == ERROR_SUCCESS)
{
// query path
servicePath = _r_reg_querystring (hkey, L"ServiceDll");
// query timestamp
serviceTimestamp = _r_reg_querytimestamp (hkey);
RegCloseKey (hkey);
}
// fallback
if (!servicePath || !serviceTimestamp)
{
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, generalKey, 0, KEY_READ, &hkey) == ERROR_SUCCESS)
{
// query path
if (!servicePath)
{
servicePath = _r_reg_querystring (hkey, L"ImagePath");
if (servicePath)
{
PathRemoveArgs (servicePath->Buffer);
_r_string_trimtonullterminator (servicePath);
PathUnquoteSpaces (servicePath->Buffer);
_r_string_trimtonullterminator (servicePath);
}
}
// query timestamp
if (!serviceTimestamp)
serviceTimestamp = _r_reg_querytimestamp (hkey);
RegCloseKey (hkey);
}
}
if (servicePath)
{
PR_STRING convertedPath = _r_path_dospathfromnt (_r_obj_getstring (servicePath));
if (convertedPath)
_r_obj_movereference (&servicePath, convertedPath);
}
PSID pserviceSid = _app_queryservicesid (service_name);
if (pserviceSid)
{
PVOID pservice_sd = NULL;
DWORD sd_length = 0;
EXPLICIT_ACCESS ea;
RtlSecureZeroMemory (&ea, sizeof (ea));
// When evaluating SECURITY_DESCRIPTOR conditions, the filter engine
// checks for FWP_ACTRL_MATCH_FILTER access. If the DACL grants access,
// it does not mean that the traffic is allowed; it just means that the
// condition evaluates to true. Likewise if it denies access, the
// condition evaluates to false.
_app_setexplicitaccess (&ea, GRANT_ACCESS, NO_INHERITANCE, FWP_ACTRL_MATCH_FILTER, pserviceSid);
// Security descriptors must be in self-relative form (i.e., contiguous).
// The security descriptor returned by BuildSecurityDescriptorW is
// already self-relative, but if you're using another mechanism to build
// the descriptor, you may have to convert it. See MakeSelfRelativeSD for
// details.
if (BuildSecurityDescriptor (NULL, NULL, 1, &ea, 0, NULL, NULL, &sd_length, &pservice_sd) != ERROR_SUCCESS)
{
SAFE_DELETE_REFERENCE (servicePath);
continue;
}
PITEM_APP_HELPER ptr_item = (PITEM_APP_HELPER)_r_obj_allocateex (sizeof (ITEM_APP_HELPER), &_app_dereferenceappshelper);
ptr_item->type = DataAppService;
ptr_item->timestamp = serviceTimestamp;
ptr_item->display_name = _r_obj_createstring (display_name);
ptr_item->internal_name = _r_obj_createstring (service_name);
_r_obj_movereference (&ptr_item->real_path, servicePath);
servicePath = NULL;
ptr_item->pdata = _r_mem_allocatezero (sd_length);
RtlCopyMemory (ptr_item->pdata, pservice_sd, sd_length);
SAFE_DELETE_LOCAL (pservice_sd);
apps_helper[app_hash] = ptr_item;
_r_mem_free (pserviceSid);
}
SAFE_DELETE_REFERENCE (servicePath);
}
_r_mem_free (buffer);
}
CloseServiceHandle (hsvcmgr);
}
VOID _app_generate_rulesmenu (HMENU hsubmenu, SIZE_T app_hash)
{
PITEM_STATUS pstatus = (PITEM_STATUS)_r_mem_allocatezero (sizeof (ITEM_STATUS));
_app_getcount (pstatus);
if (!app_hash || !pstatus->rules_count)
{
AppendMenu (hsubmenu, MF_SEPARATOR, 0, NULL);
AppendMenu (hsubmenu, MF_STRING, IDX_RULES_SPECIAL, _r_locale_getstring (IDS_STATUS_EMPTY));
_r_menu_enableitem (hsubmenu, IDX_RULES_SPECIAL, MF_BYCOMMAND, FALSE);
}
else
{
MENUITEMINFO mii = {0};
WCHAR buffer[128];
PITEM_RULE ptr_rule;
BOOLEAN is_global;
BOOLEAN is_enabled;
for (UINT8 type = 0; type < 2; type++)
{
if (type == 0)
{
if (!pstatus->rules_predefined_count)
continue;
}
else
{
if (!pstatus->rules_user_count)
continue;
}
AppendMenu (hsubmenu, MF_SEPARATOR, 0, NULL);
for (UINT8 loop = 0; loop < 2; loop++)
{
for (SIZE_T i = 0; i < rules_arr.size (); i++)
{
ptr_rule = rules_arr.at (i);
if (!ptr_rule)
continue;
ptr_rule = (PITEM_RULE)_r_obj_reference (ptr_rule);
is_global = (ptr_rule->is_enabled && ptr_rule->apps->empty ());
is_enabled = is_global || (ptr_rule->is_enabled && (ptr_rule->apps->find (app_hash) != ptr_rule->apps->end ()));
if (ptr_rule->type != DataRuleCustom || (type == 0 && (!ptr_rule->is_readonly || is_global)) || (type == 1 && (ptr_rule->is_readonly || is_global)))
{
_r_obj_dereference (ptr_rule);
continue;
}
if ((loop == 0 && !is_enabled) || (loop == 1 && is_enabled))
{
_r_obj_dereference (ptr_rule);
continue;
}
_r_str_printf (buffer, RTL_NUMBER_OF (buffer), _r_locale_getstring (IDS_RULE_APPLY_2), _r_obj_getstring (ptr_rule->name));
if (ptr_rule->is_readonly)
_r_str_append (buffer, RTL_NUMBER_OF (buffer), SZ_RULE_INTERNAL_MENU);
mii.cbSize = sizeof (mii);
mii.fMask = MIIM_ID | MIIM_FTYPE | MIIM_STATE | MIIM_STRING | MIIM_BITMAP | MIIM_CHECKMARKS;
mii.fType = MFT_STRING;
mii.dwTypeData = buffer;
mii.hbmpItem = ptr_rule->is_block ? config.hbmp_block : config.hbmp_allow;
mii.hbmpChecked = config.hbmp_checked;
mii.hbmpUnchecked = config.hbmp_unchecked;
mii.fState = (is_enabled ? MF_CHECKED : MF_UNCHECKED);
mii.wID = IDX_RULES_SPECIAL + (UINT)i;
InsertMenuItem (hsubmenu, mii.wID, FALSE, &mii);
_r_obj_dereference (ptr_rule);
}
}
}
}
AppendMenu (hsubmenu, MF_SEPARATOR, 0, NULL);
AppendMenu (hsubmenu, MF_STRING, IDM_EDITRULES, _r_locale_getstring (IDS_EDITRULES));
AppendMenu (hsubmenu, MF_STRING, IDM_OPENRULESEDITOR, _r_locale_getstring (IDS_OPENRULESEDITOR));
_r_mem_free (pstatus);
}
VOID _app_generate_timermenu (HMENU hsubmenu, SIZE_T app_hash)
{
BOOLEAN is_checked = (app_hash == 0);
time_t current_time = _r_unixtime_now ();
time_t* ptime = (time_t*)_app_getappinfo (app_hash, InfoTimerPtr);
time_t app_time = ptime ? *ptime : 0;
WCHAR intervalString[128];
for (SIZE_T i = 0; i < timers.size (); i++)
{
UINT menu_id = IDX_TIMER + (UINT)i;
time_t timer = timers.at (i);
_r_format_interval (intervalString, RTL_NUMBER_OF (intervalString), timer + 1, 1);
AppendMenu (hsubmenu, MF_STRING, menu_id, intervalString);
if (!is_checked && (app_time > current_time) && (app_time <= (current_time + timer)))
{
_r_menu_checkitem (hsubmenu, IDX_TIMER, menu_id, MF_BYCOMMAND, menu_id);
is_checked = TRUE;
}
}
if (!is_checked)
_r_menu_checkitem (hsubmenu, IDM_DISABLETIMER, IDM_DISABLETIMER, MF_BYCOMMAND, IDM_DISABLETIMER);
}
BOOLEAN _app_item_get (ENUM_TYPE_DATA type, SIZE_T app_hash, PR_STRING* displayName, PR_STRING* realPath, time_t* ptime, PVOID* lpdata)
{
PITEM_APP_HELPER ptr_app_item = _app_getapphelperitem (app_hash);
if (!ptr_app_item)
return FALSE;
if (ptr_app_item->type != type)
{
_r_obj_dereference (ptr_app_item);
return FALSE;
}
if (displayName)
{
if (!_r_str_isempty (ptr_app_item->display_name))
*displayName = _r_obj_reference (ptr_app_item->display_name);
else if (!_r_str_isempty (ptr_app_item->real_path))
*displayName = _r_obj_reference (ptr_app_item->real_path);
else if (!_r_str_isempty (ptr_app_item->internal_name))
*displayName = _r_obj_reference (ptr_app_item->internal_name);
}
if (realPath)
{
if (!_r_str_isempty (ptr_app_item->real_path))
*realPath = _r_obj_reference (ptr_app_item->real_path);
}
if (lpdata)
*lpdata = ptr_app_item->pdata;
if (ptime)
*ptime = ptr_app_item->timestamp;
_r_obj_dereference (ptr_app_item);
return TRUE;
}
PR_STRING _app_parsehostaddress_dns (LPCWSTR hostname, USHORT port)
{
if (_r_str_isempty (hostname))
return NULL;
PR_STRING string;
PDNS_RECORD ppQueryResultsSet = NULL;
string = _r_obj_createstringbuilder ();
// ipv4 address
DNS_STATUS dnsStatus = DnsQuery (hostname, DNS_TYPE_A, DNS_QUERY_NO_HOSTS_FILE, NULL, &ppQueryResultsSet, NULL);
if (dnsStatus != DNS_ERROR_RCODE_NO_ERROR)
{
if (dnsStatus != DNS_INFO_NO_RECORDS)
_r_logerror (0, L"DnsQuery (DNS_TYPE_A)", dnsStatus, hostname);
}
else
{
if (ppQueryResultsSet)
{
for (auto current = ppQueryResultsSet; current != NULL; current = current->pNext)
{
// ipv4 address
WCHAR str[INET_ADDRSTRLEN];
if (_app_formatip (AF_INET, &(current->Data.A.IpAddress), str, RTL_NUMBER_OF (str), TRUE))
{
_r_string_append (&string, str);
if (port)
_r_string_appendformat (&string, L":%d", port);
_r_string_append (&string, DIVIDER_RULE);
}
}
}
}
if (ppQueryResultsSet)
{
DnsRecordListFree (ppQueryResultsSet, DnsFreeRecordList);
ppQueryResultsSet = NULL;
}
// ipv6 address
dnsStatus = DnsQuery (hostname, DNS_TYPE_AAAA, DNS_QUERY_NO_HOSTS_FILE, NULL, &ppQueryResultsSet, NULL);
if (dnsStatus != DNS_ERROR_RCODE_NO_ERROR)
{
if (dnsStatus != DNS_INFO_NO_RECORDS)
_r_logerror (0, L"DnsQuery (DNS_TYPE_AAAA)", dnsStatus, hostname);
}
else
{
if (ppQueryResultsSet)
{
for (auto current = ppQueryResultsSet; current != NULL; current = current->pNext)
{
WCHAR str[INET6_ADDRSTRLEN];
if (_app_formatip (AF_INET6, &current->Data.AAAA.Ip6Address, str, RTL_NUMBER_OF (str), TRUE))
{
_r_string_appendformat (&string, L"[%s]", str);
if (port)
_r_string_appendformat (&string, L":%d", port);
_r_string_append (&string, DIVIDER_RULE);
}
}
}
}
if (ppQueryResultsSet)
{
DnsRecordListFree (ppQueryResultsSet, DnsFreeRecordList);
ppQueryResultsSet = NULL;
}
_r_str_trim (string, DIVIDER_RULE);
if (_r_str_isempty (string))
{
_r_obj_dereference (string);
return NULL;
}
return string;
}
BOOLEAN _app_parsenetworkstring (LPCWSTR network_string, NET_ADDRESS_FORMAT* format_ptr, PUSHORT port_ptr, FWP_V4_ADDR_AND_MASK* paddr4, FWP_V6_ADDR_AND_MASK* paddr6, LPWSTR dnsString, SIZE_T dnsLength)
{
NET_ADDRESS_INFO ni;
RtlSecureZeroMemory (&ni, sizeof (ni));
USHORT port;
BYTE prefix_length;
DWORD types = NET_STRING_ANY_ADDRESS | NET_STRING_ANY_SERVICE | NET_STRING_IP_NETWORK | NET_STRING_ANY_ADDRESS_NO_SCOPE | NET_STRING_ANY_SERVICE_NO_SCOPE;
DWORD code = ParseNetworkString (network_string, types, &ni, &port, &prefix_length);
if (code != ERROR_SUCCESS)
{
_r_logerror (0, L"ParseNetworkString", code, network_string);
return FALSE;
}
else
{
if (format_ptr)
*format_ptr = ni.Format;
if (port_ptr)
*port_ptr = port;
if (ni.Format == NET_ADDRESS_IPV4)
{
if (paddr4)
{
ULONG mask = 0;
ConvertLengthToIpv4Mask (prefix_length, &mask);
paddr4->addr = _r_byteswap_ulong (ni.Ipv4Address.sin_addr.S_un.S_addr);
paddr4->mask = _r_byteswap_ulong (mask);
}
return TRUE;
}
else if (ni.Format == NET_ADDRESS_IPV6)
{
if (paddr6)
{
RtlCopyMemory (paddr6->addr, ni.Ipv6Address.sin6_addr.u.Byte, FWP_V6_ADDR_SIZE);
paddr6->prefixLength = min (prefix_length, 128);
}
return TRUE;
}
else if (ni.Format == NET_ADDRESS_DNS_NAME)
{
if (dnsString)
{
SIZE_T dns_hash = _r_str_hash (ni.NamedAddress.Address);
if (cache_dns.find (dns_hash) != cache_dns.end ())
{
PR_STRING pdata = cache_dns.at (dns_hash);
if (pdata)
{
PR_STRING dnsCacheString = _r_obj_reference (pdata);
_r_str_copy (dnsString, dnsLength, _r_obj_getstring (dnsCacheString));
_r_obj_dereference (dnsCacheString);
return !_r_str_isempty (dnsString);
}
}
PR_STRING hostString = _app_parsehostaddress_dns (ni.NamedAddress.Address, port);
if (!hostString)
{
return FALSE;
}
else
{
_r_str_copy (dnsString, dnsLength, _r_obj_getstringorempty (hostString));
_app_freestrings_map (&cache_dns, MAP_CACHE_MAX);
cache_dns.insert_or_assign (dns_hash, hostString);
return TRUE;
}
}
return TRUE;
}
}
return FALSE;
}
BOOLEAN _app_parserulestring (PR_STRING rule, PITEM_ADDRESS ptr_addr)
{
if (_r_str_isempty (rule))
return TRUE;
if (!_app_isrulevalidchars (rule->Buffer))
return FALSE;
ENUM_TYPE_DATA type = DataUnknown;
SIZE_T rule_length = _r_obj_getstringlength (rule);
SIZE_T range_pos = _r_str_findchar (rule->Buffer, rule_length, DIVIDER_RULE_RANGE);
BOOLEAN is_range = (range_pos != INVALID_SIZE_T);
WCHAR range_start[LEN_IP_MAX] = {0};
WCHAR range_end[LEN_IP_MAX] = {0};
if (is_range)
{
PR_STRING rangeStart = _r_str_extract (rule, 0, range_pos);
PR_STRING rangeEnd = _r_str_extract (rule, range_pos + 1, INVALID_SIZE_T);
_r_str_copy (range_start, RTL_NUMBER_OF (range_start), _r_obj_getstring (rangeStart));
_r_str_copy (range_end, RTL_NUMBER_OF (range_end), _r_obj_getstring (rangeEnd));
_r_obj_dereference (rangeStart);
_r_obj_dereference (rangeEnd);
}
// auto-parse rule type
{
SIZE_T rule_hash = _r_str_hash (rule);
BOOLEAN is_exists = cache_types.find (rule_hash) != cache_types.end ();
if (is_exists)
{
type = cache_types[rule_hash];
}
else
{
if (_app_isruleport (rule->Buffer))
{
type = DataTypePort;
}
else if (is_range ? (_app_isruleip (range_start) && _app_isruleip (range_end)) : _app_isruleip (rule->Buffer))
{
type = DataTypeIp;
}
else if (_app_isrulehost (rule->Buffer))
{
type = DataTypeHost;
}
if (type != DataUnknown)
{
if (cache_types.size () >= MAP_CACHE_MAX)
cache_types.clear ();
cache_types.emplace (rule_hash, type);
}
}
}
if (type == DataUnknown)
return FALSE;
if (!ptr_addr)
return TRUE;
if (type == DataTypeHost)
is_range = FALSE;
ptr_addr->is_range = is_range;
if (type == DataTypePort)
{
if (!is_range)
{
// ...port
ptr_addr->type = DataTypePort;
ptr_addr->port = (UINT16)_r_str_touinteger (rule->Buffer);
return TRUE;
}
else
{
// ...port range
ptr_addr->type = DataTypePort;
ptr_addr->range.valueLow.type = FWP_UINT16;
ptr_addr->range.valueLow.uint16 = (UINT16)wcstoul (range_start, NULL, 10);
ptr_addr->range.valueHigh.type = FWP_UINT16;
ptr_addr->range.valueHigh.uint16 = (UINT16)wcstoul (range_end, NULL, 10);
return TRUE;
}
}
else
{
NET_ADDRESS_FORMAT format;
FWP_V4_ADDR_AND_MASK addr4 = {0};
FWP_V6_ADDR_AND_MASK addr6 = {0};
USHORT port2 = 0;
if (type == DataTypeIp && is_range)
{
// ...ip range (start)
if (_app_parsenetworkstring (range_start, &format, &port2, &addr4, &addr6, NULL, 0))
{
if (format == NET_ADDRESS_IPV4)
{
ptr_addr->range.valueLow.type = FWP_UINT32;
ptr_addr->range.valueLow.uint32 = addr4.addr;
}
else if (format == NET_ADDRESS_IPV6)
{
ptr_addr->range.valueLow.type = FWP_BYTE_ARRAY16_TYPE;
RtlCopyMemory (ptr_addr->range.valueLow.byteArray16->byteArray16, addr6.addr, FWP_V6_ADDR_SIZE);
}
else
{
return FALSE;
}
if (port2 && !ptr_addr->port)
ptr_addr->port = port2;
}
else
{
return FALSE;
}
// ...ip range (end)
if (_app_parsenetworkstring (range_end, &format, &port2, &addr4, &addr6, NULL, 0))
{
if (format == NET_ADDRESS_IPV4)
{
ptr_addr->range.valueHigh.type = FWP_UINT32;
ptr_addr->range.valueHigh.uint32 = addr4.addr;
}
else if (format == NET_ADDRESS_IPV6)
{
ptr_addr->range.valueHigh.type = FWP_BYTE_ARRAY16_TYPE;
RtlCopyMemory (ptr_addr->range.valueHigh.byteArray16->byteArray16, addr6.addr, FWP_V6_ADDR_SIZE);
}
else
{
return FALSE;
}
}
else
{
return FALSE;
}
ptr_addr->format = format;
ptr_addr->type = DataTypeIp;
}
else
{
// ...ip/host
if (_app_parsenetworkstring (rule->Buffer, &format, &port2, &ptr_addr->addr4, &ptr_addr->addr6, ptr_addr->host, RTL_NUMBER_OF (ptr_addr->host)))
{
ptr_addr->type = DataTypeIp;
ptr_addr->format = format;
if (port2)
ptr_addr->port = port2;
return TRUE;
}
else
{
return FALSE;
}
}
}
return TRUE;
}
INT _app_getlistview_id (ENUM_TYPE_DATA type)
{
if (type == DataAppRegular || type == DataAppDevice || type == DataAppNetwork || type == DataAppPico)
return IDC_APPS_PROFILE;
else if (type == DataAppService)
return IDC_APPS_SERVICE;
else if (type == DataAppUWP)
return IDC_APPS_UWP;
else if (type == DataRuleBlocklist)
return IDC_RULES_BLOCKLIST;
else if (type == DataRuleSystem)
return IDC_RULES_SYSTEM;
else if (type == DataRuleCustom)
return IDC_RULES_CUSTOM;
return 0;
}
HBITMAP _app_bitmapfromico (HICON hicon, INT icon_size)
{
if (!hicon)
return NULL;
RECT iconRectangle;
SetRect (&iconRectangle, 0, 0, icon_size, icon_size);
HBITMAP hbitmap = NULL;
HDC screenHdc = GetDC (NULL);
if (screenHdc)
{
HDC hdc = CreateCompatibleDC (screenHdc);
if (hdc)
{
BITMAPINFO bitmapInfo = {0};
bitmapInfo.bmiHeader.biSize = sizeof (bitmapInfo);
bitmapInfo.bmiHeader.biPlanes = 1;
bitmapInfo.bmiHeader.biCompression = BI_RGB;
bitmapInfo.bmiHeader.biWidth = icon_size;
bitmapInfo.bmiHeader.biHeight = icon_size;
bitmapInfo.bmiHeader.biBitCount = 32;
hbitmap = CreateDIBSection (hdc, &bitmapInfo, DIB_RGB_COLORS, NULL, NULL, 0);
if (hbitmap)
{
HGDIOBJ oldBitmap = SelectObject (hdc, hbitmap);
BLENDFUNCTION blendFunction = {0};
blendFunction.BlendOp = AC_SRC_OVER;
blendFunction.AlphaFormat = AC_SRC_ALPHA;
blendFunction.SourceConstantAlpha = 255;
BP_PAINTPARAMS paintParams = {0};
paintParams.cbSize = sizeof (paintParams);
paintParams.dwFlags = BPPF_ERASE;
paintParams.pBlendFunction = &blendFunction;
HDC bufferHdc = NULL;
HPAINTBUFFER paintBuffer = BeginBufferedPaint (hdc, &iconRectangle, BPBF_DIB, &paintParams, &bufferHdc);
if (paintBuffer)
{
DrawIconEx (bufferHdc, 0, 0, hicon, icon_size, icon_size, 0, NULL, DI_NORMAL);
EndBufferedPaint (paintBuffer, TRUE);
}
else
{
_r_dc_fillrect (hdc, &iconRectangle, GetSysColor (COLOR_MENU));
DrawIconEx (hdc, 0, 0, hicon, icon_size, icon_size, 0, NULL, DI_NORMAL);
}
SelectObject (hdc, oldBitmap);
}
SAFE_DELETE_DC (hdc);
}
ReleaseDC (NULL, screenHdc);
}
return hbitmap;
}
HBITMAP _app_bitmapfrompng (HINSTANCE hinst, LPCWSTR name, INT icon_size)
{
BOOLEAN success = FALSE;
UINT frameCount = 0;
ULONG resourceLength = 0;
HDC screenHdc = NULL;
HDC hdc = NULL;
BITMAPINFO bi = {0};
HBITMAP hbitmap = NULL;
PVOID bitmapBuffer = NULL;
IWICStream* wicStream = NULL;
IWICBitmapSource* wicBitmapSource = NULL;
IWICBitmapDecoder* wicDecoder = NULL;
IWICBitmapFrameDecode* wicFrame = NULL;
IWICImagingFactory* wicFactory = NULL;
IWICBitmapScaler* wicScaler = NULL;
WICPixelFormatGUID pixelFormat;
WICRect rect = {0, 0, icon_size, icon_size};
// Create the ImagingFactory
if (FAILED (CoCreateInstance (CLSID_WICImagingFactory1, NULL, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, (PVOID*)&wicFactory)))
goto DoExit;
// Load the resource
WICInProcPointer resourceBuffer = (WICInProcPointer)_r_loadresource (hinst, name, L"PNG", &resourceLength);
if (!resourceBuffer)
goto DoExit;
// Create the Stream
if (FAILED (wicFactory->CreateStream (&wicStream)))
goto DoExit;
// Initialize the Stream from Memory
if (FAILED (wicStream->InitializeFromMemory (resourceBuffer, resourceLength)))
goto DoExit;
if (FAILED (wicFactory->CreateDecoder (GUID_ContainerFormatPng, NULL, &wicDecoder)))
goto DoExit;
if (FAILED (wicDecoder->Initialize ((IStream*)wicStream, WICDecodeMetadataCacheOnLoad)))
goto DoExit;
// Get the Frame count
if (FAILED (wicDecoder->GetFrameCount (&frameCount)) || frameCount < 1)
goto DoExit;
// Get the Frame
if (FAILED (wicDecoder->GetFrame (0, &wicFrame)))
goto DoExit;
// Get the WicFrame image format
if (FAILED (wicFrame->GetPixelFormat (&pixelFormat)))
goto DoExit;
// Check if the image format is supported:
if (RtlEqualMemory (&pixelFormat, &GUID_WICPixelFormat32bppPRGBA, sizeof (GUID)))
{
wicBitmapSource = (IWICBitmapSource*)wicFrame;
}
else
{
IWICFormatConverter* wicFormatConverter = NULL;
if (FAILED (wicFactory->CreateFormatConverter (&wicFormatConverter)))
goto DoExit;
if (FAILED (wicFormatConverter->Initialize (
(IWICBitmapSource*)wicFrame,
GUID_WICPixelFormat32bppPBGRA,
WICBitmapDitherTypeNone,
NULL,
0.0,
WICBitmapPaletteTypeCustom
)))
{
wicFormatConverter->Release ();
goto DoExit;
}
// Convert the image to the correct format:
wicFormatConverter->QueryInterface (&wicBitmapSource);
// Cleanup the converter.
wicFormatConverter->Release ();
// Dispose the old frame now that the converted frame is in wicBitmapSource.
wicFrame->Release ();
}
bi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
bi.bmiHeader.biWidth = rect.Width;
bi.bmiHeader.biHeight = -((LONG)rect.Height);
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 32;
bi.bmiHeader.biCompression = BI_RGB;
screenHdc = GetDC (NULL);
hdc = CreateCompatibleDC (screenHdc);
hbitmap = CreateDIBSection (screenHdc, &bi, DIB_RGB_COLORS, &bitmapBuffer, NULL, 0);
if (FAILED (wicFactory->CreateBitmapScaler (&wicScaler)))
goto DoExit;
if (FAILED (wicScaler->Initialize (wicBitmapSource, rect.Width, rect.Height, WICBitmapInterpolationModeFant)))
goto DoExit;
if (FAILED (wicScaler->CopyPixels (&rect, rect.Width * 4, rect.Width * rect.Height * 4, (LPBYTE)bitmapBuffer)))
goto DoExit;
success = TRUE;
DoExit:
if (wicScaler)
wicScaler->Release ();
SAFE_DELETE_DC (hdc);
if (screenHdc)
ReleaseDC (NULL, screenHdc);
if (wicBitmapSource)
wicBitmapSource->Release ();
if (wicStream)
wicStream->Release ();
if (wicDecoder)
wicDecoder->Release ();
if (wicFactory)
wicFactory->Release ();
if (!success)
{
SAFE_DELETE_OBJECT (hbitmap);
return NULL;
}
return hbitmap;
}
VOID _app_load_appxmanifest (PITEM_APP_HELPER ptr_app_item)
{
if (_r_str_isempty (ptr_app_item->real_path))
return;
WCHAR path[512];
PR_STRING resultPath;
LPCWSTR appx_names[] = {
L"AppxManifest.xml",
L"VSAppxManifest.xml",
};
for (SIZE_T i = 0; i < RTL_NUMBER_OF (appx_names); i++)
{
_r_str_printf (path, RTL_NUMBER_OF (path), L"%s\\%s", _r_obj_getstring (ptr_app_item->real_path), appx_names[i]);
if (_r_fs_exists (path))
goto DoOpen;
}
return;
DoOpen:
resultPath = NULL;
pugi::xml_document doc;
pugi::xml_parse_result xml_result = doc.load_file (path, PUGIXML_LOAD_FLAGS, PUGIXML_LOAD_ENCODING);
if (xml_result)
{
pugi::xml_node root = doc.child (L"Package");
if (root)
{
pugi::xml_node xml_applications = root.child (L"Applications");
for (pugi::xml_node item = xml_applications.child (L"Application"); item; item = item.next_sibling (L"Application"))
{
if (!item.attribute (L"Executable").empty ())
{
SAFE_DELETE_REFERENCE (resultPath);
resultPath = _r_format_string (L"%s\\%s", _r_obj_getstring (ptr_app_item->real_path), item.attribute (L"Executable").as_string ());
if (_r_fs_exists (_r_obj_getstring (resultPath)))
break;
}
}
}
}
_r_obj_movereference (&ptr_app_item->real_path, resultPath);
}