Skip to content

Instantly share code, notes, and snippets.

@NSEcho
Created October 21, 2022 19:59
Show Gist options
  • Save NSEcho/469ea393e017b3491ee96efb7f7ba0c5 to your computer and use it in GitHub Desktop.
Save NSEcho/469ea393e017b3491ee96efb7f7ba0c5 to your computer and use it in GitHub Desktop.
FridaDeviceManager async implementation
package frida
/*
#include <frida-core.h>
#include <stdlib.h>
typedef struct _usb_device_data {
FridaDeviceManager *manager;
gint timeout;
GCancellable *cancellable;
char *ctx;
} usb_device_data;
static usb_device_data * new_usb_device_data() {
usb_device_data * data = malloc(sizeof(usb_device_data));
return data;
}
extern void get_device_by_type_error_callback(GError*, char*);
extern void get_device_by_type_success_callback(FridaDevice*, char*);
static gboolean begin_call(gpointer);
static void on_get_device_by_type_ready(GObject * source_object, GAsyncResult * res, gpointer user_data);
static void frida_schedule_get_device_by_type(gpointer data, GDestroyNotify free_data) {
GSource * source = g_idle_source_new ();
g_source_set_callback (source, begin_call, data, free_data);
g_source_attach (source, frida_get_main_context ());
g_source_unref (source);
}
static gboolean begin_call(gpointer user_data) {
usb_device_data * data = user_data;
frida_device_manager_get_device_by_type (data->manager, FRIDA_DEVICE_TYPE_USB, data->timeout, data->cancellable, on_get_device_by_type_ready, data);
return G_SOURCE_REMOVE;
}
static void on_get_device_by_type_ready(GObject * source_object, GAsyncResult * res, gpointer user_data) {
usb_device_data * data = user_data;
GError * error = NULL;
FridaDevice * device = frida_device_manager_get_device_by_type_finish (data->manager, res, &error);
if (error != NULL) {
get_device_by_type_error_callback(error, data->ctx);
} else {
get_device_by_type_success_callback(device, data->ctx);
}
}
*/
import "C"
import (
"math/rand"
"sync"
)
// map holding channels for random strings (aka context)
var channels = &sync.Map{}
//export get_device_by_type_error_callback
func get_device_by_type_error_callback(err *C.GError, ctx *C.char) {
chName := C.GoString(ctx) + "e"
chI, _ := channels.Load(chName)
ch := chI.(chan interface{})
ch <- &FridaError{err}
}
//export get_device_by_type_success_callback
func get_device_by_type_success_callback(dev *C.FridaDevice, ctx *C.char) {
chName := C.GoString(ctx) + "s"
chI, _ := channels.Load(chName)
ch := chI.(chan interface{})
ch <- &FridaDevice{dev, 0}
}
type FridaMgrAsync struct {
mgr *C.FridaDeviceManager
}
func NewMgrAsync() *FridaMgrAsync {
manager := C.frida_device_manager_new()
mgr := &FridaMgrAsync{manager}
return mgr
}
// Ignore this one, it is here just to enumerate devices quickly
func (mgr *FridaMgrAsync) EnumDevices() {
C.frida_device_manager_enumerate_devices_sync(mgr.mgr, nil, nil)
}
func (mgr *FridaMgrAsync) GetUSBDevice() (*FridaDevice, error) {
tm := C.gint(15)
chErr := make(chan interface{}) // channel where error will be sent in case of one
chSuccess := make(chan interface{}) // channel where result will be sent
defer close(chErr)
defer close(chSuccess)
// Create random string which will act as a context
randomString := randString(20)
randomStringC := C.CString(randomString)
channels.Store(randomString+"e", chErr) // error channel will be at randomString + "e"
channels.Store(randomString+"s", chSuccess) // success channel will be at randomString + "s"
// Create struct by passing the context
dt := C.usb_device_data{mgr.mgr, tm, nil, randomStringC}
dtPointer := (C.gpointer)(&dt)
C.frida_schedule_get_device_by_type(dtPointer, nil)
// poll both channels
// whichever returns first because cant have result from both
for {
select {
case dev := <-chSuccess:
return dev.(*FridaDevice), nil // convert it to FridaDevice and return
case err := <-chErr:
return nil, err.(*FridaError) // convert it to FridaError and return
}
}
}
var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
func randString(n int) string {
b := make([]rune, n)
for i := range b {
b[i] = letterRunes[rand.Intn(len(letterRunes))]
}
return string(b)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment