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

Issue

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.

Solution

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

Answered By – Robert

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published