How to communicate with minifilter driver in UWP?

380 Views Asked by At

I have a minifilter driver and want to connect it with FilterConnectCommunicationPort. It works well in wpf, but it returns E_ACCESSDENIED in UWP even after I add SECURITY_ATTRIBUTES.

    SECURITY_ATTRIBUTES sa;
    PSECURITY_DESCRIPTOR SecurityDescriptor;
    bool ret = ConvertStringSecurityDescriptorToSecurityDescriptorW(
        L"D:P(A;;GA;;;WD)(A;;GA;;;AC)(A;;GA;;;S-1-15-2-2)S:(ML;;;;;LW)", 
    SDDL_REVISION, &SecurityDescriptor, 0);

    // Initialize a security attributes structure.
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = SecurityDescriptor;
    sa.bInheritHandle = FALSE;
    HRESULT hResult = S_OK;
    hResult = FilterConnectCommunicationPort(NPMINI_PORT_NAME, 0, NULL, 0, &sa, &g_hPort);
    if (IS_ERROR(hResult))
    {
        LogError("FilterConnectCommunicationPort fail! 0x%x",hResult);
        return hResult;
    }

I modify app package manifest to declare some restricted capabilities. Still not work.

<rescap:Capability Name="interopServices"/>
<iot:Capability Name="lowLevelDevices"/>

I am not sure whether FilterConnectCommunicationPort is allowed in UWP.If the api is ok, how to work with it? Thanks.

2

There are 2 best solutions below

0
Peter Torr On

You don't need those capabilities. interopServices is a hold-out from the Windows Phone days, and lowLevelDevices only works on actual IOT (embedded-mode) OSes.

Adding the right ACE can be done with a function like this - just pass in the handle to your object, the PFN of the target app, and the desired access rights. (This hard-codes SE_KERNEL_OBJECT for simplicity; you might need to use a different object type depending on your needs).

bool GrantAccessToPackage(HANDLE handle, const wchar_t* packageName, DWORD accessRights)
{
  PSID packageSid{};

  if (!SUCCEEDED(DeriveAppContainerSidFromAppContainerName(packageName, &packageSid)))
  {
    throw std::exception("invalid pfn");
  }

  EXPLICIT_ACCESS explicitAccess{};
  explicitAccess.grfAccessMode = GRANT_ACCESS;
  explicitAccess.grfAccessPermissions = accessRights;
  explicitAccess.grfInheritance = NO_INHERITANCE;
  explicitAccess.Trustee.TrusteeType = TRUSTEE_IS_USER;
  explicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID;
  explicitAccess.Trustee.ptstrName = (LPWCH)packageSid;

  PSECURITY_DESCRIPTOR securityDescriptor{ nullptr };
  PACL oldAcl{ nullptr };
  PACL newAcl{ nullptr };

  auto retVal = GetSecurityInfo(handle, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, nullptr, nullptr, &oldAcl, nullptr, &securityDescriptor);
  if (SUCCEEDED(retVal))
  {
    retVal = SetEntriesInAclW(1, &explicitAccess, oldAcl, &newAcl);
    if (SUCCEEDED(retVal))
    {
      retVal = SetSecurityInfo(handle, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, nullptr, nullptr, newAcl, nullptr);
    }
  }

  FreeSid(packageSid);
  if (securityDescriptor != nullptr)
  {
    LocalFree(securityDescriptor);
    if (newAcl != nullptr)
    {
      LocalFree(newAcl);

      // oldAcl is NOT freed; it's just a pointer into securityDescriptor
    }
  }

  return SUCCEEDED(retVal);
}
0
Gabriel Bercea On

Security attributes for FilterConnectCommunicationPort is only used for inheritance purposes. You must make sure the security descriptor you create in your filter is allowing access for you UWP application or better said the user under which your UWP is running is allowed to have access to your communication port.

If I remember correctly your UWP app should have its own SID. So in the filter when you call FltCreateCommunicationPort you must first have you ObjectAttributes parameter contain a SD which has an allowed ACE in the DACL for you UWP app SID.

You can use RtlCreateSecurityDescriptor (you must allocate first enough memory for you SD before calling this function), RtlCreateAcl, RtlAddAccessAllowedAce, RtlSetDaclSecurityDescriptor to create one and add you SID as an allowed ACE to your DACL in the SD.

Let me know if it works out for you.