Skip to content

Commit

Permalink
feat: changing api to expose DeviceInt to provide a mockable interfac…
Browse files Browse the repository at this point in the history
…e to the caller

Expose the concrete type of DeviceManager so the end user can mock it
however they see fit. I.E the go saying of "Accept Interfaces, Return Structs".
However, return a frida.Device Interface when DeviceManager/Portal is
being used for access to provide the end user a mockable interface.
  • Loading branch information
dylanhitt committed Jan 25, 2024
1 parent ad624be commit b923faf
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 85 deletions.
68 changes: 34 additions & 34 deletions frida/device.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ import (
"unsafe"
)

type Device interface {
type DeviceInt interface {
ID() string
Name() string
DeviceIcon() any
Bus() *Bus
Manager() DeviceManager
Manager() *DeviceManager
IsLost() bool
Params() (map[string]any, error)
FrontmostApplication(scope Scope) (*Application, error)
Expand All @@ -41,29 +41,29 @@ type Device interface {
On(sigName string, fn any)
}

// DeviceImpl represents DeviceImpl struct from frida-core
type DeviceImpl struct {
// Device represents Device struct from frida-core
type Device struct {
device *C.FridaDevice
}

// ID will return the ID of the device.
func (d *DeviceImpl) ID() string {
func (d *Device) ID() string {
if d.device != nil {
return C.GoString(C.frida_device_get_id(d.device))
}
return ""
}

// Name will return the name of the device.
func (d *DeviceImpl) Name() string {
func (d *Device) Name() string {
if d.device != nil {
return C.GoString(C.frida_device_get_name(d.device))
}
return ""
}

// DeviceIcon will return the device icon.
func (d *DeviceImpl) DeviceIcon() any {
func (d *Device) DeviceIcon() any {
if d.device != nil {
icon := C.frida_device_get_icon(d.device)
dt := gPointerToGo((C.gpointer)(icon))
Expand All @@ -73,7 +73,7 @@ func (d *DeviceImpl) DeviceIcon() any {
}

// DeviceType returns type of the device.
func (d *DeviceImpl) DeviceType() DeviceType {
func (d *Device) DeviceType() DeviceType {
if d.device != nil {
fdt := C.frida_device_get_dtype(d.device)
return DeviceType(fdt)
Expand All @@ -82,7 +82,7 @@ func (d *DeviceImpl) DeviceType() DeviceType {
}

// Bus returns device bus.
func (d *DeviceImpl) Bus() *Bus {
func (d *Device) Bus() *Bus {
if d.device != nil {
bus := C.frida_device_get_bus(d.device)
return &Bus{
Expand All @@ -93,16 +93,16 @@ func (d *DeviceImpl) Bus() *Bus {
}

// Manager returns device manager for the device.
func (d *DeviceImpl) Manager() DeviceManager {
func (d *Device) Manager() *DeviceManager {
if d.device != nil {
mgr := C.frida_device_get_manager(d.device)
return &deviceManager{mgr}
return &DeviceManager{mgr}
}
return nil
}

// IsLost returns boolean whether device is lost or not.
func (d *DeviceImpl) IsLost() bool {
func (d *Device) IsLost() bool {
if d.device != nil {
lost := C.frida_device_is_lost(d.device)
return int(lost) == 1
Expand All @@ -111,7 +111,7 @@ func (d *DeviceImpl) IsLost() bool {
}

// Params returns system parameters of the device
func (d *DeviceImpl) Params() (map[string]any, error) {
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)
Expand All @@ -128,7 +128,7 @@ func (d *DeviceImpl) Params() (map[string]any, error) {

// FrontmostApplication will return the frontmost application or the application in focus
// on the device.
func (d *DeviceImpl) FrontmostApplication(scope Scope) (*Application, error) {
func (d *Device) FrontmostApplication(scope Scope) (*Application, error) {
if d.device != nil {
var err *C.GError
app := &Application{}
Expand All @@ -154,7 +154,7 @@ func (d *DeviceImpl) FrontmostApplication(scope Scope) (*Application, error) {
}

// EnumerateApplications will return slice of applications on the device
func (d *DeviceImpl) EnumerateApplications(identifier string, scope Scope) ([]*Application, error) {
func (d *Device) EnumerateApplications(identifier string, scope Scope) ([]*Application, error) {
if d.device != nil {
queryOpts := C.frida_application_query_options_new()
C.frida_application_query_options_set_scope(queryOpts, C.FridaScope(scope))
Expand Down Expand Up @@ -192,7 +192,7 @@ func (d *DeviceImpl) EnumerateApplications(identifier string, scope Scope) ([]*A
}

// ProcessByPID returns the process by passed pid.
func (d *DeviceImpl) ProcessByPID(pid int, scope Scope) (*Process, error) {
func (d *Device) ProcessByPID(pid int, scope Scope) (*Process, error) {
if d.device != nil {
opts := C.frida_process_match_options_new()
C.frida_process_match_options_set_timeout(opts, C.gint(defaultProcessTimeout))
Expand All @@ -210,7 +210,7 @@ func (d *DeviceImpl) ProcessByPID(pid int, scope Scope) (*Process, error) {
}

// ProcessByName returns the process by passed name.
func (d *DeviceImpl) ProcessByName(name string, scope Scope) (*Process, error) {
func (d *Device) ProcessByName(name string, scope Scope) (*Process, error) {
if d.device != nil {
nameC := C.CString(name)
defer C.free(unsafe.Pointer(nameC))
Expand All @@ -231,7 +231,7 @@ func (d *DeviceImpl) ProcessByName(name string, scope Scope) (*Process, error) {
}

// FindProcessByPID will try to find the process with given pid.
func (d *DeviceImpl) FindProcessByPID(pid int, scope Scope) (*Process, error) {
func (d *Device) FindProcessByPID(pid int, scope Scope) (*Process, error) {
if d.device != nil {
opts := C.frida_process_match_options_new()
C.frida_process_match_options_set_timeout(opts, C.gint(defaultProcessTimeout))
Expand All @@ -249,7 +249,7 @@ func (d *DeviceImpl) FindProcessByPID(pid int, scope Scope) (*Process, error) {
}

// FindProcessByName will try to find the process with name specified.
func (d *DeviceImpl) FindProcessByName(name string, scope Scope) (*Process, error) {
func (d *Device) FindProcessByName(name string, scope Scope) (*Process, error) {
if d.device != nil {
nameC := C.CString(name)
defer C.free(unsafe.Pointer(nameC))
Expand All @@ -270,7 +270,7 @@ func (d *DeviceImpl) FindProcessByName(name string, scope Scope) (*Process, erro
}

// EnumerateProcesses will slice of processes running with scope provided
func (d *DeviceImpl) EnumerateProcesses(scope Scope) ([]*Process, error) {
func (d *Device) EnumerateProcesses(scope Scope) ([]*Process, error) {
if d.device != nil {
opts := C.frida_process_query_options_new()
C.frida_process_query_options_set_scope(opts, C.FridaScope(scope))
Expand All @@ -297,7 +297,7 @@ func (d *DeviceImpl) EnumerateProcesses(scope Scope) ([]*Process, error) {
}

// EnableSpawnGating will enable spawn gating on the device.
func (d *DeviceImpl) EnableSpawnGating() error {
func (d *Device) EnableSpawnGating() error {
if d.device != nil {
var err *C.GError
C.frida_device_enable_spawn_gating_sync(d.device, nil, &err)
Expand All @@ -310,7 +310,7 @@ func (d *DeviceImpl) EnableSpawnGating() error {
}

// DisableSpawnGating will disable spawn gating on the device.
func (d *DeviceImpl) DisableSpawnGating() error {
func (d *Device) DisableSpawnGating() error {
if d.device != nil {
var err *C.GError
C.frida_device_disable_spawn_gating_sync(d.device, nil, &err)
Expand All @@ -323,7 +323,7 @@ func (d *DeviceImpl) DisableSpawnGating() error {
}

// EnumeratePendingSpawn will return the slice of pending spawns.
func (d *DeviceImpl) EnumeratePendingSpawn() ([]*Spawn, error) {
func (d *Device) EnumeratePendingSpawn() ([]*Spawn, error) {
if d.device != nil {
var err *C.GError
spawnList := C.frida_device_enumerate_pending_spawn_sync(d.device, nil, &err)
Expand All @@ -346,7 +346,7 @@ func (d *DeviceImpl) EnumeratePendingSpawn() ([]*Spawn, error) {
}

// EnumeratePendingChildren will return the slice of pending children.
func (d *DeviceImpl) EnumeratePendingChildren() ([]*Child, error) {
func (d *Device) EnumeratePendingChildren() ([]*Child, error) {
if d.device != nil {
var err *C.GError
childList := C.frida_device_enumerate_pending_children_sync(d.device, nil, &err)
Expand All @@ -369,7 +369,7 @@ func (d *DeviceImpl) EnumeratePendingChildren() ([]*Child, error) {
}

// Spawn will spawn an application or binary.
func (d *DeviceImpl) Spawn(name string, opts *SpawnOptions) (int, error) {
func (d *Device) Spawn(name string, opts *SpawnOptions) (int, error) {
if d.device != nil {
var opt *C.FridaSpawnOptions = nil
if opts != nil {
Expand All @@ -392,7 +392,7 @@ func (d *DeviceImpl) Spawn(name string, opts *SpawnOptions) (int, error) {
}

// Input inputs []bytes into the process with pid specified.
func (d *DeviceImpl) Input(pid int, data []byte) error {
func (d *Device) Input(pid int, data []byte) error {
if d.device != nil {
gBytesData := goBytesToGBytes(data)
runtime.SetFinalizer(gBytesData, func(g *C.GBytes) {
Expand All @@ -411,7 +411,7 @@ func (d *DeviceImpl) Input(pid int, data []byte) error {
}

// Resume will resume the process with pid.
func (d *DeviceImpl) Resume(pid int) error {
func (d *Device) Resume(pid int) error {
if d.device != nil {
var err *C.GError
C.frida_device_resume_sync(d.device, C.guint(pid), nil, &err)
Expand All @@ -424,7 +424,7 @@ func (d *DeviceImpl) Resume(pid int) error {
}

// Kill kills process with pid specified.
func (d *DeviceImpl) Kill(pid int) error {
func (d *Device) Kill(pid int) error {
if d.device != nil {
var err *C.GError
C.frida_device_kill_sync(d.device, C.guint(pid), nil, &err)
Expand All @@ -439,7 +439,7 @@ func (d *DeviceImpl) Kill(pid int) error {
// Attach will attach on specified process name or PID.
// You can pass the nil as SessionOptions or you can create it if you want
// the session to persist for specific timeout.
func (d *DeviceImpl) Attach(val any, opts *SessionOptions) (*Session, error) {
func (d *Device) Attach(val any, opts *SessionOptions) (*Session, error) {
if d.device != nil {
var pid int
switch v := reflect.ValueOf(val); v.Kind() {
Expand Down Expand Up @@ -474,7 +474,7 @@ func (d *DeviceImpl) Attach(val any, opts *SessionOptions) (*Session, error) {
// InjectLibraryFile will inject the library in the target with path to library specified.
// Entrypoint is the entrypoint to the library and the data is any data you need to pass
// to the library.
func (d *DeviceImpl) InjectLibraryFile(target any, path, entrypoint, data string) (uint, error) {
func (d *Device) InjectLibraryFile(target any, path, entrypoint, data string) (uint, error) {
if d.device != nil {
var pid int
switch v := reflect.ValueOf(target); v.Kind() {
Expand Down Expand Up @@ -531,7 +531,7 @@ func (d *DeviceImpl) InjectLibraryFile(target any, path, entrypoint, data string
// InjectLibraryBlob will inject the library in the target with byteData path.
// Entrypoint is the entrypoint to the library and the data is any data you need to pass
// to the library.
func (d *DeviceImpl) InjectLibraryBlob(target any, byteData []byte, entrypoint, data string) (uint, error) {
func (d *Device) InjectLibraryBlob(target any, byteData []byte, entrypoint, data string) (uint, error) {
if d.device != nil {
var pid int
switch v := reflect.ValueOf(target); v.Kind() {
Expand Down Expand Up @@ -588,7 +588,7 @@ func (d *DeviceImpl) InjectLibraryBlob(target any, byteData []byte, entrypoint,
}

// OpenChannel open channel with the address and returns the IOStream
func (d *DeviceImpl) OpenChannel(address string) (*IOStream, error) {
func (d *Device) OpenChannel(address string) (*IOStream, error) {
if d.device != nil {
addressC := C.CString(address)
defer C.free(unsafe.Pointer(addressC))
Expand All @@ -604,7 +604,7 @@ func (d *DeviceImpl) OpenChannel(address string) (*IOStream, error) {
}

// Clean will clean the resources held by the device.
func (d *DeviceImpl) Clean() {
func (d *Device) Clean() {
if d.device != nil {
clean(unsafe.Pointer(d.device), unrefFrida)
}
Expand All @@ -622,7 +622,7 @@ func (d *DeviceImpl) Clean() {
// - "output" with callback as func(pid, fd int, data []byte) {}
// - "uninjected" with callback as func(id int) {}
// - "lost" with callback as func() {}
func (d *DeviceImpl) On(sigName string, fn any) {
func (d *Device) On(sigName string, fn any) {
if d.device != nil {
connectClosure(unsafe.Pointer(d.device), sigName, fn)
}
Expand Down
22 changes: 11 additions & 11 deletions frida/frida.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,30 +34,30 @@ func Version() string {
return C.GoString(C.frida_version_string())
}

func getDeviceManager() DeviceManager {
func getDeviceManager() *DeviceManager {
v, ok := data.Load("mgr")
if !ok {
mgr := NewDeviceManager()
data.Store("mgr", mgr)
return mgr
}
return v.(*deviceManager)
return v.(*DeviceManager)
}

// LocalDevice is a wrapper around DeviceByType(DeviceTypeLocal).
func LocalDevice() Device {
func LocalDevice() *Device {
mgr := getDeviceManager()
v, ok := data.Load("localDevice")
if !ok {
dev, _ := mgr.DeviceByType(DeviceTypeLocal)
data.Store("localDevice", dev)
return dev
return dev.(*Device)
}
return v.(*DeviceImpl)
return v.(*Device)
}

// USBDevice is a wrapper around DeviceByType(DeviceTypeUsb).
func USBDevice() Device {
func USBDevice() *Device {
mgr := getDeviceManager()
v, ok := data.Load("usbDevice")
if !ok {
Expand All @@ -71,13 +71,13 @@ func USBDevice() Device {
return nil
}
data.Store("usbDevice", dev)
return dev
return dev.(*Device)
}
return v.(*DeviceImpl)
return v.(*Device)
}

// DeviceByID tries to get the device by id on the default manager
func DeviceByID(id string) (Device, error) {
func DeviceByID(id string) (*Device, error) {
mgr := getDeviceManager()
v, ok := data.Load(id)
if !ok {
Expand All @@ -91,9 +91,9 @@ func DeviceByID(id string) (Device, error) {
return nil, err
}
data.Store(id, dev)
return dev, nil
return v.(*Device), nil
}
return v.(*DeviceImpl), nil
return v.(*Device), nil
}

// Attach attaches at val(string or int pid) using local device.
Expand Down
Loading

0 comments on commit b923faf

Please sign in to comment.