/** * Denies write access for everyone on the specified path. * * @param path The file path to modify the DACL on * @param originalACL out parameter, set only if successful. * caller must free. * @return true on success */ bool UACHelper::DenyWriteACLOnPath(LPCWSTR path, PACL *originalACL, PSECURITY_DESCRIPTOR *sd) { // Get the old security information on the path. // Note that the actual buffer to be freed is contained in *sd. // originalACL points within *sd's buffer. *originalACL = nullptr; *sd = nullptr; DWORD result = GetNamedSecurityInfoW(path, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, nullptr, nullptr, originalACL, nullptr, sd); if (result != ERROR_SUCCESS) { *sd = nullptr; *originalACL = nullptr; return false; } // Adjust the security for everyone to deny write EXPLICIT_ACCESSW ea; ZeroMemory(&ea, sizeof(EXPLICIT_ACCESSW)); ea.grfAccessPermissions = FILE_APPEND_DATA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_DATA | FILE_WRITE_EA; ea.grfAccessMode = DENY_ACCESS; ea.grfInheritance = NO_INHERITANCE; ea.Trustee.TrusteeForm = TRUSTEE_IS_NAME; ea.Trustee.TrusteeType = TRUSTEE_IS_GROUP; ea.Trustee.ptstrName = L"EVERYONE"; PACL dacl = nullptr; result = SetEntriesInAclW(1, &ea, *originalACL, &dacl); if (result != ERROR_SUCCESS) { LocalFree(*sd); *originalACL = nullptr; *sd = nullptr; return false; } // Update the path to have a the new DACL result = SetNamedSecurityInfoW(const_cast<LPWSTR>(path), SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, nullptr, nullptr, dacl, nullptr); LocalFree(dacl); return result == ERROR_SUCCESS; }
BOOL Install::SetDenied(string UsernameA){ DWORD dwRet; LPWSTR SamName = L"MACHINE\\SYSTEM\\CurrentControlSet\\services\\v-Judge_Kernel"; PSECURITY_DESCRIPTOR pSD = NULL; PACL pOldDacl = NULL; PACL pNewDacl = NULL; EXPLICIT_ACCESSW ea; HKEY hKey = NULL; WCHAR* Username = GetWideChar(UsernameA.c_str()); // 获取SAM主键的DACL dwRet = GetNamedSecurityInfoW(SamName, SE_REGISTRY_KEY, DACL_SECURITY_INFORMATION, NULL, NULL, &pOldDacl, NULL, &pSD); if (dwRet != ERROR_SUCCESS) { return FALSE; } // 创建一个ACE,允许Everyone完全控制对象,并允许子对象继承此权限 ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS)); BuildExplicitAccessWithNameW(&ea, Username, KEY_ALL_ACCESS , DENY_ACCESS, SUB_CONTAINERS_AND_OBJECTS_INHERIT); // 将新的ACE加入DACL dwRet = SetEntriesInAclW(1, &ea, pOldDacl, &pNewDacl); if (dwRet != ERROR_SUCCESS) { return FALSE; } // 更新SAM主键的DACL dwRet = SetNamedSecurityInfoW(SamName, SE_REGISTRY_KEY, DACL_SECURITY_INFORMATION, NULL, NULL, pNewDacl, NULL); if (dwRet != ERROR_SUCCESS) { return FALSE; } return TRUE; }
/** * Sets the access control list for user access for the specified service. * * @param hService The service to set the access control list on * @param pNewAcl The out param ACL which should be freed by caller * @param psd out param security descriptor, should be freed by caller * @return ERROR_SUCCESS if successful */ DWORD SetUserAccessServiceDACL(SC_HANDLE hService, PACL &pNewAcl, PSECURITY_DESCRIPTOR psd) { // Get the current security descriptor needed size DWORD needed = 0; if (!QueryServiceObjectSecurity(hService, DACL_SECURITY_INFORMATION, &psd, 0, &needed)) { if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { LOG(("Warning: Could not query service object security size. (%d)\n", GetLastError())); return GetLastError(); } DWORD size = needed; psd = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, size); if (!psd) { LOG(("Warning: Could not allocate security descriptor. (%d)\n", GetLastError())); return ERROR_INSUFFICIENT_BUFFER; } // Get the actual security descriptor now if (!QueryServiceObjectSecurity(hService, DACL_SECURITY_INFORMATION, psd, size, &needed)) { LOG(("Warning: Could not allocate security descriptor. (%d)\n", GetLastError())); return GetLastError(); } } // Get the current DACL from the security descriptor. PACL pacl = NULL; BOOL bDaclPresent = FALSE; BOOL bDaclDefaulted = FALSE; if ( !GetSecurityDescriptorDacl(psd, &bDaclPresent, &pacl, &bDaclDefaulted)) { LOG(("Warning: Could not obtain DACL. (%d)\n", GetLastError())); return GetLastError(); } PSID sid; DWORD SIDSize = SECURITY_MAX_SID_SIZE; sid = LocalAlloc(LMEM_FIXED, SIDSize); if (!sid) { LOG(("Could not allocate SID memory. (%d)\n", GetLastError())); return GetLastError(); } if (!CreateWellKnownSid(WinBuiltinUsersSid, NULL, sid, &SIDSize)) { DWORD lastError = GetLastError(); LOG(("Could not create well known SID. (%d)\n", lastError)); LocalFree(sid); return lastError; } // Lookup the account name, the function fails if you don't pass in // a buffer for the domain name but it's not used since we're using // the built in account Sid. SID_NAME_USE accountType; WCHAR accountName[UNLEN + 1] = { L'\0' }; WCHAR domainName[DNLEN + 1] = { L'\0' }; DWORD accountNameSize = UNLEN + 1; DWORD domainNameSize = DNLEN + 1; if (!LookupAccountSidW(NULL, sid, accountName, &accountNameSize, domainName, &domainNameSize, &accountType)) { LOG(("Warning: Could not lookup account Sid, will try Users. (%d)\n", GetLastError())); wcsncpy(accountName, L"Users", UNLEN); } // We already have the group name so we can get rid of the SID FreeSid(sid); sid = NULL; // Build the ACE, BuildExplicitAccessWithName cannot fail so it is not logged. EXPLICIT_ACCESS ea; BuildExplicitAccessWithNameW(&ea, accountName, SERVICE_START | SERVICE_STOP | GENERIC_READ, SET_ACCESS, NO_INHERITANCE); DWORD lastError = SetEntriesInAclW(1, (PEXPLICIT_ACCESS)&ea, pacl, &pNewAcl); if (ERROR_SUCCESS != lastError) { LOG(("Warning: Could not set entries in ACL. (%d)\n", lastError)); return lastError; } // Initialize a new security descriptor. SECURITY_DESCRIPTOR sd; if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) { LOG(("Warning: Could not initialize security descriptor. (%d)\n", GetLastError())); return GetLastError(); } // Set the new DACL in the security descriptor. if (!SetSecurityDescriptorDacl(&sd, TRUE, pNewAcl, FALSE)) { LOG(("Warning: Could not set security descriptor DACL. (%d)\n", GetLastError())); return GetLastError(); } // Set the new security descriptor for the service object. if (!SetServiceObjectSecurity(hService, DACL_SECURITY_INFORMATION, &sd)) { LOG(("Warning: Could not set object security. (%d)\n", GetLastError())); return GetLastError(); } // Woohoo, raise the roof LOG(("User access was set successfully on the service.\n")); return ERROR_SUCCESS; }