static gboolean ProtectUser (gunichar2 *path) { DWORD retval = -1; PSID pCurrentSid = GetCurrentUserSid (); if (pCurrentSid) { PACL pDACL = NULL; EXPLICIT_ACCESS ea; ZeroMemory (&ea, sizeof (EXPLICIT_ACCESS)); /* grant exclusive access to the current user */ BuildTrusteeWithSidW (&ea.Trustee, pCurrentSid); ea.grfAccessPermissions = GENERIC_ALL; ea.grfAccessMode = SET_ACCESS; ea.grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT; ea.Trustee.TrusteeForm = TRUSTEE_IS_SID; ea.Trustee.TrusteeType = TRUSTEE_IS_USER; retval = SetEntriesInAcl (1, &ea, NULL, &pDACL); if (retval == ERROR_SUCCESS) { /* with PROTECTED_DACL_SECURITY_INFORMATION we remove any existing ACL (like inherited ones) */ retval = SetNamedSecurityInfo (path, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION, NULL, NULL, pDACL, NULL); } if (pDACL) LocalFree (pDACL); g_free (pCurrentSid); /* g_malloc0 */ } return (retval == ERROR_SUCCESS); }
bool AddSid(LPCWSTR sid_str) { if (_wcsicmp(sid_str, L"CU") == 0) { return AddSid(GetCurrentUserSid().c_str()); } else { PSID p = nullptr; if (!::ConvertStringSidToSid(sid_str, &p)) { return false; } std::unique_ptr<void, LocalFreeDeleter> buf(p); SID_IDENTIFIER_AUTHORITY il_id_auth = { { 0,0,0,0,0,0x10 } }; PSID_IDENTIFIER_AUTHORITY sid_id_auth = GetSidIdentifierAuthority(p); if (memcmp(il_id_auth.Value, sid_id_auth->Value, sizeof(il_id_auth.Value)) == 0) { return !!AddIntegrityLabelToBoundaryDescriptor(&boundary_desc_, p); } else { return !!AddSIDToBoundaryDescriptor(&boundary_desc_, p); } } }
void CreateNamespaceForUser(LPCWSTR account_name) { BYTE sid_bytes[MAX_SID_SIZE]; WCHAR domain[256]; SID_NAME_USE name_use; DWORD sid_size = MAX_SID_SIZE; DWORD domain_size = _countof(domain); if (!LookupAccountName(nullptr, account_name, (PSID)sid_bytes, &sid_size, domain, &domain_size, &name_use)) { printf("[ERROR] getting SId for account %ls: %d\n", account_name, GetLastError()); return; } LPWSTR sid_str; ConvertSidToStringSid((PSID)sid_bytes, &sid_str); std::wstring boundary_name = L"IEUser_"; boundary_name += sid_str; boundary_name += L"_MicrosoftEdge"; BoundaryDescriptor boundry; if (!boundry.Initialize(boundary_name.c_str())) { printf("[ERROR] initializing boundary descriptor: %d\n", GetLastError()); return; } PSECURITY_DESCRIPTOR psd; ULONG sd_size = 0; std::wstring sddl = L"D:(A;OICI;GA;;;WD)(A;OICI;GA;;;AC)(A;OICI;GA;;;WD)(A;OICI;GA;;;S-1-0-0)"; sddl += L"(A;OICI;GA;;;" + GetCurrentUserSid() + L")"; sddl += L"(A;OICI;GA;;;" + GetCurrentLogonSid() + L")"; sddl += L"S:(ML;OICI;NW;;;S-1-16-0)"; if (!ConvertStringSecurityDescriptorToSecurityDescriptor(sddl.c_str(), SDDL_REVISION_1, &psd, &sd_size)) { printf("[ERROR] converting SDDL: %d\n", GetLastError()); return; } std::unique_ptr<void, LocalFreeDeleter> sd_buf(psd); SECURITY_ATTRIBUTES secattr = {}; secattr.nLength = sizeof(secattr); secattr.lpSecurityDescriptor = psd; private_namespace ns(CreatePrivateNamespace(&secattr, boundry.boundry_desc(), boundary_name.c_str())); if (!ns) { printf("[ERROR] creating private namespace - %ls: %d\n", boundary_name.c_str(), GetLastError()); return; } printf("[SUCCESS] Created Namespace %ls, start Edge as other user\n", boundary_name.c_str()); std::wstring section_name = boundary_name + L"\\!PrivacIE!SharedMem!Settings"; while (true) { HANDLE hMapping = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, section_name.c_str()); if (hMapping) { printf("[SUCCESS] Opened other user's !PrivacIE!SharedMem!Settings section for write access\n"); return; } Sleep(1000); } }
BOOLEAN IssueUserlandSidResolveRequest(PIMAGE_PID_ENTRY Process) { PSID_RESOLVE_REQUEST pSidResolveRequest; USHORT Size; PCHAR UserSidBuffer; KIRQL irql; LARGE_INTEGER liDelay; NTSTATUS status; ASSERT(Process); if (!ActiveUserAgent) { LOG(LOG_SS_MISC, LOG_PRIORITY_VERBOSE, ("IssueUserlandSidResolveRequest: no Agent Service\n")); return FALSE; } if (KeGetCurrentIrql() != PASSIVE_LEVEL) { LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("IssueUserlandSidResolveRequest: Running at high IRQL\n")); return FALSE; } if (Process->ProcessId == SystemProcessId) { LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("IssueUserlandSidResolveRequest: Cannot issue requests on behalf of SYSTEM process\n")); // return FALSE; } /* * the following code assumes that SID_RESOLVE_REQUESTS consists of USERLAND_REQUEST_HEADER * followed by PSID_AND_ATTRIBUTES. * * GetCurrentUserSid() allocates memory for user sid + PSID_AND_ATTRIBUTES and converts SID * from absolute into relative format. */ Size = sizeof(USERLAND_REQUEST_HEADER); UserSidBuffer = GetCurrentUserSid(&Size); if (UserSidBuffer == NULL) { LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("IssueUserlandSidResolveRequest: out of memory\n")); return FALSE; } /* check for a previously resolved cached SID */ while (CacheSid == TRUE) { int SidSize = Size - sizeof(USERLAND_REQUEST_HEADER); /* cache hit? */ if (CachedSid && CachedSidReply && SidSize == CachedSidSize && memcmp(UserSidBuffer + sizeof(USERLAND_REQUEST_HEADER), CachedSid, CachedSidSize) == 0) { Process->WaitingForUserRequestId = 0; Process->UserlandReply = ExAllocatePoolWithTag(PagedPool, CachedSidReplySize, _POOL_TAG); if (Process->UserlandReply == NULL) { ExFreePoolWithTag(UserSidBuffer, _POOL_TAG); return FALSE; } memcpy(Process->UserlandReply, CachedSidReply, CachedSidReplySize); LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("IssueUserlandSidResolveRequest: Cache hit. Returning username %S\n", CachedSidReply->UserName)); ExFreePoolWithTag(UserSidBuffer, _POOL_TAG); return TRUE; } /* cache miss */ CachedSidSize = SidSize; if (CachedSid) ExFreePoolWithTag(CachedSid, _POOL_TAG); CachedSid = ExAllocatePoolWithTag(PagedPool, SidSize, _POOL_TAG); if (CachedSid == NULL) { ExFreePoolWithTag(UserSidBuffer, _POOL_TAG); return FALSE; } memcpy(CachedSid, UserSidBuffer + sizeof(USERLAND_REQUEST_HEADER), SidSize); if (CachedSidReply) { ExFreePoolWithTag(CachedSidReply, _POOL_TAG); CachedSidReply = NULL; } break; } pSidResolveRequest = (PSID_RESOLVE_REQUEST) UserSidBuffer; pSidResolveRequest->RequestHeader.RequestType = USERLAND_SID_RESOLVE_REQUEST; pSidResolveRequest->RequestHeader.RequestSize = Size; pSidResolveRequest->RequestHeader.ProcessId = Process->ProcessId; if (++SeqId == 0) SeqId = 1; pSidResolveRequest->RequestHeader.SeqId = SeqId; KeAcquireSpinLock(&gUserlandRequestListSpinLock, &irql); { pSidResolveRequest->RequestHeader.Next = UserlandRequestList; UserlandRequestList = (PUSERLAND_REQUEST_HEADER) pSidResolveRequest; } KeReleaseSpinLock(&gUserlandRequestListSpinLock, irql); Process->WaitingForUserRequestId = SeqId; Process->UserlandReply = NULL; KeClearEvent(&Process->UserlandRequestDoneEvent); /* signal the userland agent service */ if (UserlandRequestUserEvent) { /* pulse twice since userland sometimes misses single pulses */ KeSetEvent(UserlandRequestUserEvent, 0, FALSE); KeClearEvent(UserlandRequestUserEvent); KeSetEvent(UserlandRequestUserEvent, 0, FALSE); KeClearEvent(UserlandRequestUserEvent); } else { LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("IssueUserlandSidResolveRequest: UserlandRequestUserEvent is NULL\n")); } LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("%d IssueUserlandSidResolveRequest: Waiting for agent service\n", CURRENT_PROCESS_PID)); /* wait for the userland service to reply (wait for maximum of USERLAND_REQUEST_TIMEOUT seconds) */ liDelay.QuadPart = SECONDS(USERLAND_REQUEST_TIMEOUT); status = KeWaitForSingleObject(&Process->UserlandRequestDoneEvent, UserRequest, KernelMode, FALSE, &liDelay); Process->WaitingForUserRequestId = 0; if (status == STATUS_TIMEOUT) { LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("IssueUserlandSidResolveRequest: KeWaitForSingleObject timed out\n")); } else { LOG(LOG_SS_MISC, LOG_PRIORITY_DEBUG, ("IssueUserlandSidResolveRequest: KeWaitForSingleObject returned\n")); /* cache the resolved Sid */ if (CacheSid == TRUE && Process->UserlandReply != NULL) { CachedSidReply = ExAllocatePoolWithTag(PagedPool, Process->UserlandReply->ReplySize, _POOL_TAG); if (CachedSidReply) { memcpy(CachedSidReply, Process->UserlandReply, Process->UserlandReply->ReplySize); CachedSidReplySize = Process->UserlandReply->ReplySize; } } } /* at this point UserSidBuffer/pSidResolveRequest has already been deallocated in driver.c!DriverDeviceControl */ return TRUE; }