Created
October 21, 2022 19:59
-
-
Save NSEcho/469ea393e017b3491ee96efb7f7ba0c5 to your computer and use it in GitHub Desktop.
FridaDeviceManager async implementation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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