v-frida

December 29, 2021 ยท View on GitHub

This is the initial support of V for Frida.

V is a go-ish programming language that compiles to C and JS, this makes it ideal to target Frida, so it's possible to write host and target code using the same language.

The versatility of V and Frida, allow to write host and agent code in both C or Javascript. Making possible to reuse your nodejs host or agent scripts, or use CModule in the agent without changing a line in your V host or agent code.

Status

This is the list of checkbox to mark over time

  • Spawn local apps
  • Attach local/usb by pid
  • Trace methods (onEnter/onLeave)
  • Change return value onLeave
  • Enumerate modules, symbols and exports
  • Attach via USB by appname
  • Change argument values onEnter
  • Enumerate processes

Example

This is a simplified example usage for the host and agent side in pure V

Host

import frida.host
import os

fn load_agent() string {
	os.system('v -o agent.js agent.v')
	return os.read_file('agent.js')?
}

fn watchdog() ? {
	time.sleep(10 * 100000)
}

fn main() {
	dm := host.new_device_manager()
	device := dm.get_device_by_type(.local)?
	pid := device.spawn('/usr/local/bin/r2', {})?
	eprintln('ls: pid $pid')

	session := device.attach(pid)?
	session.on_detached(host.SessionDetachCallback(on_detached), voidptr(0))

	code := load_agent()
	script := session.create_script(code, {
		name: 'v-frida'
		on_message: host.ScriptMessageCallback(on_message)
		user_data: 0
	})?

	script.load()?
	fill := go watchdog(fs)
	fill.wait() or { eprintln('Oops: $err') }
	script.unload()?
	device.kill(pid)
}

Agent:

import frida.agent

fn on_message(mut stanza agent.Stanza, mut data agent.Data) {
	eprintln('message received! ${stanza.payload}')
	agent.recv(on_message)
}

fn main() {
	println('Hello world')
	agent.recv(on_message)
}

Show time

$ v -o agent.js agent.v
$ v run main.v
ls: pid 66485
message received: {"type":"log","level":"info","payload":"Hello world"}
message received: {"type":"log","level":"info","payload":"frida message received"}
message received: {"type":"log","level":"info","payload":"frida message received"}
message received: {"type":"log","level":"info","payload":"frida message received"}
...
V panic: The connection is closed
$

Running main demo

$ make
v -g main.v
./main
[>] frida: device-manager
[>] v: target
[>] frida: spawning
ls: pid 15709
[>] frida: loading script
[>] v: agent
loading
[main.v < agent.v]: Hello from the Agent side
[main.v < agent.v]: Symbol to hook found main__State_pull
[main.v < agent.v]: Stuff hooked
loaded
Count 666
Count 666
[main.v < agent.v]: pull method pwned
Count 666
[main.v < agent.v]: replace return value 666
Count 666
[main.v < agent.v]: pull method pwned
Count 666
[main.v < agent.v]: replace return value 666
Count 666
[main.v < agent.v]: pull method pwned
Count 666
Count 666
[main.v < agent.v]: replace return value 666
Count 666
[main.v < agent.v]: pull method pwned
Count 666
[main.v < agent.v]: replace return value 666
[main.v < agent.v]: pull method pwned
[main.v < agent.v]: replace return value 666
[main.v < agent.v]: pull method pwned
[>] frida: unloading the scene
unloaded
detached