CReateProcess() API causing Unhandled exception. C++ std:: alternative API for CreateProcess - c++

I've a Vc++ code an A.EXE project (MBCS) and a static library project (Unicode). The static library (*.lib) project has the code like below which tries to launch a different exe (pwrtest.exe for example) from within it. BUt the code is crashing when the CReateProcess() statement is executed.
Error is "Unhandled Eception at (ntdll.dll) in "A.EXE":
::Access Vioaltion reading location 0xCCCCCCCC
I made sure that the values in appPath & workdir are correct.
They are values like this ::
c:\Users\abcd\xyz\somedirectory\abc etc...
with directory names separated by double slashes "\".
I really don't understand what is the problem.
Also I've put a try catch statement but when I step in to code (F10) on the line CreateProcess() it immidiately crashes and throws exception as above.
So it's not even coming to catch statement.
As Create process() is a C API & C types are always prone to memory elaks etc.. , just wondering if there is a C++ STD:: library counterpart (some container function API) which is much simpler but doing the job of CreateProcess() C API.
PROCESS_INFORMATION pI;
STARTUPINFO sI;
LPTSTR appPath;
LPTSTR workDir;
wchar_t cwd[_MAX_PATH];
GetCurrentDirectory(_MAX_PATH, cwd);
wchar_t TestEXEPath[_MAX_PATH];
wcscpy(TestEXEPath, cwd);
wcscat(TestEXEPath, L"\\somedircetory\\abc\\pwrtest.exe /sleep /c:1");
appPath = TestEXEPath;
wchar_t workDirForTestEXE[_MAX_PATH];
wcscpy(workDirForTestEXE, cwd);
wcscat(workDirForTestEXE, L"\\somedirectory\\abc");
workDir = workDirForTestEXE;
try
{
if (!CreateProcess(NULL, appPath, NULL, NULL, FALSE, 0, NULL, workDir, &sI, &pI))
{
......
}
{
......
}
}
catch (exception& exType)
{
std::cout << "ExType is" << exType.what() << endl;
}

Your variable sI is uninitialized, and it's an input parameter. When CreateProcess reads from it, all sorts of bad things can happen. Several of the members are defined as pointers to strings. Reading from an invalid pointer is not a C++ exception, which is why your catch statement didn't handle it.
The fix is quite simple, change
STARTUPINFO sI;
to
STARTUPINFO sI = {sizeof sI};
There's no function in the standard C++ library half as powerful as the OS-specific CreateProcess. You're using the ability of CreateProcess to control the initial working directory, something that system, spawn, and exec can't do. (fork + cwd + exec can, but that's a very bad way to do things on Windows)

Related

C++ program is not exiting after starting new executable file

Consider two C++ projects:
Project 1:
// projectOne.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "windows.h"
int _tmain(int argc, _TCHAR* argv[])
{
Sleep(5000);
system("projectTwo.exe");
return 0;
}
Project 2:
// projectTwo.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "windows.h"
int _tmain(int argc, _TCHAR* argv[])
{
Sleep(5000);
system("projectOne.exe");
return 0;
}
The behavior I seek is: projectOne starts => start projectTwo => projectOne ends => projectTwo will start projectOne => projectTwo ends => projectOne will start projectTwo.
However, the programs are not ending. For example, when projectOne starts projectTwo, it will not end projectOne when return 0; is run within projectOne. So after a few minutes, there will be multiple versions of the programs running at the same time. I was thinking it had to do with the system command. Maybe it waits until the project is complete until it goes to the next line of code, and this results in circling, but I am not sure. How can I fix this? I need the programs to end after one of them is called using the system command. I hope this question is clear.
system blocks the running thread until system returns and system will not return until the executed process has terminated.
There are many ways to solve this problem. The simplest and most likely to be portable is to use a std::thread to run system in a thread that runs concurrent to the main processing thread.
std::thread procthread([processToRun] {system(processToRun.c_str());});
procthread.detach();
Short, sweet, and as portable as anything calling system can be. The first line creates a thread and executes a lambda function that runs system on the provided process name. The second line disconnects the thread from the std::thread object and allows the thread to run free. Otherwise if procthread goes out of scope the thread will be terminated and bad things will very likely happen.
If you can't do this because your development system does not support C++11 or better, you can use operating system-specific threading, but if you have to use system-specific thread creation calls, you might as well use system-specific process creation calls to directly create the new process.
In POSIX systems, posix_spawn will likely be the go-to function. I don't have a machine at my disposal to test this on at the moment, so I'll just link to Starting a process using posix_spawn.
Under Windows, use CreateProcess or your variant of choice. The following code is based on Microsoft's Creating Processes documentation page and modified to be a little less Microsoft specific and not wait for the spawned process to complete before continuing execution.
char processToRun[] = "process to run"; //NOTE: Not a std::string!
STARTUPINFO si;
PROCESS_INFORMATION pi;
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
memset(&pi, 0, sizeof(pi));
// Start the child process.
if (!CreateProcess(NULL, // No module name (use command line)
processToRun, // Command line DANGER! won't accept const char*
// cannot use std::string::c_str
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
{
std::cerr << "CreateProcess failed ("<<GetLastError()<<").\n";
return false;
}
// do stuff
// Close process and thread handles.
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return true;
Your approach makes in an endless loop and it will not end!!
You are spawning multiple instances of projectOne and projectTwo which in turn are creating more.. It's recursive -_-
EDIT
System WAITS!
SOLUTION
int execl(char * pathname, char * arg0, arg1, ..., argn, NULL);

CreateProcess won't start the proccess with arguments

So I used this code in order to start a console application with arguments:
#include <iostream>
#include <windows.h>
using namespace std;
void StartProgram(char argv[])
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
CreateProcess
(
TEXT("PlayerDebug.exe"),
(LPSTR)argv,
NULL,NULL,FALSE,
CREATE_NEW_PROCESS_GROUP | CREATE_NO_WINDOW,
NULL,NULL,
&si, &pi
);
};
int main()
{
StartProgram("sound.wav");
return 0;
}
"PlayerDebug.exe" display the arguments used to call it. But when I run it with CreateProcess the way I showed, it doesen't display anything. I checked and in Task Manager it seems to appear, but still does not display the arguments. I also tried to write cout << argv; in function void StartProgram(char argv[]) and it returned "sound.wav", which is correct. But it seems the argument is not passed to PlayerDebug.exe and I don't know why.
What I did wrong?
(I'm new at C++ programming)
The second parameter to CreateProcess is the full command line, not just the parameters to the EXE. Lets take two examples :
CreateProcess ("c:\\notepad.exe",
"c:\\notepad.exe c:\\wibble.txt",
...);
will work fine (if there is a copy of notepad.exe and a file called wibble.txt in the root of C:), whereas
CreateProcess ("c:\\notepad.exe",
"c:\\wibble.txt",
...);
will launch the EXE but fail to open the file. What this means is that when the help systems calls the second parameter the command line, it ain't lying - it wants the whole command line.
Note that you can use NULL as the first parameter if the whole command line is in the second param. That's how I normally use it in fact.

Can I launch the `GetLastError` in the first row of my function?

I know the GetLastError are to be called at once when error occured. I wrote the function:
void PrintErrorMsg() {
DWORD errCode = GetLastError();
LPTSTR msg = NULL;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, errCode, 0, (LPTSTR)&msg, 0, NULL);
wcerr << msg << endl;
HeapFree(GetProcessHeap(), 0, msg);
}
Now I use it in my code:
LPCTSTR boundaryName = L"BushmanBoundary";
HANDLE hBoundary = CreateBoundaryDescriptor(boundaryName, 0);
if (NULL == hBoundary) {
PrintErrorMsg();
}
So I called GetLastError in the first code row inside of the PrintErrorMsg function. Whether such variant of using is admissible?
That code is fine. No Windows API functions are called between CreateBoundaryDescriptor returning, and your call to GetLastError.
Functions executed by the calling thread set this value by calling the SetLastError function. You should call the GetLastError function immediately when a function's return value indicates that such a call will return useful data. That is because some functions call SetLastError with a zero when they succeed, wiping out the error code set by the most recently failed function.
Your code is fine because you are not calling a function that may call SetLastError() in between failure and your call to GetLastError() (e.g. Win32 API Calls.)
Keep in mind that the insertion operator may call SetLastError().
std::cout << "Win32 function failed with error: " << GetLastError() << std::endl;
I've been caught out by something like this in the past where GetLastError() would not return the correct error code because it had been set/reset by the insertion operator.
Yes, that's allowed. I've done something similar, except that I pass the error code in as an argument, but make the default value for the argument the result of GetLastError(), like this:
// in header file
void PrintErrorMsg( DWORD errCode = GetLastError() );
// in implementation file
void PrintErrorMsg( DWORD errCode )
{
// ...
}
It's more flexible, and worked very well for me.
I find that the best way to deal with these low-level details of the Win32 API (or any C style API), is to immediately hoist that C style API into C++ practices as soon as possible. One approach I used was to wrap C-style API calls in a macro that validates the return value and then extracts the appropriate error code into an exception if the return value indicated failure.
Chapter 1 of my book "The Direct3D Graphics Pipeline" outlines such an approach for COM HRESULT return values. A macro THR throws if the HRESULT indicates failure. In an HRESULT, the failure status and error code are contained in the same integral value, so the exception can be computed directly from the provided HRESULT. The macro decorates its argument with __FILE__ and __LINE__ before passing the value to be checked onto a helper function that checks for failure. If failure was detected, all the information is gathered up into an exception that is thrown. If the HRESULT indicates success, the HRESULT value is returned.
I also provided similar variants for Win32 API status with TWS. This does the necessary validation checks for the Win32 API (usually some version of comparing against FALSE or 0) and on failure immediately calls ::GetLastError() to obtain the error code for the exception.
In both cases, I attempt to use ::FormatMessage to obtain a meaningful error message string when building the exception value that will be thrown.
These macros are intended to be used in situations where you don't expect the API call to fail and failure is indeed truly exceptional.

Open process with debug privileges and read/write memory

Short version:
I'm trying to open a process handle with debug privileges and define a pointer which points to an object in the memory of the debuggee.
Long version
I'm a computer science university student in my final year of graduation and got tasked to build an application which should be used for educational purposes for the next generation of students.
Why am I here asking for help, you might ask? Well, the target platform is Windows and I have unfortunately no knowledge of the WinAPI whatsoever...
Okay, here is the basic requirement:
Programming language: C++
Platform: Windows (7 Professional)
Used IDE: Visual Studio 2012
No additional libraries if they aren't essential to ease the development
What will the application be used for?
Using this application the students shall learn to handle addresses, in this case static ones: the debuggee process will have some static pointers, which lead to other pointers themself to form a multi-dimensional pointer.
The students have to find these base addresses using some debugging techniques (which is not part of my work!) and try to find the values at the end of these pointers.
My application will be used by the tutors to randomly change the values and/or structures in the debuggee process.
Some search did yield the first answer: using ReadProcessMemory and WriteProcessMemory one can easily change values in the memory of another process without any need to get debug privileges.
What my tutors want, however, is to have the ability to define pointers (let's say unsigned int) which should point into the memory space of the debuggee process, effectively holding the base addresses I wrote about earlier.
They really want this and I couldn't even talk this out of them so I'm stuck to do this at the end...
And what exactly should work?
Well, I'd have accomplished my task if the following (pseudo) code works:
grantThisProcessDebugPrivileges();
openAnotherProcessWhileItsRunning("targetProcess.exe");
unsigned int * targetValue = (unsigned int*) 0xDE123F00;
// or even
myCustomClass * targetClass = (myCustomClass*) 0xDE123F00;
where the address 0xDE123F00 lies in the memory space of targetProcess.exe.
I know this is possible, else there wouldn't be debuggers which could show this information.
What I did so far (or tried...)
Okay, the thing is: I'm really confused whether I have to activate debug privileges for my application prior opening the target process, doing it after opening or rather giving the target process these privileges.
So I found an example in MSDN and tried to implement it:
BOOL SetPrivilege(
HANDLE hToken, // token handle
LPCTSTR Privilege, // Privilege to enable/disable
BOOL bEnablePrivilege // TRUE to enable. FALSE to disable
)
{
TOKEN_PRIVILEGES tp;
LUID luid;
TOKEN_PRIVILEGES tpPrevious;
DWORD cbPrevious=sizeof(TOKEN_PRIVILEGES);
if(!LookupPrivilegeValue( NULL, Privilege, &luid )) return FALSE;
//
// first pass. get current privilege setting
//
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = 0;
AdjustTokenPrivileges(
hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
&tpPrevious,
&cbPrevious
);
if (GetLastError() != ERROR_SUCCESS) return FALSE;
//
// second pass. set privilege based on previous setting
//
tpPrevious.PrivilegeCount = 1;
tpPrevious.Privileges[0].Luid = luid;
if(bEnablePrivilege) {
tpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED);
}
else {
tpPrevious.Privileges[0].Attributes ^= (SE_PRIVILEGE_ENABLED &
tpPrevious.Privileges[0].Attributes);
}
AdjustTokenPrivileges(
hToken,
FALSE,
&tpPrevious,
cbPrevious,
NULL,
NULL
);
if (GetLastError() != ERROR_SUCCESS) return FALSE;
return TRUE;
};
And in my main:
HANDLE mainToken;
// I really don't know what this block of code does :<
if(!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &mainToken))
{
if (GetLastError() == ERROR_NO_TOKEN)
{
if (!ImpersonateSelf(SecurityImpersonation))
return 1;
if(!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &mainToken)){
cout << GetLastError();
return 1;
}
}
else
return 1;
}
if (!SetPrivilege(mainToken, SE_DEBUG_NAME, true))
{
CloseHandle(mainToken);
cout << "Couldn't set DEBUG MODE: " << GetLastError() << endl;
return 1;
};
unsigned int processID = getPID("targetProcess.exe");
HANDLE hproc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processID);
if (hproc == NULL)
{
cout << "Couldn't open the process" << endl;
return 1;
};
unsigned int * theValue = (unsigned int*) 0xDE123F;
Okay, this code runs without any errors, SetPrivilege returns TRUE so I guess it really did set SE_DEBUG_NAME, which I think is the flag I need to set.
But after - for example - outputting the dereferenced value of theValue, the application crashes with an access violation message, which shows that my approach didn't work. I did especially pay attention to start the VisualStudio Debugger with admin rights (SetPrivilege failed otherwise).
I am really clueless here, the fact that I don't know whether setting SE_DEBUG_NAME is the right approach adds to my overall confusion.
I hope you can help me out :)
My hands are tied concerning the specific requests of the application , if you have ideas to achieve my goal using an entire dfferent approach, you're free to enlight me, but I won't be able to present it to my superiors so it will only add to my knowledge :D
From you description, it appears that you have gotten to the point where you can open the process with SE_DEBUG. At this point you now have a handle to the target process.
What your code appears to be missing is the use of ReadProcessMemory.
First we need to look at the definition of ReadProcessMemory:
BOOL WINAPI ReadProcessMemory(
_In_ HANDLE hProcess,
_In_ LPCVOID lpBaseAddress,
_Out_ LPVOID lpBuffer,
_In_ SIZE_T nSize,
_Out_ SIZE_T *lpNumberOfBytesRead);
This function essentially gives you the ability to copy a block of memory from one process space into your process space. So you need to use this method to read a block of memory the size of the data structure you wish to read into your process space, then you can reinterpret the memory block as that data type.
So semi pseudocode for reading an unsigned int from your target process looks like this:
unsigned int ReadUInt(HANDLE process, const void * address)
{
// Add parameter validation
unsigned char buffer[sizeof(unsigned int)] = {};
size_t bytesRead = 0;
BOOL res = ::ReadProcessMemory(process, // The handle you opened with SE_DEBUG privs
address, // The location in the other process
buffer, // Where to transfer the memory to
sizeof(unsigned int), // The number of bytes to read
&bytesRead); // The number of bytes actually read
if (!res)
{
// Deal with the error
}
if (bytesRead != sizeof(unsigned int))
{
// Deal with error where we didn't get enough memory
}
return *reinterpret_cast<unsigned int *>(buffer);
}
Instead of using this line:
unsigned int * theValue = (unsigned int*) 0xDE123F00;
You would do this:
unsigned int theValue = ReadUInt(hproc, 0xDE123F00);
Keep in mind that this requires that you know the size and memory layout of the types you are trying to read. Simple types that are contained in contiguous memory can be retrieved in a single ReadProcessMemory call. Types that contain pointers as well as values will require you to make extra calls to ReadProcessMemory to find the values referenced by the pointers.
Each process has its own virtual address space. An address in one process only has meaning in that process. De-referencing a pointer in C++ code will access the virtual address space of the executing process.
When you de-referenced the pointer in your code you were actually attempting to access memory in your process. No amount of wishful thinking on the part of your tutors can make pointer de-reference access memory in another process.
If you wish to read and write memory from other processes then you must use ReadProcessMemory and WriteProcessMemory.
I don't think you really need to go to all those lengths with tokens and privileges. If I recall correctly you add the debug privilege, call OpenProcess and go straight to it. And I think you can typically skip adding the privilege.
Some search did yield the first answer: using ReadProcessMemory and WriteProcessMemory one can easily change values in the memory of another process without
any need to get debug privileges. What my tutors want, however, is to have the ability to define pointers (let's say unsigned int) which should point into the memory space of the debuggee process, effectively holding the base addresses I wrote about earlier. They really want this and I couldn't even talk this out of them so I'm stuck to do this at the end...
What they want is impossible. I suggest you tell them to get a better understanding of virtual memory before making impossible requirements!
#Cody Gray helpfully mentions memory mapped files. If debuggee and debugger co-operate then they can use memory mapped files to share a common region of memory. In that situation then both process can map the memory into their virtual address space and access it in the normal manner.
I rather assumed that your debuggee was an unwilling victim, but if it is prepared to co-operate then sharing memory could be an option.
Even then you'd need to be careful with any pointers in that shared memory because the memory would, in general, be mapped onto different virtual addresses in each process.
I think you are trying to access kernel land memory range and hence the exception.
The user land range is from 0x00000000 - 7FFFFFFF, so try accessing in this range, as anything above is kernel space.
I am assuming you are on a 32-bit machine.
Check User Space and System Space (Microsoft Docs).
You can create a type that behaves like a pointer by implementing the appropriate operators, just like shared_ptr does:
foreign_ptr<int> ptr{0xDE123F00};
int a = *ptr;
*ptr = 1;

error by creating process

hello i want to get startet with programming with WIN32, therefore i wrote a programm that creates a process but in the line of code where i create the process the programm gets an error an dosn't work (abend). i don't know if the code in programm 1 is wrong or the code in the second programm that should be created by the first. ( I don't know if the code in the first programm after "createprocess" is right because i didn't get further with debugging, because in this line i get the error.(i tested it without the cout,waitforobject and close handle but i didn't work either )).
First Programm:
#include <iostream>
#include <windows.h>
#include <string>
using namespace std;
void main()
{
bool ret;
bool retwait;
STARTUPINFO startupinfo;
GetStartupInfo (&startupinfo);
PROCESS_INFORMATION pro2info;
ret = CreateProcess(NULL, L"D:\\betriebssystemePRA1PRO2.exe", NULL, NULL, false, CREATE_NEW_CONSOLE, NULL,
NULL, &startupinfo, &pro2info);
cout<<"hProcess: "<<pro2info.hProcess<<endl;
cout<<"dwProcessId: "<<pro2info.dwProcessId <<endl;
retwait= WaitForSingleObject (pro2info.hProcess, 100);
retwait= WaitForSingleObject (pro2info.hProcess, 100);
CloseHandle (pro2info.hProcess);//prozesshandle schließen
retwait= WaitForSingleObject (pro2info.hProcess, 100);
ExitProcess(0);
}
Seconde Programm:
#include <iostream>
#include <windows.h>
#include <string>
using namespace std;
void main()
{
int b;
b=GetCurrentProcessId();
cout<<b<<endl;
cout<<"Druecken Sie Enter zum Beenden"<<endl;
cin.get();
//warten bis Benutzer bestätigt
Sleep (700);
ExitProcess(0);
cout<<"test";
}
Thanks in advance
Notice the type of the lpCommandLine parameter to CreateProcess -- it is LPTSTR, not LPCTSTR, i.e. it is not const.
This means that CreateProcess reserves the right to actually modify the contents of lpCommandLine. However, you have provided a pointer to a string literal as parameter, and string literals are immutable (they come from your program's read-only data segment and attempts to alter them will typically result in an access violation error.)
To fix this, simply change your code not to use an immutable string literal:
wchar_t wcsCommandLine[] = L"D:\\betriebssystemePRA1PRO2.exe";
ret = CreateProcess(NULL, wcsCommandLine, NULL, NULL, ...
Interestingly enough, CreateProcessW (UNICODE) attempts to write to lpCommandLine whereas CreateProcessA (ANSI) does not, and surprise -- your first program is built as UNICODE (were you to build it as ANSI it would work out of the box, at least on Windows XP.)
I can confirm that, with the above modification, your code works.
Also note that:
unless you need to specify D:\\betriebssystemePRA1PRO2.exe's window title, position etc. you do not need to supply a STARTUPINFO structure at all, you can simply pass lpStartupInfo as NULL and a default will be used
you should not be calling WaitForSingleObject on a closed handle
You must set the size of the startupinfo struct:
startupinfo.cb = sizeof(startupinfo);
Maybe this is why CreateProcess is failing.
And by the way - why are you calling GetStartupInfo? You should just zero out the memory of startupinfo (besides setting the size as mentioned above).
See an example here.