Skip to content

Commit

Permalink
Added cshell
Browse files Browse the repository at this point in the history
  • Loading branch information
Your Name committed Mar 19, 2024
1 parent 35ba4a6 commit c370729
Show file tree
Hide file tree
Showing 10 changed files with 186 additions and 15 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[submodule "releng"]
path = releng
url = https://github.com/frida/releng.git
[submodule "src/cshell/frida-cshell"]
path = src/cshell/frida-cshell
url = https://github.com/WorksButNotTested/frida-cshell.git
52 changes: 38 additions & 14 deletions inject/inject.vala
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ namespace Frida.Inject {
private static string? target_name;
private static string? realm_str;
private static string? script_path;
private static bool cshell;
private static string? script_runtime_str;
private static string? parameters_str;
private static bool eternalize;
Expand All @@ -21,6 +22,7 @@ namespace Frida.Inject {
{ "name", 'n', 0, OptionArg.STRING, ref target_name, "attach to NAME", "NAME" },
{ "realm", 'r', 0, OptionArg.STRING, ref realm_str, "attach in REALM", "REALM" },
{ "script", 's', 0, OptionArg.FILENAME, ref script_path, null, "JAVASCRIPT_FILENAME" },
{ "cshell", 'C', 0, OptionArg.NONE, ref cshell, "Load the C-Shell", null },
{ "runtime", 'R', 0, OptionArg.STRING, ref script_runtime_str, "Script runtime to use", "qjs|v8" },
{ "parameters", 'P', 0, OptionArg.STRING, ref parameters_str, "Parameters as JSON, same as Gadget", "PARAMETERS_JSON" },
{ "eternalize", 'e', 0, OptionArg.NONE, ref eternalize, "Eternalize script and exit", null },
Expand Down Expand Up @@ -69,15 +71,24 @@ namespace Frida.Inject {
}
}

if (script_path == null || script_path == "") {
printerr ("Path to JavaScript file must be specified\n");
return 4;
}

string? script_source = null;
if (script_path == "-") {
if (cshell) {
if (script_path != null && script_path != "") {
printerr ("Cannot specify both -s and -C options\n");
return 4;
}
script_path = null;
script_source = read_stdin ();
script_source = CShellScript.get_source ();
} else {
if (script_path == null || script_path == "") {
printerr ("Path to JavaScript file must be specified\n");
return 5;
}

if (script_path == "-") {
script_path = null;
script_source = read_stdin ();
}
}

ScriptRuntime script_runtime = DEFAULT;
Expand All @@ -86,34 +97,39 @@ namespace Frida.Inject {
script_runtime = ScriptRuntime.from_nick (script_runtime_str);
} catch (Error e) {
printerr ("%s\n", e.message);
return 5;
return 6;
}
}

var parameters = new Json.Node.alloc ().init_object (new Json.Object ());
if (parameters_str != null) {
if (parameters_str == "") {
printerr ("Parameters argument must be specified as JSON if present\n");
return 6;
return 7;
}

try {
var root = Json.from_string (parameters_str);
if (root.get_node_type () != OBJECT) {
printerr ("Failed to parse parameters argument as JSON: not an object\n");
return 7;
return 8;
}

parameters.take_object (root.get_object ());
} catch (GLib.Error e) {
printerr ("Failed to parse parameters argument as JSON: %s\n", e.message);
return 8;
return 9;
}
}

if (interactive && eternalize) {
printerr ("Cannot specify both -e and -i options\n");
return 9;
return 10;
}

if (cshell && eternalize) {
printerr ("Cannot specify both -e and -C options\n");
return 11;
}

application = new Application (device_id, spawn_file, target_pid, target_name, options, script_path, script_source,
Expand Down Expand Up @@ -249,7 +265,15 @@ namespace Frida.Inject {

uint pid;
if (spawn_file != null) {
pid = yield device.spawn (spawn_file, null, io_cancellable);
/*
* If frida-inject is supposed to be interactive, then don't connect any spawned
* child process to the TTY.
*/
var options = new SpawnOptions ();
if (interactive || cshell) {
options.stdio = PIPE;
}
pid = yield device.spawn (spawn_file, options, io_cancellable);
} else if (target_name != null) {
var proc = yield device.get_process_by_name (target_name, null, io_cancellable);
pid = proc.pid;
Expand All @@ -265,7 +289,7 @@ namespace Frida.Inject {
yield r.start ();
script_runner = r;

if (interactive)
if (interactive || cshell)
watch_stdin ();

if (spawn_file != null) {
Expand Down
4 changes: 3 additions & 1 deletion meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,7 @@ have_fruity_backend = get_option('fruity_backend').allowed()
have_droidy_backend = get_option('droidy_backend').allowed()
have_socket_backend = get_option('socket_backend').allowed()
have_barebone_backend = quickjs_dep.found()
have_cshell_backend = get_option('cshell_backend').allowed()
have_compiler_backend = get_option('compiler_backend') \
.disable_if(not have_local_backend, error_message: 'compiler backend requires the local backend for script execution') \
.disable_auto_if(host_os == 'watchos') \
Expand Down Expand Up @@ -371,7 +372,8 @@ foreach b : [['local', have_local_backend],
['droidy', have_droidy_backend],
['socket', have_socket_backend],
['barebone', have_barebone_backend],
['compiler', have_compiler_backend]]
['compiler', have_compiler_backend],
['cshell', have_cshell_backend]]
if b[1]
vala_flags += '--define=HAVE_@0@_BACKEND'.format(b[0].to_upper())
endif
Expand Down
6 changes: 6 additions & 0 deletions meson.options
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ option('barebone_backend',
description: 'Include the Barebone backend',
)

option('cshell_backend',
type: 'feature',
value: 'auto',
description: 'Include the CShell backend',
)

option('compiler_backend',
type: 'feature',
value: 'auto',
Expand Down
2 changes: 2 additions & 0 deletions src/cshell/cshell.resources
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[resource-compiler]
namespace = Frida.Data.Cshell
8 changes: 8 additions & 0 deletions src/cshell/cshell.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Frida {
public class CShellScript : Object {
public static string get_source () {
string runtime_js = (string) Frida.Data.Cshell.get_frida_cshell_js_blob ().data;
return runtime_js;
}
}
}
1 change: 1 addition & 0 deletions src/cshell/frida-cshell
Submodule frida-cshell added at 58dd04
54 changes: 54 additions & 0 deletions src/cshell/generate-frida-cshell.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#!/usr/bin/env python3

import os
from pathlib import Path
import platform
import shutil
from subprocess import PIPE, STDOUT, CalledProcessError
import subprocess
import sys


def generate_runtime(input_dir, output_dir):
output_dir.mkdir(parents=True, exist_ok=True)

runtime_reldir = Path("frida-cshell")
runtime_srcdir = input_dir / runtime_reldir
runtime_intdir = output_dir / runtime_reldir
if runtime_intdir.exists():
shutil.rmtree(runtime_intdir)
shutil.copytree(runtime_srcdir, runtime_intdir)

npm = os.environ.get("NPM", make_script_filename("npm"))
try:
subprocess.run([npm, "install"], stdout=PIPE, stderr=STDOUT, cwd=runtime_intdir, check=True)
shutil.copy(runtime_intdir / "frida-cshell.js", output_dir)
except CalledProcessError as e:
message = "\n".join([
"",
"***",
"Failed to bootstrap the CShell backend script runtime:",
"\t" + str(e),
"It appears Node.js is not installed.",
"We need it for processing JavaScript code at build-time.",
"Check PATH or set NPM to the absolute path of your npm binary.",
"***\n",
e.stdout.decode("utf-8")
])
raise EnvironmentError(message)


def make_script_filename(name):
build_os = platform.system().lower()
extension = ".cmd" if build_os == "windows" else ""
return name + extension


if __name__ == "__main__":
input_dir, output_dir = [Path(d).resolve() for d in sys.argv[1:3]]

try:
generate_runtime(input_dir, output_dir)
except Exception as e:
print(e, file=sys.stderr)
sys.exit(1)
67 changes: 67 additions & 0 deletions src/cshell/meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
backend_sources += files(
'cshell.vala',
)
cshell_script_runtime = custom_target('frida-cshell',
input: [
'frida-cshell/package.json',
'frida-cshell/package-lock.json',
'frida-cshell/tsconfig.json',
'frida-cshell/src/char.ts',
'frida-cshell/src/cmdlets/assembly.ts',
'frida-cshell/src/cmdlets/bt.ts',
'frida-cshell/src/cmdlets/copy.ts',
'frida-cshell/src/cmdlets/dump.ts',
'frida-cshell/src/cmdlets/exit.ts',
'frida-cshell/src/cmdlets/help.ts',
'frida-cshell/src/cmdlets/history.ts',
'frida-cshell/src/cmdlets/math.ts',
'frida-cshell/src/cmdlets/mod.ts',
'frida-cshell/src/cmdlets/read.ts',
'frida-cshell/src/cmdlets/sym.ts',
'frida-cshell/src/cmdlets/thread.ts',
'frida-cshell/src/cmdlets.ts',
'frida-cshell/src/cmdlets/var.ts',
'frida-cshell/src/cmdlets/vm.ts',
'frida-cshell/src/cmdlets/write.ts',
'frida-cshell/src/cmdlet.ts',
'frida-cshell/src/command.ts',
'frida-cshell/src/entrypoint.ts',
'frida-cshell/src/history.ts',
'frida-cshell/src/input.ts',
'frida-cshell/src/line.ts',
'frida-cshell/src/numeric.ts',
'frida-cshell/src/output.ts',
'frida-cshell/src/parser.ts',
'frida-cshell/src/token.ts',
'frida-cshell/src/util.ts',
'frida-cshell/src/var.ts',
'frida-cshell/src/vars.ts',
],
output: [
'frida-cshell.js',
],
command: [
find_program('generate-frida-cshell.py'),
meson.current_source_dir(),
meson.current_build_dir(),
],
)
backend_sources += custom_target('frida-data-cshell',
input: [
'cshell.resources',
cshell_script_runtime,
],
output: [
'frida-data-cshell.vapi',
'frida-data-cshell.h',
'frida-data-cshell.c',
'frida-data-cshell-blob.S',
],
command: [
resource_compiler,
'--toolchain=' + host_toolchain,
'-c', '@INPUT0@',
'-o', join_paths(meson.current_build_dir(), 'frida-data-cshell'),
'@INPUT1@',
],
)
4 changes: 4 additions & 0 deletions src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,10 @@ if have_barebone_backend
subdir('barebone')
endif

if have_cshell_backend
subdir('cshell')
endif

if host_os_family != 'windows'
backend_vala_args_private += '--pkg=posix'
endif
Expand Down

0 comments on commit c370729

Please sign in to comment.