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);
}
Related
I do this
HWND lParentWinHandle = GetForegroundWindow();
if (!CreateProcessA(NULL, lArgs, NULL, NULL, FALSE,
CREATE_NEW_CONSOLE, NULL, NULL,
&StartupInfo, &ProcessInfo))
{ ... }
// at this point a new window appears in the foreground.
HWND lChildWinHandle = GetForegroundWindow();
SetParent(lChildWinHandle , lParentWinHandle );
but lParentWinHandle and lChildWinHandle have the same value !
If you want to get the handle of the new process. You should use the process and thread handle of the PROCESS_INFO structure.
And according to the documentation you should wit with WaitForInputIdle until you start the search.
Code is similar to this (it is just a dirty sample no error checking):
BOOL CALLBACK EnumThreadWndProc(HWND hWnd, LPARAM lParam)
{
hWndMain = hWnd; // got the main window...
return FALSE; // ...stop enum
}
// ...
STARTUPINFO siStartInfo = {0};
PROCESS_INFORMATION piProcessInfo = {0};
CreateProcessA(NULL, pCmd,
NULL, NULL, FALSE, 0, NULL, NULL,
&siStartInfo,&piProcessInfo);
if(WaitForInputIdle(piProcessInfo.hProcess, 5000)==0)
{
EnumThreadWindows(piProcessInfo.dwThreadId,
EnumThreadWndProc, NULL);
}
else
{
// Could not start program
...
}
// ...
But please read Is it legal to have a cross-process parent/child or owner/owned window relationship?
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.
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.
This question already has answers here:
CreateProcess() fails with an access violation [duplicate]
(3 answers)
Closed 8 years ago.
I work with WinAPI and I have a function that creates a new process:
void new_process() {
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
TCHAR szCommandLine[] = TEXT("NOTEPAD");
CreateProcess(NULL, szCommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
}
But when I call this function from main(), it's doesn't work:
void new_process(TCHAR szCommandLine[]) {
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
CreateProcess(NULL, szCommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
}
int _tmain(int argc, _TCHAR* argv[]) {
new_process(TEXT("NOTEPAD"));
return 0;
}
Where is my mistake?
The problem is explained here. MSDN says -
The Unicode version of this function, CreateProcessW, can modify the
contents of this string. Therefore, this parameter cannot be a pointer
to read-only memory (such as a const variable or a literal string). If
this parameter is a constant string, the function may cause an access
violation.
When you pass TEXT("NOTEPAD") as the parameter to the function new_process(TCHAR szCommandLine[]) which in turn passes this as the lpCommandLine parameter to the CreateProcess() API, it will try to modify this location as quoted from MSDN above.
Since the parameter TEXT("NOTEPAD") is a CONSTANT memory, when the CreateProcess() tries to modify this memory as quoted above, it will cause memory access violation.
So ideally you should call the function new_process(TCHAR szCommandLine[]) from the main() function as given below.
TCHAR APP_NAME[] = TEXT("NOTEPAD");
new_process(APP_NAME);
Hope this help!
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);
}