|
|
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <shellapi.h>
#include "SmartPtr.h"
#include "strings.h"
extern "C" { void PrependToPath( LPWSTR, LPWSTR*); void PathUnquoteSpaces( LPWSTR ); void UpdateUserEnvironment(); BOOL RegDelnode( HKEY, LPWSTR ); LPWSTR GetSidString( HANDLE UserToken ); void DeleteSidString( LPWSTR SidString ); };
#define GPO_SCRIPTS_KEY L"Software\\Policies\\Microsoft\\Windows\\System\\Scripts"
#define GP_STATE_KEY L"Software\\Microsoft\\Windows\\CurrentVersion\\Group Policy\\State"
#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
#define SCRIPT L"Script"
#define PARAMETERS L"Parameters"
#define EXECTIME L"ExecTime"
#define GPOID L"GPO-ID"
#define SOMID L"SOM-ID"
#define FILESYSPATH L"FileSysPath"
#define SCR_STARTUP L"Startup"
#define SCR_SHUTDOWN L"Shutdown"
#define SCR_LOGON L"Logon"
#define SCR_LOGOFF L"Logoff"
LPTSTR CheckSlash (LPTSTR lpDir) { LPTSTR lpEnd;
lpEnd = lpDir + lstrlen(lpDir);
if (*(lpEnd - 1) != TEXT('\\')) { *lpEnd = TEXT('\\'); lpEnd++; *lpEnd = TEXT('\0'); }
return lpEnd; }
BOOL RegDelnodeRecurse (HKEY hKeyRoot, LPTSTR lpSubKey) { LPTSTR lpEnd; LONG lResult; DWORD dwSize; TCHAR szName[MAX_PATH]; HKEY hKey; FILETIME ftWrite;
//
// First, see if we can delete the key without having
// to recurse.
//
lResult = RegDeleteKey(hKeyRoot, lpSubKey);
if (lResult == ERROR_SUCCESS) { return TRUE; }
lResult = RegOpenKeyEx (hKeyRoot, lpSubKey, 0, KEY_READ, &hKey);
if (lResult != ERROR_SUCCESS) { return FALSE; }
lpEnd = CheckSlash(lpSubKey);
//
// Enumerate the keys
//
dwSize = MAX_PATH; lResult = RegEnumKeyEx(hKey, 0, szName, &dwSize, NULL, NULL, NULL, &ftWrite);
if (lResult == ERROR_SUCCESS) {
do {
lstrcpy (lpEnd, szName);
if (!RegDelnodeRecurse(hKeyRoot, lpSubKey)) { break; }
//
// Enumerate again
//
dwSize = MAX_PATH;
lResult = RegEnumKeyEx(hKey, 0, szName, &dwSize, NULL, NULL, NULL, &ftWrite);
} while (lResult == ERROR_SUCCESS); }
lpEnd--; *lpEnd = TEXT('\0');
RegCloseKey (hKey);
//
// Try again to delete the key
//
lResult = RegDeleteKey(hKeyRoot, lpSubKey);
if (lResult == ERROR_SUCCESS) { return TRUE; }
return FALSE; }
BOOL RegDelnode (HKEY hKeyRoot, LPTSTR lpSubKey) { TCHAR szDelKey[2 * MAX_PATH];
lstrcpy (szDelKey, lpSubKey);
return RegDelnodeRecurse(hKeyRoot, szDelKey);
}
PSID GetUserSid( HANDLE UserToken ) { XPtrLF<TOKEN_USER> pUser; PTOKEN_USER pTemp; PSID pSid; DWORD BytesRequired = 200; NTSTATUS status;
//
// Allocate space for the user info
//
pUser = (PTOKEN_USER) LocalAlloc( LMEM_FIXED, BytesRequired ); if ( !pUser ) { return 0; }
//
// Read in the UserInfo
//
status = NtQueryInformationToken( UserToken, // Handle
TokenUser, // TokenInformationClass
pUser, // TokenInformation
BytesRequired, // TokenInformationLength
&BytesRequired // ReturnLength
);
if ( status == STATUS_BUFFER_TOO_SMALL ) { //
// Allocate a bigger buffer and try again.
//
pTemp = (PTOKEN_USER) LocalReAlloc( pUser, BytesRequired, LMEM_MOVEABLE ); if ( !pTemp ) { return 0; }
pUser = pTemp; status = NtQueryInformationToken( UserToken, // Handle
TokenUser, // TokenInformationClass
pUser, // TokenInformation
BytesRequired, // TokenInformationLength
&BytesRequired // ReturnLength
);
}
if ( !NT_SUCCESS(status) ) { return 0; }
BytesRequired = RtlLengthSid(pUser->User.Sid); pSid = LocalAlloc(LMEM_FIXED, BytesRequired); if ( !pSid ) { return NULL; }
status = RtlCopySid(BytesRequired, pSid, pUser->User.Sid);
if ( !NT_SUCCESS(status) ) { LocalFree(pSid); pSid = 0; }
return pSid; }
LPWSTR GetSidString( HANDLE UserToken ) { NTSTATUS NtStatus; PSID UserSid; UNICODE_STRING UnicodeString;
//
// Get the user sid
//
UserSid = GetUserSid( UserToken ); if ( !UserSid ) { return 0; }
//
// Convert user SID to a string.
//
NtStatus = RtlConvertSidToUnicodeString(&UnicodeString, UserSid, (BOOLEAN)TRUE ); // Allocate
LocalFree( UserSid );
if ( !NT_SUCCESS(NtStatus) ) { return 0; }
return UnicodeString.Buffer ; }
void DeleteSidString( LPWSTR SidString ) { UNICODE_STRING String;
RtlInitUnicodeString( &String, SidString ); RtlFreeUnicodeString( &String ); }
typedef BOOL (*PFNSHELLEXECUTEEX)(LPSHELLEXECUTEINFO lpExecInfo);
DWORD ExecuteScript( LPWSTR szCmdLine, LPWSTR szArgs, LPWSTR szWorkingDir, BOOL bSync, BOOL bHide, BOOL bRunMin, LPWSTR szType, PFNSHELLEXECUTEEX pfnShellExecuteEx, HANDLE hEventLog ) { WCHAR szCmdLineEx[MAX_PATH]; WCHAR szArgsEx[3 * MAX_PATH]; WCHAR szCurDir[MAX_PATH]; LPWSTR szOldPath = 0; BOOL bResult; DWORD dwError; SHELLEXECUTEINFO ExecInfo;
if ( GetSystemDirectory( szCurDir, ARRAYSIZE( szCurDir ) ) ) { SetCurrentDirectory( szCurDir ); }
//
// Expand the command line and args
//
ExpandEnvironmentStrings( szCmdLine, szCmdLineEx, ARRAYSIZE(szCmdLineEx) ); ExpandEnvironmentStrings( szArgs, szArgsEx, ARRAYSIZE(szArgsEx) );
//
// Put the working directory on the front of the PATH
// environment variable
//
PrependToPath( szWorkingDir, &szOldPath );
//
// Run the script
//
PathUnquoteSpaces( szCmdLineEx );
ZeroMemory(&ExecInfo, sizeof(ExecInfo)); ExecInfo.cbSize = sizeof(ExecInfo); ExecInfo.fMask = SEE_MASK_DOENVSUBST | SEE_MASK_FLAG_NO_UI | SEE_MASK_NOZONECHECKS | SEE_MASK_NOCLOSEPROCESS; ExecInfo.lpFile = szCmdLineEx; ExecInfo.lpParameters = !szArgsEx[0] ? 0 : szArgsEx; ExecInfo.lpDirectory = szWorkingDir;
if ( bHide ) { ExecInfo.nShow = SW_HIDE; } else { ExecInfo.nShow = (bRunMin ? SW_SHOWMINNOACTIVE : SW_SHOWNORMAL ); }
bResult = pfnShellExecuteEx( &ExecInfo ); dwError = GetLastError();
//
// Put the PATH environment variable back the way it was
//
if ( szOldPath ) { SetEnvironmentVariable( L"PATH", szOldPath ); LocalFree( szOldPath ); szOldPath = 0; }
if ( bResult ) { dwError = 0; if (bSync) { WaitForSingleObject(ExecInfo.hProcess, INFINITE); UpdateUserEnvironment(); } CloseHandle(ExecInfo.hProcess); } else { if ( hEventLog != 0 ) { LPWSTR szMsgBuf[2] = { (LPTSTR) ExecInfo.lpFile, 0 };
FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, 0, dwError, 0, (LPTSTR) (&szMsgBuf[1]), 1, 0);
ReportEvent(hEventLog, EVENTLOG_ERROR_TYPE, 0, SHELLEXEC_ERROR, 0, 2, 0, (LPCTSTR*) &szMsgBuf, 0); if ( szMsgBuf[1] ) { LocalFree( szMsgBuf[1] ); } } }
return dwError; }
ScrExecGPOFromReg( HKEY hKeyGPO, HKEY hKeyStateGPO, BOOL bSync, BOOL bHidden, BOOL bRunMin, LPWSTR szType, PFNSHELLEXECUTEEX pfnShellExecuteEx, HANDLE hEventLog ) { DWORD dwError = ERROR_SUCCESS; DWORD cSubKeys = 0; WCHAR szFileSysPath[3*MAX_PATH]; DWORD dwType; DWORD dwSize;
//
// FILESYSPATH
//
dwType = REG_SZ; dwSize = sizeof( szFileSysPath ); dwError = RegQueryValueEx( hKeyGPO, FILESYSPATH, 0, &dwType, (LPBYTE) szFileSysPath, &dwSize ); if ( dwError != ERROR_SUCCESS ) { return dwError; }
wcscat( szFileSysPath, L"\\Scripts\\" ); wcscat( szFileSysPath, szType );
//
// get the numer of Scripts
//
dwError = RegQueryInfoKey( hKeyGPO, 0, 0, 0, &cSubKeys, 0, 0, 0, 0, 0, 0, 0 ); if ( dwError == ERROR_SUCCESS ) { //
// for every Script
//
for ( DWORD dwIndex = 0 ; dwIndex < cSubKeys ; dwIndex++ ) { XKey hKeyScript; XKey hKeyStateScript; WCHAR szTemp[32];
dwError = RegOpenKeyEx( hKeyStateGPO, _itow( dwIndex, szTemp, 16 ), 0, KEY_ALL_ACCESS, &hKeyStateScript ); if ( dwError != ERROR_SUCCESS ) { return dwError; } //
// open the Script key (we need only read perms)
//
dwError = RegOpenKeyEx( hKeyGPO, szTemp, 0, KEY_READ, &hKeyScript ); if ( dwError != ERROR_SUCCESS ) { return dwError; }
WCHAR szScript[MAX_PATH]; WCHAR szParameters[MAX_PATH]; SYSTEMTIME execTime;
//
// script
//
dwType = REG_SZ; dwSize = sizeof( szScript ); dwError = RegQueryValueEx( hKeyScript, SCRIPT, 0, &dwType, (LPBYTE) szScript, &dwSize ); if ( dwError != ERROR_SUCCESS ) { break; }
//
// parameters
//
dwType = REG_SZ; dwSize = sizeof( szParameters ); dwError = RegQueryValueEx( hKeyScript, PARAMETERS, 0, &dwType, (LPBYTE) szParameters, &dwSize ); if ( dwError != ERROR_SUCCESS ) { break; }
//
// execute script
//
GetSystemTime( &execTime ); dwError = ExecuteScript(szScript, szParameters, szFileSysPath, bSync, bHidden, bRunMin, szType, pfnShellExecuteEx, hEventLog ); if ( dwError != ERROR_SUCCESS ) { ZeroMemory( &execTime, sizeof( execTime ) ); }
//
// write exec time
//
RegSetValueEx( hKeyStateScript, EXECTIME, 0, REG_QWORD, (LPBYTE) &execTime, sizeof( execTime ) ); } }
return dwError; }
extern "C" DWORD ScrExecGPOListFromReg( LPWSTR szType, BOOL bMachine, BOOL bSync, BOOL bHidden, BOOL bRunMin, HANDLE hEventLog ) { DWORD dwError = ERROR_SUCCESS; WCHAR szBuffer[MAX_PATH]; XKey hKeyType; XKey hKeyState; XKey hKeyStateType;
//
// create the following key
// HKLM\Software\Microsoft\Windows\CurrentVersion\Group Policy\State\<Target>\Scripts\<Type>
//
wcscpy( szBuffer, GP_STATE_KEY L"\\" ); if ( bMachine ) { wcscat( szBuffer, L"Machine\\Scripts" ); } else { XHandle hToken;
if ( !OpenProcessToken( GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken ) ) { return GetLastError(); }
LPWSTR szSid = GetSidString( hToken );
if ( !szSid ) { return GetLastError(); }
wcscat( szBuffer, szSid ); wcscat( szBuffer, L"\\Scripts" ); DeleteSidString( szSid ); }
//
// state
//
dwError = RegOpenKeyEx( HKEY_LOCAL_MACHINE, szBuffer, 0, KEY_ALL_ACCESS, &hKeyState ); if ( dwError != ERROR_SUCCESS ) { return dwError; }
dwError = RegOpenKeyEx( hKeyState, szType, 0, KEY_ALL_ACCESS, &hKeyStateType ); if ( dwError != ERROR_SUCCESS ) { return dwError; }
//
// construct "Software\\Policies\\Microsoft\\Windows\\System\\Scripts\\<Type>
//
wcscpy( szBuffer, GPO_SCRIPTS_KEY L"\\" ); wcscat( szBuffer, szType );
//
// open the key
//
dwError = RegOpenKeyEx( bMachine ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, szBuffer, 0, KEY_READ, &hKeyType ); if ( dwError != ERROR_SUCCESS ) { return dwError; } DWORD cSubKeys = 0;
//
// get the numer of GPOs
//
dwError = RegQueryInfoKey( hKeyType, 0, 0, 0, &cSubKeys, 0, 0, 0, 0, 0, 0, 0 ); if ( dwError != ERROR_SUCCESS ) { return dwError; }
HINSTANCE hShell32; PFNSHELLEXECUTEEX pfnShellExecuteEx;
hShell32 = LoadLibrary( L"shell32.dll" );
if ( hShell32 ) { pfnShellExecuteEx = (PFNSHELLEXECUTEEX) GetProcAddress( hShell32, "ShellExecuteExW" ); if ( !pfnShellExecuteEx ) { return GetLastError(); } }
//
// for every GPO
//
for ( DWORD dwIndex = 0 ; dwIndex < cSubKeys ; dwIndex++ ) { XKey hKeyGPO; XKey hKeyStateGPO;
//
// open the state GPO key
//
dwError = RegOpenKeyEx( hKeyStateType, _itow( dwIndex, szBuffer, 16 ), 0, KEY_ALL_ACCESS, &hKeyStateGPO ); if ( dwError != ERROR_SUCCESS ) { break; }
//
// open the policy GPO key (we need only read perms)
//
dwError = RegOpenKeyEx( hKeyType, szBuffer, 0, KEY_READ, &hKeyGPO ); if ( dwError != ERROR_SUCCESS ) { break; }
//
// execute all scripts in the GPO
//
DWORD dwExecError; dwExecError = ScrExecGPOFromReg(hKeyGPO, hKeyStateGPO, bSync, bHidden, bRunMin, szType, pfnShellExecuteEx, hEventLog ); if ( dwExecError != ERROR_SUCCESS ) { dwError = dwExecError; } }
return dwError; }
|