frida/frida-go

Can't resume portal device process

Opened this issue · 3 comments

I have a custom solution built on top of the frida-go, consisting of two applications: a client and a server.

Client Application (Mobile):

  1. Runs on a mobile phone.
  2. Launches the process and connects it to a frida-portal.

Server Application (Portal):

  1. Acts as a central hub.
  2. Attaches a script to each newly connected process and attempts to interact with it.

Problem: The server cannot resume the process after it has been paused unless the client application terminates.

Steps to Reproduce:

  • Launch the client application on the mobile device and connect it to the Frida-portal.
  • Observe the server successfully attaching to the process, loading the script.
  • Attempt to resume the process again through the server.
  • The process does not resume, process terminates.

Expected Behavior:

  • The server should be able to resume the process without requiring the client application to terminate.

Actual Behavior:

  • The server can only resume the process after the client application terminates.

Environment:

  • Client: Samsung SM-A256E
  • Server: Linux 5.15.153.1-microsoft-standard-WSL2 # 1 SMP Fri Mar 29 23:14:13 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
  • Frida Version: frida-go 0.11.0, frida-core 16.4.10, 16.5.2 (tried both)

Logs

2024-10-05T10:53:44+03:00 ~ info ~ selfcontroller ~ ~/portal/portal.go:124 ~ node joined ~ {"connId": 2, "app": "app_process64", "pid": 1905}
2024-10-05T10:53:44+03:00 ~ info ~ ~/appctrl/appctrl.go:46 ~ attached to application ~ {"pid": 1905}
2024-10-05T10:53:44+03:00 ~ info ~ ~/appctrl/appctrl.go:52 ~ script readen from disk ~ {"size": 24665}
2024-10-05T10:53:44+03:00 ~ info ~ ~/appctrl/appctrl.go:61 ~ script created on remote ~ {"is_destroyed": false}
2024-10-05T10:53:44+03:00 ~ info ~ ~/appctrl/appctrl.go:63 ~ script ~ {"message": "{\"type\":\"log\",\"level\":\"info\",\"payload\":\"Script loaded\"}", "data": ""}
2024-10-05T10:53:44+03:00 ~ info ~ ~/appctrl/appctrl.go:76 ~ script loaded on remote ~ {"is_destroyed": false}
2024-10-05T10:53:44+03:00 ~ info ~ ~/appctrl/appctrl.go:87 ~ application resumed on remote
2024-10-05T10:53:54+03:00 ~ info ~ ~/appctrl/appctrl.go:66 ~ script destroyed!
2024-10-05T10:53:54+03:00 ~ info ~ selfcontroller ~ ~/portal/portal.go:140 ~ node disconnect ~ {"connId": 2, "app": "/system/bin/app_process64", "pid": 1905}
2024-10-05T10:53:54+03:00 ~ info ~ ~/appctrl/appctrl.go:69 ~ detached ~ {"reason": "process-terminated", "crash": ""}

Client code (simplified):

spawnOptions := frida.NewSpawnOptions()
pid, err := bc.device.Spawn(devctrl.AppName, spawnOptions)
if err != nil {
	utils.LogController.Error("failed to spawn application", zap.Error(err))
	return
}
utils.LogController.Info("running", zap.Any("pid", pid))
session, err := bc.device.Attach(pid, frida.NewSessionOptions(frida.RealmNative, 30000))
if err != nil {
	utils.LogController.Error("failed to attach to application", zap.Error(err))
	return
}
portalOptions := frida.NewPortalOptions()
portalOptions.SetToken(bc.env.PortalToken)
portal, err := session.JoinPortal(bc.env.PortalAddress, portalOptions)
if err != nil {
	utils.LogController.Error("failed to join portal", zap.Error(err))
	return
}
utils.LogController.Info("joined to portal", zap.Any("id", portal.ID()))

Server code (simplified):

attachOptions := frida.NewSessionOptions(frida.RealmNative, 0)
session, err := device.Attach(app.PID(), attachOptions)
if err != nil {
	return err
}
logger.Info("attached to application", zap.Any("pid", app.PID()))
scriptData, err := os.ReadFile(path.Join(env.DefaultPath, env.FilenameScript))
if err != nil {
	logger.Error("failed to read script data", zap.Error(err))
	return err
}
logger.Info("script readen from disk", zap.Any("size", len(scriptData)))
scriptOptions := frida.NewScriptOptions("main")
scriptOptions.SetRuntime(frida.ScriptRuntimeV8)
master.script, err = session.CreateScriptWithOptions(string(scriptData), scriptOptions)
if err != nil {
	logger.Error("failed to create script in application", zap.Error(err))
	return err
}
logger.Info("script created on remote", zap.Any("is_destroyed", master.script.IsDestroyed()))
master.script.On("message", func(message string, data []byte) {
	logger.Info("script", zap.String("message", message), zap.String("data", string(data)))
})
master.script.On("destroyed", func() {
	logger.Info("script destroyed!")
})
session.On("detached", func(reason frida.SessionDetachReason, crash *frida.Crash) {
	logger.Info("detached", zap.Any("reason", reason), zap.Any("crash", crash.Report()))
})
err = master.script.Load()
if err != nil {
	logger.Error("failed to run script in application", zap.Error(err))
	return err
}
logger.Info("script loaded on remote", zap.Any("is_destroyed", master.script.IsDestroyed()))
err = session.Resume()
if err != nil {
	logger.Error("failed to resume script in application", zap.Error(err))
	return err
}
logger.Info("application resumed on remote")

Hi @Redict, I will get to this probably on Sunday as I was quite busy lately

@Redict you may want to give the latest frida-core a try?

I was experiencing a similar issue and has gone away since bumping to latest.

@Redict you may want to give the latest frida-core a try?

I was experiencing a similar issue and has gone away since bumping to latest.

I attempted that approach, but the results were identical. I have temporarily adopted gRPC to develop a functional product, though it's somewhat unconventional.