Centrist
Sun Jul 08 17:40:07 CDT 2007
I've found a way to make this work, and I'll explain it here for the
benefit of others (something which people here may not understand).
When the legalnoticetext and legalnoticecaption registry values have
been removed, the logon message does not appear after pressing CTL-ALT-
DEL at the login prompt. To prevent the group policy refreshes from
adding these keys back after you've deleted them, you can change the
ACL for the system key which contains these values to deny the Set
Value permission to the System account.
Unfortunately, this is very hard to do with vbscript - if not
completely impossible. So I've written a C++ program that will change
the ACL when run, and it will also remove the changes when run with a -
u argument. The source code is included at the end of this post, and
compiles fine with Dev-C++.
For my purposes, I need to write my own program rather than use
something already available (though I doubt there is anything already
out there). A benefit of using a single-purpose program is that you
can get a very small compiled executable. With Dev-C++, I got a size
of 10KB by removing the output code - which is small enough for me to
include the executable in my script.
I make no guarantees as to the safety of running this program. I
posted it on a programming board, but no one thought it was worthy of
comment.
For the time being, you can get the well-formatted version here:
http://docs.google.com/View?docid=ddmjgfnj_4d7rnzz
Here's the source:
#include <cstdlib>
#include <iostream>
#include <windows.h>
#include <aclapi.h>
using namespace std;
void Output(char errorMessage[100]);
int ChangeSysKeyPermissions(BOOL denySystem, HKEY &SysKey);
int DeleteLegalNoticeValues(HKEY &SysKey);
const DWORD REGERROR_NOTFOUND = 2;
const LPCTSTR SysKeyPath = "software\\microsoft\\windows\
\currentversion\\policies\\system";
int main(int argc, char *argv[])
{
HKEY SysKey;
// CHECK ARGS TO DETERMINE ACTION TO TAKE.
BOOL denySystem = true;
if(argc > 1 && strcmp(argv[1], "-u") == 0) denySystem = false;
//if(denySystem) Output("Ready to start."); else Output("Ready to
start. (undoing)");
// OPEN THE SYSTEM KEY.
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, SysKeyPath, 0, KEY_ALL_ACCESS,
&SysKey) != ERROR_SUCCESS)
{ Output("Could not open the system key."); return EXIT_FAILURE; }
if(denySystem)
{ // DELETE THE LEGAL NOTICE STRING VALUES.
if(DeleteLegalNoticeValues(SysKey) != 0) { Output("Could not open
the system key."); return EXIT_FAILURE; }
}
// MODIFY THE ACL TO DENY OR ALLOW SYSTEM THE SETVALUE RIGHT.
if(ChangeSysKeyPermissions(denySystem, SysKey) != 0)
{ Output("Failed to change the ACL."); return EXIT_FAILURE; }
// CLOSE THE SYSTEM KEY.
if(RegCloseKey(SysKey) != ERROR_SUCCESS) { Output("Could not close
the system key."); return EXIT_FAILURE; }
Output("All Done.");
return EXIT_SUCCESS;
}
void Output(char errorMessage[100])
{
cout << errorMessage << " " << GetLastError() << endl;
system("PAUSE");
}
int DeleteLegalNoticeValues(HKEY &SysKey)
{
// Delete the legal notice text and caption.
DWORD retval;
retval = RegDeleteValue(SysKey, "legalnoticecaption");
if(retval != ERROR_SUCCESS && retval != REGERROR_NOTFOUND)
{ Output("Could not delete caption."); return -1; }
retval = RegDeleteValue(SysKey, "legalnoticetext");
if(retval != ERROR_SUCCESS && retval != REGERROR_NOTFOUND)
{ Output("Could not delete text."); return -1; }
return 0;
}
int ChangeSysKeyPermissions(BOOL denySystem, HKEY &SysKey)
{
int result = -1;
// Get the security descriptor and DACL.
PACL OrigDacl = NULL;
PACL NewDacl = NULL;
PSECURITY_DESCRIPTOR SecDesc = NULL;
if(GetSecurityInfo(SysKey, SE_REGISTRY_KEY,
DACL_SECURITY_INFORMATION, NULL, NULL, &OrigDacl, NULL, &SecDesc) !=
ERROR_SUCCESS)
{ Output("Could not get security info."); goto cleanup; }
if(denySystem)
{
// Create an EXPLICIT_ACCESS structure for our ACE.
EXPLICIT_ACCESS Ace;
char AccountName[] = "System";
ZeroMemory(&Ace, sizeof(EXPLICIT_ACCESS));
Ace.grfAccessPermissions = KEY_SET_VALUE;
Ace.grfAccessMode = DENY_ACCESS;
Ace.grfInheritance = NO_INHERITANCE;
Ace.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
Ace.Trustee.ptstrName = AccountName;
// Create a new ACL and add our ACE to it.
if(SetEntriesInAcl(1, &Ace, OrigDacl, &NewDacl) != ERROR_SUCCESS)
{ Output("Could not add new ACE and Orig DACL."); goto cleanup; }
}
else
{
// Get the ACL's information.
ACL_SIZE_INFORMATION AclInfo;
if(!GetAclInformation(OrigDacl, &AclInfo,
sizeof(ACL_SIZE_INFORMATION), AclSizeInformation))
{ Output("Could not get the ACL information."); goto cleanup; }
// Make sure there are ACEs in our result.
if(AclInfo.AceCount < 1) { Output("Did not see any ACEs for the
system key."); goto cleanup; }
// Find and delete ACEs which deny access.
PVOID tempAce;
int AceTotal = AclInfo.AceCount;
for(int i = 0; i < AceTotal; i++)
{
// Get the ACE.
if(!GetAce(OrigDacl, i, &tempAce)) { Output("Could not get an ACE
from the Orig ACL."); goto cleanup; }
// Check to see if this ACE denies access.
if(((PACE_HEADER)tempAce)->AceType = ACCESS_DENIED_ACE_TYPE)
{
// Remove this ACE from the ACL.
if(DeleteAce(OrigDacl, i)) { AceTotal--; }
else { Output("Could not delete an ACE from the ACL."); goto
cleanup; }
}
}
// Set NewDacl to OrigDacl
NewDacl = OrigDacl;
}
// Change the key's ACL.
if(SetSecurityInfo(SysKey, SE_REGISTRY_KEY,
DACL_SECURITY_INFORMATION, NULL, NULL, NewDacl, NULL) !=
ERROR_SUCCESS)
{ Output("Could not change the key's ACL."); goto cleanup; }
result = 0; // If we got this far, it must be working!
cleanup: // These variables must have been defined before the first
goto cleanup.
if(SecDesc != NULL) LocalFree((HLOCAL)SecDesc);
if(NewDacl != NULL) LocalFree((HLOCAL)NewDacl);
return result;
}