mirror of
https://github.com/projectdiscovery/nuclei.git
synced 2025-12-18 01:35:26 +00:00
117 lines
4.1 KiB
Go
117 lines
4.1 KiB
Go
|
|
package compiler
|
||
|
|
|
||
|
|
import (
|
||
|
|
"fmt"
|
||
|
|
"sync"
|
||
|
|
|
||
|
|
"github.com/dop251/goja"
|
||
|
|
"github.com/dop251/goja_nodejs/console"
|
||
|
|
"github.com/dop251/goja_nodejs/require"
|
||
|
|
"github.com/projectdiscovery/gologger"
|
||
|
|
_ "github.com/projectdiscovery/nuclei/v3/pkg/js/generated/go/libbytes"
|
||
|
|
_ "github.com/projectdiscovery/nuclei/v3/pkg/js/generated/go/libfs"
|
||
|
|
_ "github.com/projectdiscovery/nuclei/v3/pkg/js/generated/go/libikev2"
|
||
|
|
_ "github.com/projectdiscovery/nuclei/v3/pkg/js/generated/go/libkerberos"
|
||
|
|
_ "github.com/projectdiscovery/nuclei/v3/pkg/js/generated/go/libldap"
|
||
|
|
_ "github.com/projectdiscovery/nuclei/v3/pkg/js/generated/go/libmssql"
|
||
|
|
_ "github.com/projectdiscovery/nuclei/v3/pkg/js/generated/go/libmysql"
|
||
|
|
_ "github.com/projectdiscovery/nuclei/v3/pkg/js/generated/go/libnet"
|
||
|
|
_ "github.com/projectdiscovery/nuclei/v3/pkg/js/generated/go/liboracle"
|
||
|
|
_ "github.com/projectdiscovery/nuclei/v3/pkg/js/generated/go/libpop3"
|
||
|
|
_ "github.com/projectdiscovery/nuclei/v3/pkg/js/generated/go/libpostgres"
|
||
|
|
_ "github.com/projectdiscovery/nuclei/v3/pkg/js/generated/go/librdp"
|
||
|
|
_ "github.com/projectdiscovery/nuclei/v3/pkg/js/generated/go/libredis"
|
||
|
|
_ "github.com/projectdiscovery/nuclei/v3/pkg/js/generated/go/librsync"
|
||
|
|
_ "github.com/projectdiscovery/nuclei/v3/pkg/js/generated/go/libsmb"
|
||
|
|
_ "github.com/projectdiscovery/nuclei/v3/pkg/js/generated/go/libsmtp"
|
||
|
|
_ "github.com/projectdiscovery/nuclei/v3/pkg/js/generated/go/libssh"
|
||
|
|
_ "github.com/projectdiscovery/nuclei/v3/pkg/js/generated/go/libstructs"
|
||
|
|
_ "github.com/projectdiscovery/nuclei/v3/pkg/js/generated/go/libtelnet"
|
||
|
|
_ "github.com/projectdiscovery/nuclei/v3/pkg/js/generated/go/libvnc"
|
||
|
|
"github.com/projectdiscovery/nuclei/v3/pkg/js/global"
|
||
|
|
"github.com/projectdiscovery/nuclei/v3/pkg/js/libs/goconsole"
|
||
|
|
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate"
|
||
|
|
"github.com/remeh/sizedwaitgroup"
|
||
|
|
)
|
||
|
|
|
||
|
|
var (
|
||
|
|
r *require.Registry
|
||
|
|
lazyRegistryInit = sync.OnceFunc(func() {
|
||
|
|
r = new(require.Registry) // this can be shared by multiple runtimes
|
||
|
|
// autoregister console node module with default printer it uses gologger backend
|
||
|
|
require.RegisterNativeModule(console.ModuleName, console.RequireWithPrinter(goconsole.NewGoConsolePrinter()))
|
||
|
|
})
|
||
|
|
sg sizedwaitgroup.SizedWaitGroup
|
||
|
|
lazySgInit = sync.OnceFunc(func() {
|
||
|
|
sg = sizedwaitgroup.New(JsVmConcurrency)
|
||
|
|
})
|
||
|
|
)
|
||
|
|
|
||
|
|
func getRegistry() *require.Registry {
|
||
|
|
lazyRegistryInit()
|
||
|
|
return r
|
||
|
|
}
|
||
|
|
|
||
|
|
var gojapool = &sync.Pool{
|
||
|
|
New: func() interface{} {
|
||
|
|
runtime := protocolstate.NewJSRuntime()
|
||
|
|
_ = getRegistry().Enable(runtime)
|
||
|
|
// by default import below modules every time
|
||
|
|
_ = runtime.Set("console", require.Require(runtime, console.ModuleName))
|
||
|
|
|
||
|
|
// Register embedded javacript helpers
|
||
|
|
if err := global.RegisterNativeScripts(runtime); err != nil {
|
||
|
|
gologger.Error().Msgf("Could not register scripts: %s\n", err)
|
||
|
|
}
|
||
|
|
return runtime
|
||
|
|
},
|
||
|
|
}
|
||
|
|
|
||
|
|
// executes the actual js program
|
||
|
|
func executeProgram(p *goja.Program, args *ExecuteArgs, opts *ExecuteOptions) (result goja.Value, err error) {
|
||
|
|
// its unknown (most likely cannot be done) to limit max js runtimes at a moment without making it static
|
||
|
|
// unlike sync.Pool which reacts to GC and its purposes is to reuse objects rather than creating new ones
|
||
|
|
lazySgInit()
|
||
|
|
sg.Add()
|
||
|
|
defer sg.Done()
|
||
|
|
runtime := gojapool.Get().(*goja.Runtime)
|
||
|
|
defer func() {
|
||
|
|
// reset before putting back to pool
|
||
|
|
_ = runtime.GlobalObject().Delete("template") // template ctx
|
||
|
|
// remove all args
|
||
|
|
for k := range args.Args {
|
||
|
|
_ = runtime.GlobalObject().Delete(k)
|
||
|
|
}
|
||
|
|
if opts != nil && opts.Cleanup != nil {
|
||
|
|
opts.Cleanup(runtime)
|
||
|
|
}
|
||
|
|
gojapool.Put(runtime)
|
||
|
|
}()
|
||
|
|
defer func() {
|
||
|
|
if r := recover(); r != nil {
|
||
|
|
err = fmt.Errorf("panic: %s", r)
|
||
|
|
}
|
||
|
|
}()
|
||
|
|
// set template ctx
|
||
|
|
_ = runtime.Set("template", args.TemplateCtx)
|
||
|
|
// set args
|
||
|
|
for k, v := range args.Args {
|
||
|
|
_ = runtime.Set(k, v)
|
||
|
|
}
|
||
|
|
// register extra callbacks if any
|
||
|
|
if opts != nil && opts.Callback != nil {
|
||
|
|
if err := opts.Callback(runtime); err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
// execute the script
|
||
|
|
return runtime.RunProgram(p)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Internal purposes i.e generating bindings
|
||
|
|
func InternalGetGeneratorRuntime() *goja.Runtime {
|
||
|
|
runtime := gojapool.Get().(*goja.Runtime)
|
||
|
|
return runtime
|
||
|
|
}
|