DWORD CALLBACK CaptureAndSuspendProcess(LPVOID) { ImpersonateAnonymousToken(GetCurrentThread()); while (NtGetNextProcess(nullptr, MAXIMUM_ALLOWED, 0, 0, &g_hProcess) != 0) { } NTSTATUS status = NtSuspendProcess(g_hProcess); printf("Suspended process: %08X %p %d\n", status, g_hProcess, GetProcessId(g_hProcess)); RevertToSelf(); SetProcessId(GetProcessId(g_hProcess)); WCHAR cmdline[] = L"notepad.exe"; STARTUPINFO startInfo = {}; PROCESS_INFORMATION procInfo = {}; startInfo.cb = sizeof(startInfo); if (CreateProcessWithLogonW(L"user", L"domain", L"password", LOGON_NETCREDENTIALS_ONLY, nullptr, cmdline, CREATE_SUSPENDED, nullptr, nullptr, &startInfo, &procInfo)) { printf("Created process %d\n", procInfo.dwProcessId); } else { printf("Create error: %d\n", GetLastError()); } TerminateProcess(g_hProcess, 0); ExitProcess(0); return 0; }
bool JobbedProcessManager::spawn() { HANDLE handle; STARTUPINFO si = {sizeof(STARTUPINFO), 0}; PROCESS_INFORMATION pi; if (!szUsername) return false; if (!CreatePipe(&si.hStdInput, &handle, nullptr, 0)) throw WindowsException("CreatePipe stdin"); hStdin = handle; if (!CreatePipe(&handle, &si.hStdOutput, nullptr, 0)) throw WindowsException("CreatePipe stdout"); hStdout = handle; if (!CreatePipe(&handle, &si.hStdError, nullptr, 0)) throw WindowsException("CreatePipe stderr"); hStderr = handle; si.dwFlags |= STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE; if (!CreateProcessWithLogonW(szUsername, L".", szPassword, 0, szExecutable, szCmdLine, NORMAL_PRIORITY_CLASS | CREATE_SUSPENDED | CREATE_BREAKAWAY_FROM_JOB | CREATE_UNICODE_ENVIRONMENT, szEnvBlock, szDirectory, &si, &pi)) throw WindowsException("CreateProcessWithLogonW"); CloseHandle(si.hStdInput); CloseHandle(si.hStdOutput); CloseHandle(si.hStdError); hProcess = pi.hProcess; if (!(handle = SearchForJobByService(hProcess, L"seclogon"))) throw WindowsException("Failed to find job", 0); hJob = handle; if (!SetInformationJobObject(hJob, JobObjectExtendedLimitInformation, &extLimits, sizeof extLimits)) throw WindowsException("SetInformationJobObject JobObjectExtendedLimitInformation"); if (!SetInformationJobObject(hJob, JobObjectBasicUIRestrictions, &uiLimits, sizeof uiLimits)) throw WindowsException("SetInformationJobObject JobObjectBasicUIRestrictions"); LARGE_INTEGER liFreq; QueryPerformanceFrequency(&liFreq); qpc_freq = 1.0 / liFreq.QuadPart; QueryPerformanceCounter(&liStart); ResumeThread(pi.hThread); CloseHandle(pi.hThread); if (!(handle = CreateThread(nullptr, 0, s_ShockerProc, this, 0, nullptr))) throw WindowsException("CreateThread"); hShocker = handle; return true; }
eResult CSecRunAsUser::RestartAsUser(){ USES_CONVERSION; if (m_bRunningRestricted || m_bRunningAsEmule) return RES_OK; if (!LoadAPI()) return RES_FAILED; ASSERT ( !m_strPassword.IsEmpty() ); BOOL bResult; try{ PROCESS_INFORMATION ProcessInfo = {0}; TCHAR szAppPath[MAX_PATH]; GetModuleFileName(NULL, szAppPath, MAX_PATH); CString strAppName; strAppName.Format(_T("\"%s\""),szAppPath); STARTUPINFOW StartInf = {0}; StartInf.cb = sizeof(StartInf); StartInf.dwFlags = STARTF_USESHOWWINDOW; StartInf.wShowWindow = SW_NORMAL; // remove the current mutex, so that the restart emule can create its own without problems // in the rare case CreateProcessWithLogonW fails, this will allow mult. instances, but if that function fails we have other problems anyway //MODIFIED by fengwen on 2007/03/05 <begin> : //::CloseHandle(theApp.m_hMutexOneInstance); if (NULL != theApp.m_pSingleInst) theApp.m_pSingleInst->AppEnd(); //MODIFIED by fengwen on 2007/03/05 <end> : if (NULL != theApp.m_pSingleInst2Loader) theApp.m_pSingleInst2Loader->AppEnd(); bResult = CreateProcessWithLogonW(EMULEACCOUNTW, m_strDomain, m_strPassword, LOGON_WITH_PROFILE, NULL, (LPWSTR)T2CW(strAppName), 0, NULL, NULL, &StartInf, &ProcessInfo); CloseHandle(ProcessInfo.hProcess); CloseHandle(ProcessInfo.hThread); } catch(...){ CGlobalVariable::QueueDebugLogLine(false, _T("Run as unpriveleged user: Error: Unexpected exception while loading advapi32.dll")); FreeAPI(); return RES_FAILED; } FreeAPI(); if (!bResult) CGlobalVariable::QueueDebugLogLine(false, _T("Run as unpriveleged user: Error: Failed to restart eMule as different user! Error Code: %i"),GetLastError()); if (bResult) return RES_OK_NEED_RESTART; else return RES_FAILED; }
eResult CSecRunAsUser::RestartAsUser(){ if (m_bRunningRestricted || m_bRunningAsEmule) return RES_OK; if (!LoadAPI()) return RES_FAILED; TCHAR szAppPath[MAX_PATH]; DWORD dwModPathLen = GetModuleFileName(NULL, szAppPath, _countof(szAppPath)); if (dwModPathLen == 0 || dwModPathLen == _countof(szAppPath)) return RES_FAILED; ASSERT ( !m_strPassword.IsEmpty() ); BOOL bResult; try{ PROCESS_INFORMATION ProcessInfo = {0}; CString strAppName; strAppName.Format(_T("\"%s\""),szAppPath); STARTUPINFOW StartInf = {0}; StartInf.cb = sizeof(StartInf); StartInf.dwFlags = STARTF_USESHOWWINDOW; StartInf.wShowWindow = SW_NORMAL; // remove the current mutex, so that the restart emule can create its own without problems // in the rare case CreateProcessWithLogonW fails, this will allow mult. instances, but if that function fails we have other problems anyway ::CloseHandle(theApp.m_hMutexOneInstance); bResult = CreateProcessWithLogonW(EMULEACCOUNTW, m_strDomain, m_strPassword, LOGON_WITH_PROFILE, NULL, const_cast<LPWSTR>((LPCWSTR)strAppName), 0, NULL, NULL, &StartInf, &ProcessInfo); CloseHandle(ProcessInfo.hProcess); CloseHandle(ProcessInfo.hThread); } catch(...){ theApp.QueueDebugLogLine(false, _T("Run as unpriveleged user: Error: Unexpected exception while loading advapi32.dll")); FreeAPI(); return RES_FAILED; } FreeAPI(); if (!bResult) theApp.QueueDebugLogLine(false, _T("Run as unpriveleged user: Error: Failed to restart eMule as different user! Error Code: %i"),GetLastError()); if (bResult) return RES_OK_NEED_RESTART; else return RES_FAILED; }
void wmain(int argc, WCHAR *argv[]) { DWORD dwSize; HANDLE hToken; LPVOID lpvEnv; PROCESS_INFORMATION pi = {0}; STARTUPINFO si = {0}; WCHAR szUserProfile[256] = L""; si.cb = sizeof(STARTUPINFO); if (argc != 4) { /* wprintf(L"Usage: %s [user@domain] [password] [cmd]", argv[0]); wprintf(L"\n\n"); */ // return; } dwSize = sizeof(szUserProfile)/sizeof(WCHAR); OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,&hToken); //ShowLastError(L"OpenProcessToken"); //SetPrivilege(&hToken, SE_SYSTEMTIME_NAME,TRUE); // if(!SetPrivilege(hToken, SE_TCB_NAME , TRUE)) printf("Set Privilege Failed");// DisplayError(L"SetPrivilege"); //if (!LogonUser(argv[1], NULL , argv[2], LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &hToken)) DisplayError(L"LogonUser"); if (!CreateEnvironmentBlock(&lpvEnv, hToken, TRUE)) ShowLastError(L"CreateEnvironmentBlock"); dwSize = sizeof(szUserProfile)/sizeof(WCHAR); if (!GetUserProfileDirectory(hToken, szUserProfile, &dwSize)) ShowLastError(L"GetUserProfileDirectory"); // // TO DO: change NULL to '.' to use local account database // if (!CreateProcessWithLogonW(argv[1], NULL, argv[2], LOGON_WITH_PROFILE, NULL, argv[3], CREATE_UNICODE_ENVIRONMENT, lpvEnv, szUserProfile, &si, &pi)) ShowLastError(L"CreateProcessWithLogonW"); if (!DestroyEnvironmentBlock(lpvEnv)) ShowLastError(L"DestroyEnvironmentBlock"); CloseHandle(hToken); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); }
BOOL kull_m_process_create(KULL_M_PROCESS_CREATE_TYPE type, PCWSTR commandLine, DWORD processFlags, HANDLE hUserToken, DWORD logonFlags, PCWSTR user, PCWSTR domain, PCWSTR password, PPROCESS_INFORMATION pProcessInfos, BOOL autoCloseHandle) { BOOL status = FALSE; DWORD iProcessFlags = CREATE_NEW_CONSOLE | processFlags; DWORD iLogonFlags = 0 | logonFlags; PWSTR dupCommandLine; PPROCESS_INFORMATION ptrProcessInfos; STARTUPINFO startupInfo; RtlZeroMemory(&startupInfo, sizeof(STARTUPINFO)); startupInfo.cb = sizeof(STARTUPINFO); if(ptrProcessInfos = pProcessInfos ? pProcessInfos : (PPROCESS_INFORMATION) LocalAlloc(LPTR, sizeof(PROCESS_INFORMATION))) { if(dupCommandLine = _wcsdup(commandLine)) { switch(type) { case KULL_M_PROCESS_CREATE_NORMAL: status = CreateProcess(NULL, dupCommandLine, NULL, NULL, FALSE, iProcessFlags, NULL, NULL, &startupInfo, ptrProcessInfos); break; case KULL_M_PROCESS_CREATE_USER: status = CreateProcessAsUser(hUserToken, NULL, dupCommandLine, NULL, NULL, FALSE, iProcessFlags, NULL, NULL, &startupInfo, ptrProcessInfos); break; /*case KULL_M_PROCESS_CREATE_TOKEN: status = CreateProcessWithTokenW(hUserToken, iLogonFlags, NULL, dupCommandLine, iProcessFlags, NULL, NULL, &startupInfo, ptrProcessInfos); break;*/ case KULL_M_PROCESS_CREATE_LOGON: status = CreateProcessWithLogonW(user, domain, password, iLogonFlags, NULL, dupCommandLine, iProcessFlags, NULL, NULL, &startupInfo, ptrProcessInfos); break; } if(status && (autoCloseHandle || !pProcessInfos)) { CloseHandle(ptrProcessInfos->hThread); CloseHandle(ptrProcessInfos->hProcess); } if(!pProcessInfos) LocalFree(ptrProcessInfos); free(dupCommandLine); } } return status; }
void CreatProc(int argc, WCHAR *argv[]) { DWORD dwSize; HANDLE hToken; LPVOID lpvEnv; PROCESS_INFORMATION pi = {0}; STARTUPINFO si = {0}; WCHAR szUserProfile[256] = L""; si.cb = sizeof(STARTUPINFO); // // TO DO: change NULL to '.' to use local account database // if (!LogonUser(argv[1], NULL, argv[2], LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &hToken)) DisplayError(L"LogonUser"); //if (!CreateEnvironmentBlock(&lpvEnv, hToken, TRUE)) DisplayError(L"CreateEnvironmentBlock"); // dwSize = sizeof(szUserProfile)/sizeof(WCHAR); //if (!GetUserProfileDirectory(hToken, szUserProfile, &dwSize)) DisplayError(L"GetUserProfileDirectory"); // // TO DO: change NULL to '.' to use local account database // int bResult; bResult = CreateProcessWithLogonW(argv[1], NULL, argv[2], LOGON_WITH_PROFILE, NULL, argv[3], CREATE_UNICODE_ENVIRONMENT, /*lpvEnv*/ NULL, szUserProfile, &si, &pi); DWORD dwError; dwError = ::GetLastError(); DisplayError(L"CreateProcessWithLogonW"); // if (!DestroyEnvironmentBlock(lpvEnv)) DisplayError(L"DestroyEnvironmentBlock"); CloseHandle(hToken); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); }
BOOL WINAPI OnCreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation) { //typedef BOOL (WINAPI* OnCreateProcessW_t)(LPCWSTR lpApplicationName, LPWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation); ORIGINAL_KRNL(CreateProcessW); BOOL lbRc = FALSE; DWORD dwErr = 0; DWORD ldwCreationFlags = dwCreationFlags; if (ph && ph->PreCallBack) { SETARGS10(&lbRc, lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, ldwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation); // Если функция возвращает FALSE - реальное чтение не будет вызвано if (!ph->PreCallBack(&args)) return lbRc; } CShellProc* sp = new CShellProc(); if (!sp || !sp->OnCreateProcessW(&lpApplicationName, (LPCWSTR*)&lpCommandLine, &lpCurrentDirectory, &ldwCreationFlags, lpStartupInfo)) { delete sp; SetLastError(ERROR_FILE_NOT_FOUND); return FALSE; } if ((ldwCreationFlags & CREATE_SUSPENDED) == 0) { DebugString(L"CreateProcessW without CREATE_SUSPENDED Flag!\n"); } #ifdef _DEBUG SetLastError(0); #endif #ifdef SHOWCREATEPROCESSTICK prepare_timings; force_print_timings(L"CreateProcessW"); #endif #if 0 // This is disabled for now. Command will create new visible console window, // but excpected behavior will be "reuse" of existing console window if (!sp->GetArgs()->bNewConsole && sp->GetArgs()->pszUserName) { LPCWSTR pszName = sp->GetArgs()->pszUserName; LPCWSTR pszDomain = sp->GetArgs()->pszDomain; LPCWSTR pszPassword = sp->GetArgs()->szUserPassword; STARTUPINFOW si = {sizeof(si)}; PROCESS_INFORMATION pi = {}; DWORD dwOurFlags = (ldwCreationFlags & ~EXTENDED_STARTUPINFO_PRESENT); lbRc = CreateProcessWithLogonW(pszName, pszDomain, (pszPassword && *pszPassword) ? pszPassword : NULL, LOGON_WITH_PROFILE, lpApplicationName, lpCommandLine, dwOurFlags, lpEnvironment, lpCurrentDirectory, &si, &pi); if (lbRc) *lpProcessInformation = pi; } else #endif { lbRc = F(CreateProcessW)(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, ldwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation); } dwErr = GetLastError(); #ifdef SHOWCREATEPROCESSTICK force_print_timings(L"CreateProcessW - done"); #endif // Если lbParamsChanged == TRUE - об инжектах позаботится ConEmuC.exe sp->OnCreateProcessFinished(lbRc, lpProcessInformation); delete sp; #ifdef SHOWCREATEPROCESSTICK force_print_timings(L"OnCreateProcessFinished - done"); #endif if (ph && ph->PostCallBack) { SETARGS10(&lbRc, lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, ldwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation); ph->PostCallBack(&args); } SetLastError(dwErr); return lbRc; }
void impersonateToGetData(PCSTR user, PCSTR domain, PCSTR password, PCSTR kdc, PSID *sid, DWORD *rid, PCSTR usingWhat) { NTSTATUS status; DWORD ret, *aRid, *usage; ANSI_STRING aUser, aKdc, aDomain, aPass, aProg; UNICODE_STRING uUser, uKdc, uDomain, uPass, uProg; SAMPR_HANDLE hServerHandle, hDomainHandle; PSID domainSid; HANDLE hToken, hNewToken; PROCESS_INFORMATION processInfos; STARTUPINFOW startupInfo; RtlZeroMemory(&startupInfo, sizeof(STARTUPINFOW)); startupInfo.cb = sizeof(STARTUPINFOW); RtlInitString(&aUser, user); RtlInitString(&aKdc, kdc); RtlInitString(&aDomain, domain); RtlInitString(&aPass, password); RtlInitString(&aProg, usingWhat ? usingWhat : "winver.exe"); if(NT_SUCCESS(RtlAnsiStringToUnicodeString(&uUser, &aUser, TRUE))) { if(NT_SUCCESS(RtlAnsiStringToUnicodeString(&uKdc, &aKdc, TRUE))) { if(NT_SUCCESS(RtlAnsiStringToUnicodeString(&uDomain, &aDomain, TRUE))) { if(NT_SUCCESS(RtlAnsiStringToUnicodeString(&uPass, &aPass, TRUE))) { if(NT_SUCCESS(RtlAnsiStringToUnicodeString(&uProg, &aProg, TRUE))) { if(CreateProcessWithLogonW(uUser.Buffer, uDomain.Buffer, uPass.Buffer, LOGON_NETCREDENTIALS_ONLY, uProg.Buffer, NULL, CREATE_SUSPENDED, NULL, NULL, &startupInfo, &processInfos)) { if(OpenProcessToken(processInfos.hProcess, TOKEN_DUPLICATE, &hToken)) { if(DuplicateTokenEx(hToken, TOKEN_QUERY | TOKEN_IMPERSONATE, NULL, SecurityDelegation, TokenImpersonation, &hNewToken)) { if(SetThreadToken(NULL, hNewToken)) { kprintf("[AUTH] Impersonation\n"); if(!(*sid && *rid)) { kprintf("[SID/RID] \'%s @ %s\' must be translated to SID/RID\n", user, domain); status = SamConnect(&uKdc, &hServerHandle, SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN, FALSE); if(NT_SUCCESS(status)) { status = SamLookupDomainInSamServer(hServerHandle, &uDomain, &domainSid); if(NT_SUCCESS(status)) { status = SamOpenDomain(hServerHandle, DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP, domainSid, &hDomainHandle); if(NT_SUCCESS(status)) { status = SamLookupNamesInDomain(hDomainHandle, 1, &uUser, &aRid, &usage); if(NT_SUCCESS(status)) *rid = *aRid; else PRINT_ERROR("SamLookupNamesInDomain %08x\n", status); } else PRINT_ERROR("SamOpenDomain %08x\n", status); ret = GetLengthSid(domainSid); if(*sid = (PSID) LocalAlloc(LPTR, ret)) { if(!CopySid(ret, *sid, domainSid)) { *sid = (PSID) LocalFree(*sid); PRINT_ERROR_AUTO("CopySid"); } } SamFreeMemory(domainSid); } else PRINT_ERROR("SamLookupDomainInSamServer %08x\n", status); SamCloseHandle(hServerHandle); } else PRINT_ERROR("SamConnect %08x\n", status); } RevertToSelf(); } else PRINT_ERROR_AUTO("SetThreadToken"); CloseHandle(hNewToken); } else PRINT_ERROR_AUTO("DuplicateTokenEx"); CloseHandle(hToken); } else PRINT_ERROR_AUTO("OpenProcessToken"); TerminateProcess(processInfos.hProcess, 0); CloseHandle(processInfos.hProcess); CloseHandle(processInfos.hThread); } else PRINT_ERROR_AUTO("CreateProcessWithLogonW"); RtlFreeUnicodeString(&uProg); } RtlFreeUnicodeString(&uPass); } RtlFreeUnicodeString(&uDomain); } RtlFreeUnicodeString(&uKdc); } RtlFreeUnicodeString(&uUser); } }
/** * @brief * unregister_scm - unregister_scm: return 0 for success; non-zero for fail * * @param[in] svc_name - service name. * * @return int * @retval 0 : success * @retval non-zero : fail */ int unregister_scm(char *svc_name) { SC_LOCK sclLock = NULL; SC_HANDLE schService = NULL; SC_HANDLE schSCManager = NULL; int ret = 1; SERVICE_STATUS ss; int try; schSCManager = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS); if (!schSCManager) { fprintf(stderr, "OpenSCManager failed - %d\n", GetLastError()); goto unregister_scm_cleanup; } /* Open a handle to the service instance. */ schService = OpenService(schSCManager, svc_name, SERVICE_ALL_ACCESS); if (!schService) { fprintf(stderr, "OpenService %s failed - %d\n", svc_name, GetLastError()); goto unregister_scm_cleanup; } /* Get the SCM database lock before changing the password. */ sclLock = LockServiceDatabase(schSCManager); if (sclLock == NULL) { fprintf(stderr, "LockServiceDatabase failed - %d\n", GetLastError()); goto unregister_scm_cleanup; } /* Stop the service first */ ControlService(schService, SERVICE_CONTROL_STOP, &ss); try = 0; ss.dwCurrentState = SERVICE_RUNNING; while ((try < WAIT_RETRY_MAX) && ss.dwCurrentState != SERVICE_STOPPED) { printf("[try %d] waiting for service %s to die\n", try, svc_name); sleep(3); if (!QueryServiceStatus(schService, &ss)) break; try++; } if (!DeleteService(schService)) { fprintf(stderr, "DeleteService(%s) failed - %d\n", svc_name, GetLastError()); goto unregister_scm_cleanup; } printf("\nDeleted service %s\n", svc_name); ret = 0; unregister_scm_cleanup: if (sclLock) UnlockServiceDatabase(sclLock); if (schService) CloseServiceHandle(schService); if (schSCManager) CloseServiceHandle(schSCManager); return (ret); } /** * @brief * prompt_to_get_password - prompt for password. * * @param[out] pass - password. */ void prompt_to_get_password(char pass[LM20_PWLEN+1]) { int ch, j; printf("Please enter password: "******""); if ((p=strstr((const char *)account, "\\"))) { *p = '\0'; strcpy(dname, (const char *)account); *p = '\\'; strcpy(uname, p+1); } mbstowcs(unamew, uname, UNLEN+1); mbstowcs(dnamew, dname, PBS_MAXHOSTNAME+1); mbstowcs(passwordw, password, LM20_PWLEN+1); si.cb = sizeof(si); si.lpDesktop = L""; if( !for_info_only && \ ((rc=CreateProcessWithLogonW(unamew, dnamew, passwordw, 0, NULL, L"cmd /c echo okay", flags, NULL, NULL, &si, &pi)) == 0)) { fprintf(stderr, "Password did not validate against %s err=%d\n\nClick BACK button to retry a different password.\nClick NEXT button to abort installation.", account, GetLastError()); wcsset(passwordw, 0); return (0); } WaitForSingleObject(pi.hProcess, INFINITE); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); printf("%s password for %s\n", (for_info_only?"Validating":"Validated"), account); wcsset(passwordw, 0); return (1); }
bool StartProcess(Settings& settings, HANDLE hCmdPipe) { //Launching as one of: //1. System Account //2. Specified account (or limited account) //3. As current process DWORD gle = 0; BOOL bLoadedProfile = FALSE; PROFILEINFO profile = {0}; profile.dwSize = sizeof(profile); profile.lpUserName = (LPWSTR)(LPCWSTR)settings.user; profile.dwFlags = PI_NOUI; if(false == GetUserHandle(settings, bLoadedProfile, profile, hCmdPipe)) return false; PROCESS_INFORMATION pi = {0}; STARTUPINFO si = {0}; si.cb = sizeof(si); si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_SHOW; if(!BAD_HANDLE(settings.hStdErr)) { si.hStdError = settings.hStdErr; si.hStdInput = settings.hStdIn; si.hStdOutput = settings.hStdOut; si.dwFlags |= STARTF_USESTDHANDLES; #ifdef _DEBUG Log(L"DEBUG: Using redirected handles", false); #endif } #ifdef _DEBUG else Log(L"DEBUG: Not using redirected IO", false); #endif CString path = StrFormat(L"\"%s\"", settings.app); if(FALSE == settings.appArgs.IsEmpty()) { path += L" "; path += settings.appArgs; } LPCWSTR startingDir = NULL; if(FALSE == settings.workingDir.IsEmpty()) startingDir = settings.workingDir; DWORD launchGLE = 0; CleanupInteractive ci = {0}; if(settings.bInteractive || settings.bShowUIOnWinLogon) { BOOL b = PrepForInteractiveProcess(settings, &ci, settings.sessionToInteractWith); if(FALSE == b) Log(L"Failed to PrepForInteractiveProcess", true); if(NULL == si.lpDesktop) si.lpDesktop = L"WinSta0\\Default"; if(settings.bShowUIOnWinLogon) si.lpDesktop = L"winsta0\\Winlogon"; //Log(StrFormat(L"Using desktop: %s", si.lpDesktop), false); //http://blogs.msdn.com/b/winsdk/archive/2009/07/14/launching-an-interactive-process-from-windows-service-in-windows-vista-and-later.aspx //indicates desktop names are case sensitive } #ifdef _DEBUG Log(StrFormat(L"DEBUG: PAExec using desktop %s", si.lpDesktop == NULL ? L"{default}" : si.lpDesktop), false); #endif DWORD dwFlags = CREATE_SUSPENDED | CREATE_NEW_CONSOLE; LPVOID pEnvironment = NULL; VERIFY(CreateEnvironmentBlock(&pEnvironment, settings.hUser, TRUE)); if(NULL != pEnvironment) dwFlags |= CREATE_UNICODE_ENVIRONMENT; #ifdef _DEBUG gle = GetLastError(); Log(L"DEBUG: CreateEnvironmentBlock", gle); #endif if(settings.bDisableFileRedirection) DisableFileRedirection(); if(settings.bRunLimited) if(false == LimitRights(settings.hUser)) return false; if(settings.bRunElevated) if(false == ElevateUserToken(settings.hUser)) return false; CString user, domain; GetUserDomain(settings.user, user, domain); #ifdef _DEBUG Log(StrFormat(L"DEBUG: U:%s D:%s P:%s bP:%d Env:%s WD:%s", user, domain, settings.password, settings.bDontLoadProfile, pEnvironment ? L"true" : L"null", startingDir ? startingDir : L"null"), false); #endif BOOL bLaunched = FALSE; if(settings.bUseSystemAccount) { Log(StrFormat(L"PAExec starting process [%s] as Local System", path), false); if(BAD_HANDLE(settings.hUser)) Log(L"Have bad user handle", true); EnablePrivilege(SE_IMPERSONATE_NAME); BOOL bImpersonated = ImpersonateLoggedOnUser(settings.hUser); if(FALSE == bImpersonated) { Log(L"Failed to impersonate", GetLastError()); _ASSERT(bImpersonated); } EnablePrivilege(SE_ASSIGNPRIMARYTOKEN_NAME); EnablePrivilege(SE_INCREASE_QUOTA_NAME); bLaunched = CreateProcessAsUser(settings.hUser, NULL, path.LockBuffer(), NULL, NULL, TRUE, dwFlags, pEnvironment, startingDir, &si, &pi); launchGLE = GetLastError(); path.UnlockBuffer(); #ifdef _DEBUG if(0 != launchGLE) Log(StrFormat(L"Launch (launchGLE=%u) params: user=[x%X] path=[%s] flags=[x%X], pEnv=[%s], dir=[%s], stdin=[x%X], stdout=[x%X], stderr=[x%X]", launchGLE, (DWORD)settings.hUser, path, dwFlags, pEnvironment ? L"{env}" : L"{null}", startingDir ? startingDir : L"{null}", (DWORD)si.hStdInput, (DWORD)si.hStdOutput, (DWORD)si.hStdError), false); #endif RevertToSelf(); } else { if(FALSE == settings.user.IsEmpty()) //launching as a specific user { Log(StrFormat(L"PAExec starting process [%s] as %s", path, settings.user), false); if(false == settings.bRunLimited) { bLaunched = CreateProcessWithLogonW(user, domain.IsEmpty() ? NULL : domain, settings.password, settings.bDontLoadProfile ? 0 : LOGON_WITH_PROFILE, NULL, path.LockBuffer(), dwFlags, pEnvironment, startingDir, &si, &pi); launchGLE = GetLastError(); path.UnlockBuffer(); #ifdef _DEBUG if(0 != launchGLE) Log(StrFormat(L"Launch (launchGLE=%u) params: user=[%s] domain=[%s] prof=[x%X] path=[%s] flags=[x%X], pEnv=[%s], dir=[%s], stdin=[x%X], stdout=[x%X], stderr=[x%X]", launchGLE, user, domain, settings.bDontLoadProfile ? 0 : LOGON_WITH_PROFILE, path, dwFlags, pEnvironment ? L"{env}" : L"{null}", startingDir ? startingDir : L"{null}", (DWORD)si.hStdInput, (DWORD)si.hStdOutput, (DWORD)si.hStdError), false); #endif } else bLaunched = FALSE; //force to run with CreateProcessAsUser so rights can be limited //CreateProcessWithLogonW can't be called from LocalSystem on Win2003 and earlier, so LogonUser/CreateProcessAsUser must be used. Might as well try for everyone if((FALSE == bLaunched) && !BAD_HANDLE(settings.hUser)) { #ifdef _DEBUG Log(L"DEBUG: Failed CreateProcessWithLogonW - trying CreateProcessAsUser", GetLastError()); #endif EnablePrivilege(SE_ASSIGNPRIMARYTOKEN_NAME); EnablePrivilege(SE_INCREASE_QUOTA_NAME); EnablePrivilege(SE_IMPERSONATE_NAME); BOOL bImpersonated = ImpersonateLoggedOnUser(settings.hUser); if(FALSE == bImpersonated) { Log(L"Failed to impersonate", GetLastError()); _ASSERT(bImpersonated); } bLaunched = CreateProcessAsUser(settings.hUser, NULL, path.LockBuffer(), NULL, NULL, TRUE, CREATE_SUSPENDED | CREATE_UNICODE_ENVIRONMENT | CREATE_NEW_CONSOLE, pEnvironment, startingDir, &si, &pi); if(0 == GetLastError()) launchGLE = 0; //mark as successful, otherwise return our original error path.UnlockBuffer(); #ifdef _DEBUG if(0 != launchGLE) Log(StrFormat(L"Launch (launchGLE=%u) params: user=[x%X] path=[%s] pEnv=[%s], dir=[%s], stdin=[x%X], stdout=[x%X], stderr=[x%X]", launchGLE, (DWORD)settings.hUser, path, pEnvironment ? L"{env}" : L"{null}", startingDir ? startingDir : L"{null}", (DWORD)si.hStdInput, (DWORD)si.hStdOutput, (DWORD)si.hStdError), false); #endif RevertToSelf(); } } else { Log(StrFormat(L"PAExec starting process [%s] as current user", path), false); EnablePrivilege(SE_ASSIGNPRIMARYTOKEN_NAME); EnablePrivilege(SE_INCREASE_QUOTA_NAME); EnablePrivilege(SE_IMPERSONATE_NAME); if(NULL != settings.hUser) bLaunched = CreateProcessAsUser(settings.hUser, NULL, path.LockBuffer(), NULL, NULL, TRUE, dwFlags, pEnvironment, startingDir, &si, &pi); if(FALSE == bLaunched) bLaunched = CreateProcess(NULL, path.LockBuffer(), NULL, NULL, TRUE, dwFlags, pEnvironment, startingDir, &si, &pi); launchGLE = GetLastError(); //#ifdef _DEBUG if(0 != launchGLE) Log(StrFormat(L"Launch (launchGLE=%u) params: path=[%s] user=[%s], pEnv=[%s], dir=[%s], stdin=[x%X], stdout=[x%X], stderr=[x%X]", launchGLE, path, settings.hUser ? L"{non-null}" : L"{null}", pEnvironment ? L"{env}" : L"{null}", startingDir ? startingDir : L"{null}", (DWORD)si.hStdInput, (DWORD)si.hStdOutput, (DWORD)si.hStdError), false); //#endif path.UnlockBuffer(); } } if(bLaunched) { if(gbInService) Log(L"Successfully launched", false); settings.hProcess = pi.hProcess; settings.processID = pi.dwProcessId; if(false == settings.allowedProcessors.empty()) { DWORD sysMask = 0, procMask = 0; VERIFY(GetProcessAffinityMask(pi.hProcess, &procMask, &sysMask)); procMask = 0; for(std::vector<WORD>::iterator itr = settings.allowedProcessors.begin(); settings.allowedProcessors.end() != itr; itr++) { DWORD bit = 1; bit = bit << (*itr - 1); procMask |= bit & sysMask; } VERIFY(SetProcessAffinityMask(pi.hProcess, procMask)); } VERIFY(SetPriorityClass(pi.hProcess, settings.priority)); ResumeThread(pi.hThread); VERIFY(CloseHandle(pi.hThread)); } else { Log(StrFormat(L"Failed to start %s.", path), launchGLE); if((ERROR_ELEVATION_REQUIRED == launchGLE) && (false == gbInService)) Log(L"HINT: PAExec probably needs to be \"Run As Administrator\"", false); } if(ci.bPreped) CleanUpInteractiveProcess(&ci); if(settings.bDisableFileRedirection) RevertFileRedirection(); if(NULL != pEnvironment) DestroyEnvironmentBlock(pEnvironment); pEnvironment = NULL; if(bLoadedProfile) UnloadUserProfile(settings.hUser, profile.hProfile); if(!BAD_HANDLE(settings.hUser)) { CloseHandle(settings.hUser); settings.hUser = NULL; } return bLaunched ? true : false; }
bool runner::init_process_with_logon(char *cmd, const char *wd) { WaitForSingleObject(main_job_object_access_mutex, infinite); set_allow_breakaway(false); STARTUPINFOW siw; //USES_CONVERSION; ZeroMemory(&siw, sizeof(siw)); siw.cb = sizeof(si); siw.dwFlags = si.dwFlags; siw.hStdInput = si.hStdInput; siw.hStdOutput = si.hStdOutput; siw.hStdError = si.hStdError; siw.wShowWindow = si.wShowWindow; siw.lpDesktop = NULL;//L""; std::string run_program = program + " " + options.get_arguments(); wchar_t *login = a2w(options.login.c_str()); wchar_t *password = a2w(options.password.c_str()); wchar_t *wprogram = a2w(run_program.c_str()); wchar_t *wcmd = a2w(cmd); wchar_t *wwd = a2w(wd); DWORD creation_flags = CREATE_SUSPENDED | CREATE_SEPARATE_WOW_VDM | CREATE_NO_WINDOW; HANDLE token = NULL; auto original = set_environment_for_process(); if ( !CreateProcessWithLogonW(login, NULL, password, 0, wprogram, wcmd, creation_flags, NULL, wwd, &siw, &process_info) ) { if (!options.use_cmd || !CreateProcessWithLogonW(login, NULL, password, 0, NULL, wcmd, creation_flags, NULL, wwd, &siw, &process_info) ) { ReleaseMutex(main_job_object_access_mutex); PANIC("CreateProcess: \"" + run_program + "\", " + get_win_last_error_string()); // TODO: cleanup below is useless now since we're in panic delete[] login; delete[] password; delete[] wprogram; delete[] wcmd; delete[] wwd; restore_original_environment(original); return false; } } set_allow_breakaway(true); ReleaseMutex(main_job_object_access_mutex); delete[] login; delete[] password; delete[] wprogram; delete[] wcmd; delete[] wwd; restore_original_environment(original); get_times(&creation_time, NULL, NULL, NULL); return true; }
Result<ExitCode> ProcessWithLogon::RunInternal(Trace& trace, const Settings& settings, ProcessTracker& processTracker, Environment& environment, bool changeIntegrityLevel) const { SECURITY_ATTRIBUTES securityAttributes = {}; securityAttributes.nLength = sizeof(SECURITY_DESCRIPTOR); securityAttributes.bInheritHandle = true; STARTUPINFO startupInfo = {}; startupInfo.dwFlags = STARTF_USESHOWWINDOW; startupInfo.wShowWindow = ShowModeConverter::ToShowWindowFlag(settings.GetShowMode()); PROCESS_INFORMATION processInformation = {}; trace < L"ProcessTracker::InitializeConsoleRedirection"; processTracker.InitializeConsoleRedirection(securityAttributes, startupInfo); StringBuffer userName(settings.GetUserName()); StringBuffer domain(settings.GetDomain()); StringBuffer password(settings.GetPassword()); StringBuffer workingDirectory(settings.GetWorkingDirectory()); StringBuffer commandLine(settings.GetCommandLine()); if (changeIntegrityLevel) { trace < L"::LogonUser"; auto newUserSecurityTokenHandle = Handle(L"New user security token"); if (!LogonUser( userName.GetPointer(), domain.GetPointer(), password.GetPointer(), LOGON32_LOGON_BATCH, LOGON32_PROVIDER_DEFAULT, &newUserSecurityTokenHandle)) { return Error(L"LogonUser"); } trace < L"::LoadUserProfile"; PROFILEINFO profileInfo = {}; profileInfo.dwSize = sizeof(PROFILEINFO); profileInfo.lpUserName = userName.GetPointer(); if (!LoadUserProfile(newUserSecurityTokenHandle, &profileInfo)) { return Error(L"LoadUserProfile"); } SecurityManager securityManager; auto setIntegrityLevelResult = securityManager.SetIntegrityLevel(settings.GetIntegrityLevel(), newUserSecurityTokenHandle, trace); if (setIntegrityLevelResult.HasError()) { return Result<ExitCode>(setIntegrityLevelResult.GetError()); } trace < L"::CreateProcessWithTokenW"; if (!CreateProcessWithTokenW( newUserSecurityTokenHandle, LOGON_WITH_PROFILE, nullptr, commandLine.GetPointer(), CREATE_UNICODE_ENVIRONMENT, environment.CreateEnvironment(), workingDirectory.GetPointer(), &startupInfo, &processInformation)) { return Error(L"CreateProcessWithLogonW"); } } else { trace < L"::CreateProcessWithLogonW"; if (!CreateProcessWithLogonW( userName.GetPointer(), domain.GetPointer(), password.GetPointer(), LOGON_WITH_PROFILE, nullptr, commandLine.GetPointer(), CREATE_UNICODE_ENVIRONMENT, environment.CreateEnvironment(), workingDirectory.GetPointer(), &startupInfo, &processInformation)) { return Error(L"CreateProcessWithLogonW"); } } // ReSharper disable once CppInitializedValueIsAlwaysRewritten auto processHandle = Handle(L"Process"); processHandle = processInformation.hProcess; // ReSharper disable once CppInitializedValueIsAlwaysRewritten auto threadHandle = Handle(L"Thread"); threadHandle = processInformation.hThread; return processTracker.WaiteForExit(processInformation.hProcess, trace); }