After CreateProcessWithLogonW, second application not taking credentials - windows

How can I create a process (a.exe) using CreateProcessWithLogonW that is realtime (note that I'm not an admin user but the one I'm using with CreateProcessWithLogonW is admin) and launch another process (b.exe) from a.exe using CreateProcess and have it realtime also?
Here is the code to launch a.exe:
PROCESS_INFORMATION pi = { 0 };
STARTUPINFO si = { 0 };
if (!CreateProcessWithLogonW(argv[1], argv[2], argv[3], LOGON_NETCREDENTIALS_ONLY, NULL, _T("a.exe"),
REALTIME_PRIORITY_CLASS, NULL, NULL,
&si, &pi))
{
cout << "Error!!!!\n";
}
Here is the code to launch b.exe from a.exe:
SECURITY_ATTRIBUTES security_att;
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&security_att, sizeof(security_att));
security_att.nLength = sizeof (SECURITY_ATTRIBUTES);
security_att.bInheritHandle = TRUE;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_NORMAL;
if(!CreateProcess(NULL, "b.exe", &security_att, &security_att, FALSE, REALTIME_PRIORITY_CLASS, NULL, NULL, &si, &pi))
{
cout << "Error!!!!\n";
}
Currently, a.exe will be realtime priority but b.exe is only high priority.

Related

ERROR_FILE_NOT_FOUND while CreateProcess

Trying to run notepad by using CreateProcess:
void _tmain( int argc, TCHAR *argv[] )
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
// Start the child process.
if( !CreateProcess( "notepad.exe", // No module name (use command line)
NULL, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi ) // Pointer to PROCESS_INFORMATION structure
)
{
printf( "CreateProcess failed (%d).\n", GetLastError() );
return;
}
// Wait until child process exits.
WaitForSingleObject( pi.hProcess, INFINITE );
// Close process and thread handles.
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
}
Have error in output 2. This means ERROR_FILE_NOT_FOUND. Where I should start seek for a problem? Does it means it can't find notepad.exe?
The lpApplicationName parameter must provide the full path to the application, not only its name.
More exactly:
The string can specify the full path and file name of the module to
execute or it can specify a partial name. In the case of a partial
name, the function uses the current drive and current directory to
complete the specification. The function will not use the search path.
This parameter must include the file name extension; no default
extension is assumed.
But you're supposedly not in the current folder of notepad.exe. So if you want use the name only, set it in the second argument, lpCommandLine. And note that this string is not a constant because it is defined as an LPTSTR parameter this way:
BOOL WINAPI CreateProcess(
_In_opt_ LPCTSTR lpApplicationName,
_Inout_opt_ LPTSTR lpCommandLine, [...]
So you have 2 variants:
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
WCHAR CommandLine[] = L"notepad.exe";
if( CreateProcess( 0, // No module name (use command line)
CommandLine, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi ) // Pointer to PROCESS_INFORMATION structure
)
{
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
or
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
if( CreateProcess( L"c:\\windows\\notepad.exe",
0, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi ) // Pointer to PROCESS_INFORMATION structure
)
{
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}

Running WSReset.exe with CreateProcess or system

I'm trying to run WSReset.exe on Windows 10 but keep getting a file not found error. The WSReset.exe is definitely in "C:\Windows\System32\WSReset.exe" but a CMD/Powershell window started from my program cannot seem to find it. But a CMD/Powershell window started outside my program does execute the file.
STARTUPINFO info = { sizeof(info) };
PROCESS_INFORMATION processInfo;
ZeroMemory(&processInfo, sizeof(processInfo));
int t = (CreateProcess(L"C:/Windows/System32/wsreset.exe", L"", NULL, NULL, TRUE, 0, NULL, NULL, &info, &processInfo));
WaitForSingleObject(processInfo.hProcess, INFINITE);
CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
or
SHELLEXECUTEINFO ShExecInfo = { 0 };
ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
ShExecInfo.hwnd = NULL;
ShExecInfo.lpVerb = NULL;
ShExecInfo.lpFile = L"C:/Windows/System32/wsreset.exe";
ShExecInfo.lpParameters = L"";
ShExecInfo.lpDirectory = NULL;
ShExecInfo.nShow = SW_SHOW;
ShExecInfo.hInstApp = NULL;
ShellExecuteEx(&ShExecInfo);
Produces the "Windows cannot find..." error message.
The app is 32 bits. Oddly System32 = 64 bit, SysWOW64 = 32 bit. So when I call "C:/Windows/System32/wsreset.exe" windows will turn it into "C:/Windows/SysWOW64/wsreset.exe" and there is no wsreset.exe at that location.
The solution is to disable redirection before calling CreateProcess/ShellExecuteEx/System.
//Disable redirection
PVOID OldValue = NULL;
Wow64DisableWow64FsRedirection(&OldValue);
STARTUPINFO info = { sizeof(info) };
PROCESS_INFORMATION processInfo = { 0 };
CreateProcess(L"C:/Windows/System32/WSReset.exe", L"", NULL, NULL, FALSE, 0, NULL, NULL, &info, &processInfo);
WaitForSingleObject(processInfo.hProcess, INFINITE);
CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
//Enable redirection (important, otherwise program can crash)
Wow64RevertWow64FsRedirection(OldValue);

Is there any way to "seal" a token so child processes can't inherit it?

I am trying to find a way to allow a single process to be launched as an elevated user but prohibit this process from launching any children with it's token--in a way, sort of "sealing" the token. The reasoning behind this is to prevent a user from launching cmd.exe and gaining full access to the system.
I've looked through the process privilege constants and I'm not seeing anything that could be used to implement this functionality.
I don't think you can seal the token but you can control child process creation with job objects:
static BOOL SpawnProcessAndTerminateGrandchildren(PTSTR Cmdline)
{
HANDLE hJob = CreateJobObject(0, 0);
if (!hJob) return false;
JOBOBJECT_BASIC_LIMIT_INFORMATION jobli;
jobli.LimitFlags = JOB_OBJECT_LIMIT_ACTIVE_PROCESS;
jobli.ActiveProcessLimit = 1;
BOOL retval = SetInformationJobObject(hJob, JobObjectBasicLimitInformation, &jobli, sizeof(jobli));
PROCESS_INFORMATION pi;
if (retval)
{
STARTUPINFO si;
ZeroMemory(&si, sizeof(si)), si.cb = sizeof(si);
retval = CreateProcess(0, Cmdline, 0, 0, false, CREATE_SUSPENDED|CREATE_BREAKAWAY_FROM_JOB|CREATE_NEW_CONSOLE, 0, 0, &si, &pi);
}
if (retval)
{
if (AssignProcessToJobObject(hJob, pi.hProcess)) // This can fail if we are already in a job
{
ResumeThread(pi.hThread);
WaitForSingleObject(pi.hProcess, INFINITE);
}
else
TerminateProcess(pi.hProcess, ERROR_OPERATION_ABORTED);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
CloseHandle(hJob);
return retval;
}
int main(int argc, ...)
{
TCHAR cmd[] = TEXT("cmd.exe /k regedit"); // cmd.exe is our child, regedit is the grandchild spawned by cmd.exe
SpawnProcessAndTerminateGrandchildren(cmd);
return 0;
}
If you want more control you can use JobObjectAssociateCompletionPortInformation so you get the JOB_OBJECT_MSG_NEW_PROCESS message each time a new child process is created.

can't use CreateProcess in Child process using simulating fork code on Windows 7 based on ZwCreateProcess

I try to simulate fork using ZwCreateProcess. It seems to work when I
use some simple test program. But when I try to create a new process
using CreateProcess API in the forked child process. The child process
paused for a while (and so did parent process) and then crashed.
Could you give me some hint?
The following are the test code and fork reference implementation code:
/*****************************************************/
Test program code fragment:
if ((pid = fork()) < 0) {
printf("fork error");
return -1;
}
if (pid == 0) {
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &pi, sizeof(pi) );
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
//Child process will pause here for a while and then crash.
if(CreateProcess(_T("C:\\Windows\\notepad.exe"), NULL, NULL, NULL,
FALSE, 0, NULL, NULL, &si, &pi))
{
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
}else{
// fputs("cann't create process", fp2);
}
}else{
//Parent code
}
/*****************************************************************************************************/
And the following is what I used the reference fork implementation code from internet:
int win32_fork()
{
HANDLE hProcess = 0;
HANDLE hThread = 0;
BOOL bReturn;
InheritAll();
OBJECT_ATTRIBUTES oa = {sizeof oa};
ZwCreateProcess(&hProcess, PROCESS_ALL_ACCESS, &oa,
0, 0, NULL, NULL, NULL);
CONTEXT context = {CONTEXT_FULL
| CONTEXT_DEBUG_REGISTERS
| CONTEXT_FLOATING_POINT};
ZwGetContextThread(NtCurrentThread(), &context);
context.Eip = ULONG(child);
MEMORY_BASIC_INFORMATION mbi;
ZeroMemory( &mbi, sizeof( mbi ) );
ZwQueryVirtualMemory(NtCurrentProcess(), PVOID(context.Esp),
MemoryBasicInformation, &mbi, sizeof mbi,
0);
USER_STACK stack = {0, 0, PCHAR(mbi.BaseAddress) + mbi.RegionSize,
mbi.BaseAddress, mbi.AllocationBase};
CLIENT_ID cid;
ZwCreateThread(&hThread, THREAD_ALL_ACCESS, &oa,
hProcess, &cid, &context, &stack, TRUE);
THREAD_BASIC_INFORMATION tbi;
ZeroMemory( &tbi, sizeof( tbi ) );
ZwQueryInformationThread(NtCurrentThread(),
ThreadBasicInformation,
&tbi, sizeof tbi, 0);
PNT_TIB tib = (PNT_TIB)tbi.TebBaseAddress;
ZwQueryInformationThread(hThread, ThreadBasicInformation,
&tbi, sizeof tbi, 0);
ZwWriteVirtualMemory(hProcess, tbi.TebBaseAddress,
&tib->ExceptionList, sizeof tib->ExceptionList,
0);
InformCsrss(hProcess, hThread,
ULONG(cid.UniqueProcess), ULONG(cid.UniqueThread));
ZwResumeThread(hThread, 0);
ZwClose(hThread);
ZwClose(hProcess);
return int(cid.UniqueProcess);
}

example code: A service calls CreateProcessAsUser() I want the process to run in the user's session, not session 0

I am seeking example code:
For a service calls CreateProcessAsUser() I want the process to run in the user's session, not session 0
thus far the created process is only running like a service in session 0
This was stripped from some old code that launched a console app from a service. It worked under NT4 but I haven't tested it with a modern version of Windows so can't guarantee it will work as it did on NT4.
EDIT: No, that's not going to work as-is. You need to add the code found here to create a desktop, set the SID, etc.
if (!LogonUser(userId,
domain,
password,
LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT,
&hUserToken))
{
return GetLastError();
}
if (!ImpersonateLoggedOnUser(hUserToken))
{
DWORD rc = GetLastError();
CloseHandle(hUserToken);
return rc;
}
STARTUPINFO si;
PROCESS_INFORMATION pi;
memset(&si, 0, sizeof(si));
memset(&pi, 0, sizeof(pi));
si.cb = sizeof(si);
rc = CreateProcessAsUser(hUserToken, // user token
0, // app name
"foo.exe", // command line
0, // process attributes
0, // thread attributes
FALSE, // don't inherit handles
DETACHED_PROCESS, // flags
0, // environment block
0, // current dir
&si, // startup info
&pi); // process info gets put here
if (!rc)
{
DWORD rc = GetLastError();
RevertToSelf();
CloseHandle(hUserToken);
return rc;
}
RevertToSelf();
CloseHandle(hUserToken);
return 0;
I know this is an ancient post but I happen to be working on this so here's some code that works for me.
Determine the session ID of the currently logged-on user
DWORD GetCurrentSessionId ()
{
WTS_SESSION_INFO *pSessionInfo;
DWORD n_sessions = 0;
BOOL ok = WTSEnumerateSessions (WTS_CURRENT_SERVER, 0, 1, &pSessionInfo, &n_sessions);
if (!ok)
return 0;
DWORD SessionId = 0;
for (DWORD i = 0; i < n_sessions; ++i)
{
if (pSessionInfo [i].State == WTSActive)
{
SessionId = pSessionInfo [i].SessionId;
break;
}
}
WTSFreeMemory (pSessionInfo);
return SessionId;
}
Launch process as the currently logged-on user
bool LaunchProcess (const char *process_path)
{
DWORD SessionId = GetCurrentSessioId ();
if (SessionId == 0) // no-one logged in
return false;
HANDLE hToken;
BOOL ok = WTSQueryUserToken (SessionId, &hToken);
if (!ok)
return false;
void *environment = NULL;
ok = CreateEnvironmentBlock (&environment, hToken, TRUE);
if (!ok)
{
CloseHandle (hToken);
return false;
}
STARTUPINFO si = { sizeof (si) } ;
PROCESS_INFORMATION pi = { } ;
si.lpDesktop = "winsta0\\default";
// Do NOT want to inherit handles here
DWORD dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT;
ok = CreateProcessAsUser (hToken, process_path, NULL, NULL, NULL, FALSE,
dwCreationFlags, environment, NULL, &si, &pi);
DestroyEnvironmentBlock (environment);
CloseHandle (hToken);
if (!ok)
return false;
CloseHandle (pi.hThread);
CloseHandle (pi.hProcess);
return true;
}

Resources