Compare commits

...
5 changed files with 71 additions and 12 deletions

No files matched your search

+9 -3
View File
@@ -28,9 +28,15 @@ import (
var extensions map[string]Extension
type Callbacks struct {
SendData func([]byte)
OnFinish func([]byte)
SendError func([]byte)
}
type Extension interface {
Load() error
Call(exportName string, arguments []byte, callback func([]byte)) error
Call(exportName string, arguments []byte, callbacks Callbacks) error
GetID() string
GetArch() string
}
@@ -47,9 +53,9 @@ func List() []string {
return extList
}
func Run(extID string, funcName string, arguments []byte, callback func([]byte)) error {
func Run(extID string, funcName string, arguments []byte, callbacks Callbacks) error {
if ext, found := extensions[extID]; found {
return ext.Call(funcName, arguments, callback)
return ext.Call(funcName, arguments, callbacks)
}
// {{if .Config.Debug}}
for id, ext := range extensions {
+2 -2
View File
@@ -85,7 +85,7 @@ func (d *DarwinExtension) Load() error {
return nil
}
func (d *DarwinExtension) Call(export string, arguments []byte, onFinish func([]byte)) error {
func (d *DarwinExtension) Call(export string, arguments []byte, callbacks Callbacks) error {
// We currently have 2 issues with Darwin extensions:
// - cppgo (used by universal) fucks up when calling a function with more than 1 argument
// - we don't have Go callback support for the loaded extension,
@@ -124,7 +124,7 @@ func (d *DarwinExtension) Call(export string, arguments []byte, onFinish func([]
// We currently don't have a way to trigger a callback
// in the loaded code for Darwin.
if outData.Len() > 0 {
onFinish(outData.Bytes())
callbacks.OnFinish(outData.Bytes())
}
return nil
}
+17 -5
View File
@@ -36,6 +36,12 @@ const (
Failure = 1
)
type CallbacksPtr struct {
sendData uintptr
onFinish uintptr
sendError uintptr
}
type WindowsExtension struct {
id string
data []byte
@@ -92,15 +98,21 @@ func (w *WindowsExtension) Load() error {
}
// Call - Call an extension export
func (w *WindowsExtension) Call(export string, arguments []byte, onFinish func([]byte)) error {
func (w *WindowsExtension) Call(export string, arguments []byte, callbacks Callbacks) error {
var (
argumentsPtr uintptr
argumentsSize uintptr
argumentsPtr uintptr
argumentsSize uintptr
callbacksPtr CallbacksPtr
callbacksStructPtr uintptr
)
if w.module == nil {
return errors.New("{{if .Config.Debug}} module not loaded {{end}}")
}
callback := syscall.NewCallback(newWindowsExtensionCallback(onFinish))
callbacksPtr.onFinish = syscall.NewCallback(newWindowsExtensionCallback(callbacks.OnFinish))
callbacksPtr.sendData = syscall.NewCallback(newWindowsExtensionCallback(callbacks.SendData))
callbacksPtr.sendError = syscall.NewCallback(newWindowsExtensionCallback(callbacks.SendError))
callbacksStructPtr = uintptr(unsafe.Pointer(&callbacks))
exportPtr, err := w.module.ProcAddressByName(export)
if err != nil {
return err
@@ -117,7 +129,7 @@ func (w *WindowsExtension) Call(export string, arguments []byte, onFinish func([
// where goCallback = int(char *, int)
w.Lock()
defer w.Unlock()
_, _, errNo := syscall.Syscall(exportPtr, 3, argumentsPtr, argumentsSize, callback)
_, _, errNo := syscall.Syscall(exportPtr, 3, argumentsPtr, argumentsSize, callbacksStructPtr)
if errNo != 0 {
return errors.New(errNo.Error())
}
+22 -1
View File
@@ -122,11 +122,32 @@ func callExtensionHandler(data []byte, resp RPCResponse) {
Response: &commonpb.Response{},
}
gotOutput := false
err = extension.Run(callReq.Name, callReq.Export, callReq.Args, func(out []byte) {
onFinish := func(out []byte) {
gotOutput = true
callResp.Output = out
data, err = proto.Marshal(callResp)
resp(data, err)
}
sendData := func(out []byte) {
gotOutput = true
callResp.Output = out
data, err = proto.Marshal(callResp)
resp(data, err)
}
sendError := func(out []byte) {
gotOutput = true
callResp.Output = out
data, err = proto.Marshal(callResp)
resp(data, err)
}
err = extension.Run(callReq.Name, callReq.Export, callReq.Args, extension.Callbacks{
OnFinish: onFinish,
SendData: sendData,
SendError: sendError,
})
// Only send back synchronously if there was an error
if err != nil || !gotOutput {
+21 -1
View File
@@ -924,11 +924,31 @@ func callExtensionHandler(data []byte, resp RPCResponse) {
callResp := &sliverpb.CallExtension{Response: &commonpb.Response{}}
gotOutput := false
err = extension.Run(callReq.Name, callReq.Export, callReq.Args, func(out []byte) {
var onFinish = func(out []byte) {
gotOutput = true
callResp.Output = out
data, err = proto.Marshal(callResp)
resp(data, err)
}
var sendData = func(out []byte) {
gotOutput = true
callResp.Output = out
data, err = proto.Marshal(callResp)
resp(data, err)
}
var sendError = func(out []byte) {
gotOutput = true
callResp.Output = out
data, err = proto.Marshal(callResp)
resp(data, err)
}
err = extension.Run(callReq.Name, callReq.Export, callReq.Args, extension.Callbacks{
OnFinish: onFinish,
SendData: sendData,
SendError: sendError,
})
// Only send back synchronously if there was an error
if err != nil || !gotOutput {