Windows Setup: implement removal of special LEGACY_VERACRYPT registry keys.

This commit is contained in:
Mounir IDRASSI 2015-03-15 23:30:30 +01:00
parent ed604cf0f3
commit ec4be21492

View File

@ -124,6 +124,152 @@ BOOL StatRemoveDirectory (char *lpszDir)
return TRUE;
}
/* Recursively set the given OWNER security descriptor to the key and its subkeys */
static void RecursiveSetOwner (HKEY hKey, PSECURITY_DESCRIPTOR pSD)
{
LSTATUS status = 0;
DWORD dwIndex = 0, dwMaxNameLen = 0, dwNameLen = 0, numberSubKeys = 0;
HKEY hSubKey;
if ( (ERROR_SUCCESS == status) && (ERROR_SUCCESS == RegQueryInfoKey(hKey, NULL, NULL, NULL, &numberSubKeys, &dwMaxNameLen, NULL, NULL, NULL, NULL, NULL, NULL))
&& (numberSubKeys >= 1)
)
{
dwMaxNameLen++;
char* szNameValue = new char[dwMaxNameLen];
while (true)
{
dwNameLen = dwMaxNameLen;
status = RegEnumKeyExA (hKey, dwIndex++, szNameValue, &dwNameLen, NULL, NULL, NULL, NULL);
if (status == ERROR_SUCCESS)
{
status = RegOpenKeyExA (hKey, szNameValue, 0, WRITE_OWNER | KEY_READ , &hSubKey);
if (ERROR_SUCCESS == status)
{
RecursiveSetOwner (hSubKey, pSD);
RegCloseKey(hSubKey);
}
}
else
break;
}
delete [] szNameValue;
}
RegSetKeySecurity (hKey, OWNER_SECURITY_INFORMATION, pSD);
}
/* Recursively set the given DACL security descriptor to the key and its subkeys */
static void RecursiveSetDACL (HKEY hKey, const char* SubKeyName, PSECURITY_DESCRIPTOR pSD)
{
HKEY hSubKey;
DWORD dwIndex = 0, dwMaxNameLen = 0, dwNameLen = 0, numberSubKeys = 0;
LSTATUS status = RegOpenKeyExA(hKey, SubKeyName, 0, WRITE_DAC | KEY_READ /*| ACCESS_SYSTEM_SECURITY*/, &hSubKey);
if (status == ERROR_SUCCESS)
{
status = RegSetKeySecurity (hSubKey, DACL_SECURITY_INFORMATION, pSD);
if (status == ERROR_SUCCESS)
{
RegCloseKey(hSubKey);
status = RegOpenKeyExA(hKey, SubKeyName, 0, WRITE_DAC | KEY_READ , &hSubKey);
}
if ( (ERROR_SUCCESS == status)
&& (ERROR_SUCCESS == RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &numberSubKeys, &dwMaxNameLen, NULL, NULL, NULL, NULL, NULL, NULL))
&& (numberSubKeys >= 1)
)
{
dwMaxNameLen++;
char* szNameValue = new char[dwMaxNameLen];
while (true)
{
dwNameLen = dwMaxNameLen;
status = RegEnumKeyExA (hSubKey, dwIndex++, szNameValue, &dwNameLen, NULL, NULL, NULL, NULL);
if (status == ERROR_SUCCESS)
{
RecursiveSetDACL (hSubKey, szNameValue, pSD);
}
else
break;
}
delete [] szNameValue;
}
}
}
/* Correct the key permissions to allow its deletion */
static void AllowKeyAccess(HKEY Key,const char* SubKeyName)
{
LSTATUS RegResult;
HKEY SvcKey;
DWORD dwLength;
HANDLE Token = NULL;
PTOKEN_USER pTokenUser;
std::string sNewSD;
RegResult = RegOpenKeyExA(Key, SubKeyName, 0, WRITE_OWNER | KEY_READ, &SvcKey);
if (RegResult==ERROR_SUCCESS)
{
dwLength=0;
pTokenUser = NULL;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &Token))
{
if (!GetTokenInformation(Token, TokenUser, pTokenUser, 0, &dwLength))
{
if (GetLastError() ==ERROR_INSUFFICIENT_BUFFER)
{
pTokenUser = (PTOKEN_USER) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwLength);
if (pTokenUser)
{
if (GetTokenInformation(Token, TokenUser, pTokenUser, dwLength, &dwLength))
{
SECURITY_DESCRIPTOR SecDesc;
if ( InitializeSecurityDescriptor(&SecDesc, SECURITY_DESCRIPTOR_REVISION)
&& SetSecurityDescriptorDacl(&SecDesc, TRUE, NULL, FALSE) // NULL DACL: full access to everyone
&& SetSecurityDescriptorOwner(&SecDesc, pTokenUser->User.Sid, FALSE)
)
{
RecursiveSetOwner(SvcKey, &SecDesc);
}
}
}
}
}
}
RegCloseKey(SvcKey);
}
if (pTokenUser)
{
PSID pSid = pTokenUser->User.Sid;
DWORD dwAclSize = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + ::GetLengthSid(pSid) - sizeof(DWORD);
PACL pDacl = (PACL) new BYTE[dwAclSize];
if (TRUE == ::InitializeAcl(pDacl, dwAclSize, ACL_REVISION))
{
if (TRUE == AddAccessAllowedAceEx(pDacl, ACL_REVISION, CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE, WRITE_DAC | KEY_ALL_ACCESS, pSid))
{
SECURITY_DESCRIPTOR SecDesc;
if (TRUE == ::InitializeSecurityDescriptor(&SecDesc, SECURITY_DESCRIPTOR_REVISION))
{
if (TRUE == ::SetSecurityDescriptorDacl(&SecDesc, TRUE, pDacl, FALSE))
{
RecursiveSetDACL (Key, SubKeyName, &SecDesc);
}
}
}
}
delete [] pDacl;
}
if (pTokenUser)
HeapFree(GetProcessHeap(), 0, pTokenUser);
if (Token)
CloseHandle(Token);
}
void SearchAndDeleteRegistrySubString (HKEY hKey, const char *subKey, const char *str, BOOL bEnumSubKeys, const char* enumMatchSubStr)
{
HKEY hSubKey = 0;
@ -151,6 +297,7 @@ void SearchAndDeleteRegistrySubString (HKEY hKey, const char *subKey, const char
std::string entryName = szNameValue;
entryName += "\\";
entryName += subKey;
entryName += "\\";
subKeysList.push_back(entryName);
}
else
@ -169,8 +316,15 @@ void SearchAndDeleteRegistrySubString (HKEY hKey, const char *subKey, const char
// if the string to search for is empty, delete the sub key, otherwise, look for matching value and delete them
if (subStringLength == 0)
{
if (ERROR_ACCESS_DENIED == SHDeleteKeyA (hKey, ItSubKey->c_str()))
{
// grant permission to delete
AllowKeyAccess (hKey, ItSubKey->c_str());
// try again
SHDeleteKeyA (hKey, ItSubKey->c_str());
}
}
else
{
if (RegOpenKeyExA (hKey, ItSubKey->c_str(), 0, KEY_ALL_ACCESS, &hSubKey) == ERROR_SUCCESS)
@ -222,6 +376,44 @@ void SearchAndDeleteRegistrySubString (HKEY hKey, const char *subKey, const char
}
}
/* Set the given privilege of the current process */
BOOL SetPrivilege(LPTSTR szPrivilegeName, BOOL bEnable)
{
TOKEN_PRIVILEGES tp;
LUID luid;
HANDLE hProcessToken;
BOOL bStatus = FALSE;
if ( OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
&hProcessToken) )
{
if ( LookupPrivilegeValue(
NULL,
szPrivilegeName,
&luid ) )
{
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = bEnable? SE_PRIVILEGE_ENABLED : SE_PRIVILEGE_REMOVED;
// Enable the privilege
bStatus = AdjustTokenPrivileges(
hProcessToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES) NULL,
(PDWORD) NULL);
}
CloseHandle(hProcessToken);
}
return bStatus;
}
HRESULT CreateLink (char *lpszPathObj, char *lpszArguments,
char *lpszPathLink)
{
@ -872,6 +1064,9 @@ BOOL DoRegUninstall (HWND hwndDlg, BOOL bRemoveDeprecated)
SHDeleteKey (HKEY_LOCAL_MACHINE, "Software\\Classes\\.hc");
// enable the SE_TAKE_OWNERSHIP_NAME privilege for this operation
SetPrivilege (SE_TAKE_OWNERSHIP_NAME, TRUE);
// clean MuiCache list from VeraCrypt entries
SearchAndDeleteRegistrySubString (HKEY_CLASSES_ROOT, "Local Settings\\Software\\Microsoft\\Windows\\Shell\\MuiCache", "VeraCrypt", FALSE, NULL);
@ -879,12 +1074,15 @@ BOOL DoRegUninstall (HWND hwndDlg, BOOL bRemoveDeprecated)
SearchAndDeleteRegistrySubString (HKEY_USERS, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\.hc", NULL, TRUE, NULL);
SearchAndDeleteRegistrySubString (HKEY_USERS, "Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Compatibility Assistant\\Persisted", "VeraCrypt", TRUE, NULL);
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM", 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM", 0, KEY_ALL_ACCESS | WRITE_DAC | WRITE_OWNER, &hKey) == ERROR_SUCCESS)
{
SearchAndDeleteRegistrySubString (hKey, "Enum\\Root\\LEGACY_VERACRYPT", NULL, TRUE, "ControlSet");
SearchAndDeleteRegistrySubString (hKey, "services\\veracrypt", NULL, TRUE, "ControlSet");
RegCloseKey(hKey);
}
// disable the SE_TAKE_OWNERSHIP_NAME privilege for this operation
SetPrivilege (SE_TAKE_OWNERSHIP_NAME, FALSE);
SHChangeNotify (SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
}
@ -1572,7 +1770,7 @@ void DoUninstall (void *arg)
DoServiceUninstall (hwndDlg, "VeraCryptService");
GetTempPath (sizeof (temp), temp);
StringCbPrintfA (UninstallBatch, sizeof (UninstallBatch), "%s\\VeraCrypt-Uninstall.bat", temp);
StringCbPrintfA (UninstallBatch, sizeof (UninstallBatch), "%sVeraCrypt-Uninstall.bat", temp);
UninstallBatch [sizeof(UninstallBatch)-1] = 0;
@ -1582,7 +1780,7 @@ void DoUninstall (void *arg)
bOK = FALSE;
else
{
fprintf (f, ":loop\n"
fprintf (f,":loop\n"
"del \"%s%s\"\n"
"if exist \"%s%s\" goto loop\n"
"rmdir \"%s\"\n"