Visual C++ Undesired Result When UsingCreateProcess() - visual-c++

I'm building a Visual C++ console application and I need to execute another program located in same directory as the console application. I used CreateProcess() to start it.
VOID startup(LPCTSTR lpApplicationName, LPSTR args)
{
// additional information
STARTUPINFO si;
PROCESS_INFORMATION pi;
// set the size of the structures
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
// start the program up
CreateProcess(lpApplicationName, // the path
args, // 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
);
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess); // Close process and thread handles.
CloseHandle(pi.hThread);
}
Ans this is the function call-
string command = "C:\\Users\\username\\Documents\\Visual Studio 2013\\Projects\\Project\\Debug\\potrace.exe"; //the program to be executed
string arg = "-s -o \"" + libraryDir + "\\" + outputFileName + "\" -- \"" + tempDir + "\\" + tempFileName + "\""; //program arguments to be sent
char *args = new char[200];
for (int i = 0; args[i] = arg[i]; ++i); //converting std::string to char*
startup(command.c_str(), args);
The problem is that program being called produces different result when called from within the console application and when called from a command prompt. It generated an svg file but when called from application, this generated file is corrupt. If I copy the value of char *args and use it as argument at command prompt, the output file is perfect and intact.
UPDATE: on opening the generated files I noticed that it's and EPS file, not an SVG file. This is very strange because the -s in args is for generating SVG file. Also, copying the value of command.c_str() and args and executing from command prompt does produce a valid SVG image. So why is the same command producing different result when called usign CreateProcess() and from command prompt?
UPDATE: if I modify args to include the program name too i.e., potrace.exe <arguments> and call startup using startup(NULL, args) then it runs perfectly. But I would still like to know the problem in the original approach.

The documentation for CreateProcess says:
If both lpApplicationName and lpCommandLine are non-NULL, the null-terminated string pointed to by lpApplicationName specifies the module to execute, and the null-terminated string pointed to by lpCommandLine specifies the command line.
The new process can use GetCommandLine to retrieve the entire command line. Console processes written in C can use the argc and argv arguments to parse the command line. Because argv[0] is the module name, C programmers generally repeat the module name as the first token in the command line.
When a C or C++ program starts, the runtime calls GetCommandLine to get the command line used to invoke the program. This is parsed to obtain the argc and argv to be passed to main.
If the program being spawned expects that the program name is in argv[0] and the "actual" arguments start with argv[1], then you must ensure that you include the program name in the lpCommandLine passed to CreateProcess so that it is present in the command line string returned by GetCommandLine in the spawned process.

Related

Frida: spawn a Windows/Linux process with command-line arguments

When starting frida you can provide path to an executable that frida should execute and attach to it:
frida -l myscript.js process_to_spawn.exe
I have an executable needs to be started with additional parameters, otherwise it directly terminates. Is there a way to start a new executable and provide command-line arguments for the newly started process?
I already tried
frida -l myscript.js process_to_spawn.exe --argForProcess
frida -l myscript.js "process_to_spawn.exe --argForProcess"
but both variants don't work. Frida tries to interpret all arguments and thus can not pass arguments to the spawned process. And the second variant also does not work because frida is not able to find the executable to be started.
Is there a way to spawn an executable on the local OS (e.g. Windows or Linux) by frida and provide command-line arguments?
I can not attach to a running process because the functions I want to hook are only executed once directly after start-up, so I have to spawn the process using frida.
The problem seems to be that the argument starts with a -. For regular arguments that don't start with a - using the frida option -f works:
frida -l myscript.js -f process_to_spawn.exe argForProcess
But as I need the argument --argForProcess the only way I found was hooking the main method which processes the command-line arguments and modify the arguments before main is called.
The following code works on Windows 10 which seem to pass the arguments as wchar/"Unicode"/UTF-16 string. It changes argc and argv parameters of main from one argument (the executable itself) to two (the executable plus one argument).
let mainPointer = DebugSymbol.fromName("main").address;
Interceptor.attach(mainPointer, {
onEnter(args) {
// args[0] = int argc
// args[1] = wchar *argv[]
let myarg1 = Memory.allocUtf16String("Myexecutable.exe");
let myarg2 = Memory.allocUtf16String("--argumentX");
let newArgv = Memory.alloc(2 * Process.pointerSize); // allocate space for the two argument pointers
newArgv.writePointer(myarg1);
newArgv.add(Process.pointerSize).writePointer(myarg2);
// save all created memory blocks so they don't get garbage collected before main method is completed
this.myarg1 = myarg1;
this.myarg2 = myarg2;
this.newArgs = newArgv;
// Overwrite the argument counter and the argument char**
args[0] = ptr(2);
args[1] = newArgs;
console.log("main(" + args[0] + ", " + args[1].readPointer().readUtf16String() + ", " + args[1].add(Process.pointerSize).readPointer().readUtf16String() + ")");
}
});

How can I get the value of a registry key in c++ without an access violation?

Hey I'm new to C++ and I am trying to find out if a specified registry index exists. I have to check multiple locations due to the possibility of the software being run on a 64bit machine and being under the WOW6432Node key instead of the usual position. When RegQueryValueExA (using visual c++ 6.0 on xp so I can't use a newer function) is run it should return a Boolean of true if the key exists, (I'll deal with getting the value of the key later). However on run it generates access violation 0xc00005. Any ideas whats gone wrong?
bool FindAndRemoveUninstall(string path){
bool result;
result = RegQueryValueExA(HKEY_LOCAL_MACHINE,
TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ABC"), NULL, NULL, NULL, (unsigned long *)MAX_PATH);
if (result= ERROR_SUCCESS){
cout <<" is a 32 bit program\n";
//path= Value in key
}
result = RegQueryValueEx(HKEY_LOCAL_MACHINE,
TEXT("SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ABC"), NULL, NULL, NULL, (unsigned long *)MAX_PATH);
if (result= ERROR_SUCCESS){
cout << " is 64 bit program\n";
//path= Value in key
}
return true;
}
You have multiple problems.
The last parameter to RegQueryValueExA is documented as
lpcbData [in, out, optional]
A pointer to a variable that specifies the size of the buffer pointed to by the lpData parameter,
But you are not passing a pointer to a variable. You are passing (unsigned long *)MAX_PATH, which is a garbage pointer. When the operating system tries to store the result into the pointer, it takes an access violation. You need to pass a pointer to a variable, like the documentation says.
The next problem is that you are calling the A function (explicit ANSI) but using the TEXT macro (adaptive character set). Make up your mind which model you are using (ANSI or adaptive) and choose one model or the other. Let's assume you explicit ANSI.
The next problem is that you didn't specify an output buffer, so you don't actually retrieve the path.
Another problem is that the RegQueryValueExA function does not return a bool; it returns an error code.
Yet another problem is that your if test contains an assignment, so it does not actually test anything.
Another problem is that you didn't specify a way for the function to return the path to the caller. Let's assume you want the result to be returned in the path parameter.
Yet another problem is that you have the 32-bit and 64-bit cases reversed.
Also, you are using '\n' instead of std::endl.
The eight problem is that your function returns true even if it didn't do anything.
And the ninth problem is that the function says FindAndRemove, and it finds, but doesn't remove.
bool FindUninstall(string& path){ // parameter passed by reference, fix function name
LONG result; // change variable type
char buffer[MAX_PATH]; // provide an output buffer
DWORD bufferSize = MAX_PATH; // and a variable to specify the buffer size / receive the data size
result = RegQueryValueExA(HKEY_LOCAL_MACHINE,
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ABC", NULL, NULL, (LPBYTE)buffer, &bufferSize); // remove TEXT macro, pass the buffer and buffer size
if (result== ERROR_SUCCESS){ // fix comparison
cout <<" is a 64 bit program" << std::endl; // fix message
path = buffer;
return true; // stop once we have an answer
}
buffersize = MAX_PATH; // reset for next query
result = RegQueryValueEx(HKEY_LOCAL_MACHINE,
"SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ABC", NULL, NULL, (LPBYTE)buffer, &bufferSize); // remove TEXT macro, pass the buffer and buffer size
if (result== ERROR_SUCCESS){ // fix comparison
cout << " is 32 bit program" << std::endl; // fix message
path = buffer;
return true; // stop once we have an answer
}
return false; // nothing found
}
Since you are new to C++, I would recommend that you get some experience with C++ doing simpler projects before diving into more complicated things like this.

run an EXE file and receive return value from it using VC++

Please i want to creat a program/function in VC++ that allow me to run an EXE file and receive return value from it.
My EXE file tht i want to run is a console Application, it need two argument Arg1 (String) and Arg2 (Float), and return an OutPut (Float).
Something like :
OutPut = MyEXEFile.exe Arg1 Arg2
Command-line arguments come in only one data type: array of C-style string.
Input and output come in only one data type: stream of bytes.
You can supply any command-line and redirection the output if you use CreateProcess from the <windows.h> header file. Other data types such as float will need to be handled the same way you would handle them in a data file.
Here is an example on MSDN: Creating a Child Process with Redirected Input and Output
I find the solution, this is work fine for me, i test it, and it work well.
This is the link of the page where i find the solution, i fixe some errors, and now it ready for implement.
http://www.codeproject.com/Articles/10134/Execute-a-Console-Application-From-VC?fid=172409&fr=26#xx0xx
This is the exemple we need to execute. PS: this line is not a part of the our program, it's just here to explain the algorithm:
MyEXEFile.exe Arg1 Arg2 > sResult
The "MyEXEFile.exe" take two arguments (Arg1 and Arg2) and return a value in the sResult Variable.
Let us program this exemple with Visual C++ using CreatProcess :
CString ExePath="C:\\MyEXEFile.exe";
CString arg1="2";
CString arg2="3";
CString sResult="";
CString strCommandLine = ExePath + " " + arg1 + " " + arg2;
// Call the ExecuteExternalFile function
sResult = ExecuteExternalFile(strCommandLine);
This is the Function who will read the output of MyEXEFile.exe File :
CString ExecuteExternalFile(CString csExecute)
{
SECURITY_ATTRIBUTES secattr;
ZeroMemory(&secattr,sizeof(secattr));
secattr.nLength = sizeof(secattr);
secattr.bInheritHandle = TRUE;
HANDLE rPipe, wPipe;
//Create pipes to write and read data
CreatePipe(&rPipe,&wPipe,&secattr,0);
//
STARTUPINFO sInfo;
ZeroMemory(&sInfo,sizeof(sInfo));
PROCESS_INFORMATION pInfo;
ZeroMemory(&pInfo,sizeof(pInfo));
sInfo.cb=sizeof(sInfo);
sInfo.dwFlags=STARTF_USESTDHANDLES;
sInfo.hStdInput=NULL;
sInfo.hStdOutput=wPipe;
sInfo.hStdError=wPipe;
char command[1024];
strcpy(command,csExecute.GetBuffer(csExecute.GetLength()));
//Create the process here.
CreateProcess(0,command,0,0,TRUE,NORMAL_PRIORITY_CLASS|CREATE_NO_WINDOW,0,0,&sInfo,&pInfo);
CloseHandle(wPipe);
//now read the output pipe here.
char buf[100];
DWORD reDword;
CString m_csOutput,csTemp;
BOOL res;
do
{
res=::ReadFile(rPipe,buf,100,&reDword,0);
csTemp=buf;
m_csOutput+=csTemp.Left(reDword);
}while(res);
CloseHandle( pInfo.hProcess );
CloseHandle( pInfo.hThread );
return m_csOutput;
}
Creating a Child Process with Redirected Input and Output
You are going overkill.
For a command line app, the system command will do what you are looking for.
int status = system("MyEXEFile.exe Arg1 Arg2");

How can I get argv from "struct linux_binprm"?

I want to extract all argv from an existing struct linux_binprm. On kernel 3.4, I tried this piece of code: http://www.mail-archive.com/kernelnewbies#nl.linux.org/msg00278.html in do_excve_common, but it doesn't work. It returns (null). What is the problem and how can I get ALL the arguments in a char * string?
. If you want to get the full command line before the binary loader executing in do_execve_common(), you can try following:
there is one argument *argv in the function do_execve_common() parameter table, why bother to get the argv from "struct linux_binprm"? You can use the *argv directly with following codes. In the do_execve_common(), insert some codes as following:
argc = count(argv, MAX_ARG_STRINGS);
i = 0;
while (i < argc)
{
const char __user *str;
int len;
ret = -EFAULT;
str = get_user_arg_ptr(argv, i);
if (IS_ERR(str))
goto out;
len = strnlen_user(str, MAX_ARG_STRLEN);
if (!len)
goto out;
//copy the str to kernel temporary storage
//NOTE: tmp[] is a string array,
// the memory should have been allocated already for strings storage,
// each string is ended with \0
memcpy(tmp[i], str, len)
}
After executing these codes, I think the argv strings will be all saved in tmp[] array.
. While if you want to get the full command line after binary loader executing, I think at this time the argument page has been setup correctly, then you can try following approach to get the full command line:
There is a function proc_pid_cmdline() in ./fs/proc/base.c file, you can re-use most codes in proc_pid_cmdline() function to get the full command line from the argument page.

linux get process name from pid within kernel

hi
i have used sys_getpid() from within kernel to get process id
how can I find out process name from kernel struct? does it exist in kernel??
thanks very much
struct task_struct contains a member called comm, it contains executable name excluding path.
Get current macro from this file will get you the name of the program that launched the current process (as in insmod / modprobe).
Using above info you can use get the name info.
Not sure, but find_task_by_pid_ns might be useful.
My kernel module loads with "modprobe -v my_module --allow-unsupported -o some-data" and I extract the "some-data" parameter. The following code gave me the entire command line, and here is how I parsed out the parameter of interest:
struct mm_struct *mm;
unsigned char x, cmdlen;
mm = get_task_mm(current);
down_read(&mm->mmap_sem);
cmdlen = mm->arg_end - mm->arg_start;
for(x=0; x<cmdlen; x++) {
if(*(unsigned char *)(mm->arg_start + x) == '-' && *(unsigned char *)(mm->arg_start + (x+1)) == 'o') {
break;
}
}
up_read(&mm->mmap_sem);
if(x == cmdlen) {
printk(KERN_ERR "inject: ERROR - no target specified\n");
return -EINVAL;
}
strcpy(target,(unsigned char *)(mm->arg_start + (x+3)));
"target" holds the string after the -o parameter. You can compress this somewhat - the caller (in this case, modprobe) will be the first string in mm->arg_start - to suit your needs.
you can look at the special files in /proc/<pid>/
For example, /proc/<pid>/exe is a symlink pointing to the actual binary.
/proc/<pid>/cmdline is a null-delimited list of the command line, so the first word is the process name.

Resources