HRESULT COpcSecurity::CopyACL(PACL pDest, PACL pSrc) { ACL_SIZE_INFORMATION aclSizeInfo; LPVOID pAce; ACE_HEADER *aceHeader; if (pSrc == NULL) return S_OK; if (!GetAclInformation(pSrc, (LPVOID) &aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation)) return HRESULT_FROM_WIN32(GetLastError()); // Copy all of the ACEs to the new ACL for (UINT i = 0; i < aclSizeInfo.AceCount; i++) { if (!GetAce(pSrc, i, &pAce)) return HRESULT_FROM_WIN32(GetLastError()); aceHeader = (ACE_HEADER *) pAce; if (!AddAce(pDest, ACL_REVISION, 0xffffffff, pAce, aceHeader->AceSize)) return HRESULT_FROM_WIN32(GetLastError()); } return S_OK; }
DWORD CopyACL( PACL OldACL, PACL NewACL) { ACL_SIZE_INFORMATION aclSizeInfo; LPVOID ace; ACE_HEADER *aceHeader; ULONG i; GetAclInformation( OldACL, (LPVOID) &aclSizeInfo, (DWORD) sizeof (aclSizeInfo), AclSizeInformation); // // Copy all of the ACEs to the new ACL // for (i = 0; i < aclSizeInfo.AceCount; i++) { // // Get the ACE and header info // if (!GetAce (OldACL, i, &ace)) { return GetLastError(); } aceHeader = (ACE_HEADER *) ace; // // Add the ACE to the new list // if (!AddAce( NewACL, ACL_REVISION, 0xffffffff, ace, aceHeader->AceSize)) { return GetLastError(); } } return ERROR_SUCCESS; }
BOOL AddAceToWindowStation( IN HWINSTA WinSta, IN PSID Sid) { DWORD AclSize; SECURITY_INFORMATION SecurityInformation; PACL pDefaultAcl = NULL; PSECURITY_DESCRIPTOR WinstaSd = NULL; PACCESS_ALLOWED_ACE Ace = NULL; BOOL Ret = FALSE; /* Allocate space for an ACL */ AclSize = sizeof(ACL) + 2 * (FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + GetLengthSid(Sid)); pDefaultAcl = HeapAlloc(GetProcessHeap(), 0, AclSize); if (!pDefaultAcl) { ERR("WL: HeapAlloc() failed\n"); goto cleanup; } /* Initialize it */ if (!InitializeAcl(pDefaultAcl, AclSize, ACL_REVISION)) { ERR("WL: InitializeAcl() failed (error %lu)\n", GetLastError()); goto cleanup; } /* Initialize new security descriptor */ WinstaSd = HeapAlloc(GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH); if (!InitializeSecurityDescriptor(WinstaSd, SECURITY_DESCRIPTOR_REVISION)) { ERR("WL: InitializeSecurityDescriptor() failed (error %lu)\n", GetLastError()); goto cleanup; } /* Allocate memory for access allowed ACE */ Ace = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ACCESS_ALLOWED_ACE)+ GetLengthSid(Sid) - sizeof(DWORD)); /* Create the first ACE for the window station */ Ace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE; Ace->Header.AceFlags = CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE; Ace->Header.AceSize = sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(Sid) - sizeof(DWORD); Ace->Mask = GENERIC_ACCESS; /* Copy the sid */ if (!CopySid(GetLengthSid(Sid), &Ace->SidStart, Sid)) { ERR("WL: CopySid() failed (error %lu)\n", GetLastError()); goto cleanup; } /* Add the first ACE */ if (!AddAce(pDefaultAcl, ACL_REVISION, MAXDWORD, (LPVOID)Ace, Ace->Header.AceSize)) { ERR("WL: AddAce() failed (error %lu)\n", GetLastError()); goto cleanup; } /* Add the second ACE to the end of ACL */ Ace->Header.AceFlags = NO_PROPAGATE_INHERIT_ACE; Ace->Mask = WINSTA_ALL; if (!AddAce(pDefaultAcl, ACL_REVISION, MAXDWORD, (LPVOID)Ace, Ace->Header.AceSize)) { ERR("WL: AddAce() failed (error %lu)\n", GetLastError()); goto cleanup; } /* Add ACL to winsta's security descriptor */ if (!SetSecurityDescriptorDacl(WinstaSd, TRUE, pDefaultAcl, FALSE)) { ERR("WL: SetSecurityDescriptorDacl() failed (error %lu)\n", GetLastError()); goto cleanup; } /* Apply security to the window station */ SecurityInformation = DACL_SECURITY_INFORMATION; if (!SetUserObjectSecurity(WinSta, &SecurityInformation, WinstaSd)) { ERR("WL: SetUserObjectSecurity() failed (error %lu)\n", GetLastError()); goto cleanup; } /* Indicate success */ Ret = TRUE; cleanup: /* Free allocated stuff */ if (pDefaultAcl) HeapFree(GetProcessHeap(), 0, pDefaultAcl); if (WinstaSd) HeapFree(GetProcessHeap(), 0, WinstaSd); if (Ace) HeapFree(GetProcessHeap(), 0, Ace); return Ret; }
// Add an ACE to an ACL, expanding the ACL if needed. HRESULT AddAceToAcl(LPVOID pNewAce, PACL *ppAcl, bool bAddToEndOfList) { DWORD addPosition = bAddToEndOfList ? MAXDWORD : 0; BOOL bResult = FALSE; DWORD errorCode = S_OK; PACL biggerDACL = nullptr; HRESULT hr = S_OK; ACL_SIZE_INFORMATION aclInformation; WORD aceSize; DWORD oldSize; USHORT uSize; DWORD dwNewSizeNeeded; if ( !ARGUMENT_PRESENT(pNewAce) || !ARGUMENT_PRESENT(*ppAcl) ) { return E_INVALIDARG; } bResult = AddAce( *ppAcl, ACL_REVISION, addPosition, pNewAce, ((PACE_HEADER)pNewAce)->AceSize ); // See if we failed due to an insufficient buffer size if ( !bResult ) { errorCode = GetLastError(); if ( errorCode == ERROR_INSUFFICIENT_BUFFER ) { // Not enough space. Allocate a bigger ACL. bResult = GetAclInformation( *ppAcl, &aclInformation, sizeof(aclInformation), AclSizeInformation ); FailGracefullyGLE(bResult, L"GetAclInformation"); aceSize = ((PACE_HEADER)pNewAce)->AceSize; oldSize = aclInformation.AclBytesInUse; // Can't overflow WORD boundary hr = UShortAdd(aceSize, (USHORT)oldSize, &uSize); FailGracefully(hr, L"UShortAdd"); // Give us some extra space so that we don't have to keep // reallocating. hr = UShortMult(uSize, 2, &uSize); FailGracefully(hr, L"UShortMult"); dwNewSizeNeeded = (DWORD)uSize; // Align to a DWORD dwNewSizeNeeded = (dwNewSizeNeeded + (sizeof(DWORD) - 1)) & 0xfffffffc; // Make sure the alignment didn't overflow the size of a WORD // (the process of aligning can add up to 3) if ( dwNewSizeNeeded > USHORT_MAX ) { // It's safe to subtrat now (despite the "size needed" name) // because we overestimated earlier by multiplying by 2. dwNewSizeNeeded -= 4; } biggerDACL = (PACL)LocalAlloc(LPTR, dwNewSizeNeeded); if ( !biggerDACL ) { wprintf(L"LocalAlloc failed.\n"); hr = E_OUTOFMEMORY; goto exit_gracefully; } // Note: no need to initialize the new ACL memcpy(biggerDACL, *ppAcl, oldSize); // This cast is safe because we checked for overflow earlier biggerDACL->AclSize = (WORD)dwNewSizeNeeded; *ppAcl = biggerDACL; // Make sure this doesn't get freed later biggerDACL = nullptr; bResult = AddAce( *ppAcl, ACL_REVISION, addPosition, pNewAce, ((PACE_HEADER)pNewAce)->AceSize ); FailGracefullyGLE(bResult, L"AddAce"); } else { return HRESULT_FROM_WIN32(errorCode); } } exit_gracefully: LocalFree(biggerDACL); return hr; }
// https://ru.wikipedia.org/wiki/DACL + https://github.com/hfiref0x/WinObjEx64/tree/master/Source BOOL AddAllowSidForDevice(PWCHAR wchPath, PSID lpSid, DWORD dwSidLength) { OBJECT_ATTRIBUTES ObjAtt; RtlZeroMemory(&ObjAtt, sizeof(ObjAtt)); UNICODE_STRING UserModeDeviceName; WCHAR PathBuffer[MAX_PATH] = { 0 }; wcscpy_s(PathBuffer, L"\\??\\"); wcscat_s(PathBuffer, wchPath); UserModeDeviceName.Buffer = PathBuffer; UserModeDeviceName.Length = (USHORT)(wcslen(PathBuffer) * sizeof(WCHAR)); UserModeDeviceName.MaximumLength = (USHORT)(UserModeDeviceName.Length + sizeof(WCHAR)); InitializeObjectAttributes(&ObjAtt, &UserModeDeviceName, 0, 0, 0); HANDLE hFile; IO_STATUS_BLOCK IoStatusBlock; NTSTATUS status = ntdll_ZwOpenFile(&hFile, WRITE_DAC | READ_CONTROL, &ObjAtt, &IoStatusBlock, 0, 0); if (status != STATUS_SUCCESS) { DebugOut("ZwOpenFile(..., %S,...) failed! (status=%x)\n", wchPath, status); return FALSE; } DWORD LastError; SECURITY_DESCRIPTOR *lpSd = NULL; // адрес дескриптора безопасности DWORD dwSdLength = 0; // длина SD if (!GetKernelObjectSecurity(hFile, DACL_SECURITY_INFORMATION, NULL, dwSdLength, &dwSdLength)) { LastError = GetLastError(); if (LastError == ERROR_INSUFFICIENT_BUFFER) { dwSdLength += 1000; // !! FIX_ME lpSd = (SECURITY_DESCRIPTOR*)malloc(dwSdLength); if (!GetKernelObjectSecurity(hFile, DACL_SECURITY_INFORMATION, lpSd, dwSdLength, &dwSdLength)) { DebugOut("GetKernelObjectSecurity[2](...) failed! (LastError=0x%x)\n", GetLastError()); CloseHandle(hFile); return FALSE; } } else { DebugOut("GetKernelObjectSecurity[1](...) failed! (LastError=0x%x)\n", LastError); CloseHandle(hFile); return FALSE; } } ACL* lpOldDacl; // указатель на старый DACL BOOL bDaclPresent; // признак присутствия списка DACL BOOL bDaclDefaulted; // признак списка DACL по умолчанию if (!GetSecurityDescriptorDacl(lpSd, &bDaclPresent, &lpOldDacl, &bDaclDefaulted)) { // получаем список DACL из дескриптора безопасности DebugOut("GetSecurityDescriptorDacl(...) failed! (LastError=0x%x)\n", GetLastError()); CloseHandle(hFile); return FALSE; } DWORD dwDaclLength = lpOldDacl->AclSize + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + dwSidLength; // определяем длину нового DACL ACL* lpNewDacl = (ACL*)malloc(dwDaclLength); if (!InitializeAcl(lpNewDacl, dwDaclLength, ACL_REVISION)) { // инициализируем новый DACL DebugOut("InitializeAcl(...) failed! (LastError=0x%x)\n", GetLastError()); free(lpNewDacl); CloseHandle(hFile); return FALSE; } if (!AddAccessAllowedAce(lpNewDacl, ACL_REVISION,ACCOUNT_ALLOW_RIGHTS, lpSid)) { // добавляем новый элемент в новый DACL DebugOut("AddAccessAllowedAce(...) failed! (LastError=0x%x)\n", GetLastError()); free(lpNewDacl); CloseHandle(hFile); return FALSE; } LPVOID lpAce; // указатель на элемент ACE if (!GetAce(lpOldDacl, 0, &lpAce)) { // получаем адрес первого ACE в старом списке DACL DebugOut("GetAce(...) failed! (LastError=0x%x)\n", GetLastError()); free(lpNewDacl); CloseHandle(hFile); return FALSE; } // переписываем элементы из старого DACL в новый DACL if (bDaclPresent) { if (!AddAce(lpNewDacl, ACL_REVISION, MAXDWORD, lpAce, lpOldDacl->AclSize - sizeof(ACL))) { DebugOut("AddAce(...) failed! (LastError=0x%x)\n", GetLastError()); free(lpNewDacl); CloseHandle(hFile); return FALSE; } } if (!IsValidAcl(lpNewDacl)) { // проверяем достоверность DACL DebugOut("IsValidAcl(...) == FALSE! (LastError=0x%x)\n", GetLastError()); free(lpNewDacl); CloseHandle(hFile); return FALSE; } SECURITY_DESCRIPTOR sdAbsoluteSd; // абсолютный формат SD if (!InitializeSecurityDescriptor(&sdAbsoluteSd, SECURITY_DESCRIPTOR_REVISION)) { // создаем новый дескриптор безопасности в абсолютной форме DebugOut("InitializeSecurityDescriptor(...) failed! (LastError=0x%x)\n", GetLastError()); free(lpNewDacl); CloseHandle(hFile); return FALSE; } if (!SetSecurityDescriptorDacl(&sdAbsoluteSd, TRUE, lpNewDacl, FALSE)) { // устанавливаем DACL в новый дескриптор безопасности DebugOut("SetSecurityDescriptorDacl(...) failed! (LastError=0x%x)\n", GetLastError()); free(lpNewDacl); CloseHandle(hFile); return FALSE; } // проверяем структуру дескриптора безопасности if (!IsValidSecurityDescriptor(&sdAbsoluteSd)) { DebugOut("IsValidSecurityDescriptor(...) == FALSE! (LastError=0x%x)\n", GetLastError()); free(lpNewDacl); CloseHandle(hFile); return FALSE; } if (!SetKernelObjectSecurity(hFile, DACL_SECURITY_INFORMATION, &sdAbsoluteSd)) { // устанавливаем новый дескриптор безопасности DebugOut("IsValidSecurityDescriptor(...) == FALSE! (LastError=0x%x)\n", GetLastError()); free(lpNewDacl); CloseHandle(hFile); return FALSE; } free(lpNewDacl); CloseHandle(hFile); DebugOut("ACL Rules applyed to \"%S\"\n", PathBuffer); return TRUE; }
BOOL CNTService::ModifyVistaDefaultAuditing(string dir, int remove) { PSECURITY_DESCRIPTOR pSD = NULL; HANDLE hToken; PACL mySacl=NULL; DWORD ret=0; TOKEN_PRIVILEGES tp; LUID luid; if ( !LookupPrivilegeValue(NULL,SE_SECURITY_NAME,&luid)) { printf("LookupPrivilegeValue error: %u\n", GetLastError() ); return FALSE; } tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; // Enable the privilege or disable all privileges. OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken); if ( !AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES) NULL, (PDWORD) NULL)) { printf("AdjustTokenPrivileges error: %u\n", GetLastError() ); return FALSE; } if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) { printf("The token does not have the specified privilege. \n"); return FALSE; } //recurse through the dir WIN32_FIND_DATA findData; char Match[32], Replace[32]; if (remove){ strncpy_s(Match,_countof(Match),"Everyone",_TRUNCATE); strncpy_s(Replace,_countof(Replace),"ANONYMOUS LOGON",_TRUNCATE); } else { strncpy_s(Match,_countof(Match),"ANONYMOUS LOGON",_TRUNCATE); strncpy_s(Replace,_countof(Replace),"Everyone",_TRUNCATE); } HANDLE hFind=FindFirstFile((dir+"\\*.*").c_str(), &findData); if (hFind == INVALID_HANDLE_VALUE) { return TRUE; } // iterate over file names in directory do { string sFileName(findData.cFileName); if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { // Directory if (sFileName != "." && sFileName != "..") { // descent recursively if (!ModifyVistaDefaultAuditing(dir+"\\"+sFileName, remove)) return FALSE; } } else { // File // grab and modify the file SACL ret = GetNamedSecurityInfo((char *)(dir+"\\"+findData.cFileName).c_str(),SE_FILE_OBJECT,SACL_SECURITY_INFORMATION,NULL,NULL,NULL,&mySacl,&pSD); if (ret == ERROR_SUCCESS && mySacl != NULL && mySacl->AceCount > 0) { int SetNewAcl=0; PACL pNewAcl; ACL_SIZE_INFORMATION aclSizeInfo; ZeroMemory(&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION)); aclSizeInfo.AclBytesInUse = sizeof(ACL); if (!GetAclInformation(mySacl,(LPVOID)&aclSizeInfo,sizeof(ACL_SIZE_INFORMATION),AclSizeInformation)) { printf("Can't find ACL info, exiting\n"); return FALSE; } pNewAcl = (PACL)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,aclSizeInfo.AclBytesInUse); if (!pNewAcl) { printf("Can't allocate new ACL, exiting\n"); return FALSE; } if (!InitializeAcl(pNewAcl,aclSizeInfo.AclBytesInUse,ACL_REVISION)) { printf("Can't allocate new ACL, exiting\n"); return FALSE; } //printf("Checking: %s[%d]\n",(char *)(dir+"\\"+findData.cFileName).c_str(),mySacl->AceCount); for (int i=0; i< mySacl->AceCount; i++) { PVOID pAce;//PACE_HEADER? SID *pAceSid, *pNewAceSid=NULL; DWORD dwCbName = 0; DWORD dwCbDomainName = 0; SID_NAME_USE SidNameUse; TCHAR bufName[MAX_PATH]=""; TCHAR bufDomain[MAX_PATH]=""; ACCESS_MASK mask; SYSTEM_AUDIT_ACE *SA_Ace; TCHAR bufNewDomain[MAX_PATH]; DWORD dwNewCbDomainName = 0; DWORD dwSidSize = 0; dwNewCbDomainName = _countof(bufNewDomain); BOOL bSuccess; if (GetAce(mySacl,i,&pAce)) { if (((ACE_HEADER *)pAce)->AceType != SYSTEM_AUDIT_ACE_TYPE) { printf("ACE ERROR: not SYSTEM_AUDIT_ACE_TYPE\n"); continue; } SA_Ace = (SYSTEM_AUDIT_ACE *)pAce; pAceSid = (SID *)(&SA_Ace->SidStart); mask = SA_Ace->Mask; dwCbName = _countof(bufName); dwCbDomainName = _countof(bufDomain); bSuccess = LookupAccountSid(NULL, pAceSid, bufName, &dwCbName, bufDomain, &dwCbDomainName, &SidNameUse); if (!bSuccess) { printf("Failed to grab SID [%d]", GetLastError()); return FALSE; } //printf("ACE of %s\\%s: %d\n", bufDomain, bufName, mask); if (!strcmp(bufName,Match)) { bSuccess = LookupAccountName(NULL, Replace, NULL, &dwSidSize, bufNewDomain, &dwNewCbDomainName,&SidNameUse); if (!bSuccess && GetLastError() == ERROR_INSUFFICIENT_BUFFER) { pNewAceSid = (SID *)malloc(dwSidSize); if (!pNewAceSid) { printf("memory failed\n"); if (pNewAcl) HeapFree(GetProcessHeap(), 0, (LPVOID)pNewAcl); return FALSE; } bSuccess = LookupAccountName(NULL, Replace, pNewAceSid, &dwSidSize, bufNewDomain, &dwNewCbDomainName,&SidNameUse); if (bSuccess) { if (!AddAuditAccessAce(pNewAcl,ACL_REVISION,mask,pNewAceSid,TRUE,TRUE)) { printf("Failed to updated ACL[%d]\n",GetLastError()); free(pNewAceSid); if (pNewAcl) HeapFree(GetProcessHeap(), 0, (LPVOID)pNewAcl); return FALSE; } SetNewAcl=1; } else { printf("FAILED: %d\n", GetLastError()); //printf("\n"); } free(pNewAceSid); } else { printf("FAILED to find %s\n",Replace); } } else { if (!AddAce(pNewAcl,ACL_REVISION,MAXDWORD,pAce,((PACE_HEADER)pAce)->AceSize)) { printf("Couldn't add ACE to acl [%d]\n",GetLastError()); if (pNewAcl) HeapFree(GetProcessHeap(), 0, (LPVOID)pNewAcl); return FALSE; } } } else { printf("ACE error %d:%d[%d]\n",mySacl->AceCount,i,GetLastError()); return FALSE; } } if (SetNewAcl && pNewAcl) { ret = SetNamedSecurityInfo((char *)(dir+"\\"+findData.cFileName).c_str(),SE_FILE_OBJECT,SACL_SECURITY_INFORMATION,NULL,NULL,NULL,pNewAcl); if (ret == ERROR_SUCCESS) { printf("Fixed: %s\n",(char *)(dir+"\\"+findData.cFileName).c_str()); } else { printf("Failed to fix: %s\n",(char *)(dir+"\\"+findData.cFileName).c_str()); } } if (pNewAcl) HeapFree(GetProcessHeap(), 0, (LPVOID)pNewAcl); } else { if (ret) printf("fail %d %s\n", ret,(char *)(dir+"\\"+findData.cFileName).c_str()); //else printf("NO SACL: %s\n",(char *)(dir+"\\"+findData.cFileName).c_str()); } if (pSD) LocalFree(pSD); } } while (FindNextFile(hFind, &findData)); return TRUE; }
/* * AddUserToTokenDacl(HANDLE hToken) * * This function adds the current user account to the restricted * token used when we create a restricted process. * * This is required because of some security changes in Windows * that appeared in patches to XP/2K3 and in Vista/2008. * * On these machines, the Administrator account is not included in * the default DACL - you just get Administrators + System. For * regular users you get User + System. Because we strip Administrators * when we create the restricted token, we are left with only System * in the DACL which leads to access denied errors for later CreatePipe() * and CreateProcess() calls when running as Administrator. * * This function fixes this problem by modifying the DACL of the * token the process will use, and explicitly re-adding the current * user account. This is still secure because the Administrator account * inherits its privileges from the Administrators group - it doesn't * have any of its own. */ BOOL AddUserToTokenDacl(HANDLE hToken) { int i; ACL_SIZE_INFORMATION asi; ACCESS_ALLOWED_ACE *pace; DWORD dwNewAclSize; DWORD dwSize = 0; DWORD dwTokenInfoLength = 0; PACL pacl = NULL; PTOKEN_USER pTokenUser = NULL; TOKEN_DEFAULT_DACL tddNew; TOKEN_DEFAULT_DACL *ptdd = NULL; TOKEN_INFORMATION_CLASS tic = TokenDefaultDacl; BOOL ret = FALSE; /* Figure out the buffer size for the DACL info */ if (!GetTokenInformation(hToken, tic, (LPVOID) NULL, dwTokenInfoLength, &dwSize)) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { ptdd = (TOKEN_DEFAULT_DACL *) LocalAlloc(LPTR, dwSize); if (ptdd == NULL) { log_error("could not allocate %lu bytes of memory", dwSize); goto cleanup; } if (!GetTokenInformation(hToken, tic, (LPVOID) ptdd, dwSize, &dwSize)) { log_error("could not get token information: error code %lu", GetLastError()); goto cleanup; } } else { log_error("could not get token information buffer size: error code %lu", GetLastError()); goto cleanup; } } /* Get the ACL info */ if (!GetAclInformation(ptdd->DefaultDacl, (LPVOID) &asi, (DWORD) sizeof(ACL_SIZE_INFORMATION), AclSizeInformation)) { log_error("could not get ACL information: error code %lu", GetLastError()); goto cleanup; } /* Get the current user SID */ if (!GetTokenUser(hToken, &pTokenUser)) goto cleanup; /* callee printed a message */ /* Figure out the size of the new ACL */ dwNewAclSize = asi.AclBytesInUse + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pTokenUser->User.Sid) -sizeof(DWORD); /* Allocate the ACL buffer & initialize it */ pacl = (PACL) LocalAlloc(LPTR, dwNewAclSize); if (pacl == NULL) { log_error("could not allocate %lu bytes of memory", dwNewAclSize); goto cleanup; } if (!InitializeAcl(pacl, dwNewAclSize, ACL_REVISION)) { log_error("could not initialize ACL: error code %lu", GetLastError()); goto cleanup; } /* Loop through the existing ACEs, and build the new ACL */ for (i = 0; i < (int) asi.AceCount; i++) { if (!GetAce(ptdd->DefaultDacl, i, (LPVOID *) &pace)) { log_error("could not get ACE: error code %lu", GetLastError()); goto cleanup; } if (!AddAce(pacl, ACL_REVISION, MAXDWORD, pace, ((PACE_HEADER) pace)->AceSize)) { log_error("could not add ACE: error code %lu", GetLastError()); goto cleanup; } } /* Add the new ACE for the current user */ if (!AddAccessAllowedAceEx(pacl, ACL_REVISION, OBJECT_INHERIT_ACE, GENERIC_ALL, pTokenUser->User.Sid)) { log_error("could not add access allowed ACE: error code %lu", GetLastError()); goto cleanup; } /* Set the new DACL in the token */ tddNew.DefaultDacl = pacl; if (!SetTokenInformation(hToken, tic, (LPVOID) &tddNew, dwNewAclSize)) { log_error("could not set token information: error code %lu", GetLastError()); goto cleanup; } ret = TRUE; cleanup: if (pTokenUser) LocalFree((HLOCAL) pTokenUser); if (pacl) LocalFree((HLOCAL) pacl); if (ptdd) LocalFree((HLOCAL) ptdd); return ret; }
BOOL Process::AddAceToProc(DWORD mask,PSID psid){//Здесь происходит очень сильная магия. И я не разобрался до конца почему тут косяки //Смысл в том, что нельзя просто так добавить ACE в DACL. //Придется создать DACL бОльшего размера чем предыдущий, и скопировать все в новый из старого. //Потом вручную насоздавть структур и сохранить их. //Проблема в том, что почему-то не сохраняется нужный RID. ВЫдается ошибка, что сессия уже используется. printf("Adding ace\n"); BOOL bSuccess = FALSE; ACCESS_ALLOWED_ACE *pAce = NULL; ACL_SIZE_INFORMATION aclSizeInfo; PACL pacl; PACL pNewAcl = NULL; PSECURITY_DESCRIPTOR psd = NULL; PSECURITY_DESCRIPTOR psdNew = NULL; PVOID pTemAce; SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION; DWORD dwSidSize = 0; DWORD dwSidSizeNeeded; DWORD dwNewAclSize; BOOL bDaclPresent; BOOL bDaclExist; __try{ if (!GetUserObjectSecurity( _handle, &si, psd, dwSidSize, &dwSidSizeNeeded) ) if (GetLastError() == ERROR_INSUFFICIENT_BUFFER){ psd = (PSECURITY_DESCRIPTOR)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwSidSizeNeeded); if (psd == NULL){ printf("psd: %d\n",GetLastError()); __leave; } psdNew = (PSECURITY_DESCRIPTOR)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwSidSizeNeeded); if (psdNew == NULL){ printf("psdNew : %d\n",GetLastError()); __leave; } dwSidSize = dwSidSizeNeeded; if (!GetUserObjectSecurity( _handle, &si, psd, dwSidSize, &dwSidSizeNeeded) ){ printf("GetUserObjectSEcurity: %d\n",GetLastError()); __leave; } }else{ printf("Some thing else: %d\n",GetLastError()); __leave; } if (!InitializeSecurityDescriptor( psdNew, SECURITY_DESCRIPTOR_REVISION) ){ printf("init secur descr: %d\n",GetLastError()); __leave; } if (!GetSecurityDescriptorDacl( psd, &bDaclPresent, &pacl, &bDaclExist) ){ printf("get dacl: %d\n",GetLastError()); __leave; } ZeroMemory(&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION)); aclSizeInfo.AclBytesInUse = sizeof(ACL); if (pacl != NULL){ if (!GetAclInformation( pacl, (LPVOID)&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation) ){ printf("get acl info -size : %d\n",GetLastError()); __leave; } } dwNewAclSize = aclSizeInfo.AclBytesInUse + (2*sizeof(ACCESS_ALLOWED_ACE)) + (2*GetLengthSid(psid)) - (2*sizeof(DWORD)); pNewAcl = (PACL)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwNewAclSize); if (pNewAcl == NULL) __leave; if (!InitializeAcl(pNewAcl,dwNewAclSize,ACL_REVISION)){ printf("init new acl : %d \n",GetLastError()); __leave; } if (bDaclPresent){ // Copy the ACEs to the new ACL. if (aclSizeInfo.AceCount){ for (DWORD i=0; i < aclSizeInfo.AceCount; i++){ // Get an ACE. if (!GetAce(pacl, i, &pTemAce)) __leave; // Add the ACE to the new ACL. if (!AddAce( pNewAcl, ACL_REVISION, MAXDWORD, pTemAce, ((PACE_HEADER)pTemAce)->AceSize) ){ printf("add ace in filling: %d",GetLastError()); __leave; } } } } pAce = (ACCESS_ALLOWED_ACE *)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psid) - sizeof(DWORD)); if (pAce==NULL) __leave; pAce->Header.AceType = ACCESS_ALLOWED_ACE_TYPE; pAce->Header.AceFlags = CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE; pAce->Header.AceSize = LOWORD(sizeof(ACCESS_ALLOWED_ACE)+GetLengthSid(psid)-sizeof(DWORD)); pAce->Mask = mask; // if(!CopySid(GetLengthSid(psid), &pAce->SidStart, psid)){ //official way to save sid in ace, but strange // printf("copy sid : %d\n",GetLastError()); // __leave; // } pAce->SidStart = parseRID(psid); if(!AddAce( pNewAcl, ACL_REVISION, MAXDWORD, (LPVOID)pAce, pAce->Header.AceSize) ) { printf("add new ace %d\n",GetLastError()); __leave; } printf("WAIT!!! %d %u %d\n",pAce->SidStart,pAce->Mask,parseRID(psid)); if(!SetSecurityDescriptorDacl( psdNew, TRUE, pNewAcl, FALSE) ) { printf("set dacl %d\n",GetLastError()); __leave; } if(!SetKernelObjectSecurity(_handle,si,psdNew)){ printf("set obj secur %d\n",GetLastError()); __leave; } bSuccess = TRUE; printf("Success. added %u for %d\n",pAce->Mask,pAce->SidStart); } __finally{ if (pAce != NULL) HeapFree(GetProcessHeap(), 0, (LPVOID)pAce); if (pNewAcl != NULL) HeapFree(GetProcessHeap(), 0, (LPVOID)pNewAcl); if (psd != NULL) HeapFree(GetProcessHeap(), 0, (LPVOID)psd); if (psdNew != NULL) HeapFree(GetProcessHeap(), 0, (LPVOID)psdNew); } return bSuccess; }
BOOL _ReorderACL(PACL pacl) { // acls used to only have ACCESS_DENIED_ACE's first - more complicated rules with object & inherited ACEs if (pacl->AceCount <= 1) return TRUE; BOOL ret = TRUE; DWORD aceind = 0; DWORD ace_insert_ind; DWORD aclsize=pacl->AclSize; DWORD acecount=pacl->AceCount; DWORD aclrev = pacl->AclRevision; PACE_HEADER pace; // ??? put these in an array so they can be incremented in a loop ??? DWORD access_denied_pos=0, access_denied_object_pos=0; DWORD access_allowed_pos=0, access_allowed_object_pos=0; DWORD inherited_pos=0; // create new acl to copy ace's into in correct order PACL pacl_ordered=(ACL *)malloc(aclsize); if (pacl_ordered==NULL){ PyErr_Format(PyExc_MemoryError,"Error reordering ACL: Unable to allocate acl of size %d", aclsize); return FALSE; } ZeroMemory(pacl_ordered,aclsize); if (!::InitializeAcl(pacl_ordered,aclsize,aclrev)){ ret=FALSE; goto done; } /* add ACE's in correct order, keep index of position at which to add each type ACCESS_DENIED_ACE_TYPE ACCESS_DENIED_OBJECT_ACE_TYPE ACCESS_ALLOWED_ACE_TYPE ACCESS_ALLOWED_OBJECT_ACE_TYPE followed by inherited ACEs whose order should not be changed */ for (aceind=0;aceind<acecount;aceind++){ if (!GetAce(pacl, aceind, (void **) &pace)){ PyWin_SetAPIError("ReorderACL"); ret=FALSE; goto done; } if (pace->AceFlags&INHERITED_ACE){ ace_insert_ind=inherited_pos; inherited_pos++; } else switch(pace->AceType){ case ACCESS_DENIED_ACE_TYPE: ace_insert_ind=access_denied_pos; access_denied_pos++; access_denied_object_pos++; access_allowed_pos++; access_allowed_object_pos++; inherited_pos++; break; case ACCESS_DENIED_OBJECT_ACE_TYPE: ace_insert_ind=access_denied_object_pos; access_denied_object_pos++; access_allowed_pos++; access_allowed_object_pos++; inherited_pos++; break; case ACCESS_ALLOWED_ACE_TYPE: ace_insert_ind=access_allowed_pos; access_allowed_pos++; access_allowed_object_pos++; inherited_pos++; break; case ACCESS_ALLOWED_OBJECT_ACE_TYPE: ace_insert_ind=access_allowed_object_pos; access_allowed_object_pos++; inherited_pos++; break; default: // there are several new types waiting in the wings, make no assumptions about them PyErr_Format(PyExc_NotImplementedError,"Ace type %d is not supported yet", pace->AceType); ret=FALSE; goto done; } if (!AddAce(pacl_ordered, aclrev, ace_insert_ind, pace, pace->AceSize)){ PyWin_SetAPIError("ReorderACL"); ret=FALSE; goto done; } } // copy reordered ACL back to old location memcpy(pacl,pacl_ordered,aclsize); done: free(pacl_ordered); return ret; }
// address: 0x401000 void _start(unsigned int param1, __size32 param2) { unsigned char cl; // r9 __size32 eax; // r24 __size32 eax_1; // r24{27} int eax_2; // r24{245} int eax_3; // r24{162} __size32 ebp; // r29 unsigned int ebx; // r27 unsigned short *ebx_1; // r27 unsigned int ebx_10; // r27{261} union { unsigned int x11; unsigned short * x12; } ebx_11; // r27{335} __size32 ebx_12; // r27{300} union { unsigned int x11; unsigned short * x12; } ebx_13; // r27{323} union { unsigned int x11; unsigned short * x12; } ebx_14; // r27{292} union { unsigned int x11; void * x12; } ebx_15; // r27{347} unsigned int ebx_2; // r27{34} unsigned int ebx_3; // r27{44} unsigned int ebx_4; // r27{112} __size32 ebx_5; // r27{168} __size32 ebx_6; // r27{172} unsigned short *ebx_7; // r27{305} unsigned int ebx_8; // r27{239} unsigned int ebx_9; // r27{282} int ecx; // r25 __size32 *ecx_1; // r25 __size32 *ecx_2; // r25{259} __size32 edi; // r31 int edx; // r26 void *edx_1; // r26 __size32 esi; // r30 __size32 esi_1; // r30{12} __size32 *esi_10; // r30{221} __size32 *esi_11; // r30{219} __size32 *esi_12; // r30{214} __size32 esi_13; // r30{83} unsigned int esi_14; // r30{283} unsigned int esi_15; // r30{270} unsigned int esi_16; // r30{262} __size32 *esi_17; // r30{337} __size32 *esi_18; // r30{307} __size32 *esi_19; // r30{294} __size32 esi_2; // r30{72} __size32 *esi_20; // r30{349} __size32 esi_3; // r30{253} unsigned int esi_4; // r30{94} unsigned int esi_5; // r30{108} unsigned int esi_6; // r30{132} __size32 *esi_7; // r30{150} __size32 esi_8; // r30{177} __size32 *esi_9; // r30{180} int esp; // r28 int local1; // m[esp - 52] int local12; // m[esp - 48] __size32 *local2; // m[esp - 52] int local21; // m[esp - 52]{355} __size32 *local22; // m[esp - 52]{374} unsigned int local23; // m[esp - 84]{377} unsigned int local24; // ebx_8{239} __size32 local25; // esi_13{247} __size32 local26; // esi_3{253} unsigned int local27; // ebx_10{261} unsigned int local28; // esi_16{262} unsigned int local29; // esi_15{270} unsigned int local3; // m[esp - 84] unsigned int local30; // ebx_9{282} unsigned int local31; // esi_14{283} union { unsigned int x11; unsigned short * x12; } local32; // ebx_14{292} __size32 *local33; // esi_19{294} unsigned int local34; // param1{360} __size32 local35; // ebx_12{300} __size32 *local36; // esi_18{307} unsigned int local37; // local3{369} union { unsigned int x11; unsigned short * x12; } local38; // ebx_11{335} __size32 *local39; // esi_17{337} unsigned int local40; // local3{372} int local41; // eax_3{344} union { unsigned int x11; void * x12; } local42; // ebx_15{347} __size32 *local43; // esi_20{349} union { void * x13; int x14; } local5; // m[esp - 80] esi_1 = 0; eax_1 = AddAce(); local25 = esi_1; local34 = param1; ebx_2 = eax_1 + 37; eax = AreAllAccessesGranted(); local24 = ebx_2; if (eax == 0) { ebx_3 = eax_1 + 3; local24 = ebx_3; } ebx_8 = local24; CloseHandle(89); local27 = ebx_8; ecx = VirtualProtect(); /* Warning: also results in edx */ eax = 0; edi = param2; do { eax_2 = eax; esi_13 = local25; local26 = esi_13; if (esi_13 == ebx_8) { esi_2 = 0; local26 = esi_2; } esi_3 = local26; edi += edx * 9; cl = *(esi_3 + 0x404000); ecx = ecx >> 8 & 0xffffff | (cl); *(char*)(eax_2 + 0x401278) = *(eax_2 + 0x401278) ^ cl; eax = eax_2 + 1; esi_13 = esi_3 + 1; local25 = esi_13; } while (eax_2 + 1 < 0x1420); ecx_1 = 0x402558; esi_4 = ebx_8 + (esi_3 + 1) * 4; edi = 0xf0400ff8; local1 = 0; local28 = esi_4; do { ecx_2 = ecx_1; ebx_10 = local27; esi_16 = local28; local21 = local1; eax = *(ecx_2 + 4); edx_1 = ecx_2 + 8; local30 = ebx_10; local31 = esi_16; if ((int)((eax - 8) / 2) > 0) { esi_5 = (eax - 8) / 2; local29 = esi_5; do { esi_15 = local29; eax = *(unsigned short*)edx_1; ebx_4 = eax & 0xf000; local30 = ebx_4; if ((eax & 0xf000) == 0x3000) { eax = (eax & 0xfff) + *ecx_2; *(__size32*)(eax + 0x400ff8) = *(eax + 0x400ff8) - 0xfbff008; } edx_1++; esi_6 = esi_15 - 1; local29 = esi_6; local31 = esi_6; } while (esi_15 != 1); } ebx_9 = local30; esi_14 = local31; eax = *(ecx_2 + 4); ecx_1 = ecx_2 + eax; cl = (unsigned char) ecx_2 + eax; local1 = local21 + eax; local27 = ebx_9; local28 = esi_14; local32 = ebx_9; local41 = eax; local42 = ebx_9; } while ((unsigned int)(local21 + eax) < 228); flags = SUBFLAGS32(*0x401d64, 0, global11); esi_7 = 0x401d54; local2 = 0x401d54; local33 = esi_7; local43 = esi_7; if (*0x401d64 != 0) { do { ebx_14 = local32; esi_19 = local33; param1 = local34; edx = *(esi_19 + 12); eax_3 = LoadLibraryA(edx + 0x400ff8); /* Warning: also results in ecx_1 */ local37 = param1; local38 = ebx_14; local39 = esi_19; local40 = param1; edi = eax_3; if (eax_3 != 0) { ebx_5 = *esi_19; local35 = ebx_5; if (ebx_5 == 0) { ebx_6 = *(esi_19 + 16); local35 = ebx_6; } ebx_12 = local35; ebx_1 = ebx_12 + 0x400ff8; esi_8 = *(esi_19 + 16); eax = *(ebx_12 + 0x400ff8); esi_9 = esi_8 + 0x400ff8; flags = LOGICALFLAGS32(eax); local36 = esi_9; if (eax != 0) { do { ebx_7 = ebx_1; esi_18 = local36; if (flags) { cl = (unsigned char) eax + 0x400ffa; eax = GetProcAddress(edi, eax + 0x400ffa); /* Warning: also results in ecx_1 */ } else { eax = *(unsigned short*)ebx_7; eax = GetProcAddress(edi, eax); /* Warning: also results in ecx_1 */ edi = eax_3; } ebx_1 = ebx_7 + 4; *(__size32*)esi_18 = eax; eax = *(ebx_7 + 4); esi_12 = esi_18 + 4; flags = LOGICALFLAGS32(eax); local36 = esi_12; local37 = local3; } while (eax != 0); } eax_3 = eax; ebx_13 = ebx_1; local3 = local37; esi_11 = local2; local38 = ebx_13; local39 = esi_11; local40 = local3; } ebx_11 = local38; esi_17 = local39; local3 = local40; esi_10 = esi_17 + 20; tmp1 = *(esi_17 + 36); flags = SUBFLAGS32(*(esi_17 + 36), 0, tmp1); local2 = esi_17 + 20; local32 = ebx_11; local33 = esi_10; local34 = local3; local41 = eax_3; local42 = ebx_11; local43 = esi_10; } while (*(esi_17 + 36) != 0); } eax_3 = local41; ebx_15 = local42; esi_20 = local43; (*0x401a48)(local23, local5, pc, 0x401000, 0x3000, 64, esp - 40, -1, local22, local12, 0, 0, 0, 0, param2, esi, ebp, ebx, cl, eax_3, ecx_1, 0x401a48, ebx_15, 0x400ff8, esi_20, edi, flags, ZF, CF); *(__size32*)(esp - 4) = 0; ExitProcess(*(esp - 4)); return; }
void Dacl::AddDeniedAce(const Sid& aSid, ACCESS_MASK aAccessMask) { return AddAce(aSid, DENY_ACCESS, aAccessMask); }
void Dacl::AddAllowedAce(const Sid& aSid, ACCESS_MASK aAccessMask) { return AddAce(aSid, GRANT_ACCESS, aAccessMask); }
static BOOL new_acl(SaveAclStruct *save_acl){ HANDLE tokenh; TOKEN_DEFAULT_DACL newdacl; DWORD required; PACL oldacl; PACL newacl; int i; ACL_SIZE_INFORMATION si; size_t newsize; PSID extra_sid; SID_IDENTIFIER_AUTHORITY nt_auth = SECURITY_NT_AUTHORITY; TOKEN_DEFAULT_DACL dummy; save_acl->initialized = FALSE; if(!OpenProcessToken(GetCurrentProcess(), TOKEN_READ|TOKEN_WRITE,&tokenh)){ log_warning("Failed to open access token."); return FALSE; } save_acl->defdacl = &dummy; required = sizeof(TOKEN_DEFAULT_DACL); GetTokenInformation(tokenh, TokenDefaultDacl, &(save_acl->defdacl), sizeof(TOKEN_DEFAULT_DACL), &required); if(required == 0){ log_warning("Failed to get any ACL info from token."); CloseHandle(tokenh); return FALSE; } save_acl->defdacl = LocalAlloc(LPTR,required); if(!GetTokenInformation(tokenh, TokenDefaultDacl, save_acl->defdacl, required, &required)){ #ifdef HARDDEBUG { char *mes; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &mes, 0, NULL ); log_info(mes); LocalFree(mes); } #endif log_warning("Failed to get default ACL from token."); CloseHandle(tokenh); return FALSE; } oldacl = save_acl->defdacl->DefaultDacl; if(!GetAclInformation(oldacl, &si, sizeof(si), AclSizeInformation)){ log_warning("Failed to get size information for ACL"); CloseHandle(tokenh); return FALSE; } if(!AllocateAndInitializeSid(&nt_auth, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &extra_sid)){ log_warning("Failed to initialize administrator SID."); CloseHandle(tokenh); return FALSE; } newsize = si.AclBytesInUse + sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(extra_sid); newacl = LocalAlloc(LPTR,newsize); if(!InitializeAcl(newacl, newsize, ACL_REVISION)){ log_warning("Failed to initialize new ACL."); LocalFree(newacl); FreeSid(extra_sid); CloseHandle(tokenh); return FALSE; } for(i=0;i<((int)si.AceCount);++i){ ACE_HEADER *ace_header; if (!GetAce (oldacl, i, &ace_header)){ log_warning("Failed to get ACE from old ACL."); LocalFree(newacl); FreeSid(extra_sid); CloseHandle(tokenh); return FALSE; } if(!AddAce(newacl,ACL_REVISION,0xffffffff,ace_header, ace_header->AceSize)){ log_warning("Failed to set ACE in new ACL."); LocalFree(newacl); FreeSid(extra_sid); CloseHandle(tokenh); return FALSE; } } if(!AddAccessAllowedAce(newacl, ACL_REVISION2, PROCESS_ALL_ACCESS, extra_sid)){ log_warning("Failed to add system ACE to new ACL."); LocalFree(newacl); FreeSid(extra_sid); return FALSE; } newdacl.DefaultDacl = newacl; if(!SetTokenInformation(tokenh, TokenDefaultDacl, &newdacl, sizeof(newdacl))){ log_warning("Failed to set token information"); LocalFree(newacl); FreeSid(extra_sid); CloseHandle(tokenh); return FALSE; } save_acl->initialized = TRUE; save_acl->newacl = newacl; save_acl->adminsid = extra_sid; CloseHandle(tokenh); return TRUE; }
BOOL AddAceToWindowStation(HWINSTA hwinsta, PSID psid) { // Obtain the DACL for the window station. SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION; DWORD sd_length = 0; if (!GetUserObjectSecurity(hwinsta, &si, NULL, 0, &sd_length)) { if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { printf("GetUserObjectSecurity() failed: %d\n", GetLastError()); return FALSE; } } auto_buffer<PSECURITY_DESCRIPTOR> psd(sd_length); if (!GetUserObjectSecurity(hwinsta, &si, psd.get(), sd_length, &sd_length)) { printf("GetUserObjectSecurity() failed: %d\n", GetLastError()); return FALSE; } // Create a new DACL. auto_buffer<PSECURITY_DESCRIPTOR> psd_new(sd_length); if (!InitializeSecurityDescriptor(psd_new.get(), SECURITY_DESCRIPTOR_REVISION)) { printf("InitializeSecurityDescriptor() failed: %d\n", GetLastError()); return FALSE; } // Get the DACL from the security descriptor. BOOL bDaclPresent; PACL pacl; BOOL bDaclExist; if (!GetSecurityDescriptorDacl(psd.get(), &bDaclPresent, &pacl, &bDaclExist)) { printf("GetSecurityDescriptorDacl() failed: %d\n", GetLastError()); return FALSE; } // Initialize the ACL. ACL_SIZE_INFORMATION aclSizeInfo = {}; aclSizeInfo.AclBytesInUse = sizeof(ACL); if (NULL != pacl) { // get the file ACL size info if (!GetAclInformation(pacl, &aclSizeInfo, sizeof aclSizeInfo, AclSizeInformation)) { printf("GetAclInformation() failed: %d\n", GetLastError()); return FALSE; } } // Compute the size of the new ACL. DWORD new_acl_size = aclSizeInfo.AclBytesInUse + (2 * sizeof(ACCESS_ALLOWED_ACE)) + (2 * GetLengthSid(psid)) - (2 * sizeof(DWORD)); auto_buffer<PACL> new_acl(new_acl_size); // Initialize the new DACL. if (!InitializeAcl(new_acl.get(), new_acl_size, ACL_REVISION)) { printf("InitializeAcl() failed: %d\n", GetLastError()); return FALSE; } // If DACL is present, copy it to a new DACL. if (bDaclPresent) { // Copy the ACEs to the new ACL. if (aclSizeInfo.AceCount) { for (DWORD i = 0; i != aclSizeInfo.AceCount; ++i) { LPVOID pTempAce; if (!GetAce(pacl, i, &pTempAce)) { printf("GetAce() failed: %d\n", GetLastError()); return FALSE; } if (!AddAce(new_acl.get(), ACL_REVISION, MAXDWORD, pTempAce, ((PACE_HEADER)pTempAce)->AceSize)) { printf("AddAce() failed: %d\n", GetLastError()); return FALSE; } } } } // Add the first ACE to the window station. auto_buffer<ACCESS_ALLOWED_ACE*> ace(sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psid) - sizeof(DWORD)); ace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE; ace->Header.AceFlags = CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE; ace->Header.AceSize = (WORD) (sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psid) - sizeof(DWORD)); ace->Mask = GENERIC_ACCESS; if (!CopySid(GetLengthSid(psid), &ace->SidStart, psid)) { printf("CopySid() failed: %d\n", GetLastError()); return FALSE; } if (!AddAce(new_acl.get(), ACL_REVISION, MAXDWORD, ace.get(), ace->Header.AceSize)) { printf("AddAce() failed: %d\n", GetLastError()); return FALSE; } // Add the second ACE to the window station. ace->Header.AceFlags = NO_PROPAGATE_INHERIT_ACE; ace->Mask = WINSTA_ALL; if (!AddAce(new_acl.get(), ACL_REVISION,MAXDWORD, ace.get(), ace->Header.AceSize)) { printf("AddAce() failed: %d\n", GetLastError()); return FALSE; } // Set a new DACL for the security descriptor. if (!SetSecurityDescriptorDacl(psd_new.get(), TRUE, new_acl.get(), FALSE)) { printf("SetSecurityDescriptorDacl() failed: %d\n", GetLastError()); return FALSE; } // Set the new security descriptor for the window station. if (!SetUserObjectSecurity(hwinsta, &si, psd_new.get())) { printf("SetUserObjectSecurity() failed: %d\n", GetLastError()); return FALSE; } return TRUE; }
// address: 0x401000 void _start(unsigned int param1) { short ax; // r0 unsigned char cl; // r9 __size32 eax; // r24 unsigned int eax_2; // r24{28} __size32 eax_3; // r24{245} __size32 ebp; // r29 unsigned int ebx; // r27 int *ebx_1; // r27 unsigned int ebx_2; // r27{31} unsigned int ebx_3; // r27{47} __size32 ebx_4; // r27{168} __size32 ebx_5; // r27{172} int *ebx_6; // r27{311} unsigned int ebx_7; // r27{238} __size32 ebx_8; // r27{305} int ecx; // r25 __size32 *ecx_1; // r25 __size32 *ecx_2; // r25{260} unsigned int ecx_3; // r25{160} unsigned int edi; // r31 int edx; // r26 unsigned int esi; // r30 __size32 *esi_1; // r30 unsigned int esi_10; // r30{247} unsigned int esi_11; // r30{286} unsigned int esi_12; // r30{271} unsigned int esi_13; // r30{262} union { unsigned int x7; __size32 * x8; } esi_14; // r30{313} unsigned int esi_2; // r30{12} unsigned int esi_3; // r30{57} unsigned int esi_4; // r30{69} unsigned int esi_5; // r30{101} unsigned int esi_6; // r30{128} __size32 *esi_7; // r30{218} union { unsigned int x7; __size32 * x8; } esi_8; // r30{185} unsigned int esi_9; // r30{253} int esp; // r28 void *esp_1; // r28{42} void *esp_2; // r28{298} unsigned int local0; // m[esp - 36] unsigned int local12; // m[esp - 36]{350} unsigned int local13; // ebx_7{238} unsigned int local14; // esi_10{247} unsigned int local15; // param1{248} unsigned int local16; // esi_9{253} unsigned int local17; // esi_13{262} unsigned int local18; // esi_12{271} unsigned int local19; // esi_11{286} __size32 local20; // ebx_8{305} union { unsigned int x7; __size32 * x8; } local21; // esi_14{313} __size32 *local22; // esi_7{331} union { __size32 * x5; unsigned int x6; } local23; // ecx{340} esi_2 = 0; eax_2 = AddAce(); local14 = esi_2; local15 = param1; ebx_2 = eax_2 + 22; eax = AreAnyAccessesGranted(); /* Warning: also results in ecx, esp_1 */ local13 = ebx_2; if (eax == 0) { ebx_3 = eax_2 - 12; local13 = ebx_3; } ebx_7 = local13; eax = 0; do { eax_3 = eax; esi_10 = local14; param1 = local15; local16 = esi_10; if (esi_10 == ebx_7) { esi_3 = 0; local16 = esi_3; } esi_9 = local16; edi = ecx + param1 * 4 + esi_9; cl = *(esi_9 + 0x404000); ecx = ecx >> 8 & 0xffffff | (cl); *(char*)(eax_3 + 0x401190) = *(eax_3 + 0x401190) ^ cl; eax = eax_3 + 1; esi_4 = esi_9 + 1; local14 = esi_4; local15 = edi; local17 = esi_4; } while (eax_3 + 1 < 0x1440); ecx_1 = 0x402490; ebx_1 = 0xf0400f10; local0 = 0; edi = esi_9 + edi * 4 + 1; do { ecx_2 = ecx_1; esi_13 = local17; local12 = local0; eax = *(ecx_2 + 4); edi = (eax - 8) / 2 + edi * 8; edx = ecx_2 + 8; local19 = esi_13; if ((int)((eax - 8) / 2) > 0) { esi_5 = (eax - 8) / 2; local18 = esi_5; do { esi_12 = local18; eax = *(unsigned short*)edx; edi = eax & 0xf000; if ((eax & 0xf000) == 0x3000) { eax = (eax & 0xfff) + *ecx_2; *(__size32*)(eax + 0x400f10) = *(eax + 0x400f10) - 0xfbff0f0; } edx++; esi_6 = esi_12 - 1; local18 = esi_6; local19 = esi_6; } while (esi_12 != 1); } esi_11 = local19; eax = *(ecx_2 + 4); ax = (unsigned short) eax; ecx_1 = ecx_2 + eax; cl = (unsigned char) ecx_2 + eax; local0 = local12 + eax; local17 = esi_11; local23 = ecx_1; } while (local12 + eax < 228); esi_1 = 0x401c84; edi += edi; flags = SUBFLAGS32(*0x401c94, 0, global10); if (*0x401c94 != 0) { do { esp_2 = esp_1; esi_14 = esi_1; edx = *(esi_14 + 12); *(__size32*)(esp_2 - 4) = edx + 0x400f10; eax = LoadLibraryA(*(esp_2 - 4)); /* Warning: also results in ecx_3 */ local21 = esi_14; local22 = esi_14; local22 = esi_14; edx = eax; *(union { unsigned int x3; void * x4; }*)(esp_2 + 20) = eax; ecx = ecx_3 * 3; cl = (unsigned char) ecx_3 * 3; if (eax != 0) { ebx_4 = *esi_14; local20 = ebx_4; if (ebx_4 == 0) { ebx_5 = *(esi_14 + 16); local20 = ebx_5; } ebx_8 = local20; edi = *(esi_14 + 16); ebx_1 = ebx_8 + 0x400f10; edi += 0x400f10; if (*(ebx_8 + 0x400f10) != 0) { L10: ebx_6 = ebx_1; esi_14 = local21; esi_8 = edi + esi_14 * 4; eax = *ebx_6; local21 = esi_8; if (eax >= 0) { cl = (unsigned char) eax + 0x400f12; *(__size32*)(esp_2 - 4) = eax + 0x400f12; goto L7; } else { *(unsigned int*)(esp_2 - 4) = ((unsigned short) eax); } L7: *(union { unsigned int x3; void * x4; }*)(esp_2 - 8) = edx; eax = GetProcAddress(*(esp_2 - 8), *(esp_2 - 4)); /* Warning: also results in ecx */ *(__size32*)edi = eax; ebx_1 = ebx_6 + 4; eax = ebx_6 + (eax + 1) * 4; ax = (unsigned short) eax; edi += 4; if (*(ebx_6 + 4) != 0) { edx = *(esp_2 + 20); goto L10; } esi_7 = *(esp_2 + 16); local22 = esi_7; } } esp_1 = esp_2; esi_7 = local22; esi_1 = esi_7 + 20; tmp1 = *(esi_7 + 36); flags = SUBFLAGS32(*(esi_7 + 36), 0, tmp1); *(void **)(esp_2 + 16) = esi_7 + 20; local23 = ecx; } while (*(esi_7 + 36) != 0); } ecx = local23; (*0x401960)(pc, -1, -1, 0, 0, 0x401c84, 0, 0, param1, esi, ebp, ebx, ax, cl, eax, ecx, 0x401960, ebx_1, 0x400f10, esi_1, edi, flags, ZF, CF); *(__size32*)(esp - 4) = 0; ExitProcess(*(esp - 4)); return; }
BOOL RemoveAceFromWindowStation(HWINSTA hwinsta, PSID psid) { // Obtain the DACL for the window station. SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION; DWORD sd_length = 0; if (!GetUserObjectSecurity(hwinsta, &si, NULL, 0, &sd_length)) { if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { printf("GetUserObjectSecurity() failed: %d\n", GetLastError()); return FALSE; } } auto_buffer<PSECURITY_DESCRIPTOR> psd(sd_length); if (!GetUserObjectSecurity(hwinsta, &si, psd.get(), sd_length, &sd_length)) { printf("GetUserObjectSecurity() failed: %d\n", GetLastError()); return FALSE; } // Create a new DACL. auto_buffer<PSECURITY_DESCRIPTOR> psd_new(sd_length); if (!InitializeSecurityDescriptor(psd_new.get(), SECURITY_DESCRIPTOR_REVISION)) { printf("InitializeSecurityDescriptor() failed: %d\n", GetLastError()); return FALSE; } // Get the DACL from the security descriptor. BOOL bDaclPresent; PACL pacl; BOOL bDaclExist; if (!GetSecurityDescriptorDacl(psd.get(), &bDaclPresent, &pacl, &bDaclExist)) { printf("GetSecurityDescriptorDacl() failed: %d\n", GetLastError()); return FALSE; } // Initialize the ACL. ACL_SIZE_INFORMATION aclSizeInfo = {}; aclSizeInfo.AclBytesInUse = sizeof(ACL); if (NULL != pacl) { // get the file ACL size info if (!GetAclInformation(pacl, &aclSizeInfo, sizeof aclSizeInfo, AclSizeInformation)) { printf("GetAclInformation() failed: %d\n", GetLastError()); return FALSE; } } // Compute the size of the new ACL. DWORD new_acl_size = aclSizeInfo.AclBytesInUse - ((2 * sizeof(ACCESS_ALLOWED_ACE)) + (2 * GetLengthSid(psid)) - (2 * sizeof(DWORD))); auto_buffer<PACL> new_acl(new_acl_size); // Initialize the new DACL. if (!InitializeAcl(new_acl.get(), new_acl_size, ACL_REVISION)) { printf("InitializeAcl() failed: %d\n", GetLastError()); return FALSE; } // If DACL is present, copy it to a new DACL. if (bDaclPresent) { // Copy the ACEs to the new ACL. for (DWORD i = 0; i != aclSizeInfo.AceCount; ++i) { ACCESS_ALLOWED_ACE* pace; if (!GetAce(pacl, i, (void**)&pace)) { printf("GetAce() failed: %d\n", GetLastError()); return FALSE; } if (!EqualSid(psid, &pace->SidStart)) { if (!AddAce(new_acl.get(), ACL_REVISION, MAXDWORD, pace, pace->Header.AceSize)) { printf("AddAce() failed: %d\n", GetLastError()); return FALSE; } } } } // Set a new DACL for the security descriptor. if (!SetSecurityDescriptorDacl(psd_new.get(), TRUE, new_acl.get(), FALSE)) { printf("SetSecurityDescriptorDacl() failed: %d\n", GetLastError()); return FALSE; } // Set the new security descriptor for the window station. if (!SetUserObjectSecurity(hwinsta, &si, psd_new.get())) { printf("SetUserObjectSecurity() failed: %d\n", GetLastError()); return FALSE; } return TRUE; }
BOOL RemoveAceFromDesktop(HDESK hdesk, PSID psid) { // Obtain the security descriptor for the desktop object. SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION; DWORD sd_size = 0; if (!GetUserObjectSecurity(hdesk, &si, NULL, 0, &sd_size)) { if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { printf("GetUserObjectSecurity() failed: %d\n", GetLastError()); return FALSE; } } auto_buffer<PSECURITY_DESCRIPTOR> psd(sd_size); if (!GetUserObjectSecurity(hdesk, &si, psd.get(), sd_size, &sd_size)) { printf("GetUserObjectSecurity() failed: %d\n", GetLastError()); return FALSE; } // Create a new security descriptor. auto_buffer<PSECURITY_DESCRIPTOR> psd_new(sd_size); if (!InitializeSecurityDescriptor(psd_new.get(), SECURITY_DESCRIPTOR_REVISION)) { printf("InitializeSecurityDescriptor() failed: %d\n", GetLastError()); return FALSE; } // Obtain the DACL from the security descriptor. BOOL bDaclPresent; PACL pacl; BOOL bDaclExist; if (!GetSecurityDescriptorDacl(psd.get(), &bDaclPresent, &pacl, &bDaclExist)) { printf("GetSecurityDescriptorDacl() failed: %d\n", GetLastError()); return FALSE; } // Initialize. ACL_SIZE_INFORMATION aclSizeInfo = {}; aclSizeInfo.AclBytesInUse = sizeof(ACL); if (pacl != NULL) { // Determine the size of the ACL information. if (!GetAclInformation(pacl, (LPVOID)&aclSizeInfo, sizeof aclSizeInfo, AclSizeInformation)) { printf("GetAclInformation() failed: %d\n", GetLastError()); return FALSE; } } // Allocate buffer for the new ACL. DWORD dwNewAclSize = aclSizeInfo.AclBytesInUse - (sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psid) - sizeof(DWORD)); auto_buffer<PACL> new_acl(dwNewAclSize); // Initialize the new ACL. if (!InitializeAcl(new_acl.get(), dwNewAclSize, ACL_REVISION)) { printf("InitializeAcl() failed: %d\n", GetLastError()); return FALSE; } // If DACL is present, copy it to a new DACL. if (bDaclPresent) { // Copy the ACEs to the new ACL. for (DWORD i = 0; i != aclSizeInfo.AceCount; ++i) { // Get an ACE. ACCESS_ALLOWED_ACE* pace; if (!GetAce(pacl, i, (void**)&pace)) { printf("GetAce() failed: %d\n", GetLastError()); return FALSE; } if (!EqualSid(psid, &pace->SidStart)) { // Add the ACE to the new ACL. if (!AddAce(new_acl.get(), ACL_REVISION,MAXDWORD, pace, pace->Header.AceSize)) { printf("AddAce() failed: %d\n", GetLastError()); return FALSE; } } } } // Set new DACL to the new security descriptor. if (!SetSecurityDescriptorDacl(psd_new.get(), TRUE, new_acl.get(), FALSE)) { printf("SetSecurityDescriptorDacl() failed: %d\n", GetLastError()); return FALSE; } // Set the new security descriptor for the desktop object. if (!SetUserObjectSecurity(hdesk, &si, psd_new.get())) { printf("SetUserObjectSecurity() failed: %d\n", GetLastError()); return FALSE; } return TRUE; }
bool CSecRunAsUser::SetObjectPermission(CString strDirFile, DWORD lGrantedAccess){ if (!m_hADVAPI32_DLL){ ASSERT ( false ); return false; } if ( strDirFile.IsEmpty() ) return true; SID_NAME_USE snuType; TCHAR* szDomain = NULL; LPVOID pUserSID = NULL; PACL pNewACL = NULL; PSECURITY_DESCRIPTOR pSD = NULL; BOOL fAPISuccess; try { // get user sid DWORD cbDomain = 0; DWORD cbUserSID = 0; fAPISuccess = LookupAccountName(NULL, EMULEACCOUNTW, pUserSID, &cbUserSID, szDomain, &cbDomain, &snuType); if ( (!fAPISuccess) && GetLastError() != ERROR_INSUFFICIENT_BUFFER) throw CString(_T("Run as unpriveleged user: Error: LookupAccountName() failed,")); pUserSID = MHeapAlloc(cbUserSID); if (!pUserSID) throw CString(_T("Run as unpriveleged user: Error: Allocating memory failed,")); szDomain = (TCHAR*)MHeapAlloc(cbDomain * sizeof(TCHAR)); if (!szDomain) throw CString(_T("Run as unpriveleged user: Error: Allocating memory failed,")); fAPISuccess = LookupAccountName(NULL, EMULEACCOUNTW, pUserSID, &cbUserSID, szDomain, &cbDomain, &snuType); if (!fAPISuccess) throw CString(_T("Run as unpriveleged user: Error: LookupAccountName()2 failed")); if (CStringW(szDomain) != m_strDomain) throw CString(_T("Run as unpriveleged user: Logical Error: Domainname mismatch")); // get old ACL PACL pOldACL = NULL; fAPISuccess = GetNamedSecurityInfo(strDirFile.GetBuffer(), SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &pOldACL, NULL, &pSD); strDirFile.ReleaseBuffer(); if (fAPISuccess != ERROR_SUCCESS){ throw CString(_T("Run as unpriveleged user: Error: GetNamedSecurityInfo() failed")); } // calculate size for new ACL ACL_SIZE_INFORMATION AclInfo; AclInfo.AceCount = 0; // Assume NULL DACL. AclInfo.AclBytesFree = 0; AclInfo.AclBytesInUse = sizeof(ACL); if (pOldACL != NULL && !GetAclInformation(pOldACL, &AclInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation)) throw CString(_T("Run as unpriveleged user: Error: GetAclInformation() failed")); // Create new ACL DWORD cbNewACL = AclInfo.AclBytesInUse + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pUserSID) - sizeof(DWORD); pNewACL = (PACL)MHeapAlloc(cbNewACL); if (!pNewACL) throw CString(_T("Run as unpriveleged user: Error: Allocating memory failed,")); if (!InitializeAcl(pNewACL, cbNewACL, ACL_REVISION2)) throw CString(_T("Run as unpriveleged user: Error: Allocating memory failed,")); // copy the entries form the old acl into the new one and enter a new ace in the right order uint32 newAceIndex = 0; uint32 CurrentAceIndex = 0; if (AclInfo.AceCount) { for (CurrentAceIndex = 0; CurrentAceIndex < AclInfo.AceCount; CurrentAceIndex++) { LPVOID pTempAce = NULL; if (!GetAce(pOldACL, CurrentAceIndex, &pTempAce)) throw CString(_T("Run as unpriveleged user: Error: GetAce() failed,")); if (((ACCESS_ALLOWED_ACE *)pTempAce)->Header.AceFlags & INHERITED_ACE) break; // no multiple entries if (EqualSid(pUserSID, &(((ACCESS_ALLOWED_ACE *)pTempAce)->SidStart))) continue; if (!AddAce(pNewACL, ACL_REVISION, MAXDWORD, pTempAce, ((PACE_HEADER) pTempAce)->AceSize)) throw CString(_T("Run as unpriveleged user: Error: AddAce()1 failed,")); newAceIndex++; } } // here we add the actually entry if (!AddAccessAllowedAceEx(pNewACL, ACL_REVISION2, CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE, lGrantedAccess, pUserSID)) throw CString(_T("Run as unpriveleged user: Error: AddAccessAllowedAceEx() failed,")); // copy the rest if (AclInfo.AceCount) { for (; CurrentAceIndex < AclInfo.AceCount; CurrentAceIndex++) { LPVOID pTempAce = NULL; if (!GetAce(pOldACL, CurrentAceIndex, &pTempAce)) throw CString(_T("Run as unpriveleged user: Error: GetAce()2 failed,")); if (!AddAce(pNewACL, ACL_REVISION, MAXDWORD, pTempAce, ((PACE_HEADER) pTempAce)->AceSize)) throw CString(_T("Run as unpriveleged user: Error: AddAce()2 failed,")); } } fAPISuccess = SetNamedSecurityInfo(strDirFile.GetBuffer(), SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, pNewACL, NULL); strDirFile.ReleaseBuffer(); if (fAPISuccess != ERROR_SUCCESS) throw CString(_T("Run as unpriveleged user: Error: SetNamedSecurityInfo() failed,")); fAPISuccess = TRUE; } catch(CString error){ fAPISuccess = FALSE; theApp.QueueDebugLogLine(false, error); } // clean up if (pUserSID != NULL) MHeapFree(pUserSID); if (szDomain != NULL) MHeapFree(szDomain); if (pNewACL != NULL) MHeapFree(pNewACL); if (pSD != NULL) LocalFree(pSD); // finished return fAPISuccess!=FALSE; }
/** * This function adjusts the specified Desktop to include the specfied * user. * * See: http://msdn2.microsoft.com/en-us/library/aa379608(VS.85).aspx **/ BOOL AddAceToDesktop(HDESK hdesk, PSID psid) { ACL_SIZE_INFORMATION aclSizeInfo; BOOL bDaclExist; BOOL bDaclPresent; BOOL bSuccess = FALSE; DWORD dwNewAclSize; DWORD dwSidSize = 0; DWORD dwSdSizeNeeded; PACL pacl = NULL; PACL pNewAcl = NULL; PSECURITY_DESCRIPTOR psd = NULL; PSECURITY_DESCRIPTOR psdNew = NULL; PVOID pTempAce; SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION; unsigned int i; try { // Obtain the security descriptor for the desktop object. if (!GetUserObjectSecurity( hdesk, &si, psd, dwSidSize, &dwSdSizeNeeded)) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { psd = (PSECURITY_DESCRIPTOR)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwSdSizeNeeded ); if (psd == NULL) throw; psdNew = (PSECURITY_DESCRIPTOR)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwSdSizeNeeded); if (psdNew == NULL) throw; dwSidSize = dwSdSizeNeeded; if (!GetUserObjectSecurity( hdesk, &si, psd, dwSidSize, &dwSdSizeNeeded) ) throw; } else throw; } // Create a new security descriptor. if (!InitializeSecurityDescriptor( psdNew, SECURITY_DESCRIPTOR_REVISION) ) throw; // Obtain the DACL from the security descriptor. if (!GetSecurityDescriptorDacl( psd, &bDaclPresent, &pacl, &bDaclExist) ) throw; // Initialize. ZeroMemory(&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION)); aclSizeInfo.AclBytesInUse = sizeof(ACL); // Call only if NULL DACL. if (pacl != NULL) { // Determine the size of the ACL information. if (!GetAclInformation( pacl, (LPVOID)&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation) ) throw; } // Compute the size of the new ACL. dwNewAclSize = aclSizeInfo.AclBytesInUse + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psid) - sizeof(DWORD); // Allocate buffer for the new ACL. pNewAcl = (PACL)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwNewAclSize); if (pNewAcl == NULL) throw; // Initialize the new ACL. if (!InitializeAcl(pNewAcl, dwNewAclSize, ACL_REVISION)) throw; // If DACL is present, copy it to a new DACL. if (bDaclPresent) { // Copy the ACEs to the new ACL. if (aclSizeInfo.AceCount) { for (i=0; i < aclSizeInfo.AceCount; i++) { // Get an ACE. if (!GetAce(pacl, i, &pTempAce)) throw; // Add the ACE to the new ACL. if (!AddAce( pNewAcl, ACL_REVISION, MAXDWORD, pTempAce, ((PACE_HEADER)pTempAce)->AceSize) ) throw; } } } // Add ACE to the DACL. if (!AddAccessAllowedAce( pNewAcl, ACL_REVISION, GENERIC_ALL, psid) ) throw; // Set new DACL to the new security descriptor. if (!SetSecurityDescriptorDacl( psdNew, TRUE, pNewAcl, FALSE) ) throw; // Set the new security descriptor for the desktop object. if (!SetUserObjectSecurity(hdesk, &si, psdNew)) throw; // Indicate success. bSuccess = TRUE; } catch(...) { // Free buffers. if (pNewAcl != NULL) HeapFree(GetProcessHeap(), 0, (LPVOID)pNewAcl); if (psd != NULL) HeapFree(GetProcessHeap(), 0, (LPVOID)psd); if (psdNew != NULL) HeapFree(GetProcessHeap(), 0, (LPVOID)psdNew); } return bSuccess; }
/** * This function adjusts the specified WindowStation to include the specfied * user. * * See: http://msdn2.microsoft.com/en-us/library/aa379608(VS.85).aspx **/ BOOL AddAceToWindowStation(HWINSTA hwinsta, PSID psid) { ACCESS_ALLOWED_ACE *pace = NULL; ACL_SIZE_INFORMATION aclSizeInfo; BOOL bDaclExist; BOOL bDaclPresent; BOOL bSuccess = FALSE; DWORD dwNewAclSize; DWORD dwSidSize = 0; DWORD dwSdSizeNeeded; PACL pacl = NULL; PACL pNewAcl = NULL; PSECURITY_DESCRIPTOR psd = NULL; PSECURITY_DESCRIPTOR psdNew = NULL; PVOID pTempAce; SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION; unsigned int i; try { // Obtain the DACL for the window station. if (!GetUserObjectSecurity( hwinsta, &si, psd, dwSidSize, &dwSdSizeNeeded) ) if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { psd = (PSECURITY_DESCRIPTOR)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwSdSizeNeeded); if (psd == NULL) throw; psdNew = (PSECURITY_DESCRIPTOR)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwSdSizeNeeded); if (psdNew == NULL) throw; dwSidSize = dwSdSizeNeeded; if (!GetUserObjectSecurity( hwinsta, &si, psd, dwSidSize, &dwSdSizeNeeded) ) throw; } else throw; // Create a new DACL. if (!InitializeSecurityDescriptor( psdNew, SECURITY_DESCRIPTOR_REVISION) ) throw; // Get the DACL from the security descriptor. if (!GetSecurityDescriptorDacl( psd, &bDaclPresent, &pacl, &bDaclExist) ) throw; // Initialize the ACL. ZeroMemory(&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION)); aclSizeInfo.AclBytesInUse = sizeof(ACL); // Call only if the DACL is not NULL. if (pacl != NULL) { // get the file ACL size info if (!GetAclInformation( pacl, (LPVOID)&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation) ) throw; } // Compute the size of the new ACL. dwNewAclSize = aclSizeInfo.AclBytesInUse + (2*sizeof(ACCESS_ALLOWED_ACE)) + (2*GetLengthSid(psid)) - (2*sizeof(DWORD)); // Allocate memory for the new ACL. pNewAcl = (PACL)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwNewAclSize); if (pNewAcl == NULL) throw; // Initialize the new DACL. if (!InitializeAcl(pNewAcl, dwNewAclSize, ACL_REVISION)) throw; // If DACL is present, copy it to a new DACL. if (bDaclPresent) { // Copy the ACEs to the new ACL. if (aclSizeInfo.AceCount) { for (i=0; i < aclSizeInfo.AceCount; i++) { // Get an ACE. if (!GetAce(pacl, i, &pTempAce)) throw; // Add the ACE to the new ACL. if (!AddAce( pNewAcl, ACL_REVISION, MAXDWORD, pTempAce, ((PACE_HEADER)pTempAce)->AceSize) ) throw; } } } // Add the first ACE to the window station. pace = (ACCESS_ALLOWED_ACE *)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psid) - sizeof(DWORD) ); if (pace == NULL) throw; pace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE; pace->Header.AceFlags = CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE; pace->Header.AceSize = (WORD)sizeof(ACCESS_ALLOWED_ACE) + (WORD)GetLengthSid(psid) - (WORD)sizeof(DWORD); pace->Mask = GENERIC_ALL; if (!CopySid(GetLengthSid(psid), &pace->SidStart, psid)) throw; if (!AddAce( pNewAcl, ACL_REVISION, MAXDWORD, (LPVOID)pace, pace->Header.AceSize) ) throw; // Add an ACE to the window station. pace->Header.AceFlags = NO_PROPAGATE_INHERIT_ACE; pace->Mask = GENERIC_ALL; if (!AddAce( pNewAcl, ACL_REVISION, MAXDWORD, (LPVOID)pace, pace->Header.AceSize) ) throw; // Set a new DACL for the security descriptor. if (!SetSecurityDescriptorDacl( psdNew, TRUE, pNewAcl, FALSE) ) throw; // Set the new security descriptor for the window station. if (!SetUserObjectSecurity(hwinsta, &si, psdNew)) throw; // Indicate success. bSuccess = TRUE; } catch(...) { // Free the allocated buffers. if (pace != NULL) HeapFree(GetProcessHeap(), 0, (LPVOID)pace); if (pNewAcl != NULL) HeapFree(GetProcessHeap(), 0, (LPVOID)pNewAcl); if (psd != NULL) HeapFree(GetProcessHeap(), 0, (LPVOID)psd); if (psdNew != NULL) HeapFree(GetProcessHeap(), 0, (LPVOID)psdNew); } return bSuccess; }
BOOL CAcls::AddAccessRights(LPCTSTR lpszFileName,LPCTSTR lpszAccountName,DWORD dwAccessMask) { // 声明SID变量 SID_NAME_USE snuType; // 声明和LookupAccountName相关的变量(注意,全为0,要在程序中动态分配) TCHAR * szDomain = NULL; DWORD cbDomain = 0; LPVOID pUserSID = NULL; DWORD cbUserSID = 0; // 和文件相关的安全描述符 SD 的变量 PSECURITY_DESCRIPTOR pFileSD = NULL; // 结构变量 DWORD cbFileSD = 0; // SD的size // 一个新的SD的变量,用于构造新的ACL(把已有的ACL和需要新加的ACL整合起来) SECURITY_DESCRIPTOR newSD; // 和ACL 相关的变量 PACL pACL = NULL; BOOL fDaclPresent; BOOL fDaclDefaulted; ACL_SIZE_INFORMATION AclInfo; // 一个新的 ACL 变量 PACL pNewACL = NULL; //结构指针变量 DWORD cbNewACL = 0; //ACL的size // 一个临时使用的 ACE 变量 LPVOID pTempAce = NULL; UINT CurrentAceIndex = 0; //ACE在ACL中的位置 UINT newAceIndex = 0; //新添的ACE在ACL中的位置 //API函数的返回值,假设所有的函数都返回失败。 BOOL fResult; BOOL fAPISuccess; SECURITY_INFORMATION secInfo = DACL_SECURITY_INFORMATION; // 下面的两个函数是新的API函数,仅在Windows 2000以上版本的操作系统支持。 // 在此将从Advapi32.dll文件中动态载入。如果你使用VC++ 6.0编译程序,而且你想 // 使用这两个函数的静态链接。则请为你的编译加上:/D_WIN32_WINNT=0x0500 // 的编译参数。并且确保你的SDK的头文件和lib文件是最新的。 SetSecurityDescriptorControlFnPtr _SetSecurityDescriptorControl = NULL; AddAccessAllowedAceExFnPtr _AddAccessAllowedAceEx = NULL; __try { // // STEP 1: 通过用户名取得SID // 在这一步中LookupAccountName函数被调用了两次,第一次是取出所需要 // 的内存的大小,然后,进行内存分配。第二次调用才是取得了用户的帐户信息。 // LookupAccountName同样可以取得域用户或是用户组的信息。(请参看MSDN) // fAPISuccess = LookupAccountName(NULL, lpszAccountName, pUserSID, &cbUserSID, szDomain, &cbDomain, &snuType); // 以上调用API会失败,失败原因是内存不足。并把所需要的内存大小传出。 // 下面是处理非内存不足的错误。 if (fAPISuccess) __leave; else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { // _tprintf(TEXT("LookupAccountName() failed. Error %d\n"), // GetLastError()); __leave; } pUserSID = myheapalloc(cbUserSID); if (!pUserSID) { // _tprintf(TEXT("HeapAlloc() failed. Error %d\n"), GetLastError()); __leave; } szDomain = (TCHAR *) myheapalloc(cbDomain * sizeof(TCHAR)); if (!szDomain) { // _tprintf(TEXT("HeapAlloc() failed. Error %d\n"), GetLastError()); __leave; } fAPISuccess = LookupAccountName(NULL, lpszAccountName, pUserSID, &cbUserSID, szDomain, &cbDomain, &snuType); if (!fAPISuccess) { // _tprintf(TEXT("LookupAccountName() failed. Error %d\n"), // GetLastError()); __leave; } // // STEP 2: 取得文件(目录)相关的安全描述符SD // 使用GetFileSecurity函数取得一份文件SD的拷贝,同样,这个函数也 // 是被调用两次,第一次同样是取SD的内存长度。注意,SD有两种格式:自相关的 // (self-relative)和 完全的(absolute),GetFileSecurity只能取到“自 // 相关的”,而SetFileSecurity则需要完全的。这就是为什么需要一个新的SD, // 而不是直接在GetFileSecurity返回的SD上进行修改。因为“自相关的”信息 // 是不完整的。 fAPISuccess = GetFileSecurity(lpszFileName, secInfo, pFileSD, 0, &cbFileSD); // 以上调用API会失败,失败原因是内存不足。并把所需要的内存大小传出。 // 下面是处理非内存不足的错误。 if (fAPISuccess) __leave; else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { // _tprintf(TEXT("GetFileSecurity() failed. Error %d\n"), // GetLastError()); __leave; } pFileSD = myheapalloc(cbFileSD); if (!pFileSD) { // _tprintf(TEXT("HeapAlloc() failed. Error %d\n"), GetLastError()); __leave; } fAPISuccess = GetFileSecurity(lpszFileName, secInfo, pFileSD, cbFileSD, &cbFileSD); if (!fAPISuccess) { // _tprintf(TEXT("GetFileSecurity() failed. Error %d\n"), // GetLastError()); __leave; } // // STEP 3: 初始化一个新的SD // if (!InitializeSecurityDescriptor(&newSD, SECURITY_DESCRIPTOR_REVISION)) { // _tprintf(TEXT("InitializeSecurityDescriptor() failed.") // TEXT("Error %d\n"), GetLastError()); __leave; } // // STEP 4: 从GetFileSecurity 返回的SD中取DACL // if (!GetSecurityDescriptorDacl(pFileSD, &fDaclPresent, &pACL, &fDaclDefaulted)) { // _tprintf(TEXT("GetSecurityDescriptorDacl() failed. Error %d\n"), // GetLastError()); __leave; } // // STEP 5: 取 DACL的内存size // GetAclInformation可以提供DACL的内存大小。只传入一个类型为 // ACL_SIZE_INFORMATION的structure的参数,需DACL的信息,是为了 // 方便我们遍历其中的ACE。 AclInfo.AceCount = 0; // Assume NULL DACL. AclInfo.AclBytesFree = 0; AclInfo.AclBytesInUse = sizeof(ACL); if (pACL == NULL) fDaclPresent = FALSE; // 如果DACL不为空,则取其信息。(大多数情况下“自关联”的DACL为空) if (fDaclPresent) { if (!GetAclInformation(pACL, &AclInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation)) { // _tprintf(TEXT("GetAclInformation() failed. Error %d\n"), // GetLastError()); __leave; } } // // STEP 6: 计算新的ACL的size // 计算的公式是:原有的DACL的size加上需要添加的一个ACE的size,以 // 及加上一个和ACE相关的SID的size,最后减去两个字节以获得精确的大小。 cbNewACL = AclInfo.AclBytesInUse + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pUserSID) - sizeof(DWORD); // // STEP 7: 为新的ACL分配内存 // pNewACL = (PACL) myheapalloc(cbNewACL); if (!pNewACL) { // _tprintf(TEXT("HeapAlloc() failed. Error %d\n"), GetLastError()); // __leave; } // // STEP 8: 初始化新的ACL结构 // if (!InitializeAcl(pNewACL, cbNewACL, ACL_REVISION2)) { // _tprintf(TEXT("InitializeAcl() failed. Error %d\n"), // GetLastError()); __leave; } // // STEP 9 如果文件(目录) DACL 有数据,拷贝其中的ACE到新的DACL中 // // 下面的代码假设首先检查指定文件(目录)是否存在的DACL,如果有的话, // 那么就拷贝所有的ACE到新的DACL结构中,我们可以看到其遍历的方法是采用 // ACL_SIZE_INFORMATION结构中的AceCount成员来完成的。在这个循环中, // 会按照默认的ACE的顺序来进行拷贝(ACE在ACL中的顺序是很关键的),在拷 // 贝过程中,先拷贝非继承的ACE(我们知道ACE会从上层目录中继承下来) // newAceIndex = 0; if (fDaclPresent && AclInfo.AceCount) { for (CurrentAceIndex = 0; CurrentAceIndex < AclInfo.AceCount; CurrentAceIndex++) { // // STEP 10: 从DACL中取ACE // if (!GetAce(pACL, CurrentAceIndex, &pTempAce)) { // _tprintf(TEXT("GetAce() failed. Error %d\n"), // GetLastError()); __leave; } // // STEP 11: 检查是否是非继承的ACE // 如果当前的ACE是一个从父目录继承来的ACE,那么就退出循环。 // 因为,继承的ACE总是在非继承的ACE之后,而我们所要添加的ACE // 应该在已有的非继承的ACE之后,所有的继承的ACE之前。退出循环 // 正是为了要添加一个新的ACE到新的DACL中,这后,我们再把继承的 // ACE拷贝到新的DACL中。 // if (((ACCESS_ALLOWED_ACE *)pTempAce)->Header.AceFlags & INHERITED_ACE) break; // // STEP 12: 检查要拷贝的ACE的SID是否和需要加入的ACE的SID一样, // 如果一样,那么就应该废掉已存在的ACE,也就是说,同一个用户的存取 // 权限的设置的ACE,在DACL中应该唯一。这在里,跳过对同一用户已设置 // 了的ACE,仅是拷贝其它用户的ACE。 // if (EqualSid(pUserSID, &(((ACCESS_ALLOWED_ACE *)pTempAce)->SidStart))) continue; // // STEP 13: 把ACE加入到新的DACL中 // 下面的代码中,注意 AddAce 函数的第三个参数,这个参数的意思是 // ACL中的索引值,意为要把ACE加到某索引位置之后,参数MAXDWORD的 // 意思是确保当前的ACE是被加入到最后的位置。 // if (!AddAce(pNewACL, ACL_REVISION, MAXDWORD, pTempAce, ((PACE_HEADER) pTempAce)->AceSize)) { // _tprintf(TEXT("AddAce() failed. Error %d\n"), // GetLastError()); __leave; } newAceIndex++; } } // // STEP 14: 把一个 access-allowed 的ACE 加入到新的DACL中 // 前面的循环拷贝了所有的非继承且SID为其它用户的ACE,退出循环的第一件事 // 就是加入我们指定的ACE。请注意首先先动态装载了一个AddAccessAllowedAceEx // 的API函数,如果装载不成功,就调用AddAccessAllowedAce函数。前一个函数仅 // 在Windows 2000以后的版本支持,NT则没有,我们为了使用新版本的函数,我们首 // 先先检查一下当前系统中可不可以装载这个函数,如果可以则就使用。使用动态链接 // 比使用静态链接的好处是,程序运行时不会因为没有这个API函数而报错。 // // Ex版的函数多出了一个参数AceFlag(第三人参数),用这个参数我们可以来设置一 // 个叫ACE_HEADER的结构,以便让我们所设置的ACE可以被其子目录所继承下去,而 // AddAccessAllowedAce函数不能定制这个参数,在AddAccessAllowedAce函数 // 中,其会把ACE_HEADER这个结构设置成非继承的。 // _AddAccessAllowedAceEx = (AddAccessAllowedAceExFnPtr) GetProcAddress(GetModuleHandle(TEXT("advapi32.dll")), "AddAccessAllowedAceEx"); if (_AddAccessAllowedAceEx) { if (!_AddAccessAllowedAceEx(pNewACL, ACL_REVISION2, CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE , dwAccessMask, pUserSID)) { // _tprintf(TEXT("AddAccessAllowedAceEx() failed. Error %d\n"), // GetLastError()); __leave; } }else{ if (!AddAccessAllowedAce(pNewACL, ACL_REVISION2, dwAccessMask, pUserSID)) { // _tprintf(TEXT("AddAccessAllowedAce() failed. Error %d\n"), // GetLastError()); __leave; } } // // STEP 15: 按照已存在的ACE的顺序拷贝从父目录继承而来的ACE // if (fDaclPresent && AclInfo.AceCount) { for (; CurrentAceIndex < AclInfo.AceCount; CurrentAceIndex++) { // // STEP 16: 从文件(目录)的DACL中继续取ACE // if (!GetAce(pACL, CurrentAceIndex, &pTempAce)) { // _tprintf(TEXT("GetAce() failed. Error %d\n"), // GetLastError()); __leave; } // // STEP 17: 把ACE加入到新的DACL中 // if (!AddAce(pNewACL, ACL_REVISION, MAXDWORD, pTempAce, ((PACE_HEADER) pTempAce)->AceSize)) { // _tprintf(TEXT("AddAce() failed. Error %d\n"), // GetLastError()); __leave; } } } // // STEP 18: 把新的ACL设置到新的SD中 // if (!SetSecurityDescriptorDacl(&newSD, TRUE, pNewACL, FALSE)) { // _tprintf(TEXT("SetSecurityDescriptorDacl() failed. Error %d\n"), // GetLastError()); __leave; } // // STEP 19: 把老的SD中的控制标记再拷贝到新的SD中,我们使用的是一个叫 // SetSecurityDescriptorControl() 的API函数,这个函数同样只存在于 // Windows 2000以后的版本中,所以我们还是要动态地把其从advapi32.dll // 中载入,如果系统不支持这个函数,那就不拷贝老的SD的控制标记了。 // _SetSecurityDescriptorControl =(SetSecurityDescriptorControlFnPtr) GetProcAddress(GetModuleHandle(TEXT("advapi32.dll")), "SetSecurityDescriptorControl"); if (_SetSecurityDescriptorControl) { SECURITY_DESCRIPTOR_CONTROL controlBitsOfInterest = 0; SECURITY_DESCRIPTOR_CONTROL controlBitsToSet = 0; SECURITY_DESCRIPTOR_CONTROL oldControlBits = 0; DWORD dwRevision = 0; if (!GetSecurityDescriptorControl(pFileSD, &oldControlBits, &dwRevision)) { // _tprintf(TEXT("GetSecurityDescriptorControl() failed.") // TEXT("Error %d\n"), GetLastError()); __leave; } if (oldControlBits & SE_DACL_AUTO_INHERITED) { controlBitsOfInterest = SE_DACL_AUTO_INHERIT_REQ | SE_DACL_AUTO_INHERITED ; controlBitsToSet = controlBitsOfInterest; } else if (oldControlBits & SE_DACL_PROTECTED) { controlBitsOfInterest = SE_DACL_PROTECTED; controlBitsToSet = controlBitsOfInterest; } if (controlBitsOfInterest) { if (!_SetSecurityDescriptorControl(&newSD, controlBitsOfInterest, controlBitsToSet)) { // _tprintf(TEXT("SetSecurityDescriptorControl() failed.") // TEXT("Error %d\n"), GetLastError()); __leave; } } } // // STEP 20: 把新的SD设置设置到文件的安全属性中(千山万水啊,终于到了) // if (!SetFileSecurity(lpszFileName, secInfo, &newSD)) { // _tprintf(TEXT("SetFileSecurity() failed. Error %d\n"), // GetLastError()); __leave; } fResult = TRUE; } __finally { // // STEP 21: 释放已分配的内存,以免Memory Leak // if (pUserSID) myheapfree(pUserSID); if (szDomain) myheapfree(szDomain); if (pFileSD) myheapfree(pFileSD); if (pNewACL) myheapfree(pNewACL); } return fResult; }
static int TestplatformChmod( const char *nativePath, int pmode) { static const SECURITY_INFORMATION infoBits = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION; static const DWORD readOnlyMask = FILE_DELETE_CHILD | FILE_ADD_FILE | FILE_ADD_SUBDIRECTORY | FILE_WRITE_EA | FILE_APPEND_DATA | FILE_WRITE_DATA | DELETE; /* * References to security functions (only available on NT and later). */ const BOOL set_readOnly = !(pmode & 0222); BOOL acl_readOnly_found = FALSE, curAclPresent, curAclDefaulted; SID_IDENTIFIER_AUTHORITY userSidAuthority = { SECURITY_WORLD_SID_AUTHORITY }; BYTE *secDesc = 0; DWORD secDescLen, attr, newAclSize; ACL_SIZE_INFORMATION ACLSize; PACL curAcl, newAcl = 0; WORD j; SID *userSid = 0; char *userDomain = 0; int res = 0; /* * Process the chmod request. */ attr = GetFileAttributesA(nativePath); /* * nativePath not found */ if (attr == 0xffffffff) { res = -1; goto done; } /* * If nativePath is not a directory, there is no special handling. */ if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) { goto done; } /* * Set the result to error, if the ACL change is successful it will be * reset to 0. */ res = -1; /* * Read the security descriptor for the directory. Note the first call * obtains the size of the security descriptor. */ if (!GetFileSecurityA(nativePath, infoBits, NULL, 0, &secDescLen)) { DWORD secDescLen2 = 0; if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { goto done; } secDesc = (BYTE *) ckalloc(secDescLen); if (!GetFileSecurityA(nativePath, infoBits, (PSECURITY_DESCRIPTOR) secDesc, secDescLen, &secDescLen2) || (secDescLen < secDescLen2)) { goto done; } } /* * Get the World SID. */ userSid = (SID *) ckalloc(GetSidLengthRequired((UCHAR) 1)); InitializeSid(userSid, &userSidAuthority, (BYTE) 1); *(GetSidSubAuthority(userSid, 0)) = SECURITY_WORLD_RID; /* * If curAclPresent == false then curAcl and curAclDefaulted not valid. */ if (!GetSecurityDescriptorDacl((PSECURITY_DESCRIPTOR) secDesc, &curAclPresent, &curAcl, &curAclDefaulted)) { goto done; } if (!curAclPresent || !curAcl) { ACLSize.AclBytesInUse = 0; ACLSize.AceCount = 0; } else if (!GetAclInformation(curAcl, &ACLSize, sizeof(ACLSize), AclSizeInformation)) { goto done; } /* * Allocate memory for the new ACL. */ newAclSize = ACLSize.AclBytesInUse + sizeof(ACCESS_DENIED_ACE) + GetLengthSid(userSid) - sizeof(DWORD); newAcl = (ACL *) ckalloc(newAclSize); /* * Initialize the new ACL. */ if (!InitializeAcl(newAcl, newAclSize, ACL_REVISION)) { goto done; } /* * Add denied to make readonly, this will be known as a "read-only tag". */ if (set_readOnly && !AddAccessDeniedAce(newAcl, ACL_REVISION, readOnlyMask, userSid)) { goto done; } acl_readOnly_found = FALSE; for (j = 0; j < ACLSize.AceCount; j++) { LPVOID pACE2; ACE_HEADER *phACE2; if (!GetAce(curAcl, j, &pACE2)) { goto done; } phACE2 = (ACE_HEADER *) pACE2; /* * Do NOT propagate inherited ACEs. */ if (phACE2->AceFlags & INHERITED_ACE) { continue; } /* * Skip the "read-only tag" restriction (either added above, or it is * being removed). */ if (phACE2->AceType == ACCESS_DENIED_ACE_TYPE) { ACCESS_DENIED_ACE *pACEd = (ACCESS_DENIED_ACE *) phACE2; if (pACEd->Mask == readOnlyMask && EqualSid(userSid, (PSID) &pACEd->SidStart)) { acl_readOnly_found = TRUE; continue; } } /* * Copy the current ACE from the old to the new ACL. */ if (!AddAce(newAcl, ACL_REVISION, MAXDWORD, (PACL *) pACE2, ((PACE_HEADER) pACE2)->AceSize)) { goto done; } } /* * Apply the new ACL. */ if (set_readOnly == acl_readOnly_found || SetNamedSecurityInfoA( (LPSTR) nativePath, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, newAcl, NULL) == ERROR_SUCCESS) { res = 0; } done: if (secDesc) { ckfree((char *) secDesc); } if (newAcl) { ckfree((char *) newAcl); } if (userSid) { ckfree((char *) userSid); } if (userDomain) { ckfree((char *) userDomain); } if (res != 0) { return res; } /* * Run normal chmod command. */ return chmod(nativePath, pmode); }