GPaterson
asked on
Registry Permissions C++
I am trying to create a program which takes ownership of a registry key (and subkeys), adds the current user to the permissions list and then deletes the key and all subkeys.
I can succesfully take ownership of the key and I can change the permissions on it. However all subkeys are unaffected and I cant seem to find a way to make it propogate these changes to all the subkeys.
I would like to do this if possible without having to enumerate all the subkeys and repeat the process. Is there any fast way that I am missing?
I need to know this for both 1. Taking Ownership and 2. Setting DACL's
Below is the code I am using... (I know some of it is doubled up, I will fix all that stuff once it all works)
void PStoresFix::TakeOwnership( )
{
DWORD dwResult = 0, cbtiSize = 0;
PTOKEN_USER ptiUser = NULL;
SECURITY_DESCRIPTOR sd;
HANDLE hToken;
HKEY hKey = NULL;
if (!OpenProcessToken(GetCurr entProcess (),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
return;
GetTokenInformation (hToken, TokenUser, NULL, 0, &cbtiSize);
// Allocate buffer for user information in the token.
ptiUser = (PTOKEN_USER) HeapAlloc(GetProcessHeap() , 0, cbtiSize);
// Retrieve the user information from the token.
GetTokenInformation(hToken , TokenUser, ptiUser, cbtiSize, &cbtiSize);
if (!SetPrivilege(hToken, SE_TAKE_OWNERSHIP_NAME, TRUE))
{
std::cout<<"Could not set SE_TAKE_OWNERSHIP_NAME"<<s td::endl;
return;
}
if (!SetPrivilege(hToken, SE_RESTORE_NAME, TRUE))
{
std::cout<<"Could not set SE_RESTORE_NAME"<<std::end l;
}
if(!InitializeSecurityDesc riptor(&sd , SECURITY_DESCRIPTOR_REVISI ON))
{
std::cout<<"Error initializing SD"<<std::endl;
}
if(!SetSecurityDescriptorO wner(&sd, ptiUser->User.Sid, FALSE))
{
std::cout<<"Error setting SD owner"<<std::endl;
}
// Open registry with WRITE_OWNER priveledge.
dwResult = RegOpenKeyEx(HKEY_LOCAL_MA CHINE,
"SOFTWARE\\Microsoft\\Prot ected Storage System Provider",
0,
WRITE_OWNER,
&hKey);
if(dwResult != ERROR_SUCCESS)
{
std::cout<<"Error opening key: "<<dwResult<<std::endl;
}
// Set the owner in the object's security descriptor.
dwResult = RegSetKeySecurity(hKey, OWNER_SECURITY_INFORMATION , &sd);
if (dwResult != ERROR_SUCCESS)
{
std::cout<<"Could not set owner 1. Error: "<<dwResult<<std::endl;
//return;
}
// This propogates changes to all children objects
dwResult = SetNamedSecurityInfo("MACH INE\\SOFTW ARE\\Micro soft\\Prot ected Storage System Provider",
SE_REGISTRY_KEY, OWNER_SECURITY_INFORMATION ,ptiUser-> User.Sid, NULL, NULL, NULL);
if (dwResult != ERROR_SUCCESS)
{
// Errorcheck
std::cout<<"Error setting named security info: "<<dwResult<<std::endl;
}
// Disable the SE_TAKE_OWNERSHIP_NAME privilege.
if (!SetPrivilege(hToken, SE_TAKE_OWNERSHIP_NAME, FALSE))
{
//printf("Failed SetPrivilege call unexpectedly.\n");
return;
}
// Disable the SE_TAKE_OWNERSHIP_NAME privilege.
if (!SetPrivilege(hToken, SE_RESTORE_NAME, FALSE))
{
//printf("Failed SetPrivilege call unexpectedly.\n");
return;
}
// Close registry.
dwResult = RegCloseKey(hKey);
}
void PStoresFix::GrantAccess()
{
DWORD dwResult = 0, dwAclSize = 0, cbtiSize = 0;
HKEY hKey = NULL;
HANDLE hToken;
PTOKEN_USER ptiUser = NULL;
PACL pDACL = NULL;
SECURITY_DESCRIPTOR sd;
// Open registry with WRITE_DAC priveledge.
dwResult = RegOpenKeyEx(HKEY_LOCAL_MA CHINE,
"SOFTWARE\\Microsoft\\Prot ected Storage System Provider",
0,
WRITE_DAC,
&hKey);
if(dwResult != ERROR_SUCCESS)
{
std::cout<<"Error opening key: "<<dwResult<<std::endl;
}
if (!OpenProcessToken(GetCurr entProcess (),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
{
std::cout<<"Error opening process token."<<std::endl;
return;
}
GetTokenInformation (hToken, TokenUser, NULL, 0, &cbtiSize);
// Allocate buffer for user information in the token.
ptiUser = (PTOKEN_USER) HeapAlloc(GetProcessHeap() , 0, cbtiSize);
// Retrieve the user information from the token.
GetTokenInformation(hToken , TokenUser, ptiUser, cbtiSize, &cbtiSize);
dwAclSize = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) +
GetLengthSid(ptiUser->User .Sid);
pDACL = (PACL)HeapAlloc(GetProcess Heap(), 0, dwAclSize);
if(pDACL==NULL)
{
std::cout<<"Error allocating mem for ACL"<<std::endl;
}
if(!InitializeAcl(pDACL, dwAclSize, ACL_REVISION))
{
std::cout<<"Error initializing ACL"<<std::endl;
}
if(!AddAccessAllowedAce(pD ACL, ACL_REVISION, KEY_ALL_ACCESS, ptiUser->User.Sid))
{
std::cout<<"Error adding ACE"<<std::endl;
}
if(!InitializeSecurityDesc riptor(&sd , SECURITY_DESCRIPTOR_REVISI ON))
{
std::cout<<"Error initializing SD"<<std::endl;
}
if(!SetSecurityDescriptorD acl(&sd, TRUE, pDACL, FALSE))
{
std::cout<<"Error setting SD DACL"<<std::endl;
}
dwResult = RegSetKeySecurity(hKey, DACL_SECURITY_INFORMATION, &sd);
if (dwResult != ERROR_SUCCESS)
{
std::cout<<"Could not set add permissions Error: "<<dwResult<<std::endl;
//return;
}
dwResult = SetNamedSecurityInfo("MACH INE\\SOFTW ARE\\Micro soft\\Prot ected Storage System Provider",
SE_REGISTRY_KEY, DACL_SECURITY_INFORMATION, NULL, NULL, pDACL, NULL);
if (dwResult != ERROR_SUCCESS)
{
// Errorcheck
std::cout<<"Error setting named security info."<<std::endl;
}
if(pDACL != NULL)
HeapFree(GetProcessHeap(), 0, pDACL);
RegCloseKey(hKey);
}
I can succesfully take ownership of the key and I can change the permissions on it. However all subkeys are unaffected and I cant seem to find a way to make it propogate these changes to all the subkeys.
I would like to do this if possible without having to enumerate all the subkeys and repeat the process. Is there any fast way that I am missing?
I need to know this for both 1. Taking Ownership and 2. Setting DACL's
Below is the code I am using... (I know some of it is doubled up, I will fix all that stuff once it all works)
void PStoresFix::TakeOwnership(
{
DWORD dwResult = 0, cbtiSize = 0;
PTOKEN_USER ptiUser = NULL;
SECURITY_DESCRIPTOR sd;
HANDLE hToken;
HKEY hKey = NULL;
if (!OpenProcessToken(GetCurr
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
return;
GetTokenInformation (hToken, TokenUser, NULL, 0, &cbtiSize);
// Allocate buffer for user information in the token.
ptiUser = (PTOKEN_USER) HeapAlloc(GetProcessHeap()
// Retrieve the user information from the token.
GetTokenInformation(hToken
if (!SetPrivilege(hToken, SE_TAKE_OWNERSHIP_NAME, TRUE))
{
std::cout<<"Could not set SE_TAKE_OWNERSHIP_NAME"<<s
return;
}
if (!SetPrivilege(hToken, SE_RESTORE_NAME, TRUE))
{
std::cout<<"Could not set SE_RESTORE_NAME"<<std::end
}
if(!InitializeSecurityDesc
{
std::cout<<"Error initializing SD"<<std::endl;
}
if(!SetSecurityDescriptorO
{
std::cout<<"Error setting SD owner"<<std::endl;
}
// Open registry with WRITE_OWNER priveledge.
dwResult = RegOpenKeyEx(HKEY_LOCAL_MA
"SOFTWARE\\Microsoft\\Prot
0,
WRITE_OWNER,
&hKey);
if(dwResult != ERROR_SUCCESS)
{
std::cout<<"Error opening key: "<<dwResult<<std::endl;
}
// Set the owner in the object's security descriptor.
dwResult = RegSetKeySecurity(hKey, OWNER_SECURITY_INFORMATION
if (dwResult != ERROR_SUCCESS)
{
std::cout<<"Could not set owner 1. Error: "<<dwResult<<std::endl;
//return;
}
// This propogates changes to all children objects
dwResult = SetNamedSecurityInfo("MACH
SE_REGISTRY_KEY, OWNER_SECURITY_INFORMATION
if (dwResult != ERROR_SUCCESS)
{
// Errorcheck
std::cout<<"Error setting named security info: "<<dwResult<<std::endl;
}
// Disable the SE_TAKE_OWNERSHIP_NAME privilege.
if (!SetPrivilege(hToken, SE_TAKE_OWNERSHIP_NAME, FALSE))
{
//printf("Failed SetPrivilege call unexpectedly.\n");
return;
}
// Disable the SE_TAKE_OWNERSHIP_NAME privilege.
if (!SetPrivilege(hToken, SE_RESTORE_NAME, FALSE))
{
//printf("Failed SetPrivilege call unexpectedly.\n");
return;
}
// Close registry.
dwResult = RegCloseKey(hKey);
}
void PStoresFix::GrantAccess()
{
DWORD dwResult = 0, dwAclSize = 0, cbtiSize = 0;
HKEY hKey = NULL;
HANDLE hToken;
PTOKEN_USER ptiUser = NULL;
PACL pDACL = NULL;
SECURITY_DESCRIPTOR sd;
// Open registry with WRITE_DAC priveledge.
dwResult = RegOpenKeyEx(HKEY_LOCAL_MA
"SOFTWARE\\Microsoft\\Prot
0,
WRITE_DAC,
&hKey);
if(dwResult != ERROR_SUCCESS)
{
std::cout<<"Error opening key: "<<dwResult<<std::endl;
}
if (!OpenProcessToken(GetCurr
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
{
std::cout<<"Error opening process token."<<std::endl;
return;
}
GetTokenInformation (hToken, TokenUser, NULL, 0, &cbtiSize);
// Allocate buffer for user information in the token.
ptiUser = (PTOKEN_USER) HeapAlloc(GetProcessHeap()
// Retrieve the user information from the token.
GetTokenInformation(hToken
dwAclSize = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE)
GetLengthSid(ptiUser->User
pDACL = (PACL)HeapAlloc(GetProcess
if(pDACL==NULL)
{
std::cout<<"Error allocating mem for ACL"<<std::endl;
}
if(!InitializeAcl(pDACL, dwAclSize, ACL_REVISION))
{
std::cout<<"Error initializing ACL"<<std::endl;
}
if(!AddAccessAllowedAce(pD
{
std::cout<<"Error adding ACE"<<std::endl;
}
if(!InitializeSecurityDesc
{
std::cout<<"Error initializing SD"<<std::endl;
}
if(!SetSecurityDescriptorD
{
std::cout<<"Error setting SD DACL"<<std::endl;
}
dwResult = RegSetKeySecurity(hKey, DACL_SECURITY_INFORMATION,
if (dwResult != ERROR_SUCCESS)
{
std::cout<<"Could not set add permissions Error: "<<dwResult<<std::endl;
//return;
}
dwResult = SetNamedSecurityInfo("MACH
SE_REGISTRY_KEY, DACL_SECURITY_INFORMATION,
if (dwResult != ERROR_SUCCESS)
{
// Errorcheck
std::cout<<"Error setting named security info."<<std::endl;
}
if(pDACL != NULL)
HeapFree(GetProcessHeap(),
RegCloseKey(hKey);
}
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
regedt32 pretty much does the same when you select that option. Had to do something similar a few yeary ago and had to make it work recursively, too...
ASKER
Does that apply to both setting permissions and also taking ownership?
I sort of guessed maybe it was so when taking ownership, however, in setting permissions I thought maybe different
as in regedt32 you can take ownership of the parent and reset permissions on all child folders without actually taking ownership of all the child folders.
I sort of guessed maybe it was so when taking ownership, however, in setting permissions I thought maybe different
as in regedt32 you can take ownership of the parent and reset permissions on all child folders without actually taking ownership of all the child folders.
>>Does that apply to both setting permissions and also taking ownership?
To both - there is only one API ( 'RegSetKeySecurity()'), and there's no way to tell that API todo either operation recursively.
To both - there is only one API ( 'RegSetKeySecurity()'), and there's no way to tell that API todo either operation recursively.
ASKER
Strange my last comment went up twice at two different times. Oh well, back to drawing board.
ASKER
I sort of guessed maybe it was so when taking ownership, however, in setting permissions I thought maybe different
as in regedt32 you can take ownership of the parent and reset permissions on all child folders without actually taking ownership of all the child folders.