#define _WIN32_WINNT 0x601 #include #include #define DESKTOP_ALL (DESKTOP_READOBJECTS | DESKTOP_CREATEWINDOW | \ DESKTOP_CREATEMENU | DESKTOP_HOOKCONTROL | DESKTOP_JOURNALRECORD | \ DESKTOP_JOURNALPLAYBACK | DESKTOP_ENUMERATE | DESKTOP_WRITEOBJECTS | \ DESKTOP_SWITCHDESKTOP | STANDARD_RIGHTS_REQUIRED) #define WINSTA_ALL (WINSTA_ENUMDESKTOPS | WINSTA_READATTRIBUTES | \ WINSTA_ACCESSCLIPBOARD | WINSTA_CREATEDESKTOP | \ WINSTA_WRITEATTRIBUTES | WINSTA_ACCESSGLOBALATOMS | \ WINSTA_EXITWINDOWS | WINSTA_ENUMERATE | WINSTA_READSCREEN | \ STANDARD_RIGHTS_REQUIRED) #define GENERIC_ACCESS (GENERIC_READ | GENERIC_WRITE | \ GENERIC_EXECUTE | GENERIC_ALL) #pragma comment(lib, "advapi32.lib") HANDLE hToken, hJob; STARTUPINFO si; PROCESS_INFORMATION pi; HDESK hDesk = NULL; HWINSTA hWinSta = NULL, hWinStaSave = NULL; PSID pSid; JOBOBJECT_BASIC_LIMIT_INFORMATION jobBasicLimitInformation; JOBOBJECT_BASIC_UI_RESTRICTIONS jobBasicUIRestrictions; JOBOBJECT_BASIC_ACCOUNTING_INFORMATION jobBasicAccountingInformation; const DWORD nNanosecondsPerSecond = 100000000, nMillisecondsPerSecond = 1000, nNanosecondsPerMillisecond = nNanosecondsPerSecond / nMillisecondsPerSecond; BOOL GetLogonSID(HANDLE, PSID *); VOID FreeLogonSID(PSID *); BOOL AddAceToDesktop(HDESK, PSID); BOOL AddAceToWindowStation(HWINSTA, PSID); int main(void) { ZeroMemory(&si, sizeof(STARTUPINFOW)); ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); si.cb = sizeof(STARTUPINFOW); LogonUser("RestrictedUser", ".", "Password Here", LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &hToken); printf("LastError: %u\n", GetLastError()); hWinStaSave = GetProcessWindowStation(); hWinSta = OpenWindowStation("winsta0", FALSE, READ_CONTROL | WRITE_DAC); SetProcessWindowStation(hWinSta); hDesk = OpenDesktop("default", 0, FALSE, READ_CONTROL | WRITE_DAC | DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS); SetProcessWindowStation(hWinStaSave); GetLogonSID(hToken, &pSid); AddAceToWindowStation(hWinSta, pSid); AddAceToDesktop(hDesk, pSid); ImpersonateLoggedOnUser(hToken); si.lpDesktop = "winsta0\\default"; CreateProcessAsUser(hToken, NULL, "Program", NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS | CREATE_SUSPENDED | CREATE_BREAKAWAY_FROM_JOB | CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi); printf("LastError: %u\n", GetLastError()); hJob = CreateJobObject(NULL, NULL); printf("LastError: %u\n", GetLastError()); AssignProcessToJobObject(hJob, pi.hProcess); printf("LastError: %u\n", GetLastError()); jobBasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_JOB_TIME; jobBasicLimitInformation.PerJobUserTimeLimit.QuadPart = (LONGLONG)(5 * 1.2 * nNanosecondsPerMillisecond / 100); SetInformationJobObject(hJob, JobObjectBasicLimitInformation, &jobBasicLimitInformation, sizeof(jobBasicLimitInformation)); printf("LastError: %u\n", GetLastError()); jobBasicUIRestrictions.UIRestrictionsClass = (JOB_OBJECT_UILIMIT_EXITWINDOWS | JOB_OBJECT_UILIMIT_READCLIPBOARD | JOB_OBJECT_UILIMIT_WRITECLIPBOARD | JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS | JOB_OBJECT_UILIMIT_DISPLAYSETTINGS | JOB_OBJECT_UILIMIT_DESKTOP | JOB_OBJECT_UILIMIT_HANDLES); SetInformationJobObject(hJob, JobObjectBasicUIRestrictions, &jobBasicUIRestrictions, sizeof(jobBasicUIRestrictions)); printf("LastError: %u\n", GetLastError()); SetProcessWorkingSetSize(pi.hProcess, 1, 256 * 1024 * 1024); printf("LastError: %u\n", GetLastError()); ResumeThread(pi.hThread); WaitForSingleObject(pi.hProcess, 5000); TerminateJobObject(hJob, 1); printf("LastError: %u\n", GetLastError()); QueryInformationJobObject(hJob, JobObjectBasicAccountingInformation, &jobBasicAccountingInformation, sizeof(jobBasicAccountingInformation), NULL); printf("LastError: %u\n", GetLastError()); system("pause"); return 0; } 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; PACL pNewAcl = NULL; PSECURITY_DESCRIPTOR psd = NULL; PSECURITY_DESCRIPTOR psdNew = NULL; PVOID pTempAce; SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION; unsigned int i; if (!GetUserObjectSecurity( hwinsta, &si, psd, dwSidSize, &dwSdSizeNeeded) ) if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { psd = (PSECURITY_DESCRIPTOR)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwSdSizeNeeded); if (psd == NULL) return FALSE; psdNew = (PSECURITY_DESCRIPTOR)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwSdSizeNeeded); if (psdNew == NULL) return FALSE; dwSidSize = dwSdSizeNeeded; if (!GetUserObjectSecurity( hwinsta, &si, psd, dwSidSize, &dwSdSizeNeeded) ) return FALSE; } else return FALSE; if (!InitializeSecurityDescriptor( psdNew, SECURITY_DESCRIPTOR_REVISION) ) return FALSE; if (!GetSecurityDescriptorDacl( psd, &bDaclPresent, &pacl, &bDaclExist) ) return FALSE; ZeroMemory(&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION)); aclSizeInfo.AclBytesInUse = sizeof(ACL); if (pacl != NULL) { if (!GetAclInformation( pacl, (LPVOID)&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation) ) return FALSE; } 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) return FALSE; if (!InitializeAcl(pNewAcl, dwNewAclSize, ACL_REVISION)) return FALSE; if (bDaclPresent) if (aclSizeInfo.AceCount) { for (i=0; i < aclSizeInfo.AceCount; i++) { if (!GetAce(pacl, i, &pTempAce)) return FALSE; if (!AddAce( pNewAcl, ACL_REVISION, MAXDWORD, pTempAce, ((PACE_HEADER)pTempAce)->AceSize) ) return FALSE; } } pace = (ACCESS_ALLOWED_ACE *)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psid) - sizeof(DWORD)); if (pace == NULL) return FALSE; 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 = GENERIC_ACCESS; if (!CopySid(GetLengthSid(psid), &pace->SidStart, psid)) return FALSE; if (!AddAce( pNewAcl, ACL_REVISION, MAXDWORD, (LPVOID)pace, pace->Header.AceSize) ) return FALSE; pace->Header.AceFlags = NO_PROPAGATE_INHERIT_ACE; pace->Mask = WINSTA_ALL; if (!AddAce( pNewAcl, ACL_REVISION, MAXDWORD, (LPVOID)pace, pace->Header.AceSize) ) return FALSE; if (!SetSecurityDescriptorDacl( psdNew, TRUE, pNewAcl, FALSE) ) return FALSE; if (!SetUserObjectSecurity(hwinsta, &si, psdNew)) return FALSE; 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 TRUE; } 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; PACL pNewAcl = NULL; PSECURITY_DESCRIPTOR psd = NULL; PSECURITY_DESCRIPTOR psdNew = NULL; PVOID pTempAce; SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION; unsigned int i; if (!GetUserObjectSecurity( hdesk, &si, psd, dwSidSize, &dwSdSizeNeeded)) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { psd = (PSECURITY_DESCRIPTOR)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwSdSizeNeeded ); if (psd == NULL) return FALSE; psdNew = (PSECURITY_DESCRIPTOR)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwSdSizeNeeded); if (psdNew == NULL) return FALSE; dwSidSize = dwSdSizeNeeded; if (!GetUserObjectSecurity( hdesk, &si, psd, dwSidSize, &dwSdSizeNeeded) ) return FALSE; } else return FALSE; } if (!InitializeSecurityDescriptor( psdNew, SECURITY_DESCRIPTOR_REVISION) ) return FALSE; if (!GetSecurityDescriptorDacl( psd, &bDaclPresent, &pacl, &bDaclExist) ) return FALSE; ZeroMemory(&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION)); aclSizeInfo.AclBytesInUse = sizeof(ACL); if (pacl != NULL) { if (!GetAclInformation( pacl, (LPVOID)&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation) ) return FALSE; } dwNewAclSize = aclSizeInfo.AclBytesInUse + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psid) - sizeof(DWORD); pNewAcl = (PACL)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwNewAclSize); if (pNewAcl == NULL) return FALSE; if (!InitializeAcl(pNewAcl, dwNewAclSize, ACL_REVISION)) return FALSE; if (bDaclPresent) { if (aclSizeInfo.AceCount) { for (i=0; i < aclSizeInfo.AceCount; i++) { if (!GetAce(pacl, i, &pTempAce)) return FALSE; if (!AddAce( pNewAcl, ACL_REVISION, MAXDWORD, pTempAce, ((PACE_HEADER)pTempAce)->AceSize) ) return FALSE; } } } if (!AddAccessAllowedAce( pNewAcl, ACL_REVISION, DESKTOP_ALL, psid) ) return FALSE; if (!SetSecurityDescriptorDacl( psdNew, TRUE, pNewAcl, FALSE) ) return FALSE; if (!SetUserObjectSecurity(hdesk, &si, psdNew)) return FALSE; 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 TRUE; } BOOL GetLogonSID (HANDLE hToken, PSID *ppsid) { BOOL bSuccess = FALSE; DWORD dwIndex; DWORD dwLength = 0; PTOKEN_GROUPS ptg = NULL; // Verify the parameter passed in is not NULL. if (NULL == ppsid) goto Cleanup; // Get required buffer size and allocate the TOKEN_GROUPS buffer. if (!GetTokenInformation( hToken, // handle to the access token TokenGroups, // get information about the token's groups (LPVOID) ptg, // pointer to TOKEN_GROUPS buffer 0, // size of buffer &dwLength // receives required buffer size )) { if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) goto Cleanup; ptg = (PTOKEN_GROUPS)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwLength); if (ptg == NULL) goto Cleanup; } if (!GetTokenInformation(hToken, TokenGroups, (LPVOID) ptg, dwLength, &dwLength)) goto Cleanup; for (dwIndex = 0; dwIndex < ptg->GroupCount; dwIndex++) if ((ptg->Groups[dwIndex].Attributes & SE_GROUP_LOGON_ID) == SE_GROUP_LOGON_ID) { // Found the logon SID; make a copy of it. dwLength = GetLengthSid(ptg->Groups[dwIndex].Sid); *ppsid = (PSID) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwLength); if (*ppsid == NULL) goto Cleanup; if (!CopySid(dwLength, *ppsid, ptg->Groups[dwIndex].Sid)) { HeapFree(GetProcessHeap(), 0, (LPVOID)*ppsid); goto Cleanup; } break; } bSuccess = TRUE; Cleanup: if (ptg != NULL) HeapFree(GetProcessHeap(), 0, (LPVOID)ptg); return bSuccess; } VOID FreeLogonSID (PSID *ppsid) { HeapFree(GetProcessHeap(), 0, (LPVOID)*ppsid); }