Skip to content

Commit

Permalink
Merge pull request #43 from dylanhitt/fear/cancellable
Browse files Browse the repository at this point in the history
WIP: feat: add the ability to cancel params
  • Loading branch information
NSEcho committed Sep 20, 2024
2 parents 4a05268 + 8e5b1e8 commit 6e7c3c6
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 38 deletions.
117 changes: 79 additions & 38 deletions frida/device.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package frida
//#include <frida-core.h>
import "C"
import (
"context"
"errors"
"reflect"
"runtime"
Expand All @@ -18,9 +19,9 @@ type DeviceInt interface {
Bus() *Bus
Manager() *DeviceManager
IsLost() bool
Params() (map[string]any, error)
Params(opts ...OptFunc) (map[string]any, error)
FrontmostApplication(scope Scope) (*Application, error)
EnumerateApplications(identifier string, scope Scope) ([]*Application, error)
EnumerateApplications(identifier string, scope Scope, opts ...OptFunc) ([]*Application, error)
ProcessByPID(pid int, scope Scope) (*Process, error)
ProcessByName(name string, scope Scope) (*Process, error)
FindProcessByPID(pid int, scope Scope) (*Process, error)
Expand Down Expand Up @@ -112,20 +113,54 @@ func (d *Device) IsLost() bool {
return false
}

// Params returns system parameters of the device
func (d *Device) Params() (map[string]any, error) {
if d.device != nil {
var err *C.GError
ht := C.frida_device_query_system_parameters_sync(d.device, nil, &err)
func (d *Device) ParamsCtx(ctx context.Context) (map[string]any, error) {
paramC := make(chan map[string]any, 1)
errC := make(chan error, 1)

c := NewCancellable()
go func() {
params, err := d.Params(WithCancel(c))
if err != nil {
return nil, &FError{err}
errC <- err
return
}
paramC <- params
}()

params := gHashTableToMap(ht)
for {
select {
case <-ctx.Done():
c.Cancel()
return nil, ErrContextCancelled
case params := <-paramC:
c.Unref()
return params, nil
case err := <-errC:
c.Unref()
return nil, err
}

return params, nil
}
return nil, errors.New("could not obtain params for nil device")
}

// Params returns system parameters of the device
func (d *Device) Params(opts ...OptFunc) (map[string]any, error) {
o := setupOptions(opts)
return d.params(o)
}

func (d *Device) params(opts options) (map[string]any, error) {
if d.device == nil {
return nil, errors.New("could not obtain params for nil device")
}

var err *C.GError
ht := C.frida_device_query_system_parameters_sync(d.device, opts.cancellable, &err)
if err != nil {
return nil, &FError{err}
}

return gHashTableToMap(ht), nil
}

// FrontmostApplication will return the frontmost application or the application in focus
Expand Down Expand Up @@ -155,42 +190,48 @@ func (d *Device) FrontmostApplication(scope Scope) (*Application, error) {
return nil, errors.New("could not obtain frontmost app for nil device")
}

func (d *Device) EnumerateApplications(identifier string, scope Scope, opts ...OptFunc) ([]*Application, error) {
o := setupOptions(opts)
return d.enumerateApplications(identifier, scope, o)
}

// EnumerateApplications will return slice of applications on the device
func (d *Device) EnumerateApplications(identifier string, scope Scope) ([]*Application, error) {
func (d *Device) enumerateApplications(identifier string, scope Scope, opts options) ([]*Application, error) {
if d.device != nil {
queryOpts := C.frida_application_query_options_new()
C.frida_application_query_options_set_scope(queryOpts, C.FridaScope(scope))
return nil, errors.New("could not enumerate applications for nil device")
}

if identifier != "" {
identifierC := C.CString(identifier)
defer C.free(unsafe.Pointer(identifierC))
C.frida_application_query_options_select_identifier(queryOpts, identifierC)
}
queryOpts := C.frida_application_query_options_new()
C.frida_application_query_options_set_scope(queryOpts, C.FridaScope(scope))

var err *C.GError
appList := C.frida_device_enumerate_applications_sync(d.device, queryOpts, nil, &err)
if err != nil {
return nil, &FError{err}
}
if identifier != "" {
identifierC := C.CString(identifier)
defer C.free(unsafe.Pointer(identifierC))
C.frida_application_query_options_select_identifier(queryOpts, identifierC)
}

appListSize := int(C.frida_application_list_size(appList))
apps := make([]*Application, appListSize)
var err *C.GError
appList := C.frida_device_enumerate_applications_sync(d.device, queryOpts, opts.cancellable, &err)
if err != nil {
return nil, &FError{err}
}

for i := 0; i < appListSize; i++ {
app := C.frida_application_list_get(appList, C.gint(i))
apps[i] = &Application{app}
}
appListSize := int(C.frida_application_list_size(appList))
apps := make([]*Application, appListSize)

sort.Slice(apps, func(i, j int) bool {
return apps[i].PID() > apps[j].PID()
})
for i := 0; i < appListSize; i++ {
app := C.frida_application_list_get(appList, C.gint(i))
apps[i] = &Application{app}
}

clean(unsafe.Pointer(queryOpts), unrefFrida)
clean(unsafe.Pointer(appList), unrefFrida)
sort.Slice(apps, func(i, j int) bool {
return apps[i].PID() > apps[j].PID()
})

return apps, nil
}
return nil, errors.New("could not enumerate applications for nil device")
clean(unsafe.Pointer(queryOpts), unrefFrida)
clean(unsafe.Pointer(appList), unrefFrida)

return apps, nil
}

// ProcessByPID returns the process by passed pid.
Expand Down
39 changes: 39 additions & 0 deletions frida/misc.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,45 @@ import (
"unsafe"
)

type Cancellable struct {
cancellable *C.GCancellable
}

func NewCancellable() *Cancellable {
return &Cancellable{
cancellable: C.g_cancellable_new(),
}
}

func (c *Cancellable) Cancel() {
C.g_cancellable_cancel(c.cancellable)
}


func (c *Cancellable) Unref() {
C.g_object_unref((C.gpointer)(c.cancellable))
}

type options struct {
cancellable *C.GCancellable
}

func setupOptions(opts []OptFunc) options {
o := &options{}
for _, opt := range opts {
opt(o)
}
return *o
}

type OptFunc func(o *options)

func WithCancel(cancel *Cancellable) OptFunc {
return func(o *options) {
o.cancellable = cancel.cancellable
}
}

// FError holds a pointer to GError
type FError struct {
error *C.GError
Expand Down

0 comments on commit 6e7c3c6

Please sign in to comment.