1313 lines
37 KiB
Go
1313 lines
37 KiB
Go
package axscript
|
|
|
|
import (
|
|
"AdaptixServer/core/utils/logs"
|
|
"crypto/md5"
|
|
"crypto/sha1"
|
|
"crypto/sha256"
|
|
"crypto/sha512"
|
|
"encoding/base64"
|
|
"encoding/binary"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"math/rand"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"time"
|
|
"unicode/utf16"
|
|
|
|
"github.com/dop251/goja"
|
|
)
|
|
|
|
func registerAxBridge(engine *ScriptEngine) {
|
|
rt := engine.runtime
|
|
|
|
axObj := rt.NewObject()
|
|
|
|
axObj.Set("create_command", func(call goja.FunctionCall) goja.Value {
|
|
name := ""
|
|
description := ""
|
|
example := ""
|
|
message := ""
|
|
if len(call.Arguments) > 0 {
|
|
name = call.Argument(0).String()
|
|
}
|
|
if len(call.Arguments) > 1 {
|
|
description = call.Argument(1).String()
|
|
}
|
|
if len(call.Arguments) > 2 {
|
|
example = call.Argument(2).String()
|
|
}
|
|
if len(call.Arguments) > 3 {
|
|
message = call.Argument(3).String()
|
|
}
|
|
|
|
builder := newJsCommandBuilder(engine, name, description, example, message)
|
|
|
|
obj := rt.NewObject()
|
|
obj.Set("addArgBool", builder.AddArgBool)
|
|
obj.Set("addArgInt", builder.AddArgInt)
|
|
obj.Set("addArgFlagInt", builder.AddArgFlagInt)
|
|
obj.Set("addArgString", builder.AddArgString)
|
|
obj.Set("addArgFlagString", builder.AddArgFlagString)
|
|
obj.Set("addArgFile", builder.AddArgFile)
|
|
obj.Set("addArgFlagFile", builder.AddArgFlagFile)
|
|
obj.Set("addSubCommands", builder.AddSubCommands)
|
|
obj.Set("setPreHook", builder.SetPreHook)
|
|
|
|
obj.Set("__builder", builder)
|
|
|
|
return obj
|
|
})
|
|
|
|
axObj.Set("create_commands_group", func(call goja.FunctionCall) goja.Value {
|
|
if len(call.Arguments) >= 2 {
|
|
groupName := call.Argument(0).String()
|
|
arrayVal := call.Argument(1)
|
|
group := newJsCommandGroupBuilder(engine)
|
|
group.SetParamsFromValue(groupName, arrayVal)
|
|
|
|
obj := rt.NewObject()
|
|
obj.Set("setParams", group.SetParams)
|
|
obj.Set("add", group.Add)
|
|
obj.Set("__group", group)
|
|
return obj
|
|
}
|
|
|
|
group := newJsCommandGroupBuilder(engine)
|
|
|
|
obj := rt.NewObject()
|
|
obj.Set("setParams", group.SetParams)
|
|
obj.Set("add", group.Add)
|
|
|
|
obj.Set("__group", group)
|
|
|
|
return obj
|
|
})
|
|
|
|
axObj.Set("execute_command", func(call goja.FunctionCall) goja.Value {
|
|
if engine.manager == nil {
|
|
panic(rt.NewTypeError("execute_command: script manager not available"))
|
|
}
|
|
|
|
if len(call.Arguments) < 2 {
|
|
panic(rt.NewTypeError("execute_command requires at least 2 arguments: (agentId, cmdline)"))
|
|
}
|
|
|
|
agentId := call.Argument(0).String()
|
|
cmdline := call.Argument(1).String()
|
|
|
|
var postHookFn goja.Callable
|
|
var handlerFn goja.Callable
|
|
|
|
if len(call.Arguments) > 2 && !goja.IsUndefined(call.Argument(2)) && !goja.IsNull(call.Argument(2)) {
|
|
fn, ok := goja.AssertFunction(call.Argument(2))
|
|
if ok {
|
|
postHookFn = fn
|
|
}
|
|
}
|
|
if len(call.Arguments) > 3 && !goja.IsUndefined(call.Argument(3)) && !goja.IsNull(call.Argument(3)) {
|
|
fn, ok := goja.AssertFunction(call.Argument(3))
|
|
if ok {
|
|
handlerFn = fn
|
|
}
|
|
}
|
|
|
|
err := engine.manager.ExecuteCommand(engine, agentId, cmdline, postHookFn, handlerFn)
|
|
if err != nil {
|
|
panic(rt.NewGoError(err))
|
|
}
|
|
|
|
return goja.Undefined()
|
|
})
|
|
|
|
axObj.Set("execute_alias", func(call goja.FunctionCall) goja.Value {
|
|
if engine.manager == nil {
|
|
panic(rt.NewTypeError("execute_alias: script manager not available"))
|
|
}
|
|
|
|
if len(call.Arguments) < 3 {
|
|
panic(rt.NewTypeError("execute_alias requires at least 3 arguments: (agentId, originalCmdline, aliasCmdline)"))
|
|
}
|
|
|
|
agentId := call.Argument(0).String()
|
|
displayCmdline := call.Argument(1).String()
|
|
aliasCmdline := call.Argument(2).String()
|
|
message := ""
|
|
if len(call.Arguments) > 3 && !goja.IsUndefined(call.Argument(3)) && !goja.IsNull(call.Argument(3)) {
|
|
message = call.Argument(3).String()
|
|
}
|
|
// arg4 = hook (optional)
|
|
// arg5 = handler (optional)
|
|
|
|
var postHookFn goja.Callable
|
|
var handlerFn goja.Callable
|
|
|
|
if len(call.Arguments) > 4 && !goja.IsUndefined(call.Argument(4)) && !goja.IsNull(call.Argument(4)) {
|
|
fn, ok := goja.AssertFunction(call.Argument(4))
|
|
if ok {
|
|
postHookFn = fn
|
|
}
|
|
}
|
|
if len(call.Arguments) > 5 && !goja.IsUndefined(call.Argument(5)) && !goja.IsNull(call.Argument(5)) {
|
|
fn, ok := goja.AssertFunction(call.Argument(5))
|
|
if ok {
|
|
handlerFn = fn
|
|
}
|
|
}
|
|
|
|
err := engine.manager.ExecuteAliasWithHooks(engine, agentId, displayCmdline, aliasCmdline, message, postHookFn, handlerFn)
|
|
if err != nil {
|
|
panic(rt.NewGoError(err))
|
|
}
|
|
|
|
return goja.Undefined()
|
|
})
|
|
|
|
axObj.Set("execute_alias_hook", func(call goja.FunctionCall) goja.Value {
|
|
if engine.manager == nil {
|
|
panic(rt.NewTypeError("execute_alias_hook: script manager not available"))
|
|
}
|
|
if len(call.Arguments) < 5 {
|
|
panic(rt.NewTypeError("execute_alias_hook requires 5 arguments"))
|
|
}
|
|
agentId := call.Argument(0).String()
|
|
displayCmdline := call.Argument(1).String()
|
|
aliasCmdline := call.Argument(2).String()
|
|
message := ""
|
|
if len(call.Arguments) > 3 && !goja.IsUndefined(call.Argument(3)) && !goja.IsNull(call.Argument(3)) {
|
|
message = call.Argument(3).String()
|
|
}
|
|
var hookFn goja.Callable
|
|
if fn, ok := goja.AssertFunction(call.Argument(4)); ok {
|
|
hookFn = fn
|
|
}
|
|
err := engine.manager.ExecuteAliasWithHooks(engine, agentId, displayCmdline, aliasCmdline, message, hookFn, nil)
|
|
if err != nil {
|
|
panic(rt.NewGoError(err))
|
|
}
|
|
return goja.Undefined()
|
|
})
|
|
|
|
axObj.Set("execute_alias_handler", func(call goja.FunctionCall) goja.Value {
|
|
if engine.manager == nil {
|
|
panic(rt.NewTypeError("execute_alias_handler: script manager not available"))
|
|
}
|
|
if len(call.Arguments) < 5 {
|
|
panic(rt.NewTypeError("execute_alias_handler requires 5 arguments"))
|
|
}
|
|
agentId := call.Argument(0).String()
|
|
displayCmdline := call.Argument(1).String()
|
|
aliasCmdline := call.Argument(2).String()
|
|
message := ""
|
|
if len(call.Arguments) > 3 && !goja.IsUndefined(call.Argument(3)) && !goja.IsNull(call.Argument(3)) {
|
|
message = call.Argument(3).String()
|
|
}
|
|
var handlerFn goja.Callable
|
|
if fn, ok := goja.AssertFunction(call.Argument(4)); ok {
|
|
handlerFn = fn
|
|
}
|
|
err := engine.manager.ExecuteAliasWithHooks(engine, agentId, displayCmdline, aliasCmdline, message, nil, handlerFn)
|
|
if err != nil {
|
|
panic(rt.NewGoError(err))
|
|
}
|
|
return goja.Undefined()
|
|
})
|
|
|
|
axObj.Set("agents", func(call goja.FunctionCall) goja.Value {
|
|
if engine.manager == nil {
|
|
return rt.ToValue(map[string]interface{}{})
|
|
}
|
|
agents := engine.manager.GetAgents()
|
|
return rt.ToValue(agents)
|
|
})
|
|
|
|
axObj.Set("agent_info", func(call goja.FunctionCall) goja.Value {
|
|
if engine.manager == nil || len(call.Arguments) < 2 {
|
|
return goja.Undefined()
|
|
}
|
|
agentId := call.Argument(0).String()
|
|
property := call.Argument(1).String()
|
|
info := engine.manager.GetAgentInfo(agentId, property)
|
|
if info == nil {
|
|
return goja.Undefined()
|
|
}
|
|
return rt.ToValue(info)
|
|
})
|
|
|
|
axObj.Set("ids", func(call goja.FunctionCall) goja.Value {
|
|
if engine.manager == nil {
|
|
return rt.ToValue([]string{})
|
|
}
|
|
return rt.ToValue(engine.manager.GetAgentIds())
|
|
})
|
|
|
|
axObj.Set("credentials", func(call goja.FunctionCall) goja.Value {
|
|
if engine.manager == nil {
|
|
return rt.ToValue([]interface{}{})
|
|
}
|
|
return rt.ToValue(engine.manager.GetCredentials())
|
|
})
|
|
|
|
axObj.Set("targets", func(call goja.FunctionCall) goja.Value {
|
|
if engine.manager == nil {
|
|
return rt.ToValue([]interface{}{})
|
|
}
|
|
return rt.ToValue(engine.manager.GetTargets())
|
|
})
|
|
|
|
axObj.Set("console_message", func(call goja.FunctionCall) goja.Value {
|
|
if engine.manager == nil || len(call.Arguments) < 3 {
|
|
return goja.Undefined()
|
|
}
|
|
agentId := call.Argument(0).String()
|
|
msgType := int(call.Argument(1).ToInteger())
|
|
message := call.Argument(2).String()
|
|
clearText := ""
|
|
if len(call.Arguments) > 3 {
|
|
clearText = call.Argument(3).String()
|
|
}
|
|
engine.manager.ConsoleMessage(agentId, msgType, message, clearText)
|
|
return goja.Undefined()
|
|
})
|
|
|
|
axObj.Set("log", func(call goja.FunctionCall) goja.Value {
|
|
if len(call.Arguments) > 0 {
|
|
logs.Info("", "[%s] %s", engine.name, call.Argument(0).String())
|
|
}
|
|
return goja.Undefined()
|
|
})
|
|
|
|
axObj.Set("log_error", func(call goja.FunctionCall) goja.Value {
|
|
if len(call.Arguments) > 0 {
|
|
logs.Error("", "[%s] %s", engine.name, call.Argument(0).String())
|
|
}
|
|
return goja.Undefined()
|
|
})
|
|
|
|
axObj.Set("execute_command_hook", func(call goja.FunctionCall) goja.Value {
|
|
if engine.manager == nil || len(call.Arguments) < 3 {
|
|
return goja.Undefined()
|
|
}
|
|
agentId := call.Argument(0).String()
|
|
cmdline := call.Argument(1).String()
|
|
var hookFn goja.Callable
|
|
if fn, ok := goja.AssertFunction(call.Argument(2)); ok {
|
|
hookFn = fn
|
|
}
|
|
err := engine.manager.ExecuteCommand(engine, agentId, cmdline, hookFn, nil)
|
|
if err != nil {
|
|
panic(rt.NewGoError(err))
|
|
}
|
|
return goja.Undefined()
|
|
})
|
|
|
|
axObj.Set("execute_command_handler", func(call goja.FunctionCall) goja.Value {
|
|
if engine.manager == nil || len(call.Arguments) < 3 {
|
|
return goja.Undefined()
|
|
}
|
|
agentId := call.Argument(0).String()
|
|
cmdline := call.Argument(1).String()
|
|
var handlerFn goja.Callable
|
|
if fn, ok := goja.AssertFunction(call.Argument(2)); ok {
|
|
handlerFn = fn
|
|
}
|
|
err := engine.manager.ExecuteCommand(engine, agentId, cmdline, nil, handlerFn)
|
|
if err != nil {
|
|
panic(rt.NewGoError(err))
|
|
}
|
|
return goja.Undefined()
|
|
})
|
|
|
|
axObj.Set("register_commands_group", func(call goja.FunctionCall) goja.Value {
|
|
if engine.manager == nil || len(call.Arguments) < 2 {
|
|
return goja.Undefined()
|
|
}
|
|
|
|
groupVal := call.Argument(0)
|
|
agentsVal := call.Argument(1)
|
|
|
|
var groupBuilder *jsCommandGroupBuilder
|
|
|
|
if exported := groupVal.Export(); exported != nil {
|
|
if gb, ok := exported.(*jsCommandGroupBuilder); ok {
|
|
groupBuilder = gb
|
|
} else if m, ok := exported.(map[string]interface{}); ok {
|
|
if gv, exists := m["__group"]; exists {
|
|
if gb2, ok2 := gv.(*jsCommandGroupBuilder); ok2 {
|
|
groupBuilder = gb2
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if groupBuilder == nil {
|
|
groupObj := groupVal.ToObject(rt)
|
|
gv := groupObj.Get("__group")
|
|
if gv != nil && !goja.IsUndefined(gv) && !goja.IsNull(gv) {
|
|
if gb, ok := gv.Export().(*jsCommandGroupBuilder); ok {
|
|
groupBuilder = gb
|
|
}
|
|
}
|
|
}
|
|
|
|
if groupBuilder == nil {
|
|
logs.Warn("", "register_commands_group: invalid group object")
|
|
return goja.Undefined()
|
|
}
|
|
|
|
metaVal := rt.Get("metadata")
|
|
if metaVal != nil && !goja.IsUndefined(metaVal) && !goja.IsNull(metaVal) {
|
|
metaObj := metaVal.ToObject(rt)
|
|
if groupBuilder.name == "" {
|
|
nameVal := metaObj.Get("name")
|
|
if nameVal != nil && !goja.IsUndefined(nameVal) && !goja.IsNull(nameVal) {
|
|
groupBuilder.name = nameVal.String()
|
|
}
|
|
}
|
|
if groupBuilder.description == "" {
|
|
descVal := metaObj.Get("description")
|
|
if descVal != nil && !goja.IsUndefined(descVal) && !goja.IsNull(descVal) {
|
|
groupBuilder.description = descVal.String()
|
|
}
|
|
}
|
|
}
|
|
|
|
agentNames := exportStringArray(rt, agentsVal)
|
|
|
|
var osList []int
|
|
if len(call.Arguments) > 2 {
|
|
osStrings := exportStringArray(rt, call.Argument(2))
|
|
for _, s := range osStrings {
|
|
if v := OsFromString(s); v != 0 {
|
|
osList = append(osList, v)
|
|
}
|
|
}
|
|
}
|
|
if len(osList) == 0 {
|
|
osList = []int{OsWindows, OsLinux, OsMac}
|
|
}
|
|
|
|
var listenerTypes []string
|
|
if len(call.Arguments) > 3 {
|
|
listenerTypes = exportStringArray(rt, call.Argument(3))
|
|
}
|
|
if len(listenerTypes) == 0 {
|
|
listenerTypes = []string{""}
|
|
}
|
|
|
|
var sourceType SourceType
|
|
if strings.HasPrefix(engine.name, "user:") {
|
|
sourceType = SourceUser
|
|
} else {
|
|
sourceType = SourceProfile
|
|
}
|
|
|
|
scriptName := engine.GetMetadataName()
|
|
if scriptName == "" {
|
|
scriptName = filepath.Base(engine.scriptPath)
|
|
}
|
|
|
|
for _, agentName := range agentNames {
|
|
group := groupBuilder.ToCommandGroup(scriptName)
|
|
for _, listener := range listenerTypes {
|
|
for _, osType := range osList {
|
|
engine.manager.CommandStore.RegisterGroups(sourceType, agentName, listener, osType, []CommandGroup{group}, engine)
|
|
}
|
|
}
|
|
}
|
|
|
|
return goja.Undefined()
|
|
})
|
|
|
|
axObj.Set("execute_browser", func(call goja.FunctionCall) goja.Value {
|
|
return goja.Undefined()
|
|
})
|
|
|
|
// --- Script management ---
|
|
|
|
axObj.Set("script_dir", func(call goja.FunctionCall) goja.Value {
|
|
return rt.ToValue(engine.scriptDir)
|
|
})
|
|
|
|
axObj.Set("script_load", func(call goja.FunctionCall) goja.Value {
|
|
if engine.manager == nil || len(call.Arguments) == 0 {
|
|
return goja.Undefined()
|
|
}
|
|
path := call.Argument(0).String()
|
|
err := engine.manager.LoadAxScriptChild(engine, path)
|
|
if err != nil {
|
|
logs.Error("", "script_load error: %v", err)
|
|
panic(rt.NewGoError(err))
|
|
}
|
|
return goja.Undefined()
|
|
})
|
|
|
|
axObj.Set("script_import", func(call goja.FunctionCall) goja.Value {
|
|
if engine.manager == nil || len(call.Arguments) == 0 {
|
|
return goja.Undefined()
|
|
}
|
|
path := call.Argument(0).String()
|
|
absPath, err := engine.manager.ImportAxScript(engine, path)
|
|
if err != nil {
|
|
logs.Error("", "script_import error: %v", err)
|
|
panic(rt.NewGoError(err))
|
|
}
|
|
engine.AddImportedFile(absPath)
|
|
return goja.Undefined()
|
|
})
|
|
|
|
axObj.Set("script_unload", func(call goja.FunctionCall) goja.Value {
|
|
if engine.manager == nil || len(call.Arguments) == 0 {
|
|
return goja.Undefined()
|
|
}
|
|
name := call.Argument(0).String()
|
|
err := engine.manager.UnloadAxScript(name)
|
|
if err != nil {
|
|
logs.Warn("", "script_unload error: %v", err)
|
|
}
|
|
return goja.Undefined()
|
|
})
|
|
|
|
// --- BOF support ---
|
|
|
|
axObj.Set("bof_pack", func(call goja.FunctionCall) goja.Value {
|
|
if len(call.Arguments) < 2 {
|
|
panic(rt.NewTypeError("bof_pack requires 2 arguments: (types, args)"))
|
|
}
|
|
types := call.Argument(0).String()
|
|
argsVal := call.Argument(1)
|
|
|
|
argsObj := argsVal.ToObject(rt)
|
|
lengthVal := argsObj.Get("length")
|
|
if lengthVal == nil || goja.IsUndefined(lengthVal) {
|
|
panic(rt.NewTypeError("bof_pack: args must be an array"))
|
|
}
|
|
arrLen := int(lengthVal.ToInteger())
|
|
|
|
items := strings.Split(types, ",")
|
|
for i := range items {
|
|
items[i] = strings.TrimSpace(items[i])
|
|
}
|
|
|
|
if len(items) != arrLen {
|
|
panic(rt.NewTypeError("bof_pack: types count must match args count"))
|
|
}
|
|
|
|
var data []byte
|
|
|
|
for i := 0; i < arrLen; i++ {
|
|
val := argsObj.Get(fmt.Sprintf("%d", i))
|
|
switch items[i] {
|
|
case "cstr":
|
|
s := val.String()
|
|
b := []byte(s)
|
|
b = append(b, 0)
|
|
l := uint32(len(b))
|
|
lb := make([]byte, 4)
|
|
binary.LittleEndian.PutUint32(lb, l)
|
|
data = append(data, lb...)
|
|
data = append(data, b...)
|
|
case "wstr":
|
|
s := val.String()
|
|
runes := utf16.Encode([]rune(s))
|
|
runes = append(runes, 0)
|
|
byteLen := uint32(len(runes) * 2)
|
|
lb := make([]byte, 4)
|
|
binary.LittleEndian.PutUint32(lb, byteLen)
|
|
data = append(data, lb...)
|
|
for _, r := range runes {
|
|
rb := make([]byte, 2)
|
|
binary.LittleEndian.PutUint16(rb, r)
|
|
data = append(data, rb...)
|
|
}
|
|
case "bytes":
|
|
s := val.String()
|
|
decoded, err := base64.StdEncoding.DecodeString(s)
|
|
if err != nil {
|
|
decoded = []byte{}
|
|
}
|
|
l := uint32(len(decoded))
|
|
lb := make([]byte, 4)
|
|
binary.LittleEndian.PutUint32(lb, l)
|
|
data = append(data, lb...)
|
|
data = append(data, decoded...)
|
|
case "int":
|
|
n := int32(val.ToInteger())
|
|
nb := make([]byte, 4)
|
|
binary.LittleEndian.PutUint32(nb, uint32(n))
|
|
data = append(data, nb...)
|
|
case "short":
|
|
n := int16(val.ToInteger())
|
|
nb := make([]byte, 2)
|
|
binary.LittleEndian.PutUint16(nb, uint16(n))
|
|
data = append(data, nb...)
|
|
default:
|
|
panic(rt.NewTypeError(fmt.Sprintf("bof_pack: unknown type '%s'", items[i])))
|
|
}
|
|
}
|
|
|
|
// Prepend total length
|
|
totalLen := uint32(len(data))
|
|
header := make([]byte, 4)
|
|
binary.LittleEndian.PutUint32(header, totalLen)
|
|
result := append(header, data...)
|
|
|
|
return rt.ToValue(base64.StdEncoding.EncodeToString(result))
|
|
})
|
|
|
|
axObj.Set("arch", func(call goja.FunctionCall) goja.Value {
|
|
if engine.manager == nil || len(call.Arguments) == 0 {
|
|
return rt.ToValue("x86")
|
|
}
|
|
agentId := call.Argument(0).String()
|
|
info := engine.manager.GetAgentInfo(agentId, "arch")
|
|
if info == nil {
|
|
return rt.ToValue("x86")
|
|
}
|
|
if s, ok := info.(string); ok {
|
|
return rt.ToValue(s)
|
|
}
|
|
return rt.ToValue("x86")
|
|
})
|
|
|
|
axObj.Set("is64", func(call goja.FunctionCall) goja.Value {
|
|
if engine.manager == nil || len(call.Arguments) == 0 {
|
|
return rt.ToValue(false)
|
|
}
|
|
agentId := call.Argument(0).String()
|
|
info := engine.manager.GetAgentInfo(agentId, "arch")
|
|
if s, ok := info.(string); ok {
|
|
return rt.ToValue(s == "x64")
|
|
}
|
|
return rt.ToValue(false)
|
|
})
|
|
|
|
axObj.Set("isactive", func(call goja.FunctionCall) goja.Value {
|
|
if engine.manager == nil || len(call.Arguments) == 0 {
|
|
return rt.ToValue(false)
|
|
}
|
|
agentId := call.Argument(0).String()
|
|
info := engine.manager.GetAgentInfo(agentId, "id")
|
|
if info == nil {
|
|
return rt.ToValue(false)
|
|
}
|
|
mark := engine.manager.GetAgentMark(agentId)
|
|
if mark == "Terminated" || mark == "Disconnect" || mark == "Inactive" || mark == "Unlink" {
|
|
return rt.ToValue(false)
|
|
}
|
|
return rt.ToValue(true)
|
|
})
|
|
|
|
axObj.Set("isadmin", func(call goja.FunctionCall) goja.Value {
|
|
if engine.manager == nil || len(call.Arguments) == 0 {
|
|
return rt.ToValue(false)
|
|
}
|
|
agentId := call.Argument(0).String()
|
|
info := engine.manager.GetAgentInfo(agentId, "elevated")
|
|
if b, ok := info.(bool); ok {
|
|
return rt.ToValue(b)
|
|
}
|
|
return rt.ToValue(false)
|
|
})
|
|
|
|
// --- Credentials & Targets ---
|
|
|
|
axObj.Set("credentials_add", func(call goja.FunctionCall) goja.Value {
|
|
if engine.manager == nil || engine.manager.teamserver == nil {
|
|
return goja.Undefined()
|
|
}
|
|
cred := make(map[string]interface{})
|
|
if len(call.Arguments) > 0 {
|
|
cred["username"] = call.Argument(0).String()
|
|
}
|
|
if len(call.Arguments) > 1 {
|
|
cred["password"] = call.Argument(1).String()
|
|
}
|
|
if len(call.Arguments) > 2 {
|
|
cred["realm"] = call.Argument(2).String()
|
|
}
|
|
if len(call.Arguments) > 3 {
|
|
cred["type"] = call.Argument(3).String()
|
|
}
|
|
if len(call.Arguments) > 4 {
|
|
cred["tag"] = call.Argument(4).String()
|
|
}
|
|
if len(call.Arguments) > 5 {
|
|
cred["storage"] = call.Argument(5).String()
|
|
}
|
|
if len(call.Arguments) > 6 {
|
|
cred["host"] = call.Argument(6).String()
|
|
}
|
|
_ = engine.manager.teamserver.AxCredentialsAdd([]map[string]interface{}{cred})
|
|
return goja.Undefined()
|
|
})
|
|
|
|
axObj.Set("credentials_add_list", func(call goja.FunctionCall) goja.Value {
|
|
if engine.manager == nil || engine.manager.teamserver == nil || len(call.Arguments) == 0 {
|
|
return goja.Undefined()
|
|
}
|
|
exported := call.Argument(0).Export()
|
|
arr, ok := exported.([]interface{})
|
|
if !ok {
|
|
return goja.Undefined()
|
|
}
|
|
var creds []map[string]interface{}
|
|
for _, item := range arr {
|
|
if m, ok := item.(map[string]interface{}); ok {
|
|
creds = append(creds, m)
|
|
}
|
|
}
|
|
if len(creds) > 0 {
|
|
_ = engine.manager.teamserver.AxCredentialsAdd(creds)
|
|
}
|
|
return goja.Undefined()
|
|
})
|
|
|
|
axObj.Set("targets_add", func(call goja.FunctionCall) goja.Value {
|
|
if engine.manager == nil || engine.manager.teamserver == nil {
|
|
return goja.Undefined()
|
|
}
|
|
target := make(map[string]interface{})
|
|
if len(call.Arguments) > 0 {
|
|
target["computer"] = call.Argument(0).String()
|
|
}
|
|
if len(call.Arguments) > 1 {
|
|
target["domain"] = call.Argument(1).String()
|
|
}
|
|
if len(call.Arguments) > 2 {
|
|
target["address"] = call.Argument(2).String()
|
|
}
|
|
if len(call.Arguments) > 3 {
|
|
target["os"] = call.Argument(3).String()
|
|
}
|
|
if len(call.Arguments) > 4 {
|
|
target["os_desc"] = call.Argument(4).String()
|
|
}
|
|
if len(call.Arguments) > 5 {
|
|
target["tag"] = call.Argument(5).String()
|
|
}
|
|
if len(call.Arguments) > 6 {
|
|
target["info"] = call.Argument(6).String()
|
|
}
|
|
if len(call.Arguments) > 7 {
|
|
target["alive"] = call.Argument(7).ToBoolean()
|
|
}
|
|
_ = engine.manager.teamserver.AxTargetsAdd([]map[string]interface{}{target})
|
|
return goja.Undefined()
|
|
})
|
|
|
|
axObj.Set("targets_add_list", func(call goja.FunctionCall) goja.Value {
|
|
if engine.manager == nil || engine.manager.teamserver == nil || len(call.Arguments) == 0 {
|
|
return goja.Undefined()
|
|
}
|
|
exported := call.Argument(0).Export()
|
|
arr, ok := exported.([]interface{})
|
|
if !ok {
|
|
return goja.Undefined()
|
|
}
|
|
var targets []map[string]interface{}
|
|
for _, item := range arr {
|
|
if m, ok := item.(map[string]interface{}); ok {
|
|
targets = append(targets, m)
|
|
}
|
|
}
|
|
if len(targets) > 0 {
|
|
_ = engine.manager.teamserver.AxTargetsAdd(targets)
|
|
}
|
|
return goja.Undefined()
|
|
})
|
|
|
|
// --- File operations (sandboxed) ---
|
|
|
|
axObj.Set("file_basename", func(call goja.FunctionCall) goja.Value {
|
|
if len(call.Arguments) == 0 {
|
|
return rt.ToValue("")
|
|
}
|
|
return rt.ToValue(fileBasename(call.Argument(0).String()))
|
|
})
|
|
|
|
axObj.Set("file_dirname", func(call goja.FunctionCall) goja.Value {
|
|
if len(call.Arguments) == 0 {
|
|
return rt.ToValue("")
|
|
}
|
|
return rt.ToValue(filepath.Dir(call.Argument(0).String()))
|
|
})
|
|
|
|
axObj.Set("file_extension", func(call goja.FunctionCall) goja.Value {
|
|
if len(call.Arguments) == 0 {
|
|
return rt.ToValue("")
|
|
}
|
|
ext := filepath.Ext(call.Argument(0).String())
|
|
if len(ext) > 0 {
|
|
ext = ext[1:] // remove leading dot
|
|
}
|
|
return rt.ToValue(ext)
|
|
})
|
|
|
|
axObj.Set("file_exists", func(call goja.FunctionCall) goja.Value {
|
|
if len(call.Arguments) == 0 {
|
|
return rt.ToValue(false)
|
|
}
|
|
path := call.Argument(0).String()
|
|
_, err := engine.ValidatePath(path)
|
|
if err != nil {
|
|
return rt.ToValue(false)
|
|
}
|
|
_, err = os.Stat(path)
|
|
return rt.ToValue(err == nil)
|
|
})
|
|
|
|
axObj.Set("file_read", func(call goja.FunctionCall) goja.Value {
|
|
if engine.manager == nil || len(call.Arguments) == 0 {
|
|
return rt.ToValue("")
|
|
}
|
|
path := call.Argument(0).String()
|
|
data, err := engine.manager.ReadFileSandboxed(engine, path)
|
|
if err != nil {
|
|
return rt.ToValue("")
|
|
}
|
|
return rt.ToValue(base64.StdEncoding.EncodeToString(data))
|
|
})
|
|
|
|
axObj.Set("file_size", func(call goja.FunctionCall) goja.Value {
|
|
if len(call.Arguments) == 0 {
|
|
return rt.ToValue(0)
|
|
}
|
|
path := call.Argument(0).String()
|
|
validated, err := engine.ValidatePath(path)
|
|
if err != nil {
|
|
return rt.ToValue(0)
|
|
}
|
|
info, err := os.Stat(validated)
|
|
if err != nil {
|
|
return rt.ToValue(0)
|
|
}
|
|
return rt.ToValue(info.Size())
|
|
})
|
|
|
|
axObj.Set("file_write", func(call goja.FunctionCall) goja.Value {
|
|
logs.Warn("", "file_write is disabled on server")
|
|
return rt.ToValue(false)
|
|
})
|
|
|
|
axObj.Set("file_write_text", func(call goja.FunctionCall) goja.Value {
|
|
logs.Warn("", "file_write_text is disabled on server")
|
|
return rt.ToValue(false)
|
|
|
|
// if engine.manager == nil || len(call.Arguments) < 2 {
|
|
// return rt.ToValue(false)
|
|
// }
|
|
// path := call.Argument(0).String()
|
|
// content := call.Argument(1).String()
|
|
// appendMode := false
|
|
// if len(call.Arguments) > 2 {
|
|
// appendMode = call.Argument(2).ToBoolean()
|
|
// }
|
|
// err := engine.manager.WriteFileSandboxed(engine, path, []byte(content), appendMode)
|
|
// if err != nil {
|
|
// logs.Warn("", "file_write_text error: %v", err)
|
|
// return rt.ToValue(false)
|
|
// }
|
|
// return rt.ToValue(true)
|
|
})
|
|
|
|
axObj.Set("file_write_binary", func(call goja.FunctionCall) goja.Value {
|
|
logs.Warn("", "file_write_binary is disabled on server")
|
|
return rt.ToValue(false)
|
|
|
|
// if engine.manager == nil || len(call.Arguments) < 2 {
|
|
// return rt.ToValue(false)
|
|
// }
|
|
// path := call.Argument(0).String()
|
|
// b64Content := call.Argument(1).String()
|
|
// data, err := base64.StdEncoding.DecodeString(b64Content)
|
|
// if err != nil {
|
|
// logs.Warn("", "file_write_binary: invalid base64: %v", err)
|
|
// return rt.ToValue(false)
|
|
// }
|
|
// err = engine.manager.WriteFileSandboxed(engine, path, data, false)
|
|
// if err != nil {
|
|
// logs.Warn("", "file_write_binary error: %v", err)
|
|
// return rt.ToValue(false)
|
|
// }
|
|
// return rt.ToValue(true)
|
|
})
|
|
|
|
// --- Agent management ---
|
|
|
|
axObj.Set("agent_hide", func(call goja.FunctionCall) goja.Value {
|
|
return goja.Undefined() // client-only UI operation
|
|
})
|
|
|
|
axObj.Set("agent_remove", func(call goja.FunctionCall) goja.Value {
|
|
if engine.manager == nil || engine.manager.teamserver == nil || len(call.Arguments) == 0 {
|
|
return goja.Undefined()
|
|
}
|
|
ids := exportStringArray(rt, call.Argument(0))
|
|
if len(ids) > 0 {
|
|
_ = engine.manager.teamserver.AxAgentRemove(ids)
|
|
}
|
|
return goja.Undefined()
|
|
})
|
|
|
|
axObj.Set("agent_set_color", func(call goja.FunctionCall) goja.Value {
|
|
if engine.manager == nil || engine.manager.teamserver == nil || len(call.Arguments) < 2 {
|
|
return goja.Undefined()
|
|
}
|
|
ids := exportStringArray(rt, call.Argument(0))
|
|
bg := call.Argument(1).String()
|
|
fg := ""
|
|
if len(call.Arguments) > 2 {
|
|
fg = call.Argument(2).String()
|
|
}
|
|
reset := false
|
|
if len(call.Arguments) > 3 {
|
|
reset = call.Argument(3).ToBoolean()
|
|
}
|
|
_ = engine.manager.teamserver.AxAgentSetColor(ids, bg, fg, reset)
|
|
return goja.Undefined()
|
|
})
|
|
|
|
axObj.Set("agent_set_impersonate", func(call goja.FunctionCall) goja.Value {
|
|
if engine.manager == nil || engine.manager.teamserver == nil || len(call.Arguments) < 2 {
|
|
return goja.Undefined()
|
|
}
|
|
agentId := call.Argument(0).String()
|
|
impersonate := call.Argument(1).String()
|
|
elevated := false
|
|
if len(call.Arguments) > 2 {
|
|
elevated = call.Argument(2).ToBoolean()
|
|
}
|
|
updateData := map[string]interface{}{}
|
|
if elevated {
|
|
updateData["impersonated"] = impersonate + " *"
|
|
} else {
|
|
updateData["impersonated"] = impersonate
|
|
}
|
|
_ = engine.manager.teamserver.AxAgentUpdateData(agentId, updateData)
|
|
return goja.Undefined()
|
|
})
|
|
|
|
axObj.Set("agent_set_mark", func(call goja.FunctionCall) goja.Value {
|
|
if engine.manager == nil || engine.manager.teamserver == nil || len(call.Arguments) < 2 {
|
|
return goja.Undefined()
|
|
}
|
|
ids := exportStringArray(rt, call.Argument(0))
|
|
mark := call.Argument(1).String()
|
|
_ = engine.manager.teamserver.AxAgentSetMark(ids, mark)
|
|
return goja.Undefined()
|
|
})
|
|
|
|
axObj.Set("agent_set_tag", func(call goja.FunctionCall) goja.Value {
|
|
if engine.manager == nil || engine.manager.teamserver == nil || len(call.Arguments) < 2 {
|
|
return goja.Undefined()
|
|
}
|
|
ids := exportStringArray(rt, call.Argument(0))
|
|
tag := call.Argument(1).String()
|
|
_ = engine.manager.teamserver.AxAgentSetTag(ids, tag)
|
|
return goja.Undefined()
|
|
})
|
|
|
|
axObj.Set("agent_update_data", func(call goja.FunctionCall) goja.Value {
|
|
if engine.manager == nil || engine.manager.teamserver == nil || len(call.Arguments) < 2 {
|
|
return goja.Undefined()
|
|
}
|
|
agentId := call.Argument(0).String()
|
|
data := call.Argument(1).Export()
|
|
if m, ok := data.(map[string]interface{}); ok {
|
|
_ = engine.manager.teamserver.AxAgentUpdateData(agentId, m)
|
|
}
|
|
return goja.Undefined()
|
|
})
|
|
|
|
// --- Misc ---
|
|
|
|
axObj.Set("ticks", func(call goja.FunctionCall) goja.Value {
|
|
return rt.ToValue(time.Now().Unix())
|
|
})
|
|
|
|
axObj.Set("format_time", func(call goja.FunctionCall) goja.Value {
|
|
if len(call.Arguments) < 2 {
|
|
return rt.ToValue("")
|
|
}
|
|
format := call.Argument(0).String()
|
|
unixTime := call.Argument(1).ToInteger()
|
|
t := time.Unix(unixTime, 0)
|
|
// Convert Qt-style format to Go format
|
|
goFmt := convertQtFormatToGo(format)
|
|
return rt.ToValue(t.Format(goFmt))
|
|
})
|
|
|
|
axObj.Set("validate_command", func(call goja.FunctionCall) goja.Value {
|
|
if engine.manager == nil || len(call.Arguments) < 2 {
|
|
return rt.ToValue(map[string]interface{}{"valid": false, "message": "missing arguments"})
|
|
}
|
|
agentId := call.Argument(0).String()
|
|
cmdline := call.Argument(1).String()
|
|
result, err := engine.manager.ValidateCommand(agentId, cmdline)
|
|
if err != nil {
|
|
return rt.ToValue(map[string]interface{}{"valid": false, "message": err.Error()})
|
|
}
|
|
return rt.ToValue(result)
|
|
})
|
|
|
|
axObj.Set("service_command", func(call goja.FunctionCall) goja.Value {
|
|
// Service calls are handled differently on server; no-op for now
|
|
return goja.Undefined()
|
|
})
|
|
|
|
axObj.Set("show_message", func(call goja.FunctionCall) goja.Value {
|
|
if len(call.Arguments) >= 2 {
|
|
logs.Info("", "[%s] Message: %s - %s", engine.name, call.Argument(0).String(), call.Argument(1).String())
|
|
}
|
|
return goja.Undefined()
|
|
})
|
|
|
|
axObj.Set("get_project", func(call goja.FunctionCall) goja.Value {
|
|
return rt.ToValue("")
|
|
})
|
|
|
|
axObj.Set("downloads", func(call goja.FunctionCall) goja.Value {
|
|
if engine.manager == nil {
|
|
return rt.ToValue([]interface{}{})
|
|
}
|
|
return rt.ToValue(engine.manager.GetDownloads())
|
|
})
|
|
|
|
axObj.Set("screenshots", func(call goja.FunctionCall) goja.Value {
|
|
if engine.manager == nil {
|
|
return rt.ToValue([]interface{}{})
|
|
}
|
|
return rt.ToValue(engine.manager.GetScreenshots())
|
|
})
|
|
|
|
axObj.Set("tunnels", func(call goja.FunctionCall) goja.Value {
|
|
if engine.manager == nil {
|
|
return rt.ToValue([]interface{}{})
|
|
}
|
|
return rt.ToValue(engine.manager.GetTunnels())
|
|
})
|
|
|
|
axObj.Set("copy_to_clipboard", func(call goja.FunctionCall) goja.Value { return goja.Undefined() })
|
|
|
|
registerAxUtilities(axObj, rt, engine)
|
|
|
|
rt.Set("ax", axObj)
|
|
}
|
|
|
|
func exportStringArray(rt *goja.Runtime, val goja.Value) []string {
|
|
if val == nil || goja.IsUndefined(val) || goja.IsNull(val) {
|
|
return nil
|
|
}
|
|
exported := val.Export()
|
|
if arr, ok := exported.([]interface{}); ok {
|
|
var result []string
|
|
for _, item := range arr {
|
|
if s, ok := item.(string); ok {
|
|
result = append(result, s)
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func convertQtFormatToGo(qtFmt string) string {
|
|
r := strings.NewReplacer(
|
|
"yyyy", "2006", "yy", "06",
|
|
"MM", "01", "M", "1",
|
|
"dd", "02", "d", "2",
|
|
"HH", "15", "hh", "03", "h", "3",
|
|
"mm", "04", "m", "4",
|
|
"ss", "05", "s", "5",
|
|
"AP", "PM", "ap", "pm",
|
|
)
|
|
return r.Replace(qtFmt)
|
|
}
|
|
|
|
func registerAxUtilities(axObj *goja.Object, rt *goja.Runtime, engine *ScriptEngine) {
|
|
|
|
axObj.Set("base64_encode", func(call goja.FunctionCall) goja.Value {
|
|
if len(call.Arguments) == 0 {
|
|
return rt.ToValue("")
|
|
}
|
|
data := call.Argument(0).String()
|
|
return rt.ToValue(base64.StdEncoding.EncodeToString([]byte(data)))
|
|
})
|
|
|
|
axObj.Set("base64_decode", func(call goja.FunctionCall) goja.Value {
|
|
if len(call.Arguments) == 0 {
|
|
return rt.ToValue("")
|
|
}
|
|
data := call.Argument(0).String()
|
|
decoded, err := base64.StdEncoding.DecodeString(data)
|
|
if err != nil {
|
|
return rt.ToValue("")
|
|
}
|
|
return rt.ToValue(string(decoded))
|
|
})
|
|
|
|
axObj.Set("hex_encode", func(call goja.FunctionCall) goja.Value {
|
|
if len(call.Arguments) == 0 {
|
|
return rt.ToValue("")
|
|
}
|
|
data := call.Argument(0).String()
|
|
return rt.ToValue(hex.EncodeToString([]byte(data)))
|
|
})
|
|
|
|
axObj.Set("hex_decode", func(call goja.FunctionCall) goja.Value {
|
|
if len(call.Arguments) == 0 {
|
|
return rt.ToValue("")
|
|
}
|
|
data := call.Argument(0).String()
|
|
decoded, err := hex.DecodeString(data)
|
|
if err != nil {
|
|
return rt.ToValue("")
|
|
}
|
|
return rt.ToValue(string(decoded))
|
|
})
|
|
|
|
axObj.Set("hash", func(call goja.FunctionCall) goja.Value {
|
|
if len(call.Arguments) < 2 {
|
|
return rt.ToValue("")
|
|
}
|
|
algorithm := strings.ToLower(call.Argument(0).String())
|
|
input := call.Argument(1).String()
|
|
|
|
var result string
|
|
switch algorithm {
|
|
case "md5":
|
|
h := md5.Sum([]byte(input))
|
|
result = hex.EncodeToString(h[:])
|
|
case "sha1":
|
|
h := sha1.Sum([]byte(input))
|
|
result = hex.EncodeToString(h[:])
|
|
case "sha256":
|
|
h := sha256.Sum256([]byte(input))
|
|
result = hex.EncodeToString(h[:])
|
|
case "sha512":
|
|
h := sha512.Sum512([]byte(input))
|
|
result = hex.EncodeToString(h[:])
|
|
default:
|
|
result = ""
|
|
}
|
|
|
|
length := 0
|
|
if len(call.Arguments) > 2 {
|
|
length = int(call.Argument(2).ToInteger())
|
|
}
|
|
if length > 0 && length < len(result) {
|
|
result = result[:length]
|
|
}
|
|
|
|
return rt.ToValue(result)
|
|
})
|
|
|
|
axObj.Set("random_string", func(call goja.FunctionCall) goja.Value {
|
|
length := 8
|
|
charset := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
|
if len(call.Arguments) > 0 {
|
|
length = int(call.Argument(0).ToInteger())
|
|
}
|
|
if len(call.Arguments) > 1 {
|
|
setName := call.Argument(1).String()
|
|
switch setName {
|
|
case "hex":
|
|
charset = "0123456789abcdef"
|
|
case "alpha":
|
|
charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
case "numeric":
|
|
charset = "0123456789"
|
|
case "lower":
|
|
charset = "abcdefghijklmnopqrstuvwxyz"
|
|
case "upper":
|
|
charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
}
|
|
}
|
|
|
|
b := make([]byte, length)
|
|
for i := range b {
|
|
b[i] = charset[rand.Intn(len(charset))]
|
|
}
|
|
return rt.ToValue(string(b))
|
|
})
|
|
|
|
axObj.Set("random_int", func(call goja.FunctionCall) goja.Value {
|
|
min := 0
|
|
max := 100
|
|
if len(call.Arguments) > 0 {
|
|
min = int(call.Argument(0).ToInteger())
|
|
}
|
|
if len(call.Arguments) > 1 {
|
|
max = int(call.Argument(1).ToInteger())
|
|
}
|
|
if max <= min {
|
|
return rt.ToValue(min)
|
|
}
|
|
return rt.ToValue(min + rand.Intn(max-min))
|
|
})
|
|
|
|
axObj.Set("format_size", func(call goja.FunctionCall) goja.Value {
|
|
if len(call.Arguments) == 0 {
|
|
return rt.ToValue("0 B")
|
|
}
|
|
size := call.Argument(0).ToInteger()
|
|
return rt.ToValue(formatBytes(uint64(size)))
|
|
})
|
|
|
|
axObj.Set("get_commands", func(call goja.FunctionCall) goja.Value {
|
|
if engine.manager == nil || len(call.Arguments) == 0 {
|
|
return rt.ToValue([]interface{}{})
|
|
}
|
|
agentId := call.Argument(0).String()
|
|
names, err := engine.manager.GetCommandNames(agentId)
|
|
if err != nil {
|
|
return rt.ToValue([]interface{}{})
|
|
}
|
|
var result []interface{}
|
|
for _, n := range names {
|
|
result = append(result, n)
|
|
}
|
|
if result == nil {
|
|
return rt.ToValue([]interface{}{})
|
|
}
|
|
return rt.ToValue(result)
|
|
})
|
|
|
|
axObj.Set("interfaces", func(call goja.FunctionCall) goja.Value {
|
|
if engine.manager == nil {
|
|
return rt.ToValue([]interface{}{})
|
|
}
|
|
addrs := engine.manager.GetInterfaces()
|
|
var result []interface{}
|
|
for _, a := range addrs {
|
|
result = append(result, a)
|
|
}
|
|
if result == nil {
|
|
return rt.ToValue([]interface{}{})
|
|
}
|
|
return rt.ToValue(result)
|
|
})
|
|
|
|
axObj.Set("prompt_confirm", func(call goja.FunctionCall) goja.Value {
|
|
return rt.ToValue(false)
|
|
})
|
|
axObj.Set("prompt_open_file", func(call goja.FunctionCall) goja.Value {
|
|
return rt.ToValue("")
|
|
})
|
|
axObj.Set("prompt_open_dir", func(call goja.FunctionCall) goja.Value {
|
|
return rt.ToValue("")
|
|
})
|
|
axObj.Set("prompt_save_file", func(call goja.FunctionCall) goja.Value {
|
|
return rt.ToValue("")
|
|
})
|
|
axObj.Set("clipboard_set", func(call goja.FunctionCall) goja.Value {
|
|
return goja.Undefined()
|
|
})
|
|
axObj.Set("clipboard_get", func(call goja.FunctionCall) goja.Value {
|
|
return rt.ToValue("")
|
|
})
|
|
|
|
axObj.Set("open_agent_console", func(call goja.FunctionCall) goja.Value { return goja.Undefined() })
|
|
axObj.Set("open_access_tunnel", func(call goja.FunctionCall) goja.Value { return goja.Undefined() })
|
|
axObj.Set("open_browser_files", func(call goja.FunctionCall) goja.Value { return goja.Undefined() })
|
|
axObj.Set("open_browser_process", func(call goja.FunctionCall) goja.Value { return goja.Undefined() })
|
|
axObj.Set("open_remote_terminal", func(call goja.FunctionCall) goja.Value { return goja.Undefined() })
|
|
axObj.Set("open_remote_shell", func(call goja.FunctionCall) goja.Value { return goja.Undefined() })
|
|
|
|
axObj.Set("convert_to_code", func(call goja.FunctionCall) goja.Value {
|
|
if len(call.Arguments) < 2 {
|
|
return rt.ToValue("")
|
|
}
|
|
language := strings.ToLower(call.Argument(0).String())
|
|
b64Data := call.Argument(1).String()
|
|
varName := "shellcode"
|
|
if len(call.Arguments) > 2 {
|
|
varName = call.Argument(2).String()
|
|
}
|
|
data, err := base64.StdEncoding.DecodeString(b64Data)
|
|
if err != nil {
|
|
return rt.ToValue("")
|
|
}
|
|
result := bytesToCode(language, data, varName)
|
|
return rt.ToValue(result)
|
|
})
|
|
|
|
axObj.Set("encode_data", func(call goja.FunctionCall) goja.Value {
|
|
if len(call.Arguments) < 2 {
|
|
return rt.ToValue("")
|
|
}
|
|
alg := strings.ToLower(call.Argument(0).String())
|
|
data := call.Argument(1).String()
|
|
key := ""
|
|
if len(call.Arguments) > 2 {
|
|
key = call.Argument(2).String()
|
|
}
|
|
return rt.ToValue(encodeData(alg, []byte(data), key))
|
|
})
|
|
|
|
axObj.Set("decode_data", func(call goja.FunctionCall) goja.Value {
|
|
if len(call.Arguments) < 2 {
|
|
return rt.ToValue("")
|
|
}
|
|
alg := strings.ToLower(call.Argument(0).String())
|
|
data := call.Argument(1).String()
|
|
key := ""
|
|
if len(call.Arguments) > 2 {
|
|
key = call.Argument(2).String()
|
|
}
|
|
return rt.ToValue(decodeData(alg, data, key))
|
|
})
|
|
|
|
axObj.Set("encode_file", func(call goja.FunctionCall) goja.Value {
|
|
if engine.manager == nil || len(call.Arguments) < 2 {
|
|
return rt.ToValue("")
|
|
}
|
|
alg := strings.ToLower(call.Argument(0).String())
|
|
path := call.Argument(1).String()
|
|
key := ""
|
|
if len(call.Arguments) > 2 {
|
|
key = call.Argument(2).String()
|
|
}
|
|
data, err := engine.manager.ReadFileSandboxed(engine, path)
|
|
if err != nil {
|
|
return rt.ToValue("")
|
|
}
|
|
return rt.ToValue(encodeData(alg, data, key))
|
|
})
|
|
|
|
axObj.Set("decode_file", func(call goja.FunctionCall) goja.Value {
|
|
if engine.manager == nil || len(call.Arguments) < 2 {
|
|
return rt.ToValue("")
|
|
}
|
|
alg := strings.ToLower(call.Argument(0).String())
|
|
path := call.Argument(1).String()
|
|
key := ""
|
|
if len(call.Arguments) > 2 {
|
|
key = call.Argument(2).String()
|
|
}
|
|
rawData, err := engine.manager.ReadFileSandboxed(engine, path)
|
|
if err != nil {
|
|
return rt.ToValue("")
|
|
}
|
|
decoded := decodeRawData(alg, rawData, key)
|
|
return rt.ToValue(base64.StdEncoding.EncodeToString(decoded))
|
|
})
|
|
}
|
|
|
|
// /---
|
|
func formatBytes(b uint64) string {
|
|
const unit = 1024
|
|
if b < unit {
|
|
return fmt.Sprintf("%d B", b)
|
|
}
|
|
div, exp := uint64(unit), 0
|
|
for n := b / unit; n >= unit; n /= unit {
|
|
div *= unit
|
|
exp++
|
|
}
|
|
return fmt.Sprintf("%.1f %cB", float64(b)/float64(div), "KMGTPE"[exp])
|
|
}
|