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

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() + ")");
}
});

Related

Mapping errors from Command::new("/bin/bash") arguments

I am executing a bash command, for which I would like to catch an error when the move argument fails. Since there is one more command after move, my goal is to capture specifically whether the move operation got successfully executed to a status code and to break out of the entire Rust program.
Is there a way to accomplish this? I have provided below the source code.
let path : String = "/home/directory/".to_string();
let command = Command::new("bin/bash")
.arg("-c")
.arg("mv somefile1.txt /home/")
.arg("cp ~/somefile2.txt .")
.stdout(Stdio::piped())
.output();
bash -c doesn't accept two commands like that. You could try splitting it into two separate Commands:
Command::new("bash")
.arg("-c")
.arg("mv somefile1.txt /home/")
.status()?
.success() // bool
.then(|| ()) // convert bool to Option
.ok_or("mv failed")?; // convert Option to Result
Command::new("bash")
.arg("-c")
.arg("cp ~/somefile2.txt .")
.status()?
.success() // bool
.then(|| ()) // convert bool to Option
.ok_or("cp failed")?; // convert Option to Result
Or joining them into a single command with &&:
Command::new("bash")
.arg("-c")
.arg("mv somefile1.txt /home/ && cp ~/somefile2.txt .")
.status()?
.success() # bool
.then(|| ()) # convert bool to Option
.ok_or("failed")?; # convert Option to Result
Better yet, use native Rust functions:
mv → std::fs::rename
cp → std::fs::copy
~ → home::home_dir
This avoids the overhead of calling out to bash and is portable to non-Unix operating systems.
use std::fs;
use dirs::home_dir;
if let Some(home) = home_dir() {
fs::rename("somefile1.txt", home.join("somefile1.txt"))?;
fs::copy(home.join("somefile2.txt"), ".")?;
}

Handling long probe paths in systemtap userspace scripts (variables)?

I am trying to instrument a user-space program using systemtap, Linux 4.2.0-42-generic #49~14.04.1-Ubuntu SMP; stap --version says: "Systemtap translator/driver (version 2.3/0.158, Debian version 2.3-1ubuntu1.4 (trusty))"
So I first tried getting a list of all callable functions, with:
stap -L 'process("/home/username/pathone/subpathtwo/subpaththree/subpathfour/subpathFive/subpathsix/subpathSeven/subpatheight/myprogramab").function("*").call' 2>&1 | tee /tmp/stap
This worked - however, note that the absolute path to my program is massive. So from the /tmp/stap file, I read some probes of interest, however, they are even longer, such as:
process("/home/username/pathone/subpathtwo/subpaththree/subpathfour/subpathFive/subpathsix/subpathSeven/subpatheight/myprogramab").function("DoSomething#/home/username/pathone/subpathtwo/subpaththree/subpathfour/subpathFive/src/BasicTestCodeFileInterface.cpp:201").call
... and as this is very difficult to read/unreadable for me, I wanted to do something to split this line into more readable pieces. The first thing I thought of was using variables, so I tried this test.stp script:
#!/usr/bin/env stap
global exepath = "/home/username/pathone/subpathtwo/subpaththree/subpathfour/subpathFive/subpathsix/subpathSeven/subpatheight/myprogramab"
global srcpath = "/home/username/pathone/subpathtwo/subpaththree/subpathfour/subpathFive/src"
probe begin {
printf("%s\n", exepath)
exit() # must have; else probe end runs only upon Ctrl-C
}
probe end {
newstr = "DoSomething#" . srcpath # concatenate strings
printf("%s\n", newstr)
}
This works, I can run sudo stap /path/to/test.stp, and I get the two strings printed.
However, when I try to use these strings in probes, they fail:
Writing a probe like this:
probe process(exepath).function("DoSomething#".srcpath."/BasicTestCodeFileInterface.cpp:201").call { ...
... fails with: parse error: expected literal string or number; saw: identifier 'exepath' ....
Trying to put the "process" part in a variable:
global tproc = process("/home/username/pathone/subpathtwo/subpaththree/subpathfour/subpathFive/subpathsix/subpathSeven/subpatheight/myprogramab")
... fails with parse error: expected literal string or number; saw: identifier 'process' ....
So, what options do I have, to somehow shorten the probe lines in a script?
Your best bet is probably to use macros:
#define part1 %( "/path/part/1" %)
#define part2 %( "/part/2" %)
probe process(#part1 #part2).function("...") { }
Note no explicit concatenation operator between the (macros that expand to) string literals. The parser will auto-concatenate them, just as in C.

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");

Visual C++ Undesired Result When UsingCreateProcess()

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.

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