├── .circleci └── config.yml ├── .gitignore ├── .goreleaser.yml ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── ascii_logo.txt ├── build ├── Dockerfile ├── Dockerfile-minimal ├── nanorc ├── ps1.sh └── vimrc ├── cmd ├── .DS_Store ├── gscript │ ├── compile.go │ ├── docs.go │ ├── linker.go │ ├── main.go │ ├── shell.go │ ├── templates.go │ ├── tidy.go │ └── vet.go └── poc │ ├── gdirwalk │ ├── .gitkeep │ ├── main.go │ └── main_test.go │ ├── gtypeloc │ └── main.go │ ├── ifaceresearch │ └── main.go │ └── wintech │ └── main_windows.go ├── compiler ├── compiler.go ├── computil │ ├── bindata.go │ ├── concurrency.go │ ├── golang.go │ ├── options.go │ ├── packages.go │ └── rand.go ├── embedder.go ├── genesis_ast.go ├── go_ast.go ├── linker.go ├── obfuscator │ ├── mordorifier.go │ └── stylist.go ├── preprocessor.go ├── templates │ ├── debugger.gs │ ├── entrypoint.go.tmpl │ ├── hard_reserved │ ├── obfstring.go.tmpl │ ├── preload.gs │ ├── soft_reserved │ └── vm_file.go.tmpl ├── translator │ └── translator.go └── virtual_machine.go ├── debugger ├── debugger.go ├── repl.go └── vm_functions.go ├── docs ├── ARCHITECTURE.md ├── COMPILER.md ├── DEFCON26_SLIDES.pdf ├── DEFCON26_WORKSHOP.pdf ├── ENGINE.md ├── GETTING_STARTED.md ├── STANDARD_LIBRARY.md ├── examples │ └── .gitkeep ├── stdlib │ ├── _template.md │ ├── asset.md │ ├── crypto.md │ ├── encoding.md │ ├── exec.md │ ├── file.md │ ├── net.md │ ├── os.md │ ├── rand.md │ ├── requests.md │ └── time.md └── tutorials │ ├── 01_installation.md │ ├── 02_cli_usage.md │ ├── 03_gscript_basics.md │ ├── 04_logging.md │ ├── 05_debugging.md │ ├── 06_compiler_macros.md │ ├── 07_0_using_standard_library.md │ ├── 07_1_assets.md │ ├── 08_0_compiling.md │ ├── 08_1_priorities.md │ ├── 08_2_timeouts.md │ ├── 08_3_platform_specifics.md │ ├── 09_0_advanced_gscripting.md │ ├── 09_1_multiple_scripts.md │ ├── 09_2_anti_detection.md │ ├── 09_3_persisting.md │ ├── 09_4_networking.md │ ├── 09_5_obfuscation.md │ ├── 09_6_child_processes.md │ ├── 09_7_system_services.md │ ├── 09_8_managing_team_persistence.md │ ├── 09_9_auditing_other_gscripts.md │ ├── 10_0_using_native_libraries.md │ ├── 10_1_using_experimental_libraries.md │ ├── 10_2_checking_compatibility.md │ ├── 10_3_implementing_native_code.md │ ├── 10_4_gotchas.md │ ├── 11_0_implementing_custom_engines.md │ └── 11_1_implementing_a_new_compiler.md ├── engine ├── assets.go ├── engine.go ├── errors.go ├── executor.go ├── logger.go ├── native_package.go └── types.go ├── go.mod ├── go.sum ├── gscript.go ├── logger ├── base.go ├── null │ └── null_logger.go └── standard │ ├── ascii_logo.go │ └── standard_logger.go ├── spec ├── .gitkeep ├── engine │ └── .gitkeep └── stdlib │ ├── .gitkeep │ ├── asset │ └── .gitkeep │ ├── crypto │ └── .gitkeep │ ├── encoding │ └── .gitkeep │ ├── exec │ └── .gitkeep │ ├── file │ └── .gitkeep │ ├── net │ └── .gitkeep │ ├── os │ └── .gitkeep │ ├── rand │ └── .gitkeep │ ├── requests │ └── .gitkeep │ └── time │ └── .gitkeep ├── stdlib ├── crypto │ ├── .gitkeep │ ├── crypto.go │ └── crypto_test.go ├── encoding │ ├── .gitkeep │ ├── encoding.go │ ├── encoding_test.go │ └── encoding_test.gs ├── exec │ ├── .gitkeep │ ├── exec.go │ ├── exec_test.go │ └── exec_test.gs ├── file │ ├── .gitkeep │ ├── file.go │ ├── file_test.go │ ├── file_test.gs │ ├── file_test3.gs │ ├── file_test4.gs │ ├── new_test_file.txt │ └── test_file.txt ├── net │ ├── .gitkeep │ ├── net.go │ └── net_test.go ├── os │ ├── .gitkeep │ ├── os.go │ └── os_test.go ├── rand │ ├── .gitkeep │ ├── rand.go │ ├── rand_test.go │ └── rand_test.gs ├── requests │ ├── .gitkeep │ ├── requests.go │ └── requests_test.go └── time │ ├── .gitkeep │ ├── time.go │ ├── time_test.go │ └── time_test.gs ├── tools.go ├── tools ├── linker_test │ ├── basic_example.gs │ ├── dns_test.gs │ ├── ns_test.gs │ ├── test.gs │ ├── test2.gs │ ├── test3.gs │ ├── test4.gs │ ├── test_requests.gs │ ├── test_type.gs │ ├── testlib │ │ └── lib.go │ └── typelib │ │ └── type_convert.go ├── svctest │ ├── darwin.gs │ ├── main.go │ └── windows.gs ├── test_build.sh └── typetest │ └── main.go └── x ├── darwinadventure └── adventure_darwin.go ├── svc └── service.go └── windows └── windows.go /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | # Golang CircleCI 2.0 configuration file 2 | # 3 | # Check https://circleci.com/docs/2.0/language-go/ for more details 4 | version: 2 5 | jobs: 6 | build: 7 | docker: 8 | # specify the version 9 | - image: circleci/golang:1.13.5 10 | 11 | # Specify service dependencies here if necessary 12 | # CircleCI maintains a library of pre-built images 13 | # documented at https://circleci.com/docs/2.0/circleci-images/ 14 | # - image: circleci/postgres:9.4 15 | 16 | #### TEMPLATE_NOTE: go expects specific checkout path representing url 17 | #### expecting it in the form of 18 | #### /go/src/github.com/circleci/go-tool 19 | #### /go/src/bitbucket.org/circleci/go-tool 20 | working_directory: /go/src/github.com/gen0cide/gscript 21 | steps: 22 | - checkout 23 | # go get cmd/gscript from outside GOPATH pulls dependancies into GOPATH 24 | - run: cd / ; go get github.com/gen0cide/gscript/cmd/gscript 25 | # Make sure the gscript tool continues to build properly 26 | - run: go test -v ./... 27 | - run: go build -x -v 28 | # Test compiling and running the a gscript bniary 29 | - run: gscript --debug compile --enable-logging --obfuscation-level=3 --output-file=/go/src/github.com/gen0cide/gscript/stdlib/time/time_test /go/src/github.com/gen0cide/gscript/stdlib/time/time_test.gs 30 | - run: chmod +x /go/src/github.com/gen0cide/gscript/stdlib/time/time_test 31 | - run: /go/src/github.com/gen0cide/gscript/stdlib/time/time_test 32 | # Test and compile multiple gscripts 33 | - run: gscript --debug compile --enable-logging --obfuscation-level=3 --output-file=/go/src/github.com/gen0cide/gscript/stdlib/multi_test /go/src/github.com/gen0cide/gscript/stdlib/encoding/encoding_test.gs /go/src/github.com/gen0cide/gscript/stdlib/rand/rand_test.gs /go/src/github.com/gen0cide/gscript/stdlib/exec/exec_test.gs 34 | - run: chmod +x /go/src/github.com/gen0cide/gscript/stdlib/multi_test 35 | - run: /go/src/github.com/gen0cide/gscript/stdlib/multi_test 36 | # Test multiple assets 37 | - run: gscript --debug compile --enable-logging --obfuscation-level=3 --output-file=/go/src/github.com/gen0cide/gscript/stdlib/file/file_tester /go/src/github.com/gen0cide/gscript/stdlib/file/file_test.gs /go/src/github.com/gen0cide/gscript/stdlib/file/file_test3.gs 38 | - run: chmod +x /go/src/github.com/gen0cide/gscript/stdlib/file/file_tester 39 | - run: /go/src/github.com/gen0cide/gscript/stdlib/file/file_tester 40 | # Test obfuscation 41 | - run: gscript --debug compile --touch-a-silmaril=true --obfuscation-level=0 --output-file=/go/src/github.com/gen0cide/gscript/stdlib/file/file_test4 /go/src/github.com/gen0cide/gscript/stdlib/file/file_test4.gs 42 | - run: chmod +x /go/src/github.com/gen0cide/gscript/stdlib/file/file_test4 43 | - run: /go/src/github.com/gen0cide/gscript/stdlib/file/file_test4 44 | #- run: cat /go/src/github.com/gen0cide/gscript/stdlib/file/file_test4.txt 45 | - run: grep -i "github" /go/src/github.com/gen0cide/gscript/stdlib/file/file_test4 || true 46 | - run: grep -i "go" /go/src/github.com/gen0cide/gscript/stdlib/file/file_test4 || true 47 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | .vscode 3 | .DS_Store 4 | testbuild/ 5 | -------------------------------------------------------------------------------- /.goreleaser.yml: -------------------------------------------------------------------------------- 1 | # .goreleaser.yml 2 | # Build customization 3 | project_name: gscript 4 | builds: 5 | - main: ./cmd/gscript/main.go 6 | binary: gscript 7 | goos: 8 | - darwin 9 | - linux 10 | - windows 11 | goarch: 12 | - amd64 13 | ldflags: -s 14 | # Archive customization 15 | archive: 16 | format: zip 17 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at [INSERT EMAIL ADDRESS]. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | 2 | # Contributing 3 | 4 | ## Contributing To Genesis Engine or Compiler 5 | - Must have an associated issue 6 | - Must have an associated PR against the LATEST version of the dev branch 7 | - Must compile without errors for all supported target architectures 8 | - Must pass all linter checks 9 | - Must have an associated unit test(s) written in Golang 10 | - Must include a commit updating any relevant documentation 11 | 12 | ## Contributing To The Standard Library 13 | 14 | - Must have cause to implement the function in Golang (see GOLANG.md) 15 | - Must have an associated issue 16 | - Must have an associated PR against the LATEST version of the dev branch 17 | - Must compile without errors for all supported target architectures 18 | - If package is OS specific, must be implemented in OS package 19 | - Must pass all linter checks 20 | - Must have an associated unit test(s) written in Golang 21 | - Must have an associated genesis script that implements the function standalone in a gscript for in VM testing 22 | - Must include a commit updating the standard library documentation (using the function template) and include: 23 | - Name 24 | - Description 25 | - Author 26 | - Method Signature 27 | - Arguments and their types 28 | - Returns and their types 29 | - Example usage 30 | - How to handle failure 31 | - Must have a revision to the CHANGELOG.md 32 | 33 | ## Contributing Example Scripts 34 | - PRs must be made against the LATEST version of the dev branch 35 | - Must include typical gscript meta information, including: 36 | - Title 37 | - Purpose 38 | - Author 39 | - ATT&CK link 40 | - Note usage 41 | - Uses link for an bundled assets 42 | - If it compiles to a larger subset of architectures please note that 43 | - Please start an issue on the project if you would like to discuss reorganizing directory structures 44 | 45 | ## Contributing To Documentation 46 | - PRs must be made against the LATEST version of the dev branch 47 | - Documentation should be done in Markdown unless otherwise specified 48 | - We accept documentation updates with associated issues or code commits 49 | - Updating docs is the recommended way to get familiar with adding to the project 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Gscript Logo](https://i.imgur.com/16lZGrA.png) 2 | 3 | # Genesis Scripting Engine (gscript) 4 | 5 | > Security framework to rapidly implement custom droppers for all three major operating systems 6 | 7 | 8 | 9 | [![CircleCI](https://circleci.com/gh/gen0cide/gscript/tree/master.svg?style=svg)](https://circleci.com/gh/gen0cide/gscript/tree/master) 10 | 11 | ## About 12 | 13 | Gscript is a framework for building multi-tenant executors for several implants in a stager. The engine works by embedding runtime logic (powered by the Otto Javascript Virtual Machine) for each persistence technique. This logic gets run at deploy time on the victim machine, in parallel for every implant contained with the stager. The Gscript engine leverages the multi-platform support of Golang to produce final stage one binaries for Windows, Mac, and Linux. 14 | 15 | **We encourage you to read through the slides from DEFCON26:** 16 | 17 | https://docs.google.com/presentation/d/1kHdz8DY0Zn44yn_XrZ2RVqDY1lpADThLPNPwHP-njbc/edit?usp=sharing 18 | 19 | 20 | ## Table of Contents 21 | 22 | - [Features](#features) 23 | - [Installation](#installation) 24 | - [Quick Start](#quick-start) 25 | - [Docs](#docs) 26 | - [Shoutouts](#shoutouts) 27 | 28 | ## Features 29 | 30 | - Easy to learn and write - uses javascript. 31 | - Portable - Compile droppers for OSX, Windows, or Linux from any OS. 32 | - Robust - Script's are isolated from each other in a safe execution way. 33 | - Fast. 34 | - Extensible - Can link native Golang packages directly into your Javascript. 35 | 36 | ## Installation 37 | 38 | ### Docker (Easiest) 39 | 40 | If you have docker installed, you can run: 41 | 42 | ``` 43 | $ docker pull gen0cide/gscript:v1 44 | ``` 45 | 46 | Make a local directory where you can share files between your local machine and the docker container. Replace `$LOCAL_DIR` in the following command with the path to that: 47 | 48 | ``` 49 | $ docker run -it -v $LOCAL_DIR:/root/share gen0cide/gscript:v1 50 | ``` 51 | 52 | Thats it! You're good to go. 53 | 54 | 55 | ### Local (Good for advanced) 56 | 57 | **Local installation requires you to have a Golang compiler setup and working on your machine. If you need to do this, you can grab an installer [here](https://golang.org/dl/). Make sure `$GOPATH/bin` is in your `$PATH`.** 58 | 59 | 60 | After that, all you need to do is run: 61 | 62 | ``` 63 | $ go get github.com/gen0cide/gscript/cmd/gscript 64 | ``` 65 | 66 | ## Quick Start 67 | 68 | Check out the tutorial docs here: 69 | 70 | https://github.com/gen0cide/gscript/tree/master/docs/tutorials 71 | 72 | If you want to see example scripts, we have a separate repo you can clone: 73 | 74 | https://github.com/ahhh/gscripts 75 | 76 | ## Docs 77 | 78 | Here's a list of docs and tutorials that might be helpful for you: 79 | 80 | - [Godoc for Engine and Compiler](https://godoc.org/github.com/gen0cide/gscript) 81 | - [Tutorials in docs/tutorials](https://github.com/gen0cide/gscript/tree/master/docs/tutorials) 82 | 83 | (more to come soon) 84 | 85 | ## Shoutouts 86 | 87 | mentors, contributors, and great friends of gscript 88 | 89 | - @cmc 90 | - @hecfblog 91 | - @ccdcredteam 92 | - @1njecti0n 93 | - @ahhh 94 | - @emperorcow 95 | - @vyrus001 96 | - @kos 97 | - @davehughes 98 | - @maus 99 | - @javuto 100 | 101 | -------------------------------------------------------------------------------- /ascii_logo.txt: -------------------------------------------------------------------------------- 1 | *********************************************************** 2 | ____ 3 | __,-~~/~ `---. 4 | _/_,---( , ) 5 | __ / < / ) \___ 6 | - ------===;;;'====------------------===;;;===----- - - 7 | \/ ~"~"~"~"~"~\~"~)~"/ 8 | (_ ( \ ( > \) 9 | \_( _ < >_>' 10 | ~ `-i' ::>|--" 11 | I;|.|.| 12 | <|i::|i|`. 13 | uL (` ^'"`-' ") ) 14 | .ue888Nc.. ( ( ( /( 15 | d88E`"888E` ( ( )( )\ ` ) )\()) 16 | 888E 888E )\ )\(()\((_) /(/( (_))/ 17 | 888E 888E ((_) ((_)((_)(_)((_)_\ | |_ 18 | 888E 888E (_- 3 | 4 | ENV GSCRIPT_REVISION master 5 | ENV GO111MODULE=auto 6 | ENV GOROOT='/usr/local/go' 7 | 8 | RUN mkdir -p $GOROOT && \ 9 | git clone https://github.com/gen0cide/gscript $GOPATH/src/github.com/gen0cide/gscript && \ 10 | cd $GOPATH/src/github.com/gen0cide/gscript && \ 11 | git checkout $GSCRIPT_REVISION && \ 12 | go get ./... && \ 13 | git clone https://github.com/robertkrimen/otto /usr/local/go/src/github.com/robertkrimen/otto && \ 14 | git clone -b v1.0.5 https://github.com/go-sourcemap/sourcemap /usr/local/go/src/gopkg.in/sourcemap.v1 && \ 15 | cd cmd/gscript && \ 16 | go install -i -a 17 | 18 | WORKDIR /root 19 | 20 | RUN DEBIAN_FRONTEND=noninteractive \ 21 | apt-get update && \ 22 | apt-get upgrade -y && \ 23 | apt-get install -y --no-install-recommends \ 24 | file build-essential vim nano wget curl sudo net-tools pwgen locales \ 25 | git-core logrotate software-properties-common && \ 26 | locale-gen en_US en_US.UTF-8 && \ 27 | apt-get clean && \ 28 | rm -rf /var/lib/apt/lists/* 29 | 30 | ADD ps1.sh /etc/profile.d/Z1_PS1.sh 31 | 32 | RUN chmod +x /etc/profile.d/Z1_PS1.sh && \ 33 | echo "" >> /root/.bashrc && \ 34 | echo "GSCRIPT_REVISION=$GSCRIPT_REVISION" >> /root/.bashrc && \ 35 | echo "source /etc/profile.d/Z1_PS1.sh" >> /root/.bashrc 36 | 37 | RUN git clone https://github.com/scopatz/nanorc.git /usr/share/nano-syntax-highlighting/ 38 | 39 | ADD nanorc /etc/nanorc 40 | 41 | RUN git clone --depth=1 https://github.com/amix/vimrc.git /opt/vim 42 | 43 | ADD vimrc /root/.vimrc 44 | 45 | RUN echo "autocmd BufNewFile,BufRead *.gs set syntax=javascript" >> /opt/vim/my_configs.vim 46 | RUN echo "set tabstop=4" >> /opt/vim/my_configs.vim 47 | RUN echo "set shiftwidth=4" >> /opt/vim/my_configs.vim 48 | RUN echo "set expandtab" >> /opt/vim/my_configs.vim 49 | 50 | VOLUME /root/share 51 | 52 | ENV HOME /root 53 | WORKDIR /root 54 | -------------------------------------------------------------------------------- /build/Dockerfile-minimal: -------------------------------------------------------------------------------- 1 | FROM golang:1.17.13-bullseye 2 | MAINTAINER Alex Levinson 3 | 4 | ENV GSCRIPT_REVISION master 5 | ENV GO111MODULE=auto 6 | ENV GOROOT='/usr/local/go' 7 | 8 | RUN mkdir -p $GOROOT && \ 9 | git clone https://github.com/gen0cide/gscript $GOPATH/src/github.com/gen0cide/gscript && \ 10 | cd $GOPATH/src/github.com/gen0cide/gscript && \ 11 | git checkout $GSCRIPT_REVISION && \ 12 | go get ./... && \ 13 | git clone https://github.com/robertkrimen/otto /usr/local/go/src/github.com/robertkrimen/otto && \ 14 | git clone -b v1.0.5 https://github.com/go-sourcemap/sourcemap /usr/local/go/src/gopkg.in/sourcemap.v1 && \ 15 | cd cmd/gscript && \ 16 | go install -i -a 17 | 18 | ENTRYPOINT ["/go/bin/gscript"] 19 | -------------------------------------------------------------------------------- /build/nanorc: -------------------------------------------------------------------------------- 1 | set nowrap 2 | set smooth 3 | set suspend 4 | set tabsize 2 5 | 6 | include /usr/share/nano-syntax-highlighting/*.nanorc 7 | 8 | syntax "GScript" "\.gs$" 9 | 10 | color blue "\<[-+]?([1-9][0-9]*|0[0-7]*|0x[0-9a-fA-F]+)([uU][lL]?|[lL][uU]?)?\>" 11 | color blue "\<[-+]?([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([EePp][+-]?[0-9]+)?[fFlL]?" 12 | color blue "\<[-+]?([0-9]+[EePp][+-]?[0-9]+)[fFlL]?" 13 | color brightblue "[A-Za-z_][A-Za-z0-9_]*[[:space:]]*[(]" 14 | color cyan "\<(break|case|catch|continue|default|delete|do|else|finally)\>" 15 | color cyan "\<(for|function|get|if|in|instanceof|new|return|set|switch)\>" 16 | color cyan "\<(switch|this|throw|try|typeof|var|void|while|with)\>" 17 | color cyan "\<(null|undefined|NaN)\>" 18 | color cyan "\<(import|as|from|export)\>" 19 | color cyan "\<(const|let|class|extends|get|set|of|async|await|yield)\>" 20 | color brightcyan "\<(true|false)\>" 21 | color green "\<(Array|Boolean|Date|Enumerator|Error|Function|Math)\>" 22 | color green "\<(Map|WeakMap|Set|WeakSet|Promise|Symbol)\>" 23 | color green "\<(Number|Object|RegExp|String)\>" 24 | color red "[-+/*=<>!~%?:&|]" 25 | color magenta "/[^*]([^/]|(\\/))*[^\\]/[gim]*" 26 | color magenta "\\[0-7][0-7]?[0-7]?|\\x[0-9a-fA-F]+|\\[bfnrt'"\?\\]" 27 | color brightblack "(^|[[:space:]])//.*" 28 | color brightblack "/\*.+\*/" 29 | color brightwhite,cyan "TODO:?" 30 | color yellow ""(\\.|[^"])*"|'(\\.|[^'])*'|(`|\})(\\.|[^`$]|$[^{])*(\$\{|`)" 31 | color ,green "[[:space:]]+$" 32 | color ,red " + +| + +" -------------------------------------------------------------------------------- /build/ps1.sh: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------ 2 | export CLICOLOR=1 3 | export LSCOLORS=GxFxCxDxBxegedabagaced 4 | export PATH=$HOME/go/bin:$PATH 5 | NO_COLOUR="\[\033[0m\]" 6 | RED="\[\033[00;31m\]" 7 | GREEN="\[\033[00;32m\]" 8 | YELLOW="\[\033[00;33m\]" 9 | BLUE="\[\033[00;34m\]" 10 | MAGENTA="\[\033[00;35m\]" 11 | PURPLE="\[\033[00;35m\]" 12 | CYAN="\[\033[00;36m\]" 13 | LIGHTGRAY="\[\033[00;37m\]" 14 | LRED="\[\033[01;31m\]" 15 | LGREEN="\[\033[01;32m\]" 16 | LYELLOW="\[\033[01;33m\]" 17 | LBLUE="\[\033[01;34m\]" 18 | LMAGENTA="\[\033[01;35m\]" 19 | LPURPLE="\[\033[01;35m\]" 20 | LCYAN="\[\033[01;36m\]" 21 | LWHITE="\[\033[01;37m\]" 22 | WHITE="\e[97m" 23 | GSCRIPT_VERSION="master" 24 | # ------------------------------------------------------------------------------ 25 | PS1="$WHITE[$RED""gscript$NO_COLOUR/$YELLOW""docker $WHITE"" $YELLOW\w$WHITE]$NO_COLOUR\\$ " 26 | # ------------------------------------------------------------------------------ 27 | -------------------------------------------------------------------------------- /build/vimrc: -------------------------------------------------------------------------------- 1 | set runtimepath+=/opt/vim 2 | 3 | source /opt/vim/vimrcs/basic.vim 4 | source /opt/vim/vimrcs/filetypes.vim 5 | source /opt/vim/vimrcs/plugins_config.vim 6 | source /opt/vim/vimrcs/extended.vim 7 | 8 | try 9 | source /opt/vim/my_configs.vim 10 | catch 11 | endtry 12 | -------------------------------------------------------------------------------- /cmd/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gen0cide/gscript/d65a5ce55f79c4f544a93997e7eb635a72a64118/cmd/.DS_Store -------------------------------------------------------------------------------- /cmd/gscript/docs.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/fatih/color" 7 | "github.com/urfave/cli/v2" 8 | ) 9 | 10 | var ( 11 | docsSubcommands = []*cli.Command{ 12 | { 13 | Name: "macros", 14 | Usage: "shows macros available to the gscript compiler", 15 | Action: docsMacrosSubcommand, 16 | }, 17 | { 18 | Name: "scripts", 19 | Usage: "shows an overview of genesis scripting and entry points to use", 20 | Action: docsScriptsSubcommand, 21 | }, 22 | { 23 | Name: "stdlib", 24 | Usage: "prints a reference to the genesis standard library and each library's commands", 25 | Action: docsStandardLibSubcommand, 26 | }, 27 | } 28 | docsCommand = &cli.Command{ 29 | Name: "docs", 30 | Usage: "Shows documentation on a variety of gscript topics", 31 | Subcommands: docsSubcommands, 32 | } 33 | 34 | macroHelp = fmt.Sprintf( 35 | "For more information on the available macros, please check the README at:\n %s", 36 | color.HiGreenString("https://github.com/gen0cide/gscript"), 37 | ) 38 | scriptHelp = fmt.Sprintf( 39 | "For more information on the scripts, please refer to:\n %s: %s\n %s: %s", 40 | color.HiWhiteString("README"), 41 | color.HiGreenString("https://github.com/gen0cide/gscript"), 42 | color.HiWhiteString("EXAMPLES"), 43 | color.HiGreenString("https://github.com/ahhh/gscripts"), 44 | ) 45 | stdlibHelp = fmt.Sprintf( 46 | "For more information on the standard library, please refer to:\n %s: %s\n %s: %s\n %s: %s", 47 | color.HiWhiteString("README"), 48 | color.HiGreenString("https://github.com/gen0cide/gscript"), 49 | color.HiWhiteString("EXAMPLES"), 50 | color.HiGreenString("https://github.com/ahhh/gscripts"), 51 | color.HiWhiteString("INTERACTIVE"), 52 | color.HiCyanString("Run \"gscript shell\" and enter the command \"SymbolTable()\""), 53 | ) 54 | ) 55 | 56 | func docsMacrosSubcommand(c *cli.Context) error { 57 | cliLogger.Infoln(macroHelp) 58 | return nil 59 | } 60 | 61 | func docsScriptsSubcommand(c *cli.Context) error { 62 | cliLogger.Infoln(scriptHelp) 63 | return nil 64 | } 65 | 66 | func docsStandardLibSubcommand(c *cli.Context) error { 67 | cliLogger.Infoln(stdlibHelp) 68 | return nil 69 | } 70 | -------------------------------------------------------------------------------- /cmd/gscript/linker.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | 6 | "github.com/urfave/cli/v2" 7 | ) 8 | 9 | var ( 10 | linkerCommand = &cli.Command{ 11 | Name: "linker", 12 | Usage: "provide information about how compatible functions in a native golang package from a genesis script", 13 | UsageText: "gscript linker GO_IMPORT_PATH", 14 | Action: linkerPackageLookupCommand, 15 | } 16 | ) 17 | 18 | func linkerPackageLookupCommand(c *cli.Context) error { 19 | if c.Args().First() == "" { 20 | return errors.New("must supply a golang package import path as an argument") 21 | } 22 | return commandNotImplemented(c) 23 | } 24 | -------------------------------------------------------------------------------- /cmd/gscript/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | 7 | "github.com/sirupsen/logrus" 8 | 9 | "github.com/fatih/color" 10 | "github.com/gen0cide/gscript" 11 | "github.com/gen0cide/gscript/compiler/computil" 12 | "github.com/gen0cide/gscript/logger/standard" 13 | "github.com/urfave/cli/v2" 14 | ) 15 | 16 | var ( 17 | defaultCompileOptions = computil.DefaultOptions() 18 | cliLogger = standard.NewStandardLogger(nil, "gscript", "cli", false, false) 19 | displayBefore = true 20 | debugOutput = false 21 | ) 22 | 23 | func init() { 24 | cli.HelpFlag = &cli.BoolFlag{Name: "help, h"} 25 | cli.VersionFlag = &cli.BoolFlag{Name: "version"} 26 | 27 | cli.VersionPrinter = func(c *cli.Context) { 28 | fmt.Fprintf(c.App.Writer, "%s\n", gscript.Version) 29 | } 30 | } 31 | 32 | func main() { 33 | app := cli.NewApp() 34 | 35 | app.Writer = color.Output 36 | app.ErrWriter = color.Output 37 | 38 | cli.AppHelpTemplate = fmt.Sprintf("%s\n%s", standard.ASCIILogo(), cli.AppHelpTemplate) 39 | app.Name = "gscript" 40 | app.Usage = "Cross platform dropper framework" 41 | app.Description = "Framework to rapidly implement custom droppers for all three major operating systems." 42 | 43 | app.Flags = []cli.Flag{ 44 | &cli.BoolFlag{ 45 | Name: "debug, d", 46 | Usage: "enables verbose debug output", 47 | Destination: &debugOutput, 48 | }, 49 | } 50 | 51 | app.Version = gscript.Version 52 | app.Authors = []*cli.Author{ 53 | &cli.Author{ 54 | Name: "Alex Levinson", 55 | Email: "gen0cide.threats@gmail.com", 56 | }, 57 | &cli.Author{ 58 | Name: "Dan Borges", 59 | Email: "ahhh.db@gmail.com", 60 | }, 61 | &cli.Author{ 62 | Name: "Vyrus", 63 | Email: "vyrus@dc949.org", 64 | }, 65 | &cli.Author{ 66 | Name: "Lucas Morris", 67 | Email: "emperorcow@gmail.com", 68 | }, 69 | } 70 | app.Copyright = "(c) 2018 Alex Levinson" 71 | app.Commands = []*cli.Command{ 72 | docsCommand, 73 | templatesCommand, 74 | shellCommand, 75 | linkerCommand, 76 | vetCommand, 77 | tidyCommand, 78 | compileCommand, 79 | } 80 | 81 | app.Before = func(c *cli.Context) error { 82 | if debugOutput { 83 | cliLogger.Logger.SetLevel(logrus.DebugLevel) 84 | } 85 | return nil 86 | } 87 | 88 | // ignore error so we don't exit non-zero and break gfmrun README example tests 89 | err := app.Run(os.Args) 90 | if err != nil { 91 | cliLogger.Fatalf("Error Encountered: %v", err) 92 | } 93 | } 94 | 95 | func commandNotImplemented(c *cli.Context) error { 96 | return fmt.Errorf("%s command not implemented", c.Command.FullName()) 97 | } 98 | -------------------------------------------------------------------------------- /cmd/gscript/shell.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "io/ioutil" 6 | "os" 7 | "os/exec" 8 | "path/filepath" 9 | 10 | "github.com/gen0cide/gscript/compiler" 11 | "github.com/gen0cide/gscript/compiler/computil" 12 | "github.com/urfave/cli/v2" 13 | ) 14 | 15 | var ( 16 | shellOpts = computil.DefaultOptions() 17 | shellCommand = &cli.Command{ 18 | Name: "shell", 19 | Usage: "drop into an interactive REPL within the genesis runtime", 20 | UsageText: "gscript shell [--macro MACRO] [--macro MACRO] ...", 21 | Action: interactiveShellCommand, 22 | Flags: []cli.Flag{ 23 | &cli.StringFlag{ 24 | Name: "build-dir", 25 | Usage: "Perform the gscript compile in a specific build directory.", 26 | Destination: &shellOpts.BuildDir, 27 | }, 28 | &cli.StringSliceFlag{ 29 | Name: "macro, m", 30 | Usage: "apply a compiler macro to the interactive shell", 31 | }, 32 | }, 33 | } 34 | ) 35 | 36 | func interactiveShellCommand(c *cli.Context) error { 37 | displayBefore = false 38 | buf := new(bytes.Buffer) 39 | if len(c.StringSlice("macro")) > 0 { 40 | for _, m := range c.StringSlice("macro") { 41 | buf.WriteString("//") 42 | buf.WriteString(m) 43 | buf.WriteString("\n") 44 | } 45 | } 46 | buf.WriteString("\n") 47 | buf.WriteString(string(computil.MustAsset("debugger.gs"))) 48 | shellOpts.ObfuscationLevel = 3 49 | shellOpts.ImportAllNativeFuncs = true 50 | shellOpts.UseHumanReadableNames = true 51 | shellOpts.DebuggerEnabled = true 52 | shellOpts.LoggingEnabled = true 53 | gc := compiler.New(&shellOpts) 54 | scriptPath := filepath.Join(gc.BuildDir, "debugger") 55 | gc.SetLogger(cliLogger) 56 | err := ioutil.WriteFile(scriptPath, buf.Bytes(), 0644) 57 | if err != nil { 58 | cliLogger.Errorf("Error writing script to file path: %s", scriptPath) 59 | return err 60 | } 61 | err = gc.AddScript(scriptPath) 62 | if err != nil { 63 | cliLogger.Errorf("Error adding to runtime: %s", scriptPath) 64 | return err 65 | } 66 | err = gc.Do() 67 | if err != nil { 68 | cliLogger.Errorf("Build Dir Located At: %s", gc.BuildDir) 69 | return err 70 | } 71 | err = runShell(gc.OutputFile) 72 | os.RemoveAll(gc.BuildDir) 73 | return err 74 | } 75 | 76 | func runShell(exePath string) error { 77 | cmd := exec.Command(exePath) 78 | cmd.Stderr = os.Stderr 79 | cmd.Stdout = os.Stdout 80 | cmd.Stdin = os.Stdin 81 | if err := cmd.Start(); err != nil { 82 | return err 83 | } 84 | return cmd.Wait() 85 | } 86 | -------------------------------------------------------------------------------- /cmd/gscript/templates.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | 7 | "github.com/urfave/cli/v2" 8 | ) 9 | 10 | var ( 11 | templatesSubcommands = []*cli.Command{ 12 | { 13 | Name: "list", 14 | Usage: "show a list of all templates and their descriptions", 15 | Action: templatesListSubcommand, 16 | }, 17 | { 18 | Name: "show", 19 | Usage: "print the named template to standard output", 20 | Action: templatesPrintSubcommand, 21 | Flags: []cli.Flag{ 22 | &cli.StringFlag{ 23 | Name: "template, t", 24 | Usage: "Show code for `TEMPLATE`", 25 | }, 26 | }, 27 | }, 28 | } 29 | templatesCommand = &cli.Command{ 30 | Name: "templates", 31 | Usage: "access a library of pre-templated gscripts", 32 | Subcommands: templatesSubcommands, 33 | } 34 | ) 35 | 36 | func templatesListSubcommand(c *cli.Context) error { 37 | return commandNotImplemented(c) 38 | } 39 | 40 | func templatesPrintSubcommand(c *cli.Context) error { 41 | if c.String("template") == "" { 42 | return errors.New("must provide a --template/-t NAME argument") 43 | } 44 | fmt.Fprintf(c.App.Writer, "Template to print: %s\n", c.String("template")) 45 | return commandNotImplemented(c) 46 | } 47 | -------------------------------------------------------------------------------- /cmd/gscript/tidy.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "io/ioutil" 7 | "os" 8 | 9 | "github.com/ditashi/jsbeautifier-go/jsbeautifier" 10 | 11 | "github.com/urfave/cli/v2" 12 | ) 13 | 14 | var ( 15 | tidyCommand = &cli.Command{ 16 | Name: "tidy", 17 | Usage: "tidy the syntax of a provided gscript", 18 | UsageText: "gscript tidy GSCRIPT", 19 | Action: tidyScriptCommand, 20 | } 21 | 22 | defaultTidyOptions = map[string]interface{}{ 23 | "indent_size": 2, 24 | "indent_char": " ", 25 | "indent_with_tabs": false, 26 | "preserve_newlines": true, 27 | "max_preserve_newlines": 10, 28 | "space_in_paren": false, 29 | "space_in_empty_paren": false, 30 | "e4x": false, 31 | "jslint_happy": false, 32 | "space_after_anon_function": false, 33 | "brace_style": "collapse", 34 | "keep_array_indentation": false, 35 | "keep_function_indentation": false, 36 | "eval_code": false, 37 | "unescape_strings": false, 38 | "wrap_line_length": 0, 39 | "break_chained_methods": false, 40 | "end_with_newline": true, 41 | } 42 | ) 43 | 44 | func tidyScriptCommand(c *cli.Context) error { 45 | if c.Args().First() == "" { 46 | return errors.New("must supply a gscript to this command") 47 | } 48 | target := c.Args().First() 49 | if _, err := os.Stat(target); err != nil { 50 | return err 51 | } 52 | data, err := ioutil.ReadFile(target) 53 | if err != nil { 54 | return err 55 | } 56 | dataString := string(data) 57 | 58 | beautified, err := jsbeautifier.Beautify(&dataString, defaultTidyOptions) 59 | if err != nil { 60 | return err 61 | } 62 | 63 | fmt.Println(beautified) 64 | return nil 65 | } 66 | -------------------------------------------------------------------------------- /cmd/gscript/vet.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "os" 7 | "path/filepath" 8 | 9 | "github.com/fatih/color" 10 | "github.com/robertkrimen/otto/parser" 11 | 12 | "github.com/urfave/cli/v2" 13 | ) 14 | 15 | var ( 16 | vetCommand = &cli.Command{ 17 | Name: "vet", 18 | Usage: "verifies the syntax of a supplied gscripts", 19 | UsageText: "gscript vet LOCATION", 20 | Action: vetScriptCommand, 21 | } 22 | ) 23 | 24 | func vetScriptCommand(c *cli.Context) error { 25 | if c.Args().Len() == 0 { 26 | return errors.New("must supply a script to this command") 27 | } 28 | for _, a := range c.Args().Slice() { 29 | if _, err := os.Stat(a); err != nil { 30 | cliLogger.Errorf("Error locating file %s:\n %v", a, err) 31 | continue 32 | } 33 | basename := filepath.Base(a) 34 | fi, err := os.Open(a) 35 | if err != nil { 36 | cliLogger.Errorf("Error loading file %s:\n %v", basename, err) 37 | continue 38 | } 39 | _, err = parser.ParseFile(nil, a, fi, 0) 40 | if err != nil { 41 | fmt.Fprintf( 42 | color.Output, 43 | "%s%s%s\n %s: %s\n %s: %s\n %s: %s\n", 44 | color.HiWhiteString("["), 45 | color.HiRedString("SYNTAX ERROR"), 46 | color.HiWhiteString("]"), 47 | color.HiWhiteString("FILE"), 48 | color.HiYellowString(a), 49 | color.HiWhiteString("REASON"), 50 | color.HiYellowString(err.Error()), 51 | color.HiWhiteString("STATUS"), 52 | color.HiRedString("failed"), 53 | ) 54 | } else { 55 | fmt.Fprintf( 56 | color.Output, 57 | "%s%s%s\n %s: %s\n %s: %s\n", 58 | color.HiWhiteString("["), 59 | color.HiGreenString("SYNTAX OK"), 60 | color.HiWhiteString("]"), 61 | color.HiWhiteString("FILE"), 62 | color.HiGreenString(a), 63 | color.HiWhiteString("STATUS"), 64 | color.HiGreenString("passed"), 65 | ) 66 | } 67 | } 68 | return nil 69 | } 70 | -------------------------------------------------------------------------------- /cmd/poc/gdirwalk/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gen0cide/gscript/d65a5ce55f79c4f544a93997e7eb635a72a64118/cmd/poc/gdirwalk/.gitkeep -------------------------------------------------------------------------------- /cmd/poc/gdirwalk/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | "path/filepath" 6 | 7 | "github.com/karrick/godirwalk" 8 | "github.com/pkg/errors" 9 | "github.com/ahhh/gopkgs" 10 | ) 11 | 12 | var ( 13 | packages = getPackages() 14 | errSkipDir = errors.New("skipping this directory") 15 | ) 16 | 17 | func getPackages() map[string]gopkgs.Pkg { 18 | p, _ := gopkgs.Packages(gopkgs.Options{NoVendor: true}) 19 | switched := map[string]gopkgs.Pkg{} 20 | for _, pkg := range p { 21 | switched[pkg.Dir] = pkg 22 | } 23 | return switched 24 | } 25 | 26 | func walkWithNative(p string) error { 27 | err := filepath.Walk(p, func(sp string, fi os.FileInfo, err error) error { 28 | abspath, _ := filepath.Abs(sp) 29 | if _, ok := packages[abspath]; ok { 30 | return filepath.SkipDir 31 | } 32 | return nil 33 | }) 34 | return err 35 | } 36 | 37 | func walkWithLib(p string) error { 38 | err := godirwalk.Walk(p, &godirwalk.Options{ 39 | Callback: func(osp string, de *godirwalk.Dirent) error { 40 | abspath, _ := filepath.Abs(osp) 41 | if _, ok := packages[abspath]; ok { 42 | return errSkipDir 43 | } 44 | return nil 45 | }, 46 | ErrorCallback: func(d string, e error) godirwalk.ErrorAction { 47 | if errors.Cause(e) == errSkipDir { 48 | return godirwalk.SkipNode 49 | } 50 | return godirwalk.Halt 51 | }, 52 | Unsorted: true, 53 | }) 54 | return err 55 | } 56 | 57 | func main() { 58 | 59 | } 60 | -------------------------------------------------------------------------------- /cmd/poc/gdirwalk/main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | "testing" 6 | ) 7 | 8 | func BenchmarkWalkWithNative(b *testing.B) { 9 | gp := os.Getenv("GOPATH") 10 | err := walkWithNative(gp) 11 | if err != nil { 12 | b.Error(err) 13 | } 14 | } 15 | 16 | func BenchmarkWalkWithLib(b *testing.B) { 17 | gp := os.Getenv("GOPATH") 18 | err := walkWithLib(gp) 19 | if err != nil { 20 | b.Error(err) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /cmd/poc/ifaceresearch/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | "reflect" 7 | 8 | "github.com/Jeffail/gabs/v2" 9 | 10 | "github.com/gen0cide/gscript/compiler" 11 | 12 | "github.com/davecgh/go-spew/spew" 13 | "github.com/robertkrimen/otto" 14 | "github.com/sirupsen/logrus" 15 | prefixed "github.com/x-cray/logrus-prefixed-formatter" 16 | ) 17 | 18 | var ( 19 | logger *logrus.Logger 20 | vm *otto.Otto 21 | ) 22 | 23 | const testval = ` 24 | function fappy(e) { 25 | return 5; 26 | } 27 | 28 | var a = { 29 | "Content-Type": "application/json", 30 | "Happy": 1337, 31 | "Robert": function(e) { 32 | return 5; 33 | }, 34 | "Becky": fappy 35 | } 36 | 37 | var x = {} 38 | ` 39 | 40 | func init() { 41 | logger = logrus.New() 42 | logger.Formatter = new(prefixed.TextFormatter) 43 | logger.SetLevel(logrus.DebugLevel) 44 | vm = otto.New() 45 | vm.Eval(testval) 46 | } 47 | 48 | func test(name string, v otto.Value) { 49 | isObj := v.IsObject() 50 | logger.Infof("%s is an object: %v", name, isObj) 51 | isPrim := v.IsPrimitive() 52 | logger.Infof("%s is a primative: %v", name, isPrim) 53 | val, err := v.Export() 54 | if err != nil { 55 | panic(err) 56 | } 57 | ttype(name, val) 58 | } 59 | 60 | func ttype(name string, val interface{}) { 61 | rval := reflect.ValueOf(val) 62 | rtype := rval.Type() 63 | logger.Infof("%s name is %s", name, rtype.Name()) 64 | logger.Infof("%s string is %s", name, rtype.String()) 65 | logger.Infof("%s kind is %s", name, rtype.Kind().String()) 66 | if rtype.Kind() == reflect.Map { 67 | logger.Infof("%s is a map", name) 68 | real, ok := val.(map[string]interface{}) 69 | if !ok { 70 | logger.Infof("%s is not a map[string]interface{}", name) 71 | } else { 72 | logger.Infof("%s is a map[string]interface{}", name) 73 | jsonObj := gabs.Wrap(val) 74 | if jsonObj != nil { 75 | logger.Infof("JSON VERSION of %s:\n%s\n", name, jsonObj.StringIndent("", " ")) 76 | } else { 77 | logger.Errorf("Could not produce JSON for %s", name) 78 | } 79 | hedr, ok2 := val.(http.Header) 80 | if !ok2 { 81 | logger.Infof("%s is not an http.Header", name) 82 | newHeaders := map[string]string{} 83 | for k, item := range real { 84 | ttype(fmt.Sprintf("%s[%s]", name, k), item) 85 | newHeaders[k] = fmt.Sprintf("%v", item) 86 | } 87 | spew.Dump(newHeaders) 88 | } else { 89 | logger.Infof("%s is a http.Header", name) 90 | spew.Dump(hedr) 91 | } 92 | } 93 | } 94 | } 95 | 96 | func testvmret(name string) { 97 | v, err := vm.Get(name) 98 | if err != nil { 99 | panic(err) 100 | } 101 | test(name, v) 102 | } 103 | 104 | func main() { 105 | b := []string{ 106 | "hello", 107 | "world", 108 | } 109 | vm.Set("b", b) 110 | 111 | c := compiler.New(nil) 112 | vm.Set("c", c) 113 | 114 | d := map[string]interface{}{ 115 | "Content-Type": []string{ 116 | "English", 117 | "Mother", 118 | }, 119 | } 120 | vm.Set("d", d) 121 | 122 | e := map[string]interface{}{} 123 | 124 | e["dog"] = "house" 125 | e["barf"] = []string{"bobz"} 126 | e["george"] = &http.Transport{} 127 | vm.Set("e", e) 128 | 129 | testvmret("a") 130 | testvmret("b") 131 | testvmret("c") 132 | testvmret("d") 133 | testvmret("e") 134 | testvmret("x") 135 | } 136 | -------------------------------------------------------------------------------- /cmd/poc/wintech/main_windows.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | "syscall" 8 | ) 9 | 10 | var ( 11 | valar = syscall.NewLazyDLL("advapi32.dll") 12 | eru = valar.NewProc("OpenSCManagerW") 13 | modkernel32 = syscall.NewLazyDLL("kernel32.dll") 14 | procCloseHandle = modkernel32.NewProc("CloseHandle") 15 | ) 16 | 17 | const ( 18 | STANDARD_RIGHTS_REQUIRED = 0x000F 19 | SC_MANAGER_CONNECT = 0x0001 20 | SC_MANAGER_CREATE_SERVICE = 0x0002 21 | SC_MANAGER_ENUMERATE_SERVICE = 0x0004 22 | SC_MANAGER_LOCK = 0x0008 23 | SC_MANAGER_QUERY_LOCK_STATUS = 0x0010 24 | SC_MANAGER_MODIFY_BOOT_CONFIG = 0x0020 25 | SC_MANAGER_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE | SC_MANAGER_ENUMERATE_SERVICE | SC_MANAGER_LOCK | SC_MANAGER_QUERY_LOCK_STATUS | SC_MANAGER_MODIFY_BOOT_CONFIG 26 | ) 27 | 28 | func main() { 29 | a := TravelToWhiteShores() 30 | if a == true { 31 | fmt.Println("WE ARE ADMIN") 32 | } else { 33 | fmt.Println("WE ARE *NOT* ADMIN") 34 | } 35 | } 36 | 37 | func TravelToWhiteShores() bool { 38 | ret, _, _ := eru.Call(uintptr(0), uintptr(0), uintptr(SC_MANAGER_ALL_ACCESS)) 39 | if ret == 0 { 40 | return false 41 | } 42 | _, _, _ = procCloseHandle.Call(ret) 43 | return true 44 | } 45 | -------------------------------------------------------------------------------- /compiler/computil/concurrency.go: -------------------------------------------------------------------------------- 1 | package computil 2 | 3 | import "sync" 4 | 5 | // ExecuteFuncsInParallel is a meta function that takes an array of function pointers (hopefully for each VM) 6 | // and executes them in parallel to decrease compile times. This is setup to handle errors within 7 | // each VM gracefully and not allow a goroutine to fail silently. 8 | func ExecuteFuncsInParallel(fns []func() error) error { 9 | var wg sync.WaitGroup 10 | errChan := make(chan error, 1) 11 | finChan := make(chan bool, 1) 12 | for _, fn := range fns { 13 | wg.Add(1) 14 | go func(f func() error) { 15 | err := f() 16 | if err != nil { 17 | errChan <- err 18 | } 19 | wg.Done() 20 | }(fn) 21 | } 22 | go func() { 23 | wg.Wait() 24 | close(finChan) 25 | }() 26 | select { 27 | case <-finChan: 28 | case err := <-errChan: 29 | if err != nil { 30 | return err 31 | } 32 | } 33 | return nil 34 | } 35 | -------------------------------------------------------------------------------- /compiler/computil/golang.go: -------------------------------------------------------------------------------- 1 | package computil 2 | 3 | import ( 4 | "path/filepath" 5 | "regexp" 6 | "strings" 7 | ) 8 | 9 | const ( 10 | goosList = `android darwin dragonfly freebsd js linux nacl netbsd openbsd plan9 solaris windows zos` 11 | goarchList = `386 amd64 amd64p32 arm armbe arm64 arm64be ppc64 ppc64le mips mipsle mips64 mips64le mips64p32 mips64p32le ppc riscv riscv64 s390 s390x sparc sparc64 wasm` 12 | ) 13 | 14 | var ( 15 | // GOOS maintains a cache of valid go OS's 16 | GOOS = GOOSList() 17 | 18 | // GOARCH maintains a cache of valid go architectures 19 | GOARCH = GOARCHList() 20 | 21 | archRegexp = regexp.MustCompile(strings.Join(GOARCH, "|")) 22 | osRegexp = regexp.MustCompile(strings.Join(GOOS, "|")) 23 | ) 24 | 25 | // GOOSList returns a slice of all possible go architectures 26 | func GOOSList() []string { 27 | return strings.Split(goosList, " ") 28 | } 29 | 30 | // GOARCHList returns a slice of all possible go architectures 31 | func GOARCHList() []string { 32 | return strings.Split(goarchList, " ") 33 | } 34 | 35 | // IsBuildSpecificFile tests a file to see if it's got platform specific naming to it's convention 36 | func IsBuildSpecificFile(fn string) bool { 37 | base := filepath.Base(fn) 38 | if archRegexp.MatchString(base) { 39 | return true 40 | } 41 | if osRegexp.MatchString(base) { 42 | return true 43 | } 44 | return false 45 | } 46 | -------------------------------------------------------------------------------- /compiler/computil/packages.go: -------------------------------------------------------------------------------- 1 | package computil 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "os" 7 | "os/user" 8 | "path/filepath" 9 | "regexp" 10 | "runtime" 11 | 12 | "github.com/ahhh/gopkgs" 13 | ) 14 | 15 | var ( 16 | baseImportPath = `github.com/gen0cide/gscript` 17 | baseRegexpStr = `github\.com/gen0cide/gscript` 18 | baseRegexp = regexp.MustCompile(baseRegexpStr) 19 | testFileRegexp = regexp.MustCompile(`.*_test\.go$`) 20 | windowsFix = regexp.MustCompile(`\\`) 21 | 22 | // GenesisLibs is the name of the packages within the genesis standard library 23 | GenesisLibs = map[string]bool{ 24 | "crypto": true, 25 | "encoding": true, 26 | "exec": true, 27 | "file": true, 28 | "net": true, 29 | "os": true, 30 | "rand": true, 31 | "requests": true, 32 | "time": true, 33 | } 34 | 35 | // InstalledGoPackages holds a cache of all currently installed golang libraries 36 | InstalledGoPackages = GatherInstalledGoPackages() 37 | ) 38 | 39 | func regexpForModule(mod ...string) *regexp.Regexp { 40 | if runtime.GOOS == "windows" { 41 | return regexp.MustCompile(windowsFix.ReplaceAllString(filepath.Join(append([]string{baseImportPath}, mod...)...), `/`)) 42 | } 43 | return regexp.MustCompile(filepath.Join(append([]string{baseRegexpStr}, mod...)...)) 44 | } 45 | 46 | // GatherInstalledGoPackages retrieves a list of all installed go packages in the context of current GOPATH and GOROOT 47 | func GatherInstalledGoPackages() map[string]gopkgs.Pkg { 48 | goPackages, err := gopkgs.Packages(gopkgs.Options{NoVendor: true}) 49 | if err != nil { 50 | panic(err) 51 | } 52 | if runtime.GOOS == "windows" { 53 | pathFix := regexp.MustCompile(`\\`) 54 | newMap := map[string]gopkgs.Pkg{} 55 | for n, p := range goPackages { 56 | newMap[pathFix.ReplaceAllString(n, `/`)] = p 57 | } 58 | return newMap 59 | } 60 | return goPackages 61 | } 62 | 63 | // SourceFileIsTest determines if the given source file is named after the test convention 64 | func SourceFileIsTest(src string) bool { 65 | return testFileRegexp.MatchString(src) 66 | } 67 | 68 | // ResolveGoPath attempts to resolve the current user's GOPATH 69 | func ResolveGoPath() string { 70 | gp := os.Getenv("GOPATH") 71 | if gp != "" { 72 | return gp 73 | } 74 | u, err := user.Current() 75 | if err != nil { 76 | // really shouldn't happen 77 | panic(err) 78 | } 79 | return filepath.Join(u.HomeDir, "go") 80 | } 81 | 82 | // ResolveGenesisPackageDir attempts to resolve the base directory for the genesis package 83 | func ResolveGenesisPackageDir() (targetDir string, err error) { 84 | guess := filepath.Join(ResolveGoPath(), baseImportPath) 85 | if _, ok := os.Stat(guess); ok == nil { 86 | return guess, nil 87 | } 88 | for name, pkg := range InstalledGoPackages { 89 | if !baseRegexp.MatchString(name) { 90 | continue 91 | } 92 | targetDir = pkg.Dir 93 | } 94 | if targetDir == "" { 95 | return targetDir, errors.New("could not locate the base genesis package") 96 | } 97 | return targetDir, nil 98 | } 99 | 100 | // ResolveEngineDir attempts to resolve the absolute path of the genesis engine directory 101 | func ResolveEngineDir() (targetDir string, err error) { 102 | dirMatch := regexpForModule("engine") 103 | for name, pkg := range InstalledGoPackages { 104 | if !dirMatch.MatchString(name) { 105 | continue 106 | } 107 | targetDir = pkg.Dir 108 | } 109 | if targetDir == "" { 110 | return targetDir, fmt.Errorf("coult not locate the genesis engine directory") 111 | } 112 | return targetDir, nil 113 | } 114 | 115 | // ResolveStandardLibraryDir attempts to resolve the absolute path of the specified standard library package 116 | func ResolveStandardLibraryDir(pkg string) (*gopkgs.Pkg, error) { 117 | dirMatch := regexpForModule("stdlib", pkg) 118 | for name, gpkg := range InstalledGoPackages { 119 | if !dirMatch.MatchString(name) { 120 | continue 121 | } 122 | return &gpkg, nil 123 | } 124 | return nil, fmt.Errorf("could not locate standard library package %s", pkg) 125 | } 126 | 127 | func ResolveGlobalImport(pkg string) (*gopkgs.Pkg, error) { 128 | for _, gpkg := range InstalledGoPackages { 129 | if gpkg.ImportPath == pkg { 130 | return &gpkg, nil 131 | } 132 | } 133 | return nil, errors.New("could not locate gopackage of that name") 134 | } 135 | -------------------------------------------------------------------------------- /compiler/computil/rand.go: -------------------------------------------------------------------------------- 1 | package computil 2 | 3 | import ( 4 | "crypto/rand" 5 | "math/big" 6 | "strings" 7 | ) 8 | 9 | const ( 10 | lowercaseAlphaNumericChars = "abcdefghijklmnopqrstuvwxyz0123456789" 11 | lowerAlphaChars = "abcdefghijklmnopqrstuvwxyz" 12 | mixedAlphaNumericChars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" 13 | mixedAlphaChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" 14 | upperAlphaChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 15 | ) 16 | 17 | // RandAlphaNumericString creates a random lowercase alpha-numeric string of a given length 18 | func RandAlphaNumericString(strlen int) string { 19 | result := make([]byte, strlen) 20 | for i := range result { 21 | var val *big.Int 22 | var err error 23 | if i == 0 { 24 | val, err = rand.Int(rand.Reader, big.NewInt(int64(len(lowerAlphaChars)))) 25 | } else { 26 | val, err = rand.Int(rand.Reader, big.NewInt(int64(len(lowercaseAlphaNumericChars)))) 27 | } 28 | if err != nil { 29 | panic(err) 30 | } 31 | result[i] = lowercaseAlphaNumericChars[val.Int64()] 32 | } 33 | return string(result) 34 | } 35 | 36 | // RandUpperAlphaNumericString creates a random uppercase alpha-numeric string of a given length 37 | func RandUpperAlphaNumericString(strlen int) string { 38 | return strings.ToUpper(RandAlphaNumericString(strlen)) 39 | } 40 | 41 | // RandomInt returns a random integer between a min and max value 42 | func RandomInt(min, max int) int { 43 | r, _ := rand.Int(rand.Reader, big.NewInt(int64(max-min))) 44 | return int(r.Int64()) + min 45 | } 46 | 47 | // RandMixedAlphaNumericString creates a random mixed-case alpha-numeric string of a given length 48 | func RandMixedAlphaNumericString(n int) string { 49 | b := make([]byte, n) 50 | for i := range b { 51 | var val *big.Int 52 | var err error 53 | if i == 0 { 54 | val, err = rand.Int(rand.Reader, big.NewInt(int64(len(mixedAlphaChars)))) 55 | } else { 56 | val, err = rand.Int(rand.Reader, big.NewInt(int64(len(mixedAlphaNumericChars)))) 57 | } 58 | if err != nil { 59 | panic(err) 60 | } 61 | b[i] = mixedAlphaNumericChars[val.Int64()] 62 | } 63 | return string(b) 64 | } 65 | 66 | // RandUpperAlphaString creates a random uppercase alpha-only string of a given length 67 | func RandUpperAlphaString(strlen int) string { 68 | return strings.ToUpper(RandLowerAlphaString(strlen)) 69 | } 70 | 71 | // RandLowerAlphaString creates a random lowercase alpha-only string of a given length 72 | func RandLowerAlphaString(strlen int) string { 73 | result := make([]byte, strlen) 74 | for i := range result { 75 | val, err := rand.Int(rand.Reader, big.NewInt(int64(len(lowerAlphaChars)))) 76 | if err != nil { 77 | panic(err) 78 | } 79 | result[i] = lowerAlphaChars[val.Int64()] 80 | } 81 | return string(result) 82 | } 83 | -------------------------------------------------------------------------------- /compiler/embedder.go: -------------------------------------------------------------------------------- 1 | package compiler 2 | 3 | import ( 4 | "bytes" 5 | "compress/gzip" 6 | "crypto/aes" 7 | "crypto/cipher" 8 | "encoding/base64" 9 | "fmt" 10 | "io" 11 | "io/ioutil" 12 | "os" 13 | "path/filepath" 14 | 15 | "github.com/gen0cide/gscript/compiler/computil" 16 | ) 17 | 18 | // EmbeddedFile is an object that manages the lifecycle of resolving and translating 19 | // embedded assets referenced in the Genesis VM into callable values that are 20 | // embedded by the compiler 21 | type EmbeddedFile struct { 22 | // local file path to the target file 23 | SourcePath string 24 | 25 | // url to the target file (optional) 26 | CachedPath string 27 | 28 | // the composite ($ID_$OrigName) filename of the referenced file 29 | Filename string 30 | 31 | // the original basename of the referenced file 32 | OrigName string 33 | 34 | // unique identifier that is used by the compiler to reference file contents 35 | ID string 36 | 37 | // unique identifier that is used by the compiler to swizzle the file decoding and decrypting into a function pointer 38 | FuncID string 39 | 40 | // uncompressed embedded file data 41 | Uncompressed []byte 42 | 43 | // compressed embedded file data 44 | Compressed []byte 45 | 46 | // used to AES encrypt the embedded assets 47 | EncryptionKey []byte 48 | 49 | // temporary buffer used to generate the intermediate representation of the compressed data 50 | EmbedData *bytes.Buffer 51 | } 52 | 53 | // NewEmbeddedFile takes a path on the local file system and returns an EmbeddedFile object reference 54 | func NewEmbeddedFile(source string, key []byte) (*EmbeddedFile, error) { 55 | if _, err := os.Stat(source); os.IsNotExist(err) { 56 | return nil, err 57 | } 58 | absPath, err := filepath.Abs(source) 59 | if err != nil { 60 | return nil, err 61 | } 62 | id := computil.RandUpperAlphaString(18) 63 | ef := &EmbeddedFile{ 64 | SourcePath: absPath, 65 | OrigName: filepath.Base(source), 66 | Filename: fmt.Sprintf("%s_%s", id, filepath.Base(source)), 67 | ID: id, 68 | EncryptionKey: key, 69 | } 70 | return ef, nil 71 | } 72 | 73 | // CacheFile attempts to copy the files original location (e.SourcePath) to the 74 | // destination cacheDir provided as an argument to this function call 75 | func (e *EmbeddedFile) CacheFile(cacheDir string) error { 76 | dstAbsPath := filepath.Join(cacheDir, e.Filename) 77 | fileData, err := ioutil.ReadFile(e.SourcePath) 78 | if err != nil { 79 | return err 80 | } 81 | err = ioutil.WriteFile(dstAbsPath, fileData, 0644) 82 | if err != nil { 83 | return err 84 | } 85 | e.CachedPath = dstAbsPath 86 | return nil 87 | } 88 | 89 | // Data retrieves the current EmbedData's buffer as a string 90 | func (e *EmbeddedFile) Data() string { 91 | return e.EmbedData.String() 92 | } 93 | 94 | // GenerateEmbedData enumerates the compressed embed and creates a byte slice representation of it 95 | func (e *EmbeddedFile) GenerateEmbedData() error { 96 | pipeBuf := new(bytes.Buffer) 97 | ioReader, err := os.Open(e.CachedPath) 98 | if err != nil { 99 | return err 100 | } 101 | w, err := gzip.NewWriterLevel(pipeBuf, gzip.BestCompression) 102 | if err != nil { 103 | return err 104 | } 105 | _, err = io.Copy(w, ioReader) 106 | if err != nil { 107 | return err 108 | } 109 | ioReader.Close() 110 | w.Close() 111 | block, err := aes.NewCipher(e.EncryptionKey) 112 | if err != nil { 113 | return err 114 | } 115 | var iv [aes.BlockSize]byte 116 | stream := cipher.NewOFB(block, iv[:]) 117 | e.EmbedData = new(bytes.Buffer) 118 | encoder := base64.NewEncoder(base64.StdEncoding, e.EmbedData) 119 | encWriter := &cipher.StreamWriter{S: stream, W: encoder} 120 | if _, err := io.Copy(encWriter, pipeBuf); err != nil { 121 | return err 122 | } 123 | encoder.Close() 124 | return nil 125 | } 126 | 127 | // ExampleDecodeEmbed is a reference implementation of how embedded assets should be unpacked 128 | // inside of a genesis engine 129 | func ExampleDecodeEmbed(b64encoded string, key string) []byte { 130 | block, err := aes.NewCipher([]byte(key)) 131 | if err != nil { 132 | panic(err) 133 | } 134 | db1 := new(bytes.Buffer) 135 | db2 := new(bytes.Buffer) 136 | src := bytes.NewReader([]byte(b64encoded)) 137 | var iv [aes.BlockSize]byte 138 | stream := cipher.NewOFB(block, iv[:]) 139 | decoder := base64.NewDecoder(base64.StdEncoding, src) 140 | encReader := &cipher.StreamReader{S: stream, R: decoder} 141 | if _, err := io.Copy(db1, encReader); err != nil { 142 | panic(err) 143 | } 144 | gzr, err := gzip.NewReader(db1) 145 | if err != nil { 146 | panic(err) 147 | } 148 | _, err = io.Copy(db2, gzr) 149 | if err != nil { 150 | panic(err) 151 | } 152 | gzr.Close() 153 | return db2.Bytes() 154 | } 155 | -------------------------------------------------------------------------------- /compiler/genesis_ast.go: -------------------------------------------------------------------------------- 1 | package compiler 2 | 3 | import ( 4 | "go/ast" 5 | "go/token" 6 | 7 | gast "github.com/robertkrimen/otto/ast" 8 | "github.com/robertkrimen/otto/file" 9 | ) 10 | 11 | var ( 12 | 13 | // NamespaceConversionMap is a temporary mapping to allow genesis scripts 14 | // written in the v0 specification to be backwards compatible with v1 scripts. 15 | // The major difference is that v1 did not have namespaces for the standard library 16 | // where as v1 implements them with a deprecation and v2 will remove them entirely 17 | NamespaceConversionMap = map[string]*LegacyFunctionCall{} 18 | ) 19 | 20 | // LegacyLibrary defines one of the original standard library golang packages 21 | // for backward compatibility during linking to associate global namespace 22 | // function calls with the v1 package style 23 | type LegacyLibrary struct { 24 | // name of the owning package in the legacy standard library 25 | Name string `yaml:"package"` 26 | 27 | // path to the golang file located in which this library is implemented 28 | Path string `yaml:"path"` 29 | 30 | // file set for the AST walk and re-write 31 | FSet *token.FileSet `yaml:"-"` 32 | 33 | // Golang AST representation of the library's source file 34 | AST *ast.File `yaml:"-"` 35 | 36 | // map of the function names to their LegacyFunctionCall objects 37 | Funcs map[string]*LegacyFunctionCall `yaml:"-"` 38 | 39 | // the raw file data for the legacy library source 40 | Source []byte `yaml:"-"` 41 | } 42 | 43 | // LegacyFunctionCall uses the old generator to represent v0 standard library 44 | // functions so they can be deprecated in subsequent versions without 45 | // forcing users to convert all v0 scripts to v1 at this time 46 | type LegacyFunctionCall struct { 47 | // name of the legacy function 48 | Name string `yaml:"name"` 49 | 50 | // description of the legacy function 51 | Description string `yaml:"description"` 52 | 53 | // owner of the legacy function 54 | Author string `yaml:"author"` 55 | 56 | // package name the legacy function is in 57 | Package string `yaml:"package"` 58 | 59 | // the expected arguments to the legacy function call 60 | ExpectedArgTypes []LegacyArgDef `yaml:"args"` 61 | 62 | // the expected returns to the legacy function call 63 | ExpectedReturnTypes []LegacyRetDef `yaml:"returns"` 64 | } 65 | 66 | // LegacyArgDef is used by LegacyFunctionCall objects to create mappings for 67 | // legacy function argument's for the linker to inject into the build 68 | type LegacyArgDef struct { 69 | // the name of the argument passed into the function 70 | Name string `yaml:"label"` 71 | 72 | // the golang type argument is expected to be 73 | GoType string `yaml:"gotype"` 74 | } 75 | 76 | // LegacyRetDef is used by LegacyFunctionCall objects to create mappings for 77 | // legacy return values for the linker to inject into the build 78 | type LegacyRetDef struct { 79 | // name of the rerturn value parameter 80 | Name string `yaml:"label"` 81 | 82 | // the golang type return parameter is expected to be 83 | GoType string `yaml:"gotype"` 84 | 85 | // optional value to determine if you wish to return this value to the VM 86 | ReturnToVM bool `yaml:"return,omitempty"` 87 | } 88 | 89 | // FunctionCall contains information relating to a Golang native function call 90 | // that is being used within a genesis vm 91 | type FunctionCall struct { 92 | // genesis vm namespace the function call corrasponds to 93 | Namespace string 94 | 95 | // name of the function call as used in the genesis vm 96 | FuncName string 97 | 98 | // list of arguments passed to the genesis vm function caller 99 | ArgumentList []gast.Expression 100 | } 101 | 102 | // genesisWalker is a type used to recursively walk the genesis vm AST 103 | type genesisWalker struct { 104 | // reference to the parent genesis VM object 105 | vm *GenesisVM 106 | 107 | // source as represented as text 108 | source string 109 | 110 | // offset record used during the AST talk 111 | shift file.Idx 112 | 113 | err error 114 | } 115 | 116 | func (g *genesisWalker) Enter(n gast.Node) gast.Visitor { 117 | switch a := n.(type) { 118 | case *gast.CallExpression: 119 | switch b := a.Callee.(type) { 120 | case *gast.DotExpression: 121 | fnName := b.Identifier.Name 122 | switch c := b.Left.(type) { 123 | case *gast.Identifier: 124 | if _, ok := g.vm.GoPackageByNamespace[c.Name]; !ok { 125 | return g 126 | } 127 | // we got em :) adding to the gopackge vm caller table 128 | gop := g.vm.GoPackageByNamespace[c.Name] 129 | gop.ScriptCallers[fnName] = &FunctionCall{ 130 | Namespace: c.Name, 131 | FuncName: fnName, 132 | ArgumentList: a.ArgumentList, 133 | } 134 | case *gast.DotExpression: 135 | switch pp := c.Left.(type) { 136 | case *gast.Identifier: 137 | if pp.Name != "G" { 138 | return g 139 | } 140 | // found a call to the standard library 141 | fnName := b.Identifier.Name 142 | pkgName := c.Identifier.Name 143 | gop, err := g.vm.EnableStandardLibrary(pkgName) 144 | if err == nil { 145 | gop.ScriptCallers[fnName] = &FunctionCall{ 146 | Namespace: pkgName, 147 | FuncName: fnName, 148 | ArgumentList: a.ArgumentList, 149 | } 150 | return g 151 | } 152 | g.err = err 153 | return nil 154 | } 155 | default: 156 | // caller's left side was not an identifier (probably a function) 157 | // move on 158 | return g 159 | } 160 | } 161 | } 162 | return g 163 | } 164 | 165 | func (g *genesisWalker) Exit(n gast.Node) { 166 | // we done here - bye! 167 | return 168 | } 169 | -------------------------------------------------------------------------------- /compiler/preprocessor.go: -------------------------------------------------------------------------------- 1 | package compiler 2 | 3 | import ( 4 | "fmt" 5 | "regexp" 6 | 7 | gast "github.com/robertkrimen/otto/ast" 8 | ) 9 | 10 | var ( 11 | basicMacro = `(?P\S*)\z` 12 | goImportMacro = `(?P\S*?) as (?P\w*)\z` 13 | 14 | validMacros = map[string]*regexp.Regexp{ 15 | "import": generateMacroRegexp("import", basicMacro), 16 | "priority": generateMacroRegexp("priority", basicMacro), 17 | "os": generateMacroRegexp("os", basicMacro), 18 | "timeout": generateMacroRegexp("timeout", basicMacro), 19 | "arch": generateMacroRegexp("arch", basicMacro), 20 | "version": generateMacroRegexp("version", basicMacro), 21 | "lib": generateMacroRegexp("lib", basicMacro), 22 | "go_import": generateMacroRegexp("go_import", goImportMacro), 23 | } 24 | 25 | // DefaultPriority is the default value for a script's priority during execution 26 | DefaultPriority = 100 27 | 28 | // DefaultTimeout is the default time in seconds a script will be allowed to run 29 | DefaultTimeout = 30 30 | ) 31 | 32 | // Macro defines the object created by each macro parsed by the preprocessor 33 | type Macro struct { 34 | // the genesis compiler option's name for this macro 35 | Key string 36 | 37 | // map of the values associated with this macro 38 | Params map[string]string 39 | } 40 | 41 | // ScanForMacros takes the genesis comments from the AST and parses known 42 | // macros out for the compiler 43 | func ScanForMacros(commentMap gast.CommentMap) []*Macro { 44 | macros := []*Macro{} 45 | for _, tmp := range commentMap { 46 | for _, comment := range tmp { 47 | for name, res := range validMacros { 48 | if res.MatchString(comment.Text) { 49 | keys := res.SubexpNames() 50 | matches := res.FindAllStringSubmatch(comment.Text, -1)[0] 51 | keymap := map[string]string{} 52 | mac := &Macro{} 53 | for i, n := range matches { 54 | if i < 2 { 55 | continue 56 | } 57 | keymap[keys[i]] = n 58 | } 59 | mac.Key = name 60 | mac.Params = keymap 61 | macros = append(macros, mac) 62 | } 63 | } 64 | } 65 | } 66 | return macros 67 | } 68 | 69 | // used to create the composable macro regular expressions at compile time 70 | func generateMacroRegexp(name, valRegExp string) *regexp.Regexp { 71 | return regexp.MustCompile(fmt.Sprintf("\\A(?P%s):%s", name, valRegExp)) 72 | } 73 | -------------------------------------------------------------------------------- /compiler/templates/debugger.gs: -------------------------------------------------------------------------------- 1 | function Deploy() { 2 | DebugConsole(); 3 | } -------------------------------------------------------------------------------- /compiler/templates/entrypoint.go.tmpl: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "syscall" 4 | 5 | func main() { 6 | {{ if and $.IsProductionBuild (ne targetOS "windows") -}} 7 | // gracefully exit when receiving signals that would usually print stack traces 8 | sigs := make(chan os.Signal, 1) 9 | //signal.Notify(sigs, syscall.SIGQUIT, syscall.SIGILL, syscall.SIGTRAP, syscall.SIGABRT, syscall.SIGSTKFLT, syscall.SIGSYS) 10 | signal.Notify(sigs, syscall.SIGQUIT, syscall.SIGILL, syscall.SIGTRAP, syscall.SIGABRT, syscall.SIGSYS) 11 | go func() { 12 | for { 13 | _ = <- sigs 14 | os.Exit(0) 15 | } 16 | }() 17 | {{- end }} 18 | {{ if $.IsProductionBuild -}} 19 | // make sure any panics are swallowed to prevent stack traces 20 | defer func() { 21 | if r := recover(); r != nil { 22 | os.Exit(0) 23 | } 24 | }() 25 | {{- end }} 26 | var wg sync.WaitGroup 27 | {{- range $_, $pri := $.UniqPriorities }} 28 | {{- range $_, $vm := (index $.SortedVMs $pri) }} 29 | wg.Add(1) 30 | go func() { 31 | {{ if $.IsProductionBuild -}} 32 | // make sure any panics are swallowed to prevent stack traces 33 | defer func() { 34 | if r := recover(); r != nil { 35 | os.Exit(0) 36 | } 37 | }() 38 | {{- end }} 39 | 40 | defer wg.Done() 41 | a{{ $vm.ID }} := New{{ $vm.ID }}() 42 | if a{{ $vm.ID }} == nil { 43 | return 44 | } 45 | err := a{{ $vm.ID }}.{{ $vm.FunctionKey "import_assets" }}() 46 | if err != nil { 47 | a{{ $vm.ID }}.E.Logger.Errorf("Error importing assets for VM %s: %v", "{{ $vm.ID }}", err) 48 | return 49 | } 50 | err = a{{ $vm.ID }}.{{ $vm.FunctionKey "import_standard_library" }}() 51 | if err != nil { 52 | a{{ $vm.ID }}.E.Logger.Errorf("Error injecting standard library for VM %s: %v", "{{ $vm.ID }}", err) 53 | return 54 | } 55 | err = a{{ $vm.ID }}.{{ $vm.FunctionKey "preload" }}() 56 | if err != nil { 57 | a{{ $vm.ID }}.E.Logger.Errorf("Error for preloading %s: %v", "{{ $vm.ID }}", err) 58 | return 59 | } 60 | err = a{{ $vm.ID }}.{{ $vm.FunctionKey "import_native" }}() 61 | if err != nil { 62 | a{{ $vm.ID }}.E.Logger.Errorf("Error importing native VM %s: %v", "{{ $vm.ID }}", err) 63 | return 64 | } 65 | err = a{{ $vm.ID }}.{{ $vm.FunctionKey "import_script" }}() 66 | if err != nil { 67 | a{{ $vm.ID }}.E.Logger.Errorf("Error importing script for VM %s: %v", "{{ $vm.ID }}", err) 68 | return 69 | } 70 | err = a{{ $vm.ID }}.{{ $vm.FunctionKey "execute" }}() 71 | if err != nil { 72 | a{{ $vm.ID }}.E.Logger.Errorf("Error executing VM %s: %v", "{{ $vm.ID }}", err) 73 | return 74 | } 75 | }() 76 | {{ end -}} 77 | wg.Wait() 78 | {{ end -}} 79 | } 80 | 81 | func g(k rune, b []rune) string { 82 | for i := range b { 83 | b[i] ^= k 84 | k ^= b[i] 85 | } 86 | q := string(0x22) 87 | s, _ := strconv.Unquote(q + string(b) + q) 88 | return s 89 | } 90 | 91 | // --- Tangled Hairs Below 92 | // 93 | 94 | 95 | -------------------------------------------------------------------------------- /compiler/templates/hard_reserved: -------------------------------------------------------------------------------- 1 | gscript 2 | gen0cide 3 | GSCRIPT 4 | OTTO 5 | main[[:word:]\.\\/ ]*? 6 | Engine[[:word:]\.\\/ ]*? 7 | NullLogger[[:word:]\.\\/ ]*? 8 | engine 9 | Engine 10 | new 11 | \.go: -------------------------------------------------------------------------------- /compiler/templates/obfstring.go.tmpl: -------------------------------------------------------------------------------- 1 | // {{ $.ID }} contains an encrypted representation of the string "{{ $.Value }}" 2 | var {{ $.ID }} = []rune{ 3 | {{- range $idx, $b := $.Data -}} 4 | {{- if mod $idx 7 -}} 5 | {{ printf "\n\t" }} 6 | {{- end -}} 7 | {{ printf "0x%x, " $b -}} 8 | {{ end }} 9 | } 10 | -------------------------------------------------------------------------------- /compiler/templates/preload.gs: -------------------------------------------------------------------------------- 1 | function StringToByteArray(s) { 2 | var data = []; 3 | for (var i = 0; i < s.length; i++) { 4 | data.push(s.charCodeAt(i)); 5 | } 6 | return data; 7 | } 8 | 9 | function ByteArrayToString(a) { 10 | return String.fromCharCode.apply(String, a); 11 | } 12 | 13 | function Dump(obj) { 14 | return "\n" + JSON.stringify(obj, null, 2); 15 | } 16 | 17 | function BeforeDeploy() { 18 | return true; 19 | } 20 | 21 | function Deploy() { 22 | return false; 23 | } 24 | 25 | function AfterDeploy() { 26 | return true; 27 | } 28 | 29 | function OnError() { 30 | return false; 31 | } 32 | 33 | function Sleep(seconds) { 34 | var start = new Date().getTime(); 35 | for (var i = 0; i < 1e7; i++) { 36 | if ((new Date().getTime() - start) > (seconds * 1000)) { 37 | break; 38 | } 39 | } 40 | } 41 | 42 | function DebugConsole() { 43 | return true; 44 | } -------------------------------------------------------------------------------- /compiler/templates/soft_reserved: -------------------------------------------------------------------------------- 1 | google 2 | gopkg 3 | UPX 4 | otto 5 | Otto -------------------------------------------------------------------------------- /compiler/translator/translator.go: -------------------------------------------------------------------------------- 1 | package translator 2 | 3 | // type BuiltInConverter func(t string) (string, error) 4 | 5 | var ( 6 | //BuiltInMap defines various mappings that need to exist between the virtual machine and golang 7 | BuiltInMap = map[string]string{ 8 | "int": "int64", 9 | "uintptr": "int64", 10 | } 11 | 12 | // TypeAliasMap maps a package to it's various type alias conversion types 13 | TypeAliasMap = map[string]TypeAliasToBuiltIn{ 14 | "syscall": TypeAliasToBuiltIn{ 15 | "Signal": "int", 16 | }, 17 | "time": TypeAliasToBuiltIn{ 18 | "Duration": "int64", 19 | }, 20 | } 21 | ) 22 | 23 | // TypeAliasToBuiltIn maps package type aliases to built in types for conversion 24 | type TypeAliasToBuiltIn map[string]string 25 | -------------------------------------------------------------------------------- /debugger/debugger.go: -------------------------------------------------------------------------------- 1 | package debugger 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/gen0cide/gscript/engine" 7 | "github.com/gen0cide/gscript/logger" 8 | "github.com/gen0cide/gscript/logger/standard" 9 | ) 10 | 11 | // Debugger is a wrapper type for handling interactive debug consoles in the genesis engine 12 | type Debugger struct { 13 | VM *engine.Engine 14 | Logger logger.Logger 15 | OldLogger logger.Logger 16 | } 17 | 18 | // New returns a new debugger object wrapping the provided engine 19 | func New(e *engine.Engine) *Debugger { 20 | dbgLogger := standard.NewStandardLogger(nil, "gscript", "debugger", false, true) 21 | dbg := &Debugger{ 22 | VM: e, 23 | Logger: dbgLogger, 24 | OldLogger: e.Logger, 25 | } 26 | return dbg 27 | } 28 | 29 | // InjectDebugConsole injects the DebugConsole command into the runtime 30 | func (d *Debugger) InjectDebugConsole() error { 31 | d.VM.VM.Set("_DEBUGGER", d) 32 | err := d.VM.VM.Set("DebugConsole", d.vmDebugConsole) 33 | if err != nil { 34 | return err 35 | } 36 | err = d.VM.VM.Set("SymbolTable", d.vmSymbolTable) 37 | if err != nil { 38 | return err 39 | } 40 | err = d.VM.VM.Set("TypeTable", d.vmTypeTable) 41 | if err != nil { 42 | return err 43 | } 44 | err = d.VM.VM.Set("ConstTable", d.vmConstTable) 45 | if err != nil { 46 | return err 47 | } 48 | err = d.VM.VM.Set("VarTable", d.vmVarTable) 49 | if err != nil { 50 | return err 51 | } 52 | err = d.VM.VM.Set("Docs", d.vmPackageDocs) 53 | if err != nil { 54 | return err 55 | } 56 | 57 | return d.VM.VM.Set("TypeOf", d.vmTypeChecker) 58 | } 59 | 60 | // AvailableFuncs returns the current debugger's symbol table 61 | func (d *Debugger) AvailableFuncs() map[string][]string { 62 | ret := map[string][]string{} 63 | for name, p := range d.VM.Packages { 64 | flist := []string{} 65 | idx := 0 66 | for _, f := range p.SymbolTable { 67 | flist = append(flist, fmt.Sprintf("%d) %s", idx, f.Signature)) 68 | idx++ 69 | } 70 | if len(flist) > 0 { 71 | ret[name] = flist 72 | } 73 | } 74 | return ret 75 | } 76 | 77 | // AvailableTypes generates a type table for the debugger 78 | func (d *Debugger) AvailableTypes() map[string][]string { 79 | ret := map[string][]string{} 80 | for name, p := range d.VM.Packages { 81 | tlist := []string{} 82 | idx := 0 83 | for tn := range p.Types { 84 | tlist = append(tlist, fmt.Sprintf("%d) %s.%s", idx, name, tn)) 85 | idx++ 86 | } 87 | if len(tlist) > 0 { 88 | ret[name] = tlist 89 | } 90 | } 91 | return ret 92 | } 93 | 94 | // AvailableConsts generates a const symbol table for the debugger 95 | func (d *Debugger) AvailableConsts() map[string][]string { 96 | ret := map[string][]string{} 97 | for name, p := range d.VM.Packages { 98 | clist := []string{} 99 | idx := 0 100 | for c, cv := range p.Consts { 101 | clist = append(clist, fmt.Sprintf("%d) %s.%s = %v", idx, name, c, cv.Value)) 102 | idx++ 103 | } 104 | if len(clist) > 0 { 105 | ret[name] = clist 106 | } 107 | } 108 | return ret 109 | } 110 | 111 | // AvailableVars generates a var symbol table for the debugger 112 | func (d *Debugger) AvailableVars() map[string][]string { 113 | ret := map[string][]string{} 114 | for name, p := range d.VM.Packages { 115 | vlist := []string{} 116 | idx := 0 117 | for vname, va := range p.Vars { 118 | vlist = append(vlist, fmt.Sprintf("%d) %s.%s (%s)", idx, name, vname, va.Signature)) 119 | idx++ 120 | } 121 | if len(vlist) > 0 { 122 | ret[name] = vlist 123 | } 124 | } 125 | return ret 126 | } 127 | -------------------------------------------------------------------------------- /debugger/repl.go: -------------------------------------------------------------------------------- 1 | package debugger 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "os" 7 | "os/user" 8 | "path/filepath" 9 | 10 | "github.com/fatih/color" 11 | "github.com/gen0cide/gscript/logger/standard" 12 | "github.com/gohxs/readline" 13 | isatty "github.com/mattn/go-isatty" 14 | "github.com/robertkrimen/otto" 15 | ) 16 | 17 | func (d *Debugger) runDebugger() error { 18 | prompt := fmt.Sprintf("%s%s", color.HiRedString("gscript"), color.HiWhiteString("> ")) 19 | 20 | var err error 21 | 22 | interactive := isatty.IsTerminal(os.Stdout.Fd()) && isatty.IsTerminal(os.Stdin.Fd()) 23 | cygwin := isatty.IsCygwinTerminal(os.Stdout.Fd()) && isatty.IsCygwinTerminal(os.Stdin.Fd()) 24 | 25 | var stdin io.ReadCloser 26 | if cygwin { 27 | stdin = os.Stdin 28 | } else { 29 | stdin = readline.Stdin 30 | } 31 | 32 | var histfile string 33 | cu, err := user.Current() 34 | if err != nil { 35 | return err 36 | } 37 | histfile = filepath.Join(cu.HomeDir, ".gscript_history") 38 | 39 | if interactive { 40 | stdin = readline.NewCancelableStdin(stdin) 41 | } 42 | 43 | // create readline instance 44 | rl, err := readline.NewEx(&readline.Config{ 45 | HistoryFile: histfile, 46 | InterruptPrompt: "^C", 47 | Stdin: stdin, 48 | Stdout: color.Output, 49 | Stderr: color.Output, 50 | Prompt: prompt, 51 | FuncIsTerminal: func() bool { 52 | return interactive || cygwin 53 | }, 54 | FuncFilterInputRune: func(r rune) (rune, bool) { 55 | if r == readline.CharCtrlZ { 56 | return r, false 57 | } 58 | return r, true 59 | }, 60 | }) 61 | if err != nil { 62 | return err 63 | } 64 | 65 | standard.PrintLogo() 66 | title := fmt.Sprintf( 67 | "%s %s %s %s", 68 | color.HiWhiteString("***"), 69 | color.HiRedString("GSCRIPT"), 70 | color.YellowString("INTERACTIVE SHELL"), 71 | color.HiWhiteString("***"), 72 | ) 73 | fmt.Fprintf(color.Output, "%s\n", title) 74 | rl.Refresh() 75 | 76 | for { 77 | l, err := rl.Readline() 78 | if err != nil { 79 | if err == readline.ErrInterrupt { 80 | if d != nil { 81 | d = nil 82 | rl.SetPrompt(prompt) 83 | rl.Refresh() 84 | continue 85 | } 86 | break 87 | } 88 | return err 89 | } 90 | if l == "" { 91 | continue 92 | } 93 | if l == "exit" { 94 | break 95 | } 96 | if l == "halt" { 97 | fmt.Println("") 98 | os.Exit(0) 99 | } 100 | s, err := d.VM.VM.Compile("debugger", l) 101 | if err != nil { 102 | d.Logger.Errorf("%v", err) 103 | rl.SetPrompt(prompt) 104 | rl.Refresh() 105 | continue 106 | } 107 | v, err := d.VM.VM.Eval(s) 108 | if err != nil { 109 | if oerr, ok := err.(*otto.Error); ok { 110 | d.Logger.Error(oerr.Error()) 111 | } else { 112 | d.Logger.Error(err.Error()) 113 | } 114 | } else { 115 | rl.Write([]byte(fmt.Sprintf(">>> %s\n", v.String()))) 116 | } 117 | rl.Refresh() 118 | } 119 | 120 | return rl.Close() 121 | } 122 | -------------------------------------------------------------------------------- /debugger/vm_functions.go: -------------------------------------------------------------------------------- 1 | package debugger 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | 7 | "github.com/davecgh/go-spew/spew" 8 | "github.com/fatih/color" 9 | "github.com/robertkrimen/otto" 10 | ) 11 | 12 | func (d *Debugger) vmDebugConsole(call otto.FunctionCall) otto.Value { 13 | d.VM.SetLogger(d.Logger) 14 | d.VM.Paused = true 15 | d.runDebugger() 16 | d.VM.Paused = false 17 | d.VM.SetLogger(d.OldLogger) 18 | return otto.UndefinedValue() 19 | } 20 | 21 | func (d *Debugger) vmVarTable(call otto.FunctionCall) otto.Value { 22 | vars := d.AvailableVars() 23 | for ns, va := range vars { 24 | d.Logger.Infof(">>> %s Package\n\t%s\n", ns, strings.Join(va, "\n\t")) 25 | } 26 | return otto.UndefinedValue() 27 | } 28 | 29 | func (d *Debugger) vmConstTable(call otto.FunctionCall) otto.Value { 30 | consts := d.AvailableConsts() 31 | for ns, cs := range consts { 32 | d.Logger.Infof(">>> %s Package\n\t%s\n", ns, strings.Join(cs, "\n\t")) 33 | } 34 | return otto.UndefinedValue() 35 | } 36 | 37 | func (d *Debugger) vmTypeTable(call otto.FunctionCall) otto.Value { 38 | types := d.AvailableTypes() 39 | for ns, ts := range types { 40 | d.Logger.Infof(">>> %s Package\n\t%s\n", ns, strings.Join(ts, "\n\t")) 41 | } 42 | return otto.UndefinedValue() 43 | } 44 | 45 | func (d *Debugger) vmSymbolTable(call otto.FunctionCall) otto.Value { 46 | sym := d.AvailableFuncs() 47 | for ns, funcs := range sym { 48 | d.Logger.Infof(">>> %s Package\n\t%s\n", ns, strings.Join(funcs, "\n\t")) 49 | } 50 | return otto.UndefinedValue() 51 | } 52 | 53 | func (d *Debugger) vmPackageDocs(call otto.FunctionCall) otto.Value { 54 | if len(call.ArgumentList) != 1 { 55 | return d.VM.Raise("arg", "must provide one string argument to Docs()") 56 | } 57 | val, err := call.Argument(0).Export() 58 | if err != nil { 59 | return d.VM.Raise("jsexport", "coult not convert argument number 0") 60 | } 61 | 62 | realval, ok := val.(string) 63 | if !ok { 64 | return d.VM.Raise("type", "argument was not of type string") 65 | } 66 | 67 | consts := d.AvailableConsts() 68 | types := d.AvailableTypes() 69 | funcs := d.AvailableFuncs() 70 | vars := d.AvailableVars() 71 | 72 | cl, clok := consts[realval] 73 | tl, tlok := types[realval] 74 | fl, flok := funcs[realval] 75 | vl, vlok := vars[realval] 76 | 77 | if !clok && !tlok && !flok && !vlok { 78 | return d.VM.Raise("undefined", "package is not defined in this genesis engine") 79 | } 80 | 81 | title := fmt.Sprintf(">> Package Documentation: %s\n\n", realval) 82 | 83 | contstext := fmt.Sprintf("\n %s\n\t%s\n", color.HiYellowString("-- CONSTS --"), strings.Join(cl, "\n\t")) 84 | varstext := fmt.Sprintf("\n %s\n\t%s\n", color.HiYellowString("-- VARS --"), strings.Join(vl, "\n\t")) 85 | typestext := fmt.Sprintf("\n %s\n\t%s\n", color.HiYellowString("-- TYPES --"), strings.Join(tl, "\n\t")) 86 | funcstext := fmt.Sprintf("\n %s\n\t%s\n", color.HiYellowString("-- FUNCS --"), strings.Join(fl, "\n\t")) 87 | 88 | finaltext := strings.Join([]string{title, contstext, varstext, typestext, funcstext}, "") 89 | 90 | d.Logger.Infof("%s", finaltext) 91 | return otto.UndefinedValue() 92 | } 93 | 94 | func (d *Debugger) vmTypeChecker(call otto.FunctionCall) otto.Value { 95 | if len(call.ArgumentList) == 0 { 96 | return d.VM.Raise("arg", "no argument provided") 97 | } else if len(call.ArgumentList) == 1 { 98 | val, err := call.Argument(0).Export() 99 | if err != nil { 100 | return d.VM.Raise("jsexport", "could not convert argument number 0") 101 | } 102 | retVal, _ := call.Otto.ToValue(spew.Sdump(val)) 103 | return retVal 104 | } else { 105 | return d.VM.Raise("arg", "too many arguments provided") 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /docs/ARCHITECTURE.md: -------------------------------------------------------------------------------- 1 | # Genesis Scripting Architecture -------------------------------------------------------------------------------- /docs/COMPILER.md: -------------------------------------------------------------------------------- 1 | # Genesis Compiler -------------------------------------------------------------------------------- /docs/DEFCON26_SLIDES.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gen0cide/gscript/d65a5ce55f79c4f544a93997e7eb635a72a64118/docs/DEFCON26_SLIDES.pdf -------------------------------------------------------------------------------- /docs/DEFCON26_WORKSHOP.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gen0cide/gscript/d65a5ce55f79c4f544a93997e7eb635a72a64118/docs/DEFCON26_WORKSHOP.pdf -------------------------------------------------------------------------------- /docs/ENGINE.md: -------------------------------------------------------------------------------- 1 | # Genesis Engine -------------------------------------------------------------------------------- /docs/GETTING_STARTED.md: -------------------------------------------------------------------------------- 1 | # Getting Started -------------------------------------------------------------------------------- /docs/STANDARD_LIBRARY.md: -------------------------------------------------------------------------------- 1 | # Genesis Scripting Standard Library -------------------------------------------------------------------------------- /docs/examples/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gen0cide/gscript/d65a5ce55f79c4f544a93997e7eb635a72a64118/docs/examples/.gitkeep -------------------------------------------------------------------------------- /docs/stdlib/_template.md: -------------------------------------------------------------------------------- 1 | # Package: asset 2 | 3 | Handles embedded assets. 4 | 5 | ## Function Index 6 | 7 | * Foo 8 | * Bar 9 | 10 | ## Details 11 | 12 | ### GetAssetAsString 13 | 14 | **Author:** gen0cide 15 | 16 | **Description:** fizzbuzz 17 | 18 | **Method Signature:** 19 | 20 | ``` 21 | GetAssetAsString(name string) (string, error) 22 | ``` 23 | 24 | **Arguments:** 25 | 26 | | Label | Type | Description | 27 | |---------|--------------|------------------------------| 28 | | `name` | `string` | name of the asset | 29 | 30 | **Returns:** 31 | 32 | | Position | Type | Description | 33 | |----------|--------------|------------------------------| 34 | | `0` | `string` | Asset bytes as a string | 35 | | `1` | `error` | (optional) function error | 36 | 37 | **Example Usage:** 38 | 39 | ``` 40 | // when an asset was embedded into a binary 41 | var asset = G.asset.GetAssetAsString("real.txt"); 42 | console.log(asset[0]); 43 | // => "contents of real.txt" 44 | console.log(asset[1]); 45 | // => null 46 | 47 | // if you call the wrong asset name 48 | var asset2 = G.asset.GetAssetAsString("notreal.txt"); 49 | console.log(asset[0]); 50 | // => "" 51 | console.log(asset[1]); 52 | // => "error msg..." 53 | ``` 54 | 55 | - 56 | -------------------------------------------------------------------------------- /docs/stdlib/asset.md: -------------------------------------------------------------------------------- 1 | # Package: asset -------------------------------------------------------------------------------- /docs/stdlib/encoding.md: -------------------------------------------------------------------------------- 1 | # Package: encoding 2 | 3 | ## Function Index 4 | 5 | - DecodeBase64(data string) (string, error) 6 | - EncodeBase64(data string) string 7 | - EncodeStringAsBytes(data string) []byte 8 | - EncodeBytesAsString(data []byte) string 9 | 10 | ## Details 11 | 12 | ### DecodeBase64 13 | 14 | **Author:** ahhh 15 | 16 | **Description:** decodes a base64 string and returns a string 17 | 18 | **Method Signature:** 19 | 20 | ``` 21 | DecodeBase64(data string) string 22 | ``` 23 | 24 | **Arguments:** 25 | 26 | | Label | Type | Description | 27 | |-----------|--------------|--------------------------------------------| 28 | | `data` | `string` | the data to base64 decode | 29 | 30 | **Returns:** 31 | 32 | | Position | Type | Description | 33 | |-----------|--------------|--------------------------------------------| 34 | | `0` | `string` | the decoded string | 35 | | `1` | `error` | (optional) function error | 36 | 37 | **Example Usage:** 38 | 39 | ``` 40 | 41 | ``` 42 | 43 | ### EncodeBase64 44 | 45 | **Author:** ahhh 46 | 47 | **Description:** encodes a string and returns a base64 string 48 | 49 | **Method Signature:** 50 | 51 | ``` 52 | EncodeBase64(data string) string 53 | ``` 54 | 55 | **Arguments:** 56 | 57 | | Label | Type | Description | 58 | |-----------|--------------|--------------------------------------------| 59 | | `data` | `string` | the string to encoded | 60 | 61 | **Returns:** 62 | 63 | | Position | Type | Description | 64 | |-----------|--------------|--------------------------------------------| 65 | | `0` | `string` | the encoded base64 string | 66 | 67 | **Example Usage:** 68 | 69 | ``` 70 | var b64 = G.encoding.EncodeBase64("hello world"); 71 | ``` 72 | 73 | ### EncodeStringAsBytes 74 | 75 | **Author:** ahhh 76 | 77 | **Description:** decodes a base64 string and returns a string 78 | 79 | **Method Signature:** 80 | 81 | ``` 82 | EncodeStringAsBytes(data string) []bytes 83 | ``` 84 | 85 | **Arguments:** 86 | 87 | | Label | Type | Description | 88 | |-----------|--------------|--------------------------------------------| 89 | | `data` | `string` | the string to bytes | 90 | 91 | **Returns:** 92 | 93 | | Position | Type | Description | 94 | |-----------|--------------|--------------------------------------------| 95 | | `0` | `[]bytes` | the bytes of the string | 96 | 97 | **Example Usage:** 98 | 99 | ``` 100 | var bytes = encoding.EncodeStringAsBytes("test"); 101 | ``` 102 | 103 | ### EncodeBytesAsString 104 | 105 | **Author:** ahhh 106 | 107 | **Description:** decodes a base64 string and returns a string 108 | 109 | **Method Signature:** 110 | 111 | ``` 112 | EncodeBytesAsString(data []bytes) string 113 | ``` 114 | 115 | **Arguments:** 116 | 117 | | Label | Type | Description | 118 | |-----------|--------------|--------------------------------------------| 119 | | `data` | `[]bytes` | the data to turn to a string | 120 | 121 | **Returns:** 122 | 123 | | Position | Type | Description | 124 | |-----------|--------------|--------------------------------------------| 125 | | `0` | `string` | the string from the bytes | 126 | 127 | **Example Usage:** 128 | 129 | ``` 130 | var bytes = encoding.EncodeStringAsBytes("test"); 131 | var bstring = encoding.EncodeBytesAsString(bytes); 132 | ``` 133 | -------------------------------------------------------------------------------- /docs/stdlib/exec.md: -------------------------------------------------------------------------------- 1 | # Package: exec 2 | 3 | ## Function Index 4 | 5 | - ExecuteCommand(progname string, args []string) (pid int, stdout string, stderr string, exitCode int, err error) 6 | - ExecuteCommandAsync(progname string, args []string) (proc *exec.Cmd, err error) 7 | 8 | ## Details 9 | 10 | ### ExecuteCommand 11 | 12 | **Author:** ahhh 13 | 14 | **Description:** Executes a single command and waits for it to complete 15 | 16 | **Method Signature:** 17 | 18 | ``` 19 | ExecuteCommand(progname string, args []string) (pid int, stdout string, stderr string, exitCode int, err error) 20 | ``` 21 | 22 | **Arguments:** 23 | 24 | | Label | Type | Description | 25 | |-----------|--------------|--------------------------------------------| 26 | | `command` | `string` | The target command to run | 27 | |-----------|--------------|--------------------------------------------| 28 | | `args` | `[]string` | The arguments to command | 29 | 30 | **Returns:** 31 | 32 | | Position | Type | Description | 33 | |-----------|--------------|--------------------------------------------| 34 | | `0` | `int` | the pid of the executed program | 35 | | `1` | `string` | the stdout of the execute progam | 36 | | `2` | `string` | the stderr of the execute progam | 37 | | `3` | `int` | the exitcode of the executed program | 38 | | `4` | `error` | (optional) function error | 39 | 40 | **Example Usage:** 41 | 42 | ``` 43 | var exec = G.exec.ExecuteCommand("launchctl", ["submit", "-l", label, "--", name]); 44 | if (exec[4] == null) { 45 | console.log("Pid: "+exec[0]);; 46 | console.log("stdout: "+exec[1]); 47 | console.log("stderr: "+exec[2]); 48 | console.log("exit code: "+exec[3]); 49 | } else { 50 | console.log("go errors: "+exec[4].Error()) ; 51 | } 52 | ``` 53 | 54 | ### ExecuteCommandAsync 55 | 56 | **Author:** ahhh 57 | 58 | **Description:** Executes a single command but does not wait for it to complete 59 | 60 | **Method Signature:** 61 | 62 | ``` 63 | ExecuteCommandAsync(progname string, args []string) (proc *exec.Cmd, err error) 64 | ``` 65 | 66 | **Arguments:** 67 | 68 | | Label | Type | Description | 69 | |-----------|--------------|--------------------------------------------| 70 | | `command` | `string` | The target command to run | 71 | | `args` | `[]string` | The arguments to command | 72 | 73 | **Returns:** 74 | 75 | | Position | Type | Description | 76 | |-----------|------------------|--------------------------------------------| 77 | | `0` | `proc *exec.Cmd` | an exec/cmd object | 78 | | `1` | `error` | (optional) function error | 79 | 80 | **Example Usage:** 81 | 82 | ``` 83 | var fullpath = "/bin/cp" 84 | var running = G.exec.ExecuteCommandAsync(fullpath, ["arg1", "arg2"]); 85 | if (running[1] != null) { 86 | console.log("errors: "+running[1].Error()); 87 | } else { 88 | console.log("pid: "+running[0].Process.Pid); 89 | } 90 | ``` 91 | -------------------------------------------------------------------------------- /docs/stdlib/net.md: -------------------------------------------------------------------------------- 1 | # Package: net 2 | 3 | ## Function Index 4 | 5 | - CheckForInUseTCP(port int) (bool, error) 6 | - CheckForInUseUDP(port int) (bool, error) 7 | 8 | ## Details 9 | 10 | ### CheckForInUseTCP 11 | 12 | **Author:** ahhh 13 | 14 | **Description:** 15 | 16 | **Method Signature:** 17 | 18 | ``` 19 | CheckForInUseTCP(port int) (bool, error) 20 | ``` 21 | 22 | **Arguments:** 23 | 24 | | Label | Type | Description | 25 | |-----------|--------------|--------------------------------------------| 26 | | `port` | `int` | The target port to see if it's in use | 27 | 28 | **Returns:** 29 | 30 | | Position | Type | Description | 31 | |-----------|--------------|--------------------------------------------| 32 | | `0` | `bool` | is the port open or closed | 33 | | `1` | `error` | (optional) function error | 34 | 35 | **Example Usage:** 36 | 37 | ``` 38 | var response = G.net.CheckForInUseTCP(22); 39 | if (response[1] != null) { 40 | console.log("errors: " + response[1].Error()); 41 | } else { 42 | console.log("TCP port open: " + response[0]); 43 | } 44 | ``` 45 | 46 | ### CheckForInUseUDP 47 | 48 | **Author:** ahhh 49 | 50 | **Description:** 51 | 52 | **Method Signature:** 53 | 54 | ``` 55 | CheckForInUseUDP(port int) (bool, error) 56 | ``` 57 | 58 | **Arguments:** 59 | 60 | | Label | Type | Description | 61 | |-----------|--------------|--------------------------------------------| 62 | | `port` | `int` | The target port to see if it's in use | 63 | 64 | **Returns:** 65 | 66 | | Position | Type | Description | 67 | |-----------|--------------|--------------------------------------------| 68 | | `0` | `bool` | is the port open or closed | 69 | | `1` | `error` | (optional) function error | 70 | 71 | **Example Usage:** 72 | 73 | ``` 74 | var response = G.net.CheckForInUseUDP(161); 75 | if (response[1] != null) { 76 | console.log("errors: " + response[1].Error()); 77 | } else { 78 | console.log("TCP port open: " + response[0]); 79 | } 80 | ``` -------------------------------------------------------------------------------- /docs/stdlib/os.md: -------------------------------------------------------------------------------- 1 | # Package: os 2 | 3 | ## Function Index 4 | 5 | - TerminateSelf() error 6 | - TerminateVM() 7 | 8 | ## Details 9 | 10 | ### TerminateSelf 11 | 12 | **Author:** ahhh 13 | 14 | **Description:** TerminateSelf will kill the current process, this a dangerous function 15 | 16 | **Method Signature:** 17 | 18 | ``` 19 | TerminateSelf() error 20 | ``` 21 | 22 | **Arguments:** 23 | 24 | | Label | Type | Description | 25 | |-----------|--------------|--------------------------------------------| 26 | 27 | **Returns:** 28 | 29 | | Position | Type | Description | 30 | |-----------|--------------|--------------------------------------------| 31 | | `0` | `error` | (optional) function error | 32 | 33 | **Example Usage:** 34 | 35 | ``` 36 | if (check == true) { 37 | TerminateSelf(); 38 | } 39 | ``` 40 | -------------------------------------------------------------------------------- /docs/stdlib/rand.md: -------------------------------------------------------------------------------- 1 | # Package: rand 2 | 3 | ## Function Index 4 | 5 | - GetInt(min int, max int) int 6 | - GetAlphaNumericString(len int) string 7 | - GetAlphaString(len int) string 8 | - GetAlphaNumericSpecialString(len int) string 9 | - GetBool() bool 10 | 11 | ## Details 12 | 13 | ### GetInt 14 | 15 | **Author:** ahhh 16 | 17 | **Description:** RandomInt generates a random number between min and max 18 | 19 | **Method Signature:** 20 | 21 | ``` 22 | GetInt(min int, max int) int 23 | ``` 24 | 25 | **Arguments:** 26 | 27 | | Label | Type | Description | 28 | |-----------|--------------|--------------------------------------------| 29 | | `min` | `int` | the min range of int to will return | 30 | | `max` | `int` | the max range of int to will return | 31 | 32 | **Returns:** 33 | 34 | | Position | Type | Description | 35 | |-----------|--------------|--------------------------------------------| 36 | | `0` | `int` | a random int between min and max | 37 | 38 | **Example Usage:** 39 | 40 | ``` 41 | var out1 = G.rand.RandomInt(1, 10); 42 | console.log("out: "+out1); 43 | ``` 44 | 45 | ### GetAlphaNumericString 46 | 47 | **Author:** ahhh 48 | 49 | **Description:** GetAlphaNumericString Generates a random alpha numeric string of a specified length, all mixed case 50 | 51 | **Method Signature:** 52 | 53 | ``` 54 | GetAlphaNumericString(len int) string 55 | ``` 56 | 57 | **Arguments:** 58 | 59 | | Label | Type | Description | 60 | |-----------|--------------|--------------------------------------------| 61 | | `len` | `int` | length of random string to return | 62 | 63 | **Returns:** 64 | 65 | | Position | Type | Description | 66 | |-----------|--------------|--------------------------------------------| 67 | | `0` | `string` | a random Alphanumeric string of the length | 68 | 69 | **Example Usage:** 70 | 71 | ``` 72 | var out2 = G.rand.GetAlphaNumericString(4); 73 | console.log("out: " +out2); 74 | console.log("out upper: "+ out2.toUpperCase()); 75 | console.log("out lower: "+ out2.toLowerCase()); 76 | ``` 77 | 78 | ### GetAlphaString 79 | 80 | **Author:** ahhh 81 | 82 | **Description:** GetAlphaString generates a random alpha string of a specified length, all mixed case 83 | 84 | **Method Signature:** 85 | 86 | ``` 87 | GetAlphaString(len int) string 88 | ``` 89 | 90 | **Arguments:** 91 | 92 | | Label | Type | Description | 93 | |-----------|--------------|--------------------------------------------| 94 | | `len` | `int` | length of random string to return | 95 | 96 | **Returns:** 97 | 98 | | Position | Type | Description | 99 | |-----------|--------------|--------------------------------------------| 100 | | `0` | `string` | a random alpha string of the length | 101 | 102 | **Example Usage:** 103 | 104 | ``` 105 | var out3 = G.rand.GetAlphaString(5); 106 | console.log("out: "+ out3); 107 | console.log("out upper: "+ out3.toUpperCase()); 108 | console.log("out lower: "+ out3.toLowerCase()); 109 | ``` 110 | 111 | ### GetAlphaNumericSpecialString 112 | 113 | **Author:** ahhh 114 | 115 | **Description:** generates a random alphanumeric and special char string of a specified length 116 | 117 | **Method Signature:** 118 | 119 | ``` 120 | GetAlphaNumericSpecialString(len int) string 121 | ``` 122 | 123 | **Arguments:** 124 | 125 | | Label | Type | Description | 126 | |-----------|--------------|--------------------------------------------| 127 | | `len` | `int` | length of random string to return | 128 | 129 | **Returns:** 130 | 131 | | Position | Type | Description | 132 | |-----------|--------------|--------------------------------------------| 133 | | `0` | `string` | a random string of the length | 134 | 135 | **Example Usage:** 136 | 137 | ``` 138 | var out4 = G.rand.GetAlphaNumericSpecialString(6); 139 | console.log("out: "+ out4); 140 | console.log("out upper: "+ out4.toUpperCase()); 141 | console.log("out lower: "+ out4.toLowerCase()); 142 | ``` 143 | 144 | ### GetBool 145 | 146 | **Author:** ahhh 147 | 148 | **Description:** generates a random bool, true or false 149 | 150 | **Method Signature:** 151 | 152 | ``` 153 | GetBool() bool 154 | ``` 155 | 156 | **Arguments:** 157 | 158 | | Label | Type | Description | 159 | |-----------|--------------|--------------------------------------------| 160 | 161 | **Returns:** 162 | 163 | | Position | Type | Description | 164 | |-----------|--------------|--------------------------------------------| 165 | | `0` | `bool` | a random bool, true or false | 166 | 167 | **Example Usage:** 168 | 169 | ``` 170 | var out5 = G.rand.GetBool(); 171 | console.log("out: "+ out5); 172 | ``` -------------------------------------------------------------------------------- /docs/stdlib/time.md: -------------------------------------------------------------------------------- 1 | # Package: time 2 | 3 | ## Function Index 4 | 5 | - GetUnix() int 6 | 7 | ## Details 8 | 9 | ### GetMD5FromString 10 | 11 | **Author:** ahhh 12 | 13 | **Description:** GetUnix takes no input and returns the current 14 | 15 | 16 | **Method Signature:** 17 | 18 | ``` 19 | GetUnix() int64 20 | ``` 21 | 22 | **Arguments:** 23 | 24 | | Label | Type | Description | 25 | |-----------|--------------|--------------------------------------------| 26 | 27 | **Returns:** 28 | 29 | | Position | Type | Description | 30 | |-----------|--------------|--------------------------------------------| 31 | | `0` | `int` | the current unix timestamp | 32 | 33 | **Example Usage:** 34 | 35 | ``` 36 | var response = G.time.GetUnix(); 37 | console.log("Time: "+response); 38 | ``` -------------------------------------------------------------------------------- /docs/tutorials/01_installation.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | Welcome to the GSCRIPT install! 4 | 5 | ## Docker 6 | 7 | If you have docker installed, you can run: 8 | 9 | ```sh 10 | docker pull gen0cide/gscript:v1 11 | ``` 12 | 13 | Make a local directory where you can share files between your local machine and the docker container. Replace `$LOCAL_DIR` in the following command with the path to that: 14 | 15 | ```sh 16 | docker run -it -v $LOCAL_DIR:/root/share gen0cide/gscript:v1 17 | ``` 18 | 19 | ## Manually 20 | 21 | ### Download GSCRIPT 22 | 23 | First pull down the gscript command line utility or source. 24 | https://github.com/gen0cide/gscript (or your fork if you want to change things) 25 | Make sure you save this project in your `GOPATH`, i.e: 26 | 27 | ```sh 28 | $ echo $GOPATH 29 | ~/go/ 30 | ``` 31 | 32 | Then the save would go here: 33 | 34 | ```sh 35 | ~/go/src/github/gen0cide/gscript/ 36 | ``` 37 | 38 | Like so: 39 | 40 | ```sh 41 | mkdir -p ~/go/src/github/gen0cide/gscript/ && \ 42 | git clone https://github.com/gen0cide/gscript.git ~/go/src/github/gen0cide/gscript 43 | ``` 44 | 45 | 46 | ### Build GSCRIPT 47 | 48 | !!NOTE: This doesn't need to happen if you download gscript by doing `go get -a github.com/gen0cide/gscript/cmd/gscript` 49 | 50 | First we need to get all of the dependencies: 51 | 52 | ```sh 53 | go get github.com/faith/color 54 | go get github.com/robertkrimen/otto 55 | go get golang.org/x/tools 56 | go get github.com/vigneshuvi/GoDateFormat 57 | go get github.com/urfave/cli 58 | go get github.com/ahhh/gopkgs 59 | go get github.com/tdewolff/minify/js 60 | go get github.com/sirupsen/logrus 61 | ``` 62 | 63 | Then build the CLI tool: 64 | 65 | ```sh 66 | cd ~/go/src/github.com/gen0cide/gscript/cmd/gscript 67 | go build 68 | cp ./gscript /usr/local/bin/ 69 | gscript --help 70 | ``` 71 | -------------------------------------------------------------------------------- /docs/tutorials/02_cli_usage.md: -------------------------------------------------------------------------------- 1 | # GSCRIPT CLI Usage 2 | 3 | ## Basic Usage 4 | 5 | With lots of debugging and logging enabled: 6 | 7 | ```sh 8 | gscript --debug compile --enable-logging --obfuscation-level 3 /path/to/gscript.gs 9 | ``` 10 | 11 | With max obfuscation and no debugging: 12 | 13 | ```sh 14 | gscript c /path/to/gscript.gs 15 | ``` 16 | 17 | With multiple gscripts: 18 | 19 | ```sh 20 | gscript c /path/to/gscripts/*.gs 21 | ``` 22 | 23 | ## Basic Flags 24 | 25 | ```sh 26 | --help # prints the help menu 27 | --version # prints the version of gscript 28 | --debug # prints verbose output when the cli tool runs 29 | ``` 30 | 31 | ## Basic Commands 32 | 33 | ```sh 34 | gscript compile # The essential command for compiling gscripts into binaries 35 | gscript docs # Generate the docs localy for gscript 36 | gscript shell # Drop the user into the gscript repl 37 | gscript templates # Generate a starter gscript 38 | ``` 39 | 40 | ### Docs Options 41 | 42 | ```sh 43 | gscript docs macros # Generate macro docs 44 | gscript docs scripts # Generate script docs 45 | gscript docs stdlib # Generate stdlib docs 46 | ``` 47 | 48 | ### Templates Options 49 | 50 | ```sh 51 | gscript templates list # List all available templates 52 | gscript templates show # Show the specified template 53 | ``` 54 | 55 | ### Shell Options 56 | 57 | ```sh 58 | gscript shell # will drop the user into the gscript repl 59 | ``` 60 | 61 | ### Compile Options 62 | 63 | ```sh 64 | gscript compile --os # For specifying the platform to compile the target binary to 65 | gscript compile --arch # For specifying the archatecture to compile the target binary to 66 | gscript compile --output-file # For specifying an output file to save the final binary as opposed to a temp path 67 | gscript compile --keep-build-dir # For keeping the build directory that contains the intermediate golang to debug any gscript compiler issues 68 | gscript compile --enable-human-readable-names # This options is useful for debugging any potential linker issues. 69 | gscript compile --enable-debugging # This option only works with obfuscation disabled, it will drop the running vm into an interactive debugger with the fist instance of DebugConsole() 70 | gscript compile --enable-import-all-native-funcs # This options is useful for importing and linking all of the golang native libraries for when the user specifies the --enable-debugging option 71 | gscript compile --enable-logging # This flag is helpful for logging all of the console.log() functions output to stdout. Will only work when obfuscation is disabled. 72 | gscript compile --obfuscation-level # This flag takes a vale of 0-3 with 0 being the highest level obuscation and 3 being no obfuscation applied to the final binary. 73 | gscript compile --disable-native-compilation # This flag will specifically not compile the intermediate representation to a native binary (default: false) 74 | gscript compile --enable-test-build # This will enable the test harness in the build - for testing only! (default: false) 75 | gscript compile --enable-upx-compression # This will ompress the final binary using UPX (default: false) 76 | ``` 77 | -------------------------------------------------------------------------------- /docs/tutorials/03_gscript_basics.md: -------------------------------------------------------------------------------- 1 | # GSCRIPT Basics 2 | 3 | Writing gscripts is very simple, the syntax is a very loose JavaScript, 4 | giving you all native JavaScript functions. 5 | 6 | ## Things to know 7 | 8 | - JavaScript Engine 5 9 | That gives you these native functions: 10 | 11 | - You will want to be familiar w/ the native Lib 12 | These are helper GoLang functions we wrote just for GSCRIPT - You will want to read the native lib docs 13 | These will help you understand how to handle native lib return objects 14 | 15 | - You will want to read the GoDocs of any GoLang Native Library you use 16 | These are very helpful for understand the objects that things will return 17 | 18 | - You will want to Debug and Log when testing your scripts 19 | Read more about that in 4 and 5 20 | 21 | - You will want to use Obfuscation when deploying your scripts to your targets 22 | Read more about that in 9_5 23 | 24 | ## Writing Your First Script 25 | 26 | To start your first script, try a simple function like the one that follows: 27 | 28 | ```js 29 | function Deploy() { 30 | console.log("Hello World"); 31 | var out = G.rand.GetAlphaNumericString(4); 32 | console.log("out uppecase: " + out.toUpperCase()); 33 | } 34 | ``` 35 | 36 | ## Compiling Your First Script 37 | 38 | You will want to compile the above script with logging, such that you can see the output of 39 | your randomly generated string 40 | 41 | ```sh 42 | $ gscript compile --enable-logging --obfuscation-level 3 ./hello_world.gs 43 | ``` 44 | 45 | ## More simple examples 46 | 47 | - https://github.com/ahhh/gscripts/tree/master/attack/multi 48 | -------------------------------------------------------------------------------- /docs/tutorials/04_logging.md: -------------------------------------------------------------------------------- 1 | # Logging 2 | ## About Logging 3 | 4 | By default, gscript will disable and suppress all javascript logging, using 5 | 6 | ```sh 7 | > console.log("something to log") . 8 | ``` 9 | 10 | Logging is done by outputting the logged statements, and their associated javascript VM to the stdout where the compiled Genesis binary is running. 11 | 12 | This is done to protect the final binaries from reverse engineering and logging will only be included in the final binary when enabled. 13 | 14 | ## Enabling Logging 15 | 16 | To enable logging simple provide the `gscript compile` subcommand the `--enable-logging` switch. This will by default disable obfuscation and won't work when obfuscation has been explicitly enabled. Obfuscation disabled is equivalent to the cli flag `--obfuscation-level 3`. 17 | 18 | ### Example 19 | 20 | An example of this would look like: 21 | 22 | ```sh 23 | > gscript compile --obfuscation-level 3 --enable-logging /path/to/gscript.gs 24 | ``` 25 | 26 | ### Compiler Logging 27 | 28 | If you would like to get more verbose logs from the compiler itself, while building your GSCRIPTs and bundling your assets then you should use the `--debug` flag on the GSCRIPT binary before the subcomand. This will produce verbose logs on all GSCRIPT subcommands. 29 | -------------------------------------------------------------------------------- /docs/tutorials/05_debugging.md: -------------------------------------------------------------------------------- 1 | # Debugging 2 | 3 | ## Using The Interactive Debugger 4 | 5 | GSCRIPT includes the ability to drop into an interactive debugger using `DebugConsole()` function within a GSCRIPT. 6 | 7 | To enable this feature the `--enable-debugging` must be specified on the command line. Otherwise this function will be skipped in the final binary. Further, obfuscation can not be used when using the `--enable-debugging` command line flag. 8 | 9 | ### Useful Debugging Compiler Flags 10 | `--enable-debugging` - This is compiler flag that is used for dropping into the interactive GSCRIPT interpreter, and testing functions in GSCRIPT. 11 | `enable-import-all-native-funcs` - This can be extremely useful for testing native GoLang funcs in the interactive debugger, before writing a script that calls them. Normally the vm will only be compiled with the functions that are used in the script or namespace. 12 | `keep-build-dir` - This can be helpful for reviewing the intermediate representation before the source code is compiled down to a native binary. This is what comes from the templating and is useful for debugging compiler errors 13 | 14 | ### Useful Debugging functions 15 | `DebugConsole()` - This is the GSCRIPT function that will drop a running GSCRIPT into the interactive debugging console. It is often helpful to put these where you want to start debugging, after importing and using some functions. 16 | `TypeOf(object)` - This is a function only exposed in the interactive GSCRIPT debugger, but it will dump the GoLang types of the target object, letting one debug type confusion issues between javascript and GoLang native functions. 17 | 18 | -------------------------------------------------------------------------------- /docs/tutorials/06_compiler_macros.md: -------------------------------------------------------------------------------- 1 | # Compiler Macros 2 | 3 | ## Included 4 | 5 | ### //go_import: 6 | 7 | This command will take a path to a local go library that is discoverable via the GOPATH. This is equivalent to a go import style declaration at the top of a GoLang program. 8 | 9 | ### //import: 10 | 11 | This macro will take a path to a binary file to be included in the final payload and addressable by the gscript as an asset, using the (AssetFuncs) 12 | 13 | ### //priority: 14 | 15 | this is a value 0-1000 (defaults 100) that specifies the order that the gscript VM should be executed in. 16 | 17 | ### //timeout: 18 | 19 | This is a value 0-1000 (defaults 30), representing the maximum number of seconds a VM should run for. 20 | 21 | ## Suggested 22 | 23 | ### // title: 24 | 25 | the name of the gscript file 26 | 27 | ### // author: 28 | 29 | the person who wrote the gscript 30 | 31 | ### // purpose: 32 | 33 | a short description of the gscript or how it is intended to be used 34 | 35 | ### // gscript_version: 36 | 37 | The minimum version of the gscript compiler needed for this gscript 38 | 39 | ### // ATT&CK: 40 | 41 | A link to the MITRE ATT&CK technique the gscript emulates 42 | 43 | ### // Tactic: 44 | 45 | Additional operational advice about the gscript, such as how to trigger an implant or further leverage a technique 46 | 47 | ### // Using: 48 | 49 | A link or description to any imported assets that the gscript uses 50 | -------------------------------------------------------------------------------- /docs/tutorials/07_0_using_standard_library.md: -------------------------------------------------------------------------------- 1 | # Using the Standard Library 2 | 3 | ## Crypto 4 | 5 | - GetMD5FromString(data string) string 6 | 7 | - GetMD5FromBytes(data []byte) string 8 | 9 | - GetSHA1FromString(data string) string 10 | 11 | - GetSHA1FromBytes(data []byte) string 12 | 13 | - GetSHA256FromString(data string) string 14 | 15 | - GetSHA256FromBytes(data []byte) string 16 | 17 | - GenerateRSASSHKeyPair(size int) (pubkey string, privkey string, error) 18 | 19 | ## Encoding 20 | 21 | - DecodeBase64(data string) (string, error) 22 | 23 | - EncodeBase64(data string) string 24 | 25 | - EncodeStringAsBytes(data string) []byte 26 | 27 | - EncodeBytesAsString(data []byte) string 28 | 29 | ## Exec 30 | 31 | - ExecuteCommand(progname string, args []string) (pid int, stdout string, stderr string, exitCode int, err error) 32 | 33 | - ExecuteCommandAsync(progname string, args []string) (proc *exec.Cmd, err error) 34 | 35 | ## File 36 | 37 | - WriteFileFromBytes(filepath string, data []byte) error 38 | 39 | - WriteFileFromString(filepath string, data string) error 40 | 41 | - ReadFileAsBytes(filepath string) ([]byte, error) 42 | 43 | - ReadFileAsString(filepath string) (string, error) 44 | 45 | - AppendBytesToFile(filepath string, data []byte) error 46 | 47 | - AppendStringToFile(filepath string, data string) error 48 | 49 | - CopyFile(srcpath string, dstpath string, perms string) (bytesWritten int, err error) 50 | 51 | - ReplaceInFileWithString(match string, new string) error 52 | 53 | - ReplaceInFileWithRegex(regexString string, replaceWith string) error 54 | 55 | - SetPerms(filepath string, perms string) error 56 | 57 | - CheckExists(targetPath string) bool 58 | 59 | ## Net 60 | 61 | - CheckForInUseTCP(port int) (bool, error) 62 | 63 | - CheckForInUseUDP(port int) (bool, error) 64 | 65 | ## Os 66 | 67 | - TerminateSelf() error 68 | 69 | - TerminateVM() 70 | 71 | ## rand 72 | 73 | - GetInt(min int, max int) int 74 | 75 | - GetAlphaNumericString(len int) string 76 | 77 | - GetAlphaString(len int) string 78 | 79 | - GetAlphaNumericSpecialString(len int) string 80 | 81 | - GetBool() bool 82 | 83 | ## requests 84 | 85 | - PostURL(url string, data string, headers map[string]string, ignoresslerrors bool) (resp *http.Response, body string, err error) 86 | 87 | - PostJSON(url string, jsondata string, headers map[string]string, ignoresslerrors bool) (resp *http.Response, body string, err error) 88 | 89 | - PostFile(url string, filepath string, headers map[string]string, ignoresslerrors bool) (resp *http.Response, body string, err error) 90 | 91 | - GetURLAsString(url string, headers map[string]string, ignoresslerrors bool) (resp *http.Response, body string, err error) 92 | 93 | - GetURLAsBytes(url string, headers map[string]string, ignoresslerrors bool) (resp *http.Response, body string, err error) 94 | 95 | ## time 96 | 97 | - GetUnix() int 98 | -------------------------------------------------------------------------------- /docs/tutorials/07_1_assets.md: -------------------------------------------------------------------------------- 1 | # Assets 2 | 3 | ## Embedding Assets 4 | 5 | As previously covered in **Macros**, you can use the `//import:` macro to include arbitrary files into your final binary. These files are addressable in the gscripts they are called in. These assets have weak static encryption applied to them while embedded, and are not addressable from other gscripts. 6 | 7 | ### Asset embedding example: 8 | 9 | `//import:/path/to/binary/file.exe` 10 | 11 | ## Asset retrieval functions 12 | 13 | ### GetAssetAsBytes("embedded_asset") 14 | 15 | This function returns two objects, a byte array (pos 0) and an error object (pos 1), this takes a string as a variable which is referenced by the filename of the embedded asset. 16 | 17 | ### GetAssetAsBytes example: 18 | 19 | ```js 20 | file = GetAssetAsBytes("file.exe"); 21 | errors = G.file.WriteFileFromBytes("example_test", file[0]); 22 | ``` 23 | 24 | ### GetAssetAsString("embedded_asset") 25 | 26 | This function returns two objects, a string (pos 0) and an error object (pos 1), this takes a string as a variable which is referenced by the filename of the embedded asset. A useful workaround in javascript to avoid type errors is converting most things to a string, then bringing them back to their original type in GoLang. 27 | 28 | ### GetAssetAsString example: 29 | 30 | ```js 31 | file = GetAssetAsString("file.exe"); 32 | errors = G.file.WriteFileFromString("example_test", file[0]); 33 | ``` 34 | 35 | -------------------------------------------------------------------------------- /docs/tutorials/08_0_compiling.md: -------------------------------------------------------------------------------- 1 | 2 | # Compiling 3 | Compiling is as simple as running the command line utility, with any number of syntactically valid gscripts at the end. 4 | 5 | ### Compiler options 6 | 7 | ```sh 8 | gscript --os # for specifying the platform to compile the target binary to 9 | gscript --arch # for specifying the archatecture to compile the target binary to 10 | gscript --output-file # for specifying an output file to save the final binary as opposed to a temp path 11 | gscript --keep-build-dir # for keeping the build directory that contains the intermediate golang to debug any gscript compiler issues 12 | gscript --enable-human-readable-names # this options is useful for debugging any potential linker issues. 13 | gscript --enable-debugging # This option only works with obfuscation disabled, it will drop the running vm into an interactive debugger with the fist instance of DebugConsole() 14 | gscript --enable-import-all-native-funcs # this options is useful for importing and linking all of the golang native libraries for when the user specifies the --enable-debugging option 15 | gscript --enable-logging # This flag is helpful for logging all of the console.log() functions output to stdout. Will only work when obfuscation is disabled. 16 | gscript --obfuscation-level # This flag takes a vale of 0-3 with 0 being the highest level obuscation and 3 being no obfuscation applied to the final binary. 17 | gscript --disable-native-compilation # This flag will specifically not compile the intermediate representation to a native binary (default is false) 18 | gscript --enable-test-build # This will enable the test harness in the build - for testing only! (default # false) 19 | gscript --enable-upx-compression # This will ompress the final binary using UPX (default # false) 20 | ``` 21 | 22 | ## Compiler examples 23 | 24 | ```sh 25 | gscript compile /path/to/gscript.gs 26 | gscript c /path/to/gscript.gs 27 | gscirpt c --enable-logging --obfuscation-level 3 /path/to/gscript.gs 28 | gscirpt c --enable-debugging --obfuscation-level 3 /path/to/gscript.gs 29 | gscript compile /gscripts/technique1.gs /gscripts/technique2.gs 30 | gscript c /gscripts/technique1.gs /gscripts/technique2.gs 31 | gscript compile /gscripts/*.gs 32 | gscript c /gscripts/*.gs 33 | ``` 34 | 35 | ## Compiler details 36 | 37 | The compiler executes a complex series of tasks, as defined below: 38 | 39 | - CheckForConfigErrors 40 | Validated compiler configuration 41 | 42 | - CreateBuildDir 43 | Creates the build dir 44 | 45 | - ProcessMacros 46 | Parses and processes compiler macros 47 | 48 | - InitializeImports 49 | checks the import references in golang 50 | 51 | - DetectVersions 52 | entry points located within scripts 53 | 54 | - GatherAssets 55 | asset tree built 56 | 57 | - WalkGenesisASTs 58 | genesis scripts analyzed 59 | 60 | - LocateGoDependencies 61 | native dependencies resolved 62 | 63 | - BuildGolangASTs 64 | native code bundles mapped to the virtual machine 65 | 66 | - SanityCheckScriptToNativeMapping 67 | script callers for native code validated 68 | 69 | - SwizzleNativeCalls 70 | native code dynamically linked to the genesis virtual machine 71 | 72 | - SanityCheckSwizzles 73 | dynamic link correctness validated 74 | 75 | - WritePreloads 76 | built in genesis helper library injected 77 | 78 | - WriteScripts 79 | scripts staged for compilation 80 | 81 | - EncodeAssets 82 | assets encrypted and embedded into the genesis VMs 83 | 84 | - WriteVMBundles 85 | virtual machines compiled into intermediate representation 86 | 87 | - CreateEntryPoint 88 | genesis vm callers embedded into final binary entry point 89 | 90 | - PerformPreCompileObfuscation 91 | pre-obfuscation completed (stylist tangled all hairs) 92 | 93 | - BuildNativeBinary 94 | statically linked native binary built 95 | 96 | - PerformPostCompileObfuscation 97 | post-obfuscation completed (mordor has assaulted the binary) 98 | -------------------------------------------------------------------------------- /docs/tutorials/08_1_priorities.md: -------------------------------------------------------------------------------- 1 | # Priorities 2 | 3 | priorities will default to `100` unless specifically set w/ the macro. 4 | 5 | ## Macro 6 | 7 | One of the most import macros, the `//priorities: ` macro 8 | It lets you set the order in which the gscripts are executed 9 | -------------------------------------------------------------------------------- /docs/tutorials/08_2_timeouts.md: -------------------------------------------------------------------------------- 1 | # Timeouts 2 | 3 | Timeouts will terminate a gscript at a specified time, in case it's hanging in some way. Unless specified w/ the `//timeouts: ` macro this defaults to `30` which is seconds. 4 | 5 | ## Macro 6 | 7 | One of the most import macros, the `//timeouts: ` macro 8 | It lets you set the explicitly how long a gscirpt can run for. 9 | This is often useful for an operator to set to limit user submitted gscripts to a specified runtime. 10 | -------------------------------------------------------------------------------- /docs/tutorials/08_3_platform_specifics.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gen0cide/gscript/d65a5ce55f79c4f544a93997e7eb635a72a64118/docs/tutorials/08_3_platform_specifics.md -------------------------------------------------------------------------------- /docs/tutorials/09_0_advanced_gscripting.md: -------------------------------------------------------------------------------- 1 | # Advanced GSCRIPTing 2 | 3 | - [Multiple Scripts](https://github.com/gen0cide/gscript/blob/master/docs/tutorials/09_1_multiple_scripts.md) 4 | 5 | - [Anti Detection](https://github.com/gen0cide/gscript/blob/master/docs/tutorials/09_2_anti_detection.md) 6 | 7 | - [Persisting](https://github.com/gen0cide/gscript/blob/master/docs/tutorials/09_3_persisting.md) 8 | 9 | - [Networking](https://github.com/gen0cide/gscript/blob/master/docs/tutorials/09_4_networking.md) 10 | 11 | - [Obfuscation](https://github.com/gen0cide/gscript/blob/master/docs/tutorials/09_5_obfuscation.md) 12 | 13 | - [Child Processes](https://github.com/gen0cide/gscript/blob/master/docs/tutorials/09_6_child_processes.md) 14 | 15 | - [System Services](https://github.com/gen0cide/gscript/blob/master/docs/tutorials/09_7_system_services.md) 16 | 17 | - [Managing Team Persistence](https://github.com/gen0cide/gscript/blob/master/docs/tutorials/09_8_managing_team_persistence.md) 18 | 19 | - [Auditing Other GSCRIPTs](https://github.com/gen0cide/gscript/blob/master/docs/tutorials/09_9_auditing_other_gscripts.md) 20 | -------------------------------------------------------------------------------- /docs/tutorials/09_1_multiple_scripts.md: -------------------------------------------------------------------------------- 1 | # Multiple Scripts 2 | 3 | One of the massive powers of GSCRIPT is that you can compile any number of scripts into a single binary. This means individual gscripts are often written as atomic as possible, usually accomplishing a single task. These multiple scripts are then selectively compiled into a single binary based on the desired techniques. 4 | 5 | ## N Number of Scripts 6 | 7 | The final argument `gscript` takes is a path to a script, or any number of paths to a script. This must be the final command line argument. This can include wildcards or any type of path expansion in bash. 8 | 9 | ## Multiple Script Examples 10 | 11 | ```sh 12 | gscript c /path/to/gscript.gs /path/to/another_gscript.gs /path/to/a_last_gscript.gs 13 | ``` 14 | 15 | ```sh 16 | gscript c /path/to/*t.gs 17 | ``` 18 | -------------------------------------------------------------------------------- /docs/tutorials/09_2_anti_detection.md: -------------------------------------------------------------------------------- 1 | # Anti-Detection 2 | Good anti-detection should run with a low priority seeking for artifacts that are only available on virtual machines, detection sandboxes, or analyst machines. Once these items are detected the individual gscript can run KillSelf() which looks up its own PID and terminates the process. Through this method you can use multiple gscripts (some of which are anti-detection based) to modularly add these capabilities to a genesis binary and other payloads. 3 | 4 | ## TerminateSelf() 5 | Calling this function will get the PID of the gscript master process and terminate this process. This itself is a fairly detectable event as opposed to invoking a crash. 6 | 7 | Call it like so: 8 | 9 | ```sh 10 | G.os.TerminateSelf(); 11 | ``` 12 | 13 | ### Example 14 | https://github.com/ahhh/gscripts/blob/master/anti-re/sandbox_hostname.gs 15 | -------------------------------------------------------------------------------- /docs/tutorials/09_3_persisting.md: -------------------------------------------------------------------------------- 1 | # Persisting 2 | 3 | Leveraging GSCRIPT to persist stored assets is a great way to document persitence techniques in code. 4 | In this way you can write persistence logic in generic terms and persist arbitrary binaries independent of the persistence technique. 5 | 6 | ## Persistence Examples 7 | 8 | ### Windows Persitence example 9 | 10 | The following is a simple regkey persistence example, showing how the technique can remain independent of the binary 11 | 12 | #### Excerpt 13 | 14 | `windows.AddRegKeyString("CURRENT_USER", "Software\\Microsoft\\Windows\\CurrentVersion\\Run", "ExampleExe", fullpath);` 15 | 16 | #### Full Example: 17 | 18 | __https://github.com/ahhh/gscripts/blob/master/attack/windows/runkey_persistence.gs__ 19 | 20 | 21 | ### Linux Persistence Example 22 | 23 | The following is a simple sshkey persistence example, showing how the technique can remain independent of the binary 24 | 25 | ### Excerpt: 26 | 27 | ```js 28 | G.file.WriteFileFromBytes(myUser[0].HomeDir+ "/.ssh/authorized_keys", pubKey[0]); 29 | ``` 30 | 31 | #### Full Example: 32 | 33 | __https://github.com/ahhh/gscripts/blob/master/attack/linux/sshkey_persistence.gs__ 34 | 35 | 36 | ### MacOS Persistence Example 37 | 38 | The following is a simple login hook persistence example, showing how the technique can remain independent of the binary 39 | 40 | ### Exceprt: 41 | 42 | ```js 43 | G.exec.ExecuteCommand("defaults", ["write", "com.apple.loginwindow", "LoginHook", name]); 44 | ``` 45 | 46 | ### Full Example: 47 | 48 | __https://github.com/ahhh/gscripts/blob/master/attack/os_x/loginhook_persistence.gs__ 49 | 50 | -------------------------------------------------------------------------------- /docs/tutorials/09_4_networking.md: -------------------------------------------------------------------------------- 1 | # Networking 2 | 3 | Some of the standard library functions provide great networking capabilities 4 | 5 | ## Requests library 6 | 7 | Here are some examples using the request library to do basic web requests. 8 | 9 | In the following example we change the user agents, as the default user agents using golang can easily trip detections 10 | 11 | ## Hosted Networking 12 | -------------------------------------------------------------------------------- /docs/tutorials/09_5_obfuscation.md: -------------------------------------------------------------------------------- 1 | # Obfuscation 2 | 3 | ## Built in GSCRIPT Obfuscation 4 | 5 | GSCRIPT does two types of obfuscation: 6 | 7 | - **Pre Compile Obfuscation** - This step is done _after_ GSCRIPT generates it's Golang intermediate representation, but _before_ it compiles a native binary with Go's compiler. 8 | - **Post Compile Obfuscation** - This step is done _after_ GSCRIPT uses the Go compiler to build a native binary and operates atomically on the produced binary. 9 | 10 | Each have strengths and weaknesses and knowing more about them will help you decide in what cases you will find them most useful. 11 | 12 | **WARNING - Before reading about them, it's encouraged that you have an understanding of the GSCRIPT compiler and how it works at a high level.** 13 | 14 | ### Pre-Compiler Obfuscation 15 | 16 | The **Pre Compile Obfuscator** is known as the **Stylist**. The basic premise of the Stylist is to remove string literals out of the intermediate representation Go source code. 17 | 18 | Here is a hypothetical example of this: 19 | 20 | ```js 21 | // Original Source 22 | var foo = "bar" 23 | ``` 24 | 25 | And after the Stylist is run over this Go source: 26 | 27 | ```js 28 | var foo = s(31337, generatedVarA) 29 | 30 | var generatedVarA = []rune{ 31 | 0x0001, 0x0002, 0x0003, //... this is a rune slice containing encrypted bytes of the string 32 | } 33 | 34 | func s(key int, data []rune) string { 35 | // this function contains the logic to decrypt, decode, and translate the generated var into a string 36 | } 37 | ``` 38 | 39 | Note that the Stylist only does this for Golang source code existing within the build directory and will not tangle strings outside of the GSCRIPT intermediate representation's `main` package. 40 | 41 | If you want to see this in action, you can use the compiler flag `--keep-build-dir` and examine the differences between source with the Stylist turned on vs. off. 42 | 43 | ### Post-Compiler Obfuscation 44 | 45 | **WARNING: There be dragons here. Proceed with caution.** 46 | 47 | The **Post Compile Obfuscation** is known as the **Mordorifier**. The basic premise of the Mordorifier is that once GSCRIPT uses the Go compiler to build a native binary, regardless of platform, plaintext strings might exist which would be undesirable in a production build. This includes references to GSCRIPT, it's Engine, your `$HOME` directory or username, etc. 48 | 49 | The **Mordorifier** follows the following basic steps: 50 | 51 | 1. As the compiler runs, various pieces of it (including each VM, the Stylist, and the Compiler) retain a cache of "known strings". 52 | 2. When the compiler initializes the Mordorifier, the cache of strings is supplied. 53 | 3. The newly instantiated `Mordor` will enumerate this list of strings, creating 0-N number of regular expression matchers (known as `Orc` objects) 54 | 4. Note if the regular expression cannot be built, the `Mordorifier` will discard string. 55 | 5. Also `Orc` objects within the "`Horde`" (the map of `Orc` types within the `Mordor` object) are uniquely keyed. You will not get two `Orc` objects with the same string base. 56 | 6. Besides the compiler provided cache, the `Mordorifier` also attempts to intelligently add `Orc` objects to it's `Horde` based on some presets we've defined within the code. This includes references to `gscript` as well as a number of other Golang specific strings we'd rather not be present in plain text. 57 | 7. Finally, the compiler runs an **Assault** on the compiled executable - this enumerates each `Orc` within the `Horde`, performing a binary search and replace on any byte sequences which match the regular expression of the `Orc`. When a match is found, it is substituted simply with random data. 58 | 59 | A quick glance at a fully obfuscated GSCRIPT binary in a disassembler will show you the magic of this. (Or the pain, depending on how you're looking at it). 60 | 61 | Note that you cannot use the Mordorifier with either `--enable-logging` or `--enable-debugging` because you will end up with a _very_ messed up STDOUT buffer. 62 | 63 | // NOTE: The **Mordorifier** has been known to cause some execution time problems. Debugging them is an incredibly difficult and slow process and if you experience binary failure during testing, it's always advised to simply disable the **Mordorifier** for the same build and check for any differences in execution. 64 | 65 | ### JavaScript Obfuscation 66 | 67 | Currently, the compiler will attempt to "minify" your GSCRIPTs. While this is not "obfuscation" it does add another layer of stuff to reverse engineer. It is also written in a way where a javascript obfuscation engine could theoretically be easily bolted in. 68 | -------------------------------------------------------------------------------- /docs/tutorials/09_6_child_processes.md: -------------------------------------------------------------------------------- 1 | # Child Processes 2 | 3 | ## Command Exec 4 | 5 | When calling `G.exec.ExecuteCommand` a child process is spawned that waits for execution to finish before proceding. 6 | 7 | ## Async Exec 8 | 9 | When calling `G.exec.ExecuteComandAsync` all Signals for SigHup will be caught by default. 10 | 11 | ### Async Example 12 | 13 | ```js 14 | var running = G.exec.ExecuteCommandAsync(naming, [""]); 15 | if (running[1] != null) { 16 | console.log("errors: "+running[1].Error()); 17 | } else { 18 | console.log("pid: "+running[0].Process.Pid); 19 | } 20 | ``` 21 | -------------------------------------------------------------------------------- /docs/tutorials/09_7_system_services.md: -------------------------------------------------------------------------------- 1 | # System Services 2 | -------------------------------------------------------------------------------- /docs/tutorials/09_8_managing_team_persistence.md: -------------------------------------------------------------------------------- 1 | # Managing Team Persistence 2 | 3 | One of the features of GSCRIPT is being able to have co-operative, single payloads. This means multiple red team members can sumbit arbitrary payloads and their associated gscripts which map to their desired persistence technique. In this way a single person can manage all of the team's payloads and compile them into a final bianry. This person can also audit the payloads and gscripts to make sure there are no conflicting binaries or persistence locations, such that two agents will stomp each other in some race condition. 4 | 5 | ## Testing 6 | 7 | It is important to test the implants on a wide variety of systems before wrapping them in gscript. Further, it is important to test individual gscripts before testing multiple scripts in a single binary. When testing use no obfuscation and enable logging. During final testing use the desired obfuscation level and no logging before running the final payload. 8 | 9 | ## Priority 10 | 11 | One of the biggest advantages of gscript is leveraging the priority to allow certain payloads to run before others. In this way the genesis builder can select payloads that disable security controls to run before other implants, protecting other team members' dropped binaries. 12 | -------------------------------------------------------------------------------- /docs/tutorials/09_9_auditing_other_gscripts.md: -------------------------------------------------------------------------------- 1 | # Auditing Other gscripts 2 | 3 | 4 | ## Use a Javascript Linter 5 | 6 | Configure your preferred text editor/IDE with a Javascript linter to parse `.gs` files for quickly spotting syntax errors. 7 | 8 | ## Build and Test Scripts Individually 9 | 10 | Building individual scripts with their associated assets against their target platforms is a recommended way to see if the native libraries and script will even build. 11 | 12 | ## Sandbox/Automated Testing 13 | 14 | Automating test builds of individual gscripts will identify build errors with the scripts at runtime. 15 | -------------------------------------------------------------------------------- /docs/tutorials/10_0_using_native_libraries.md: -------------------------------------------------------------------------------- 1 | # Using Native Libraries 2 | 3 | The native libraries are designed to be helper functions that save the casual gscript writer from needing to interact with go docs. Using go native libraries are the prefered way to write gscripts with gscript 1.0.0, however, we have included to the native library to make gscript easier. 4 | 5 | ## Examples 6 | 7 | Cross-platform examples of the standard library can be found at the following link: __https://github.com/ahhh/gscripts/tree/master/attack/multi__ 8 | -------------------------------------------------------------------------------- /docs/tutorials/10_1_using_experimental_libraries.md: -------------------------------------------------------------------------------- 1 | # Using Experimental Libraries 2 | 3 | The experimental libraries are less stable than the standard libraries and often only support a limited purpose. They are not cross platform and well tested, but are often still crtitical to the mission of gscript. We have included them in the official gscript project but only as an experimental ibrary. The experimental library is the first place to get new commands added and 4 | 5 | ## Windows Examples 6 | 7 | Windows specific examples of the experimental library are available at the following links: 8 | 9 | ### Using registry functions: 10 | __https://github.com/ahhh/gscripts/blob/master/attack/windows/disable_uac.gs__ 11 | __https://github.com/ahhh/gscripts/blob/master/attack/windows/enable_adminShares.gs__ 12 | __https://github.com/ahhh/gscripts/blob/master/attack/windows/enable_smbv1.gs__ 13 | 14 | ### Using process injection: 15 | 16 | A full example for this is currently unavailable, but the functions are available at this link: 17 | __https://github.com/gen0cide/gscript/blob/alex-dev/x/windows/windows.go#L222__ 18 | -------------------------------------------------------------------------------- /docs/tutorials/10_2_checking_compatibility.md: -------------------------------------------------------------------------------- 1 | # Checking Compatibility 2 | 3 | It is important to check the os and arch of each portion included in your gscripts as you will be building to a single final target in the end. 4 | 5 | ## Checking Native Libraries 6 | 7 | Some native libraries are not cross platform for platform specific functions. Make sure the specified native libraries can build to the target platform and arch before building the final binaries. 8 | 9 | ## Checking Assets 10 | 11 | Assets are usually less of an issue but each asset should be tested and working independently before putting them in gscript. 12 | 13 | ## Using OS & Arch 14 | -------------------------------------------------------------------------------- /docs/tutorials/10_3_implementing_native_code.md: -------------------------------------------------------------------------------- 1 | # Implementing Native Code 2 | 3 | Native Code in GSCRIPT is when you use the //go_import: macro to reference a native GoLang library in GSCRIPT, allowing you to call those exported GoLang packages and functions directly from GSCRIPT. This allows Go code to be used when Javascript limitations are encountered. 4 | 5 | ## Converting a Tool Into a GSCRIPT Library 6 | 7 | Sometimes you will want to call an existing GoLang library from GSCRIPT, but the tool may need a bit of tweaking to be used by GSCRIPT. 8 | 9 | An example of this can be seen in the conversion of GoRedLoot to gloot: 10 | 11 | #### GoRedLoot: 12 | - __https://github.com/ahhh/GoRedLoot/blob/master/main.go__ 13 | 14 | #### Gloot: 15 | - __https://github.com/ahhh/gloot/blob/master/gloot.go__ 16 | 17 | #### Gscript: 18 | - __https://github.com/ahhh/GSCRIPTs/blob/master/attack/os_x/looter_example.gs__ 19 | 20 | ### Reasons For Converting a Tool Into a GSCRIPT Libary: 21 | 22 | - Adding a non-main package: Many GoLang tools are written inside of main, or in the main package. These tools should be converted into a library so they can be called from GSCRIPT. 23 | 24 | - Creating helper functions: GSCRIPT cannot use custom types from native libraries directly, unless a function returns that type. Helper functions could be used to make the type GSCRIPT compatable. 25 | 26 | ## Writing Your Own Native Library 27 | 28 | Sometimes you will need to write your tools in GoLang so that they can be used in GSCRIPT. 29 | -------------------------------------------------------------------------------- /docs/tutorials/10_4_gotchas.md: -------------------------------------------------------------------------------- 1 | # Gotchas 2 | 3 | ## Casting Types 4 | 5 | To cast a type directly from a libary, you will need a helper function that returns that type for you. 6 | This is a great usecase for converting an existing library into a gscript specific library 7 | -------------------------------------------------------------------------------- /docs/tutorials/11_0_implementing_custom_engines.md: -------------------------------------------------------------------------------- 1 | # Implementing Custom Engines 2 | -------------------------------------------------------------------------------- /docs/tutorials/11_1_implementing_a_new_compiler.md: -------------------------------------------------------------------------------- 1 | # Implementing A New Compiler 2 | -------------------------------------------------------------------------------- /engine/assets.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/robertkrimen/otto" 7 | ) 8 | 9 | func (e *Engine) retrieveAssetAsString(name string) (string, error) { 10 | if e.Imports[name] == nil { 11 | return "", fmt.Errorf("could not locate asset %s", name) 12 | } 13 | ret := e.Imports[name]() 14 | return string(ret), nil 15 | } 16 | 17 | func (e *Engine) retrieveAssetAsBytes(name string) ([]byte, error) { 18 | ret := []byte{} 19 | if e.Imports[name] == nil { 20 | return ret, fmt.Errorf("could not locate asset %s", name) 21 | } 22 | ret = e.Imports[name]() 23 | return ret, nil 24 | } 25 | 26 | func (e *Engine) vmRetrieveAssetAsString(call otto.FunctionCall) otto.Value { 27 | if len(call.ArgumentList) != 1 { 28 | return e.Raise("argument", "argument count mismatch for %s", "GetAssetAsString") 29 | } 30 | 31 | var a0 string 32 | ra0, err := call.Argument(0).Export() 33 | if err != nil { 34 | return e.Raise("jsexport", "could not export argument %d of function %s", 0, "GetAssetAsString") 35 | } 36 | switch v := ra0.(type) { 37 | case string: 38 | a0 = v 39 | default: 40 | return e.Raise("type conversion", "argument type mismatch - expected %s, got %T", "string", v) 41 | } 42 | 43 | var r0 string 44 | var r1 error 45 | 46 | r0, r1 = e.retrieveAssetAsString(a0) 47 | 48 | if r1 != nil { 49 | return e.Raise("asset", "retrieving asset from asset table failed - %v", r1) 50 | } 51 | 52 | retVal, err := call.Otto.ToValue(r0) 53 | if err != nil { 54 | return e.Raise("return", "conversion failed for return 0 (type=%T) - %v", r0, err) 55 | } 56 | 57 | return retVal 58 | } 59 | 60 | func (e *Engine) vmRetrieveAssetAsBytes(call otto.FunctionCall) otto.Value { 61 | if len(call.ArgumentList) != 1 { 62 | return e.Raise("argument", "argument count mismatch for %s", "GetAssetAsBytes") 63 | } 64 | 65 | var a0 string 66 | ra0, err := call.Argument(0).Export() 67 | if err != nil { 68 | return e.Raise("jsexport", "could not export argument %d of function %s", 0, "GetAssetAsBytes") 69 | } 70 | switch v := ra0.(type) { 71 | case string: 72 | a0 = v 73 | default: 74 | return e.Raise("type conversion", "argument type mismatch - expected %s, got %T", "string", v) 75 | } 76 | 77 | var r0 []byte 78 | var r1 error 79 | 80 | r0, r1 = e.retrieveAssetAsBytes(a0) 81 | 82 | if r1 != nil { 83 | return e.Raise("asset", "retrieving asset from asset table failed - %v", r1) 84 | } 85 | 86 | retVal, err := call.Otto.ToValue(r0) 87 | if err != nil { 88 | return e.Raise("return", "conversion failed for return 0 (type=%T) - %v", r0, err) 89 | } 90 | 91 | return retVal 92 | } 93 | -------------------------------------------------------------------------------- /engine/errors.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/robertkrimen/otto" 7 | ) 8 | 9 | // Raise is a convenience method for throwing a javascript runtime error from go space 10 | func (e *Engine) Raise(name string, format string, args ...interface{}) otto.Value { 11 | msg := fmt.Sprintf(format, args...) 12 | e.Logger.Errorf("%s error: %s", name, msg) 13 | return e.VM.MakeCustomError(name, msg) 14 | } 15 | -------------------------------------------------------------------------------- /engine/executor.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | import ( 4 | "errors" 5 | "time" 6 | 7 | "github.com/robertkrimen/otto" 8 | "github.com/robertkrimen/otto/ast" 9 | ) 10 | 11 | var errTimeout = errors.New("Script Timeout") 12 | 13 | // SetEntryPoint sets the function name of the entry point function for the script 14 | func (e *Engine) SetEntryPoint(fnName string) { 15 | e.EntryPoint = fnName 16 | } 17 | 18 | // LoadScriptWithTimeout evaluates an expression in the VM that honors the VMs timeout setting 19 | func (e *Engine) LoadScriptWithTimeout(script *ast.Program) (otto.Value, error) { 20 | start := time.Now() 21 | defer e.recoveryHandler(start) 22 | e.VM.Interrupt = make(chan func(), 1) 23 | go e.timeoutMonitor() 24 | return e.VM.Eval(script) 25 | } 26 | 27 | // CallFunctionWithTimeout calls a given top level function in the VM that honors the VMs timeout setting 28 | func (e *Engine) CallFunctionWithTimeout(fn string) (otto.Value, error) { 29 | start := time.Now() 30 | defer e.recoveryHandler(start) 31 | e.VM.Interrupt = make(chan func(), 1) 32 | go e.timeoutMonitor() 33 | return e.VM.Call(fn, nil, nil) 34 | } 35 | 36 | func (e *Engine) recoveryHandler(begin time.Time) { 37 | duration := time.Since(begin) 38 | if caught := recover(); caught != nil { 39 | if caught == errTimeout { 40 | e.Logger.Errorf("VM hit timeout after %v seconds", duration) 41 | return 42 | } 43 | e.Logger.Errorf("VM encountered unexpected error: %v", caught) 44 | return 45 | } 46 | return 47 | } 48 | 49 | func (e *Engine) timeoutMonitor() { 50 | for { 51 | time.Sleep(time.Duration(e.Timeout) * time.Second) 52 | if !e.Paused { 53 | e.VM.Interrupt <- func() { 54 | panic(errTimeout) 55 | } 56 | return 57 | } else { 58 | continue 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /engine/logger.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "strings" 7 | 8 | "github.com/robertkrimen/otto" 9 | ) 10 | 11 | var ( 12 | // the console functions that belong to the javascript console object 13 | consoleLogLevels = []string{ 14 | "log", 15 | "debug", 16 | "info", 17 | "error", 18 | "warn", 19 | } 20 | ) 21 | 22 | // converts arguments passed into console into helpful string representations 23 | // otto by default prints objects as [Object object] which is incredibly not 24 | // helpful -.- 25 | func normalizeConsoleArgs(c otto.FunctionCall) string { 26 | o := []string{} 27 | jsonNs, err := c.Otto.Object("JSON") 28 | if err != nil { 29 | return errors.New("runtime error: could not locate the JSON runtime object").Error() 30 | } 31 | for _, i := range c.ArgumentList { 32 | if i.Class() == "Object" { 33 | i, err = jsonNs.Call("stringify", i) 34 | if err != nil { 35 | o = append(o, err.Error()) 36 | continue 37 | } 38 | } 39 | o = append(o, fmt.Sprintf("%v", i)) 40 | } 41 | return strings.Join(o, " ") 42 | 43 | } 44 | 45 | // generates native functions for each of the log levels that use the appropriate logger function 46 | // belonging to the provided engine 47 | func logFuncFactory(e *Engine, level string) func(call otto.FunctionCall) otto.Value { 48 | prefix := fmt.Sprintf("console.%s >>> ", level) 49 | switch level { 50 | case "log": 51 | return func(call otto.FunctionCall) otto.Value { 52 | e.Logger.Info(prefix, normalizeConsoleArgs(call)) 53 | return otto.Value{} 54 | } 55 | case "debug": 56 | return func(call otto.FunctionCall) otto.Value { 57 | e.Logger.Debug(prefix, normalizeConsoleArgs(call)) 58 | return otto.Value{} 59 | } 60 | case "info": 61 | return func(call otto.FunctionCall) otto.Value { 62 | e.Logger.Info(prefix, normalizeConsoleArgs(call)) 63 | return otto.Value{} 64 | } 65 | case "error": 66 | return func(call otto.FunctionCall) otto.Value { 67 | e.Logger.Error(prefix, normalizeConsoleArgs(call)) 68 | return otto.Value{} 69 | } 70 | case "warn": 71 | return func(call otto.FunctionCall) otto.Value { 72 | e.Logger.Warn(prefix, normalizeConsoleArgs(call)) 73 | return otto.Value{} 74 | } 75 | default: 76 | return func(call otto.FunctionCall) otto.Value { 77 | e.Logger.Info(prefix, normalizeConsoleArgs(call)) 78 | return otto.Value{} 79 | } 80 | } 81 | } 82 | 83 | // HijackConsoleLogging intercepts the javascript runtimes console logging functions (i.e. console.log) 84 | // and dynamically generates new native function implementations of those build ins that use 85 | // the engine object's Logger interface 86 | func HijackConsoleLogging(e *Engine) error { 87 | c, err := e.VM.Object(`console`) 88 | if err != nil { 89 | return err 90 | } 91 | for _, l := range consoleLogLevels { 92 | err = c.Set(l, logFuncFactory(e, l)) 93 | if err != nil { 94 | return err 95 | } 96 | } 97 | return nil 98 | } 99 | -------------------------------------------------------------------------------- /engine/native_package.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | import "github.com/robertkrimen/otto" 4 | 5 | // NativePackage defines a golang library that is being imported into the genesis VM 6 | type NativePackage struct { 7 | ImportPath string 8 | Name string 9 | SymbolTable map[string]*NativeFunc 10 | Types map[string]*NativeType 11 | Consts map[string]*NativeConst 12 | Vars map[string]*NativeVar 13 | } 14 | 15 | // NativeFunc defines a golang library function that is callable from within the genesis VM 16 | type NativeFunc struct { 17 | Name string 18 | Signature string 19 | Func func(call otto.FunctionCall) otto.Value 20 | } 21 | 22 | // NativeConst defines a golang const declared within a given library 23 | type NativeConst struct { 24 | Name string 25 | Value interface{} 26 | } 27 | 28 | // NativeVar defines a golang top level var declaration within a given library 29 | type NativeVar struct { 30 | Name string 31 | Signature string 32 | Value interface{} 33 | } 34 | 35 | // ParamDef defines basic information about either an argument or return value for NativeFunc 36 | type ParamDef struct { 37 | Name string 38 | GoType string 39 | JSType string 40 | } 41 | 42 | // NativeType expresses a native Golang type definition that can be used within the engine 43 | type NativeType struct { 44 | Name string 45 | Factory func(call otto.FunctionCall) otto.Value 46 | Fields map[string]*NativeField 47 | } 48 | 49 | // NativeField expresses a struct field within a Go native type within the engine 50 | type NativeField struct { 51 | Label string 52 | Signature string 53 | } 54 | 55 | func (e *Engine) createType(call otto.FunctionCall) otto.Value { 56 | if len(call.ArgumentList) < 1 { 57 | return e.Raise("argument", "not enough arguments for call to new()") 58 | } 59 | if len(call.ArgumentList) > 1 { 60 | return e.Raise("argument", "too many arguments for call to new()") 61 | } 62 | arg := call.Argument(0) 63 | if !arg.IsDefined() { 64 | return e.Raise("type", "invalid type passed to new()") 65 | } 66 | 67 | var nt *NativeType 68 | 69 | rarg, err := arg.Export() 70 | if err != nil { 71 | return e.Raise("jsexport", "could not export argument %d of function %s", 0, "new()") 72 | } 73 | switch v := rarg.(type) { 74 | case *NativeType: 75 | nt = v 76 | default: 77 | return e.Raise("type conversion", "argument type mismatch - expected %s, got %T", "*NativeType", v) 78 | } 79 | 80 | return nt.Factory(call) 81 | } 82 | -------------------------------------------------------------------------------- /engine/types.go: -------------------------------------------------------------------------------- 1 | package engine 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "reflect" 7 | ) 8 | 9 | type typeBuffer struct { 10 | Input interface{} 11 | Orig reflect.Value 12 | Copy reflect.Value 13 | Buf *bytes.Buffer 14 | Engine *Engine 15 | } 16 | 17 | func (e *Engine) newTypeBuffer(i interface{}) *typeBuffer { 18 | if i == nil { 19 | return nil 20 | } 21 | orig := reflect.ValueOf(i) 22 | copy := reflect.New(orig.Type()).Elem() 23 | t := &typeBuffer{ 24 | Input: i, 25 | Buf: new(bytes.Buffer), 26 | Orig: orig, 27 | Copy: copy, 28 | Engine: e, 29 | } 30 | return t 31 | } 32 | 33 | // func translate(obj interface{}) interface{} { 34 | // // Wrap the original in a reflect.Value 35 | // original := reflect.ValueOf(obj) 36 | 37 | // copy := reflect.New(original.Type()).Elem() 38 | // translateRecursive(copy, original) 39 | 40 | // // Remove the reflection wrapper 41 | // return copy.Interface() 42 | // } 43 | 44 | func (t *typeBuffer) WalkType() (string, error) { 45 | t.translateRecursive(t.Copy, t.Orig, 0) 46 | return t.Buf.String(), nil 47 | } 48 | 49 | func (t *typeBuffer) Tab(i int) { 50 | for x := 0; x < i; x++ { 51 | t.Buf.WriteString(" ") 52 | } 53 | } 54 | 55 | func (t *typeBuffer) translateRecursive(copy, original reflect.Value, depth int) { 56 | switch original.Kind() { 57 | // The first cases handle nested structures and translate them recursively 58 | 59 | // If it is a pointer we need to unwrap and call once again 60 | case reflect.Ptr: 61 | originalValue := original.Elem() 62 | // Check if the pointer is nil 63 | if !originalValue.IsValid() { 64 | t.Buf.WriteString("") 65 | return 66 | } 67 | 68 | t.Buf.WriteString("*") 69 | 70 | if !originalValue.CanSet() { 71 | t.Buf.WriteString("") 72 | return 73 | } 74 | // Allocate a new object and set the pointer to it 75 | copy.Set(reflect.New(originalValue.Type())) 76 | // Unwrap the newly created pointer 77 | t.translateRecursive(copy.Elem(), originalValue, depth) 78 | 79 | // If it is an interface (which is very similar to a pointer), do basically the 80 | // same as for the pointer. Though a pointer is not the same as an interface so 81 | // note that we have to call Elem() after creating a new object because otherwise 82 | // we would end up with an actual pointer 83 | case reflect.Interface: 84 | // Get rid of the wrapping interface 85 | originalValue := original.Elem() 86 | // Create a new object. Now new gives us a pointer, but we want the value it 87 | // points to, so we have to call Elem() to unwrap it 88 | copyValue := reflect.New(originalValue.Type()).Elem() 89 | t.translateRecursive(copyValue, originalValue, depth) 90 | copy.Set(copyValue) 91 | 92 | // If it is a struct we translate each field 93 | case reflect.Struct: 94 | t.Buf.WriteString(original.Type().String()) 95 | t.Buf.WriteString("{") 96 | //numberOfFields := original.NumField() 97 | fieldFound := false 98 | for i := 0; i < original.NumField(); i++ { 99 | if !original.Field(i).CanSet() { 100 | continue 101 | } 102 | t.Buf.WriteString("\n") 103 | t.Tab(depth + 1) 104 | t.Buf.WriteString(original.Type().Field(i).Name) 105 | t.Buf.WriteString(": ") 106 | t.translateRecursive(copy.Field(i), original.Field(i), depth+1) 107 | t.Buf.WriteString(", ") 108 | } 109 | if fieldFound { 110 | t.Buf.WriteString("\n") 111 | t.Tab(depth) 112 | } 113 | t.Buf.WriteString("}") 114 | 115 | // If it is a slice we create a new slice and translate each element 116 | case reflect.Slice: 117 | t.Buf.WriteString(original.Type().String()) 118 | t.Buf.WriteString(" { ") 119 | copy.Set(reflect.MakeSlice(original.Type(), original.Len(), original.Cap())) 120 | for i := 0; i < original.Len(); i++ { 121 | t.translateRecursive(copy.Index(i), original.Index(i), depth) 122 | t.Buf.WriteString(", ") 123 | } 124 | t.Buf.WriteString(" } ") 125 | 126 | // If it is a map we create a new map and translate each value 127 | case reflect.Map: 128 | t.Buf.WriteString(original.Type().String()) 129 | t.Buf.WriteString(" { ") 130 | copy.Set(reflect.MakeMap(original.Type())) 131 | for _, key := range original.MapKeys() { 132 | 133 | originalValue := original.MapIndex(key) 134 | // New gives us a pointer, but again we want the value 135 | copyValue := reflect.New(originalValue.Type()).Elem() 136 | t.translateRecursive(copyValue, originalValue, depth) 137 | copy.SetMapIndex(key, copyValue) 138 | } 139 | t.Buf.WriteString(" }") 140 | return 141 | 142 | // Otherwise we cannot traverse anywhere so this finishes the the recursion 143 | 144 | // If it is a string translate it (yay finally we're doing what we came for) 145 | case reflect.String: 146 | t.Buf.WriteString("\"") 147 | t.Buf.WriteString(original.Interface().(string)) 148 | t.Buf.WriteString("\"") 149 | return 150 | 151 | // And everything else will simply be taken from the original 152 | 153 | case reflect.Bool: 154 | t.Buf.WriteString(fmt.Sprintf("%v", original.Interface().(bool))) 155 | return 156 | default: 157 | t.Buf.WriteString(original.String()) 158 | return 159 | } 160 | 161 | } 162 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/gen0cide/gscript 2 | 3 | require ( 4 | github.com/Jeffail/gabs v1.4.0 5 | github.com/Jeffail/gabs/v2 v2.5.0 6 | github.com/ahhh/gopkgs v0.0.0-20180927222900-9e331bbdc80f 7 | github.com/chzyer/logex v1.1.10 // indirect 8 | github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 // indirect 9 | github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect 10 | github.com/davecgh/go-spew v1.1.1 11 | github.com/ditashi/jsbeautifier-go v0.0.0-20141206144643-2520a8026a9c 12 | github.com/fatih/color v1.9.0 13 | github.com/gen0cide/privcheck v0.0.0-20180729084834-a84d5602afb2 14 | github.com/gen0cide/randstr v1.0.3 15 | github.com/gen0cide/waiter v0.0.0-20180804103907-1df131552b6a 16 | github.com/gohxs/readline v0.0.0-20171011095936-a780388e6e7c 17 | github.com/kardianos/service v1.0.0 18 | github.com/karrick/godirwalk v1.15.6 19 | github.com/kr/pretty v0.2.0 // indirect 20 | github.com/mattn/go-colorable v0.1.6 // indirect 21 | github.com/mattn/go-isatty v0.0.12 22 | github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect 23 | github.com/mitchellh/go-ps v1.0.0 24 | github.com/onsi/gomega v1.4.2 // indirect 25 | github.com/phayes/permbits v0.0.0-20190612203442-39d7c581d2ee 26 | github.com/pkg/errors v0.9.1 27 | github.com/robertkrimen/otto v0.0.0-20191219234010-c382bd3c16ff 28 | github.com/sirupsen/logrus v1.6.0 29 | github.com/stretchr/objx v0.1.1 // indirect 30 | github.com/stretchr/testify v1.2.2 31 | github.com/tdewolff/minify v2.3.6+incompatible 32 | github.com/tdewolff/parse v2.3.4+incompatible // indirect 33 | github.com/tdewolff/test v0.0.0-20171106182207-265427085153 // indirect 34 | github.com/urfave/cli/v2 v2.2.0 35 | github.com/uudashr/gopkgs v2.0.1+incompatible // indirect 36 | github.com/vigneshuvi/GoDateFormat v0.0.0-20190923034126-379ee8a8c45f 37 | github.com/x-cray/logrus-prefixed-formatter v0.5.2 38 | golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37 // indirect 39 | golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25 40 | golang.org/x/tools v0.0.0-20200512001501-aaeff5de670a 41 | gopkg.in/VividCortex/ewma.v1 v1.1.1 // indirect 42 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect 43 | gopkg.in/cheggaaa/pb.v2 v2.0.7 // indirect 44 | gopkg.in/fatih/color.v1 v1.7.0 // indirect 45 | gopkg.in/mattn/go-colorable.v0 v0.1.0 // indirect 46 | gopkg.in/mattn/go-isatty.v0 v0.0.4 // indirect 47 | gopkg.in/mattn/go-runewidth.v0 v0.0.4 // indirect 48 | gopkg.in/sourcemap.v1 v1.0.5 // indirect 49 | ) 50 | 51 | go 1.13 52 | -------------------------------------------------------------------------------- /gscript.go: -------------------------------------------------------------------------------- 1 | package gscript 2 | 3 | // Version defines the version of gscript 4 | const Version = "1.0.0" 5 | -------------------------------------------------------------------------------- /logger/base.go: -------------------------------------------------------------------------------- 1 | package logger 2 | 3 | // Logger is an interface that allows for generic logging capabilities to be defined 4 | // for the genesis VM. In production, this will be a nil logger, where as while 5 | // developing or using the console, this can be altered without having to include 6 | // the logging dependencies in the base engine. 7 | type Logger interface { 8 | Print(args ...interface{}) 9 | Printf(format string, args ...interface{}) 10 | Println(args ...interface{}) 11 | 12 | Debug(args ...interface{}) 13 | Debugf(format string, args ...interface{}) 14 | Debugln(args ...interface{}) 15 | 16 | Info(args ...interface{}) 17 | Infof(format string, args ...interface{}) 18 | Infoln(args ...interface{}) 19 | 20 | Warn(args ...interface{}) 21 | Warnf(format string, args ...interface{}) 22 | Warnln(args ...interface{}) 23 | 24 | Error(args ...interface{}) 25 | Errorf(format string, args ...interface{}) 26 | Errorln(args ...interface{}) 27 | 28 | Fatal(args ...interface{}) 29 | Fatalf(format string, args ...interface{}) 30 | Fatalln(args ...interface{}) 31 | } 32 | -------------------------------------------------------------------------------- /logger/null/null_logger.go: -------------------------------------------------------------------------------- 1 | package null 2 | 3 | // Logger is a built in type that implements the Logger interface to prevent scripts 4 | // from writing output to the screen during execution (default logging behavior of binary) 5 | type Logger struct{} 6 | 7 | // Print implements the Logger interface type to prevent debug output 8 | func (n *Logger) Print(args ...interface{}) { 9 | _ = args 10 | return 11 | } 12 | 13 | // Printf implements the Logger interface type to prevent debug output 14 | func (n *Logger) Printf(format string, args ...interface{}) { 15 | _ = format 16 | _ = args 17 | return 18 | } 19 | 20 | // Println implements the Logger interface type to prevent debug output 21 | func (n *Logger) Println(args ...interface{}) { 22 | _ = args 23 | return 24 | } 25 | 26 | // Debug implements the Logger interface type to prevent debug output 27 | func (n *Logger) Debug(args ...interface{}) { 28 | _ = args 29 | return 30 | } 31 | 32 | // Debugf implements the Logger interface type to prevent debug output 33 | func (n *Logger) Debugf(format string, args ...interface{}) { 34 | _ = format 35 | _ = args 36 | return 37 | } 38 | 39 | // Debugln implements the Logger interface type to prevent debug output 40 | func (n *Logger) Debugln(args ...interface{}) { 41 | _ = args 42 | return 43 | } 44 | 45 | // Info implements the Logger interface type to prevent debug output 46 | func (n *Logger) Info(args ...interface{}) { 47 | _ = args 48 | return 49 | } 50 | 51 | // Infof implements the Logger interface type to prevent debug output 52 | func (n *Logger) Infof(format string, args ...interface{}) { 53 | _ = format 54 | _ = args 55 | return 56 | } 57 | 58 | // Infoln implements the Logger interface type to prevent debug output 59 | func (n *Logger) Infoln(args ...interface{}) { 60 | _ = args 61 | return 62 | } 63 | 64 | // Warn implements the Logger interface type to prevent debug output 65 | func (n *Logger) Warn(args ...interface{}) { 66 | _ = args 67 | return 68 | } 69 | 70 | // Warnf implements the Logger interface type to prevent debug output 71 | func (n *Logger) Warnf(format string, args ...interface{}) { 72 | _ = format 73 | _ = args 74 | return 75 | } 76 | 77 | // Warnln implements the Logger interface type to prevent debug output 78 | func (n *Logger) Warnln(args ...interface{}) { 79 | _ = args 80 | return 81 | } 82 | 83 | // Error implements the Logger interface type to prevent debug output 84 | func (n *Logger) Error(args ...interface{}) { 85 | _ = args 86 | return 87 | } 88 | 89 | // Errorf implements the Logger interface type to prevent debug output 90 | func (n *Logger) Errorf(format string, args ...interface{}) { 91 | _ = format 92 | _ = args 93 | return 94 | } 95 | 96 | // Errorln implements the Logger interface type to prevent debug output 97 | func (n *Logger) Errorln(args ...interface{}) { 98 | _ = args 99 | return 100 | } 101 | 102 | // Fatal implements the Logger interface type to prevent debug output 103 | func (n *Logger) Fatal(args ...interface{}) { 104 | _ = args 105 | return 106 | } 107 | 108 | // Fatalf implements the Logger interface type to prevent debug output 109 | func (n *Logger) Fatalf(format string, args ...interface{}) { 110 | _ = format 111 | _ = args 112 | return 113 | } 114 | 115 | // Fatalln implements the Logger interface type to prevent debug output 116 | func (n *Logger) Fatalln(args ...interface{}) { 117 | _ = args 118 | return 119 | } 120 | -------------------------------------------------------------------------------- /logger/standard/ascii_logo.go: -------------------------------------------------------------------------------- 1 | package standard 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | 7 | "github.com/fatih/color" 8 | "github.com/gen0cide/gscript" 9 | ) 10 | 11 | // PrintLogo prints the genesis logo to the current standard out 12 | func PrintLogo() { 13 | fmt.Fprintf(color.Output, "%s\n", ASCIILogo()) 14 | } 15 | 16 | // ASCIILogo returns a string containing a color formatted logo block 17 | func ASCIILogo() string { 18 | lines := []string{ 19 | errorLevel.Sprint("***********************************************************"), 20 | infoMsg.Sprint(" ____ "), 21 | infoMsg.Sprint(" __,-~~/~ `---. "), 22 | infoMsg.Sprint(" _/_,---( , ) "), 23 | infoMsg.Sprint(" __ / < / ) \\___ "), 24 | infoMsg.Sprint(" - ------===;;;'====-----------------===;;;===----- - - "), 25 | infoMsg.Sprint(" \\/ ~\"~\"~\"~\"~\"~\\~\"~)~\"/ "), 26 | infoMsg.Sprint(" (_ ( \\ ( > \\) "), 27 | infoMsg.Sprint(" \\_( _ < >_>' "), 28 | infoMsg.Sprint(" ~ `-i' ::>|--\" "), 29 | infoMsg.Sprint(" I;|.|.| "), 30 | infoMsg.Sprint(" <|i::|i|`. "), 31 | fmt.Sprintf(" %s %s %s ", color.HiGreenString("uL"), color.HiWhiteString("(` ^'\"`-' \")"), color.HiYellowString(")")), 32 | fmt.Sprintf(" %s %s ", color.HiGreenString(".ue888Nc.."), color.HiYellowString("( ( ( /(")), 33 | fmt.Sprintf(" %s %s ", color.HiGreenString("d88E`\"888E`"), color.HiYellowString("( ( )( )\\ ` ) )\\())")), 34 | fmt.Sprintf(" %s %s ", color.HiGreenString("888E 888E"), color.YellowString(")\\ )\\(()\\((_) /(/( (_))/")), 35 | fmt.Sprintf(" %s %s ", color.HiGreenString("888E 888E"), fatalLevel.Sprint("((_) ((_)((_)(_)((_)_\\ | |_")), 36 | fmt.Sprintf(" %s %s ", color.HiGreenString("888E 888E"), color.HiRedString("(_- 0 { 56 | ret = append(ret, strVal) 57 | } 58 | } 59 | } 60 | return ret 61 | } 62 | -------------------------------------------------------------------------------- /stdlib/exec/exec_test.go: -------------------------------------------------------------------------------- 1 | package exec 2 | 3 | import ( 4 | executer "os/exec" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestExecuteCommand(t *testing.T) { 11 | s := make([]interface{}, 0) 12 | pid, stdout, stderr, exitCode, err := ExecuteCommand("whoami", s) 13 | assert.Nil(t, err) 14 | assert.Equal(t, "", stderr, "should be no errors") 15 | assert.Equal(t, 0, exitCode, "should exit cleanly") 16 | assert.NotNil(t, pid) 17 | assert.NotEqual(t, "user", stdout, "can test the returned data") 18 | } 19 | 20 | func TestExecuteCommandAsync(t *testing.T) { 21 | s := make([]interface{}, 1) 22 | s = append(s, "10") 23 | var retcmd *executer.Cmd 24 | retcmd, err := ExecuteCommandAsync("sleep", s) 25 | assert.Nil(t, err) 26 | assert.NotNil(t, retcmd.Process) 27 | } 28 | -------------------------------------------------------------------------------- /stdlib/exec/exec_test.gs: -------------------------------------------------------------------------------- 1 | // Example gscript template 2 | // Title: Cross Platform Execute Example 3 | // Author: ahhh 4 | // Purpose: executes something that should work on multiple platforms 5 | // Gscript version: 1.0.0 6 | 7 | //priority:150 8 | //timeout:150 9 | //go_import:github.com/gen0cide/gscript/stdlib/exec as exec 10 | 11 | function Deploy() { 12 | console.log("Starting Exec Command"); 13 | var response = G.exec.ExecuteCommand("netstat", ["-a"]); 14 | console.log("Pid: "+response[0]); 15 | console.log("stdout: "+response[1]) 16 | console.log("stderr: "+response[2]) 17 | console.log("exit code: "+response[3]) 18 | console.log("go errors: "+response[4]) 19 | return true; 20 | } 21 | 22 | -------------------------------------------------------------------------------- /stdlib/file/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gen0cide/gscript/d65a5ce55f79c4f544a93997e7eb635a72a64118/stdlib/file/.gitkeep -------------------------------------------------------------------------------- /stdlib/file/file_test.go: -------------------------------------------------------------------------------- 1 | package file 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "os" 7 | "testing" 8 | 9 | "github.com/stretchr/testify/assert" 10 | ) 11 | 12 | func TestWriteFileFromBytes(t *testing.T) { 13 | err := WriteFileFromBytes("test_file.txt", []byte("just another test")) 14 | assert.Nil(t, err) 15 | contents, err := ioutil.ReadFile("test_file.txt") 16 | assert.Nil(t, err) 17 | assert.Equal(t, "just another test", string(contents), "they should be equal") 18 | err = os.Remove("test_file.txt") 19 | assert.Nil(t, err) 20 | } 21 | 22 | func TestWriteFileFromString(t *testing.T) { 23 | 24 | err := WriteFileFromString("test_file.txt", "this is a test") 25 | assert.Nil(t, err) 26 | contents, err := ioutil.ReadFile("test_file.txt") 27 | if err == nil { 28 | assert.Equal(t, "this is a test", string(contents), "they should be equal") 29 | //err = os.Remove("test_file.txt") 30 | //if err != nil { 31 | // assert.Nil(t, "file not deleted") 32 | //} 33 | } else { 34 | assert.Nil(t, "bad news") 35 | } 36 | } 37 | 38 | func TestReadFileAsString(t *testing.T) { 39 | fileString, err := ReadFileAsString("test_file.txt") 40 | assert.Nil(t, err) 41 | assert.NotNil(t, fileString) 42 | assert.Equal(t, "this is a test", fileString, "they should be equal") 43 | } 44 | 45 | func TestReadFileAsBytes(t *testing.T) { 46 | bytes, err := ReadFileAsBytes("test_file.txt") 47 | assert.Nil(t, err) 48 | assert.NotNil(t, bytes) 49 | assert.Equal(t, "this is a test", string(bytes), "they should be equal") 50 | } 51 | 52 | func TestCopyFile(t *testing.T) { 53 | dataCopied, err := CopyFile("test_file.txt", "new_test_file.txt") 54 | assert.Nil(t, err) 55 | assert.Equal(t, 14, dataCopied, "they should be equal") 56 | } 57 | 58 | func TestAppendFileBytes(t *testing.T) { 59 | firstData, _ := ioutil.ReadFile("test_file.txt") 60 | fmt.Println(string(firstData)) 61 | err := AppendFileBytes("test_file.txt", []byte("some new data")) 62 | assert.Nil(t, err) 63 | secondData, _ := ioutil.ReadFile("test_file.txt") 64 | fmt.Println(string(secondData)) 65 | assert.NotEqual(t, firstData, secondData, "Should not be equal") 66 | } 67 | 68 | func TestAppendFileString(t *testing.T) { 69 | firstData, _ := ioutil.ReadFile("test_file.txt") 70 | fmt.Println(string(firstData)) 71 | err := AppendFileString("test_file.txt", "\nsome new data\n") 72 | assert.Nil(t, err) 73 | secondData, _ := ioutil.ReadFile("test_file.txt") 74 | fmt.Println(string(secondData)) 75 | assert.NotEqual(t, firstData, secondData, "Should not be equal") 76 | } 77 | 78 | func TestReplaceInFileWithString(t *testing.T) { 79 | replaced, err := ReplaceInFileWithString("test_file.txt", "data", "replaced") 80 | assert.Nil(t, err) 81 | assert.NotNil(t, replaced) 82 | } 83 | 84 | func TestReplaceInFileWithRegex(t *testing.T) { 85 | replaced, err := ReplaceInFileWithRegex("test_file.txt", "(place)", "regexed") 86 | assert.Nil(t, err) 87 | assert.NotNil(t, replaced) 88 | } 89 | 90 | func TestSetPerms(t *testing.T) { 91 | err := SetPerms("test_file.txt", 0777) 92 | assert.Nil(t, err) 93 | } 94 | 95 | func TestCheckExists(t *testing.T) { 96 | exists := CheckExists("test_file.txt") 97 | assert.NotNil(t, exists) 98 | assert.Equal(t, true, exists, "should exist") 99 | } 100 | -------------------------------------------------------------------------------- /stdlib/file/file_test.gs: -------------------------------------------------------------------------------- 1 | // Example gscript template 2 | // Title: Multi Platform Write File Example 3 | // Author: ahhh 4 | // Purpose: Testing an asset and write file 5 | // Gscript version: 1.0.0 6 | // ATT&CK: 7 | 8 | //import:/go/src/github.com/gen0cide/gscript/stdlib/file/file_test.gs 9 | //import:/go/src/github.com/gen0cide/gscript/stdlib/file/file_test.go 10 | 11 | //priority:150 12 | //timeout:150 13 | 14 | function Deploy() { 15 | 16 | console.log("Starting Write First File form Bytes"); 17 | var myBin = GetAssetAsBytes("file_test.gs"); 18 | errors = G.file.WriteFileFromBytes("/go/src/github.com/gen0cide/gscript/stdlib/file/file_test", myBin[0]); 19 | console.log("errors: "+errors); 20 | 21 | console.log("Running ReadFileAsString on file_test 1"); 22 | var readFile = G.file.ReadFileAsString("/go/src/github.com/gen0cide/gscript/stdlib/file/file_test"); 23 | console.log("errors: "+ readFile[1]); 24 | console.log("contains:\n"+readFile[0]); 25 | 26 | console.log("Starting Write Second File form Bytes"); 27 | var myBin2 = GetAssetAsBytes("file_test.go"); 28 | errors = G.file.WriteFileFromBytes("/go/src/github.com/gen0cide/gscript/stdlib/file/file_test2", myBin2[0]); 29 | console.log("errors: "+errors); 30 | 31 | console.log("Running ReadFileAsString on file_test 2"); 32 | var readFile2 = G.file.ReadFileAsString("/go/src/github.com/gen0cide/gscript/stdlib/file/file_test2"); 33 | console.log("errors: "+ readFile2[1]); 34 | console.log("contains:\n"+readFile2[0]); 35 | 36 | return true; 37 | } 38 | -------------------------------------------------------------------------------- /stdlib/file/file_test3.gs: -------------------------------------------------------------------------------- 1 | // Example gscript template 2 | // Title: Multi Platform Write File Example 3 | // Author: ahhh 4 | // Purpose: Testing an asset and write file 5 | // Gscript version: 1.0.0 6 | // ATT&CK: 7 | 8 | //import:/go/src/github.com/gen0cide/gscript/stdlib/file/file.go 9 | 10 | //priority:150 11 | //timeout:150 12 | 13 | function Deploy() { 14 | 15 | console.log("Starting Write Third File form Bytes"); 16 | var myBin = GetAssetAsBytes("file.go"); 17 | errors = G.file.WriteFileFromBytes("/go/src/github.com/gen0cide/gscript/stdlib/file/file_test3", myBin[0]); 18 | console.log("errors: "+errors); 19 | 20 | console.log("Running ReadFileAsString on file_test3"); 21 | var readFile = G.file.ReadFileAsString("/go/src/github.com/gen0cide/gscript/stdlib/file/file_test3"); 22 | console.log("errors: "+ readFile[1]); 23 | console.log("contains:\n"+readFile[0]); 24 | 25 | 26 | return true; 27 | } 28 | -------------------------------------------------------------------------------- /stdlib/file/file_test4.gs: -------------------------------------------------------------------------------- 1 | // Example gscript template 2 | // Title: Multi Platform Write File Example 3 | // Author: ahhh 4 | // Purpose: Testing an asset and write file on different platforms 5 | // Gscript version: 1.0.0 6 | // ATT&CK: 7 | 8 | 9 | //priority:150 10 | //timeout:150 11 | 12 | function Deploy() { 13 | 14 | console.log("Starting Write file from String"); 15 | var writeStringErrors = G.file.WriteFileFromString("/go/src/github.com/gen0cide/gscript/stdlib/file/file_test4.txt", "Testing some stuff\n"); 16 | console.log("errors: "+ writeStringErrors) 17 | 18 | }; 19 | -------------------------------------------------------------------------------- /stdlib/file/new_test_file.txt: -------------------------------------------------------------------------------- 1 | this is a test -------------------------------------------------------------------------------- /stdlib/file/test_file.txt: -------------------------------------------------------------------------------- 1 | this is a testsome new reregexedd 2 | some new reregexedd 3 | -------------------------------------------------------------------------------- /stdlib/net/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gen0cide/gscript/d65a5ce55f79c4f544a93997e7eb635a72a64118/stdlib/net/.gitkeep -------------------------------------------------------------------------------- /stdlib/net/net.go: -------------------------------------------------------------------------------- 1 | package net 2 | 3 | import ( 4 | "fmt" 5 | gonet "net" 6 | "strconv" 7 | "strings" 8 | "sync" 9 | "time" 10 | ) 11 | 12 | //CheckForInUseTCP is a function that checks all local IPv4 interfaces for to see if something is listening on the specified TCP port will timeout after 3 seconds 13 | func CheckForInUseTCP(port int) (bool, error) { 14 | timeout, err := time.ParseDuration("50ms") 15 | portString := strconv.Itoa(port) 16 | addr := "0.0.0.0:" + portString 17 | fmt.Println(addr) 18 | conn, err := gonet.DialTimeout("tcp", addr, timeout) 19 | if err != nil { 20 | if strings.ContainsAny(err.Error(), "connection refused") { 21 | return false, nil 22 | } 23 | return false, err 24 | } 25 | if conn != nil { 26 | conn.Close() 27 | return true, nil 28 | } 29 | return false, nil 30 | } 31 | 32 | //CheckForInUseUDP will send a UDP packet to the local port and see it gets a response or will timeout 33 | func CheckForInUseUDP(port int) (bool, error) { 34 | timeout, err := time.ParseDuration("50ms") 35 | if err != nil { 36 | return false, err 37 | } 38 | conn, err := gonet.DialTimeout("udp", fmt.Sprintf("0.0.0.0:%d", port), timeout) 39 | if err != nil { 40 | return false, err 41 | } 42 | timeNow := time.Now() 43 | nextTick := timeNow.Add(timeout) 44 | conn.SetReadDeadline(nextTick) 45 | conn.SetWriteDeadline(nextTick) 46 | writeBuf := make([]byte, 1024, 1024) 47 | for i := 0; i < 1024; i++ { 48 | writeBuf[i] = 0x00 49 | } 50 | retSize, err := conn.Write(writeBuf) 51 | if err != nil { 52 | return false, err 53 | } 54 | readBuf := make([]byte, 1024, 1024) 55 | retSize, err = conn.Read(readBuf) 56 | if err != nil { 57 | opError, ok := err.(*gonet.OpError) 58 | if !ok { 59 | return false, err 60 | } 61 | if opError.Timeout() { 62 | return true, nil 63 | } 64 | return false, err 65 | } 66 | if retSize > 0 { 67 | return true, nil 68 | } 69 | var wg sync.WaitGroup 70 | wg.Add(1) 71 | go func() { 72 | time.Sleep(timeout) 73 | wg.Done() 74 | }() 75 | wg.Wait() 76 | return false, nil 77 | } 78 | -------------------------------------------------------------------------------- /stdlib/net/net_test.go: -------------------------------------------------------------------------------- 1 | package net 2 | 3 | import ( 4 | "fmt" 5 | gonet "net" 6 | "testing" 7 | 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func TestCheckForInUseTCP(t *testing.T) { 12 | t.Helper() 13 | ln, err := gonet.Listen("tcp", "127.0.0.1:31337") 14 | assert.Nil(t, err) 15 | assert.NotNil(t, ln) 16 | var server gonet.Conn 17 | _ = server 18 | go func() { 19 | defer ln.Close() 20 | server, err = ln.Accept() 21 | }() 22 | inUse, err := CheckForInUseTCP(31337) 23 | assert.Nil(t, err) 24 | assert.NotNil(t, inUse) 25 | assert.Equal(t, true, inUse, "will be true if running a listener") 26 | notInUse, err := CheckForInUseTCP(31338) 27 | assert.Nil(t, err) 28 | assert.NotNil(t, notInUse) 29 | assert.Equal(t, false, notInUse, "will be false when the port is not in use") 30 | } 31 | 32 | func TestCheckForInUseUDP(t *testing.T) { 33 | t.Helper() 34 | addr, err := gonet.ResolveUDPAddr("udp", "127.0.0.1:29201") 35 | assert.Nil(t, err) 36 | assert.NotNil(t, addr) 37 | serverConn, err := gonet.ListenUDP("udp", addr) 38 | assert.Nil(t, err) 39 | assert.NotNil(t, serverConn) 40 | go func() { 41 | defer serverConn.Close() 42 | 43 | buf := make([]byte, 1024) 44 | for { 45 | n, addr, err := serverConn.ReadFromUDP(buf) 46 | fmt.Println("Received ", string(buf[0:n]), " from ", addr) 47 | 48 | if err != nil { 49 | fmt.Println("Error: ", err) 50 | } 51 | } 52 | }() 53 | inUse, err := CheckForInUseUDP(29201) 54 | assert.Nil(t, err) 55 | assert.NotNil(t, inUse) 56 | assert.Equal(t, true, inUse, "will be true if something is listening on that udp port") 57 | notInUse, err := CheckForInUseUDP(67) 58 | assert.NotNil(t, err) 59 | assert.NotNil(t, notInUse) 60 | assert.Equal(t, false, notInUse, "will be true if something is not in use") 61 | } 62 | -------------------------------------------------------------------------------- /stdlib/os/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gen0cide/gscript/d65a5ce55f79c4f544a93997e7eb635a72a64118/stdlib/os/.gitkeep -------------------------------------------------------------------------------- /stdlib/os/os.go: -------------------------------------------------------------------------------- 1 | package os 2 | 3 | import ( 4 | goOs "os" 5 | ) 6 | 7 | //TerminateVM will halt the execution of the current gscript 8 | func TerminateVM() { 9 | //Implement later 10 | } 11 | 12 | //TerminateSelf will kill the current process 13 | func TerminateSelf() error { 14 | pid := goOs.Getpid() 15 | proc, err := goOs.FindProcess(int(pid)) 16 | if err != nil { 17 | return err 18 | } 19 | err = proc.Kill() 20 | if err != nil { 21 | return err 22 | } 23 | return nil 24 | } 25 | -------------------------------------------------------------------------------- /stdlib/os/os_test.go: -------------------------------------------------------------------------------- 1 | package os 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | // DANGEROUS FUNCTION 10 | func TestTerminateSelf(t *testing.T) { 11 | // DANGEROUS FUNCTION 12 | // TerminateSelf() 13 | var lol = "" 14 | assert.Equal(t, "", lol, "temp test") 15 | } 16 | -------------------------------------------------------------------------------- /stdlib/rand/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gen0cide/gscript/d65a5ce55f79c4f544a93997e7eb635a72a64118/stdlib/rand/.gitkeep -------------------------------------------------------------------------------- /stdlib/rand/rand.go: -------------------------------------------------------------------------------- 1 | package rand 2 | 3 | import ( 4 | random "crypto/rand" 5 | "math/big" 6 | ) 7 | 8 | //RandomInt Generates a random number between min and max. 9 | func RandomInt(min, max int) int { 10 | r, _ := random.Int(random.Reader, big.NewInt(int64(max-min))) 11 | return int(r.Int64() + int64(min)) 12 | } 13 | 14 | //GetAlphaNumericString Generates a random alpha numeric string of a specified length 15 | func GetAlphaNumericString(strlen int) string { 16 | const chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" 17 | result := make([]byte, strlen) 18 | for i := range result { 19 | val, err := random.Int(random.Reader, big.NewInt(int64(len(chars)))) 20 | if err != nil { 21 | panic(err) 22 | } 23 | result[i] = chars[val.Int64()] 24 | } 25 | return string(result) 26 | } 27 | 28 | //GetAlphaString generates a random alpha string of a specified length 29 | func GetAlphaString(strlen int) string { 30 | const chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" 31 | result := make([]byte, strlen) 32 | for i := range result { 33 | val, err := random.Int(random.Reader, big.NewInt(int64(len(chars)))) 34 | if err != nil { 35 | panic(err) 36 | } 37 | result[i] = chars[val.Int64()] 38 | } 39 | return string(result) 40 | } 41 | 42 | //GetAlphaNumericSpecialString generates a random alpha numeric and special char string of a specified length 43 | func GetAlphaNumericSpecialString(strlen int) string { 44 | const chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()" 45 | result := make([]byte, strlen) 46 | for i := range result { 47 | val, err := random.Int(random.Reader, big.NewInt(int64(len(chars)))) 48 | if err != nil { 49 | panic(err) 50 | } 51 | result[i] = chars[val.Int64()] 52 | } 53 | return string(result) 54 | } 55 | 56 | //GetBool returns a random true or false 57 | func GetBool() bool { 58 | val, _ := random.Int(random.Reader, big.NewInt(int64(2))) 59 | if int(val.Int64()) == int(0) { 60 | return false 61 | } 62 | return true 63 | } 64 | -------------------------------------------------------------------------------- /stdlib/rand/rand_test.go: -------------------------------------------------------------------------------- 1 | package rand 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestRandomInt(t *testing.T) { 10 | rando := RandomInt(1, 2147483640) 11 | assert.NotZero(t, rando) 12 | //assert.EqualValues(t, rando, 0, "testing") 13 | } 14 | 15 | func TestGetAlphaNumericString(t *testing.T) { 16 | rando := GetAlphaNumericString(10) 17 | assert.NotEqual(t, "", rando, "should not be an empty string") 18 | assert.Len(t, rando, 10, "should be 10 chars long") 19 | //assert.Equal(t, rando, "", "testing") 20 | } 21 | 22 | func TestGetAlphaString(t *testing.T) { 23 | rando := GetAlphaString(5) 24 | assert.NotEqual(t, "", rando, "should not be an empty string") 25 | assert.Len(t, rando, 5, "should be 10 chars long") 26 | //assert.Equal(t, rando, "", "testing") 27 | } 28 | 29 | func TestGetAlphaNumericSpecialString(t *testing.T) { 30 | rando := GetAlphaNumericSpecialString(7) 31 | assert.NotEqual(t, "", rando, "should not be an empty string") 32 | assert.Len(t, rando, 7, "should be 10 chars long") 33 | //assert.Equal(t, rando, "", "testing") 34 | } 35 | 36 | func TestGetBool(t *testing.T) { 37 | rando := GetBool() 38 | assert.NotNil(t, rando) 39 | //assert.Equal(t, false, rando, "passes half the time") 40 | } 41 | -------------------------------------------------------------------------------- /stdlib/rand/rand_test.gs: -------------------------------------------------------------------------------- 1 | // Example gscript template 2 | // Title: Multi Platform Randomness Example 3 | // Author: ahhh 4 | // Purpose: Testing randomness on different platforms 5 | // Gscript version: 1.0.0 6 | 7 | //priority:150 8 | //timeout:150 9 | 10 | function Deploy() { 11 | 12 | console.log("Starting RandomInt"); 13 | out1 = G.rand.RandomInt(12, 20); 14 | console.log("out: "+out1); 15 | 16 | console.log("Starting GetAlphaNumericString"); 17 | var out2 = G.rand.GetAlphaNumericString(12); 18 | console.log("out: " +out2); 19 | console.log("out upper: "+ out2.toUpperCase()); 20 | console.log("out lower: "+ out2.toLowerCase()); 21 | 22 | console.log("Starting GetAlphaString"); 23 | var out3 = G.rand.GetAlphaString(10); 24 | console.log("out: "+ out3); 25 | console.log("out upper: "+ out3.toUpperCase()); 26 | console.log("out lower: "+ out3.toLowerCase()); 27 | 28 | console.log("Starting GetAlphaNumericSpecialString"); 29 | var out4 = G.rand.GetAlphaNumericSpecialString(7); 30 | console.log("out: "+ out4); 31 | console.log("out upper: "+ out4.toUpperCase()); 32 | console.log("out lower: "+ out4.toLowerCase()); 33 | 34 | console.log("Starting GetBools"); 35 | var out5 = G.rand.GetBool(); 36 | console.log("out: "+ out5); 37 | 38 | return true; 39 | } 40 | -------------------------------------------------------------------------------- /stdlib/requests/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gen0cide/gscript/d65a5ce55f79c4f544a93997e7eb635a72a64118/stdlib/requests/.gitkeep -------------------------------------------------------------------------------- /stdlib/requests/requests.go: -------------------------------------------------------------------------------- 1 | package requests 2 | 3 | import ( 4 | "crypto/tls" 5 | "fmt" 6 | "io" 7 | "io/ioutil" 8 | "net/http" 9 | "os" 10 | "path/filepath" 11 | "strings" 12 | 13 | // IMPORT EXCEPTION OVERRIDE (gen0cide): 14 | // This library is used for JSON serialization 15 | // and follows our rules of no dependencies outside 16 | // of the standard library. It's stable, widely used, 17 | // and is literally the exact thing I was going to 18 | // implement for serializing arbitrary JSON but 19 | // has the advantage of being more widely tested 20 | // and stable. 21 | "github.com/Jeffail/gabs/v2" 22 | 23 | // IMPORT EXCEPTION OVERRIDE (gen0cide): 24 | // This is a small wrapper by the *AUTHORS OF GO ITSELF* 25 | // to provide the ability to stack and wrap 26 | // multiple error messages for better context. 27 | // It's stable, widely used, incredibly small, 28 | // and has zero dependencies except for a few 29 | // standard library packages. 30 | "github.com/pkg/errors" 31 | ) 32 | 33 | //GetURLAsString will fetch a url and return an http response object, the body as a string, and an error 34 | func GetURLAsString(url string, headers map[string]interface{}, ignoresslerrors bool) (*http.Response, string, error) { 35 | c := createClient(ignoresslerrors) 36 | req, err := createReq("GET", url, headers, nil) 37 | if err != nil { 38 | return nil, "", err 39 | } 40 | return do(c, req) 41 | } 42 | 43 | //GetURLAsBytes will fetch a url, headers, and a bool for ignoring ssl errors. this returns an http response object, the body as a string, and an error 44 | func GetURLAsBytes(url string, headers map[string]interface{}, ignoresslerrors bool) (*http.Response, []byte, error) { 45 | c := createClient(ignoresslerrors) 46 | req, err := createReq("GET", url, headers, nil) 47 | if err != nil { 48 | return nil, []byte{}, err 49 | } 50 | resp, data, err := do(c, req) 51 | return resp, []byte(data), err 52 | } 53 | 54 | //PostJSON takes a url, json data, a map of headers, and a bool to ignore ssl errors, posts json data to url 55 | func PostJSON(url string, data map[string]interface{}, headers map[string]interface{}, ignoresslerrors bool) (*http.Response, string, error) { 56 | jsonData, err := genJSON(data) 57 | if err != nil { 58 | return nil, "", err 59 | } 60 | c := createClient(ignoresslerrors) 61 | if _, ok := headers["Content-Type"]; !ok { 62 | headers["Content-Type"] = "application/json" 63 | } 64 | req, err := createReq("POST", url, headers, jsonData) 65 | if err != nil { 66 | return nil, "", err 67 | } 68 | return do(c, req) 69 | } 70 | 71 | //PostURL posts the specified data to a url endpoint as text/plain data 72 | func PostURL(url string, data string, headers map[string]interface{}, ignoresslerrors bool) (*http.Response, string, error) { 73 | c := createClient(ignoresslerrors) 74 | if _, ok := headers["Content-Type"]; !ok { 75 | headers["Content-Type"] = "text/plain" 76 | } 77 | req, err := createReq("POST", url, headers, strings.NewReader(data)) 78 | if err != nil { 79 | return nil, "", errors.Wrap(err, "error creating HTTP request") 80 | } 81 | return do(c, req) 82 | } 83 | 84 | //PostBinary posts the specified data to a url endpoint as application/octet-stream data 85 | func PostBinary(url string, readPath string, headers map[string]interface{}, ignoresslerrors bool) (*http.Response, string, error) { 86 | absPath, err := filepath.Abs(readPath) 87 | if err != nil { 88 | return nil, "", errors.Wrap(err, "error reading body file") 89 | } 90 | fileReader, err := os.Open(absPath) 91 | if err != nil { 92 | return nil, "", errors.Wrap(err, "error reading body file") 93 | } 94 | c := createClient(ignoresslerrors) 95 | if _, ok := headers["Content-Type"]; !ok { 96 | headers["Content-Type"] = "application/octet-stream" 97 | } 98 | req, err := createReq("POST", url, headers, fileReader) 99 | if err != nil { 100 | return nil, "", errors.Wrap(err, "error creating HTTP request") 101 | } 102 | return do(c, req) 103 | } 104 | 105 | func do(c *http.Client, r *http.Request) (*http.Response, string, error) { 106 | resp, err := c.Do(r) 107 | if err != nil { 108 | return resp, "", err 109 | } 110 | defer resp.Body.Close() 111 | data, err := ioutil.ReadAll(resp.Body) 112 | if err != nil { 113 | return resp, "", errors.Wrap(err, "could not read response body") 114 | } 115 | return resp, string(data), nil 116 | } 117 | 118 | func createClient(ignoreSSL bool) *http.Client { 119 | return &http.Client{ 120 | Transport: &http.Transport{ 121 | TLSClientConfig: &tls.Config{ 122 | InsecureSkipVerify: ignoreSSL, 123 | }, 124 | }, 125 | } 126 | } 127 | 128 | func genJSON(data map[string]interface{}) (*strings.Reader, error) { 129 | jsonObj := gabs.Wrap(data) 130 | if jsonObj == nil { 131 | return strings.NewReader("{}"), errors.New("could not generate JSON body") 132 | } 133 | return strings.NewReader(jsonObj.String()), nil 134 | } 135 | 136 | func createReq(method, url string, headers map[string]interface{}, body io.Reader) (*http.Request, error) { 137 | req, err := http.NewRequest(method, url, body) 138 | if err != nil { 139 | return nil, err 140 | } 141 | for k, v := range headers { 142 | req.Header.Set(k, fmt.Sprintf("%v", v)) 143 | } 144 | return req, nil 145 | } 146 | -------------------------------------------------------------------------------- /stdlib/requests/requests_test.go: -------------------------------------------------------------------------------- 1 | package requests 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/davecgh/go-spew/spew" 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | var ( 11 | testHeaders = map[string]interface{}{ 12 | "X-Test-ID": "gscript", 13 | } 14 | ) 15 | 16 | func TestGetURLAsString(t *testing.T) { 17 | obj, resp, err := GetURLAsString("http://icanhazip.com/", testHeaders, false) 18 | assert.Nil(t, err) 19 | assert.NotNil(t, obj) 20 | assert.NotNil(t, resp) 21 | 22 | obj, resp, err = GetURLAsString("https://google.com/", testHeaders, false) 23 | assert.Nil(t, err) 24 | assert.NotNil(t, obj) 25 | assert.NotNil(t, resp) 26 | 27 | obj, resp, err = GetURLAsString("https://wrong.host.badssl.com/", testHeaders, true) 28 | assert.Nil(t, err) 29 | assert.NotNil(t, obj) 30 | assert.NotNil(t, resp) 31 | 32 | obj, resp, err = GetURLAsString("https://wrong.host.badssl.com/", testHeaders, false) 33 | assert.NotNil(t, err) 34 | assert.Nil(t, obj) 35 | assert.Equal(t, "", resp, "blank means received no data, due to error") 36 | 37 | testslice := make([]string, 0, 0) 38 | spew.Dump(testslice) 39 | } 40 | 41 | func TestGetURLAsBytes(t *testing.T) { 42 | obj, resp, err := GetURLAsBytes("http://icanhazip.com/", testHeaders, false) 43 | assert.Nil(t, err) 44 | assert.NotNil(t, obj) 45 | assert.NotNil(t, resp) 46 | } 47 | 48 | func TestPostJSON(t *testing.T) { 49 | json := map[string]interface{}{ 50 | "menu": "item", 51 | } 52 | obj, resp, err := PostJSON("http://postb.in/5d83jRPR", json, testHeaders, false) 53 | assert.Nil(t, err) 54 | assert.NotNil(t, obj) 55 | assert.NotNil(t, resp) 56 | } 57 | 58 | func TestPostURL(t *testing.T) { 59 | obj, resp, err := PostURL("http://postb.in/dEH0maRf", "first test data", testHeaders, false) 60 | assert.Nil(t, err) 61 | assert.NotNil(t, obj) 62 | assert.NotNil(t, resp) 63 | } 64 | 65 | //func TestPostBinary(t *testing.T) { 66 | // obj, resp, err := PostBinary("http://postb.in/L7daTOz8", "./example_test.txt", nil, true) 67 | // assert.Nil(t, err) 68 | // assert.NotNil(t, obj) 69 | // assert.NotNil(t, resp) 70 | // assert.Equal(t, resp, "blah blah", "should throw an error") 71 | //} 72 | -------------------------------------------------------------------------------- /stdlib/time/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gen0cide/gscript/d65a5ce55f79c4f544a93997e7eb635a72a64118/stdlib/time/.gitkeep -------------------------------------------------------------------------------- /stdlib/time/time.go: -------------------------------------------------------------------------------- 1 | package time 2 | 3 | import ( 4 | gotime "time" 5 | ) 6 | 7 | //GetUnix fetches the current unixtime 8 | func GetUnix() int { 9 | return int(gotime.Now().Unix()) 10 | } 11 | -------------------------------------------------------------------------------- /stdlib/time/time_test.go: -------------------------------------------------------------------------------- 1 | package time 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestGetUnix(t *testing.T) { 10 | unixTime := GetUnix() 11 | assert.NotNil(t, unixTime) 12 | //assert.Equal(t, unixTime, int(1531208097), "will likyl fail") 13 | } 14 | -------------------------------------------------------------------------------- /stdlib/time/time_test.gs: -------------------------------------------------------------------------------- 1 | // Example gscript template 2 | // Title: Cross Platform Time Example 3 | // Author: ahhh 4 | // Purpose: gets the current Unix time on multiple platforms 5 | // Gscript version: 1.0.0 6 | 7 | //priority:150 8 | //timeout:150 9 | 10 | function Deploy() { 11 | console.log("Starting Time"); 12 | var response = G.time.GetUnix(); 13 | console.log("Time: "+response); 14 | return true; 15 | } 16 | -------------------------------------------------------------------------------- /tools.go: -------------------------------------------------------------------------------- 1 | // +build tools 2 | 3 | package tools 4 | 5 | import ( 6 | _ "github.com/gen0cide/gscript/stdlib/crypto" 7 | _ "github.com/gen0cide/gscript/stdlib/encoding" 8 | _ "github.com/gen0cide/gscript/stdlib/exec" 9 | _ "github.com/gen0cide/gscript/stdlib/file" 10 | _ "github.com/gen0cide/gscript/stdlib/net" 11 | _ "github.com/gen0cide/gscript/stdlib/os" 12 | _ "github.com/gen0cide/gscript/stdlib/rand" 13 | _ "github.com/gen0cide/gscript/stdlib/requests" 14 | _ "github.com/gen0cide/gscript/stdlib/time" 15 | ) 16 | -------------------------------------------------------------------------------- /tools/linker_test/basic_example.gs: -------------------------------------------------------------------------------- 1 | //go_import:time as gotimelib 2 | //go_import:os as oslib 3 | 4 | function Deploy() { 5 | filetowrite = "/tmp/nikki.txt" 6 | 7 | timeobj = gotimelib.Now() 8 | timestring = timeobj.String() 9 | 10 | G.file.WriteFileFromString(filetowrite, timestring) 11 | 12 | console.log(timestring) 13 | 14 | DebugConsole() 15 | } -------------------------------------------------------------------------------- /tools/linker_test/dns_test.gs: -------------------------------------------------------------------------------- 1 | //go_import:github.com/hoisie/web as web 2 | //go_import:net/http as http 3 | 4 | function Deploy() { 5 | DebugConsole() 6 | } -------------------------------------------------------------------------------- /tools/linker_test/ns_test.gs: -------------------------------------------------------------------------------- 1 | // Example gscript template 2 | // Title: Cross Platform Execute Async Example 3 | // Author: ahhh 4 | // Purpose: executes something that should work on multiple platforms 5 | // Gscript version: 1.0.0 6 | // ATT&CK: 7 | 8 | //priority:150 9 | //timeout:150 10 | 11 | function Deploy() { 12 | console.log("Starting Exec Command"); 13 | var response = G.exec.ExecuteCommandAsync("netstat", ["-a"]); 14 | console.log("cmd_obj: " + response[0]); 15 | return true; 16 | } -------------------------------------------------------------------------------- /tools/linker_test/test.gs: -------------------------------------------------------------------------------- 1 | //go_import:github.com/gen0cide/gscript/internal/linker_test/testlib as testlib 2 | 3 | function Deploy() { 4 | param1 = "hello"; 5 | param2 = "world"; 6 | param3 = "this is longggg"; 7 | ret = testlib.Test1("http://google.com/search"); 8 | console.log(ret[0].Host); 9 | } -------------------------------------------------------------------------------- /tools/linker_test/test2.gs: -------------------------------------------------------------------------------- 1 | //go_import:github.com/deckarep/gosx-notifier as notifier 2 | //go_import:github.com/atotto/clipboard as clipboard 3 | //go_import:github.com/gen0cide/gscript/ternals/linker_test/testlib as testlib 4 | //go_import:github.com/bettercap/bettercap/network as betnet 5 | //go_import:github.com/bettercap/bettercap/modules as betmod 6 | //go_import:github.com/bettercap/bettercap/session as betsesh 7 | 8 | function Deploy() { 9 | param1 = "hello"; 10 | param2 = "world"; 11 | param3 = "this is longggg"; 12 | hotmama = notifier.NewNotification(param1 + " " + param2 + " " + param3); 13 | da_error = hotmama.Push(); 14 | console.log(da_error); 15 | clippy = clipboard.ReadAll(); 16 | console.log(clippy[0]); 17 | urlObj = testlib.Test1( 18 | "https://bing.com/search" 19 | );, , , 20 | console.warn(urlObj[0].Host); 21 | DebugConsole(); 22 | } -------------------------------------------------------------------------------- /tools/linker_test/test3.gs: -------------------------------------------------------------------------------- 1 | // Example gscript template 2 | // Title: Multi Platform Delete File Example 3 | // Author: ahhh 4 | // Purpose: Testing a delete file on different platforms 5 | // Gscript version: 1.0.0 6 | // ATT&CK: 7 | 8 | //priority:150 9 | //timeout:150 10 | //go_import:os as os 11 | 12 | function Deploy() { 13 | 14 | console.log("Starting Delete File"); 15 | var errors = os.Remove("test_file.txt"); 16 | console.log("errors: " + errors.Error()); 17 | 18 | return true; 19 | } 20 | 21 | // //import:/tmp/testasset.txt 22 | 23 | // function Deploy() { 24 | // a = G.time.GetUnix(); 25 | // console.log("CURRENT UNIX TIME: " + a); 26 | // b = GetAssetAsString("testasset.txt"); 27 | // console.log(b); 28 | // return true; 29 | // } -------------------------------------------------------------------------------- /tools/linker_test/test4.gs: -------------------------------------------------------------------------------- 1 | //go_import:os as osl 2 | 3 | function Deploy() { 4 | DebugConsole(); 5 | } -------------------------------------------------------------------------------- /tools/linker_test/test_requests.gs: -------------------------------------------------------------------------------- 1 | function Deploy() { 2 | resp = G.requests.GetURLAsString("https://icanhazip.com/", {}, false) 3 | DebugConsole() 4 | } -------------------------------------------------------------------------------- /tools/linker_test/test_type.gs: -------------------------------------------------------------------------------- 1 | //go_import:github.com/gen0cide/gscript/tools/linker_test/typelib as typelib 2 | 3 | function Deploy() { 4 | val = 12345 5 | console.log(typelib.TakePointer(val)) 6 | console.log(typelib.TakeHandle(val)) 7 | var naming = G.rand.GetAlphaString(4) 8 | console.log(naming) 9 | DebugConsole() 10 | } -------------------------------------------------------------------------------- /tools/linker_test/testlib/lib.go: -------------------------------------------------------------------------------- 1 | package testlib 2 | 3 | import ( 4 | "errors" 5 | "net/url" 6 | "strings" 7 | ) 8 | 9 | // Aspy is a test type for me to work on the linker 10 | type Aspy struct { 11 | Name string 12 | } 13 | 14 | // (s string, a2 map[*url.URL][]*Aspy, b []*Aspy, c url.URL, d *Aspy, e *url.URL) (*url.URL, error) { 15 | 16 | // Test1 is a test function 17 | func Test1(s string) (*url.URL, error) { 18 | u, err := url.Parse(s) 19 | _ = u 20 | if err != nil { 21 | return nil, err 22 | } 23 | return u, nil 24 | } 25 | 26 | // Test2 is a test function 27 | func Test2(p1, p2 string) string { 28 | return strings.Join([]string{p1, p2}, " ") 29 | } 30 | 31 | // Test3 is a test function 32 | func Test3(s string) bool { 33 | if len(s) > 4 { 34 | return true 35 | } 36 | return false 37 | } 38 | 39 | // Test5 is a test function 40 | func Test5() *Aspy { 41 | return &Aspy{ 42 | Name: "simmons", 43 | } 44 | } 45 | 46 | // Test4 is a test function 47 | func Test4(a *Aspy) string { 48 | return strings.ToUpper(a.Name) 49 | } 50 | 51 | // Test6 is a test function 52 | func (a *Aspy) Test6(s string) (*Aspy, error) { 53 | if len(s) > 5 { 54 | return nil, errors.New("string should be 1-4 chars") 55 | } 56 | newName := strings.Join([]string{a.Name, s}, "-") 57 | return &Aspy{Name: newName}, nil 58 | } 59 | 60 | // Test7 is a test function 61 | func Test7(s string) Aspy { 62 | return Aspy{ 63 | Name: s, 64 | } 65 | } 66 | 67 | // Test8 is a test function 68 | func (a Aspy) Test8() string { 69 | return a.Name 70 | } 71 | -------------------------------------------------------------------------------- /tools/linker_test/typelib/type_convert.go: -------------------------------------------------------------------------------- 1 | package typelib 2 | 3 | import "syscall" 4 | 5 | // TakePointer is a test function for translating uintptr types 6 | func TakePointer(arg uintptr) error { 7 | return nil 8 | } 9 | 10 | // TakeHandle is a test function for converting aliased types 11 | func TakeHandle(arg syscall.Signal) error { 12 | return nil 13 | } 14 | -------------------------------------------------------------------------------- /tools/svctest/darwin.gs: -------------------------------------------------------------------------------- 1 | //go_import:github.com/gen0cide/gscript/x/svc as svc 2 | //import:/tmp/svctest-darwin.bin 3 | 4 | var service_bin_path = "/usr/local/bin/svctest" 5 | 6 | 7 | var serviceSettings = { 8 | name: "gscript_eicar_service", 9 | display_name: "gscript eicar service", 10 | description: "genesis engine eicar example service", 11 | arguments: [], 12 | executable_path: service_bin_path, 13 | working_directory: "/usr/local/", 14 | options: {} 15 | } 16 | 17 | function Deploy() { 18 | console.log("Writing binary to disk...") 19 | 20 | filedata = GetAssetAsString("svctest-darwin.bin") 21 | 22 | var quitAfterDebug = false; 23 | DebugConsole() 24 | 25 | if (quitAfterDebug == true) { 26 | return 27 | } 28 | 29 | errchk = G.file.WriteFileFromString(service_bin_path, filedata[0]) 30 | if (errchk !== undefined) { 31 | console.error("Error writing file: " + errchk.Error()) 32 | DebugConsole() 33 | return 34 | } 35 | 36 | console.log("Creating new service object...") 37 | 38 | var svcObj = svc.NewFromJSON(serviceSettings) 39 | if (svcObj[1] !== undefined) { 40 | console.error("Error creating service: " + svcObj[1].Error()) 41 | DebugConsole() 42 | return 43 | } 44 | 45 | console.log("Checking service config sanity...") 46 | 47 | confchk = svcObj[0].CheckConfig(true) 48 | if (confchk[1] !== undefined || confchk[0] === false) { 49 | console.error("Error checking config: " + confchk[1].Error()) 50 | DebugConsole() 51 | return 52 | } 53 | 54 | console.log("Installing service...") 55 | 56 | installchk = svcObj[0].Install(true) 57 | if (installchk !== undefined) { 58 | console.error("Error installing service: " + installchk.Error()) 59 | DebugConsole() 60 | return 61 | } 62 | 63 | console.log("Starting service...") 64 | 65 | startchk = svcObj[0].Start() 66 | if (startchk !== undefined) { 67 | console.error("Error starting service: " + startchk.Error()) 68 | DebugConsole() 69 | return 70 | } 71 | 72 | DebugConsole() 73 | } -------------------------------------------------------------------------------- /tools/svctest/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net/http" 7 | 8 | "github.com/kardianos/service" 9 | ) 10 | 11 | func sayhelloName(w http.ResponseWriter, r *http.Request) { 12 | fmt.Fprintf(w, "Hello astaxie!") // send data to client side 13 | } 14 | 15 | var logger service.Logger 16 | 17 | type program struct{} 18 | 19 | func (p *program) Start(s service.Service) error { 20 | go p.run() 21 | return nil 22 | } 23 | func (p *program) run() { 24 | http.HandleFunc("/", sayhelloName) 25 | err := http.ListenAndServe(":9090", nil) 26 | if err != nil { 27 | log.Fatal("ListenAndServe: ", err) 28 | } 29 | } 30 | func (p *program) Stop(s service.Service) error { 31 | return nil 32 | } 33 | 34 | func main() { 35 | svcConfig := &service.Config{ 36 | Name: "GenesisEicarService", 37 | DisplayName: "Genesis Eicar Example Service", 38 | Description: "This is a cross platform test binary for multiple operating systems.", 39 | } 40 | 41 | prg := &program{} 42 | s, err := service.New(prg, svcConfig) 43 | if err != nil { 44 | log.Fatal(err) 45 | } 46 | logger, err = s.Logger(nil) 47 | if err != nil { 48 | log.Fatal(err) 49 | } 50 | err = s.Run() 51 | if err != nil { 52 | logger.Error(err) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /tools/svctest/windows.gs: -------------------------------------------------------------------------------- 1 | //go_import:github.com/gen0cide/gscript/x/svc as svc 2 | //import:/tmp/svctest-win.exe 3 | 4 | var service_bin_path = "C:\\WINDOWS\\system32\\megadeath.exe" 5 | 6 | 7 | var serviceSettings = { 8 | name: "gscript_eicar_service", 9 | display_name: "gscript eicar service", 10 | description: "genesis engine eicar example service", 11 | arguments: [], 12 | executable_path: service_bin_path, 13 | working_directory: "C:\\WINDOWS\\system32", 14 | options: {} 15 | } 16 | 17 | function Deploy() { 18 | console.log("Writing binary to disk...") 19 | 20 | filedata = GetAssetAsString("svctest-win.exe") 21 | 22 | var quitAfterDebug = false; 23 | DebugConsole() 24 | 25 | if (quitAfterDebug == true) { 26 | return 27 | } 28 | 29 | errchk = G.file.WriteFileFromString(service_bin_path, filedata[0]) 30 | if (errchk !== undefined) { 31 | console.error("Error writing file: " + errchk.Error()) 32 | DebugConsole() 33 | return 34 | } 35 | 36 | console.log("Creating new service object...") 37 | 38 | var svcObj = svc.NewFromJSON(serviceSettings) 39 | if (svcObj[1] !== undefined) { 40 | console.error("Error creating service: " + svcObj[1].Error()) 41 | DebugConsole() 42 | return 43 | } 44 | 45 | console.log("Checking service config sanity...") 46 | 47 | confchk = svcObj[0].CheckConfig(true) 48 | if (confchk[1] !== undefined || confchk[0] === false) { 49 | console.error("Error checking config: " + confchk[1].Error()) 50 | DebugConsole() 51 | return 52 | } 53 | 54 | console.log("Installing service...") 55 | 56 | installchk = svcObj[0].Install(true) 57 | if (installchk !== undefined) { 58 | console.error("Error installing service: " + installchk.Error()) 59 | DebugConsole() 60 | return 61 | } 62 | 63 | console.log("Starting service...") 64 | 65 | startchk = svcObj[0].Start() 66 | if (startchk !== undefined) { 67 | console.error("Error starting service: " + startchk.Error()) 68 | DebugConsole() 69 | return 70 | } 71 | 72 | DebugConsole() 73 | } 74 | -------------------------------------------------------------------------------- /tools/test_build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/bash 2 | 3 | set -e 4 | 5 | CWD=$(pwd) 6 | GSCRIPT_HOME="$GOPATH/src/github.com/gen0cide/gscript" 7 | cd "$GSCRIPT_HOME" 8 | go-bindata -o compiler/computil/bindata.go -pkg computil -prefix compiler/templates compiler/templates/... 9 | cd "$GSCRIPT_HOME/cmd/gscript" 10 | go build -o "/usr/local/bin/gscript" -v 11 | echo "[*] Build Exit Status: $?" 12 | cd "$CWD" 13 | -------------------------------------------------------------------------------- /x/darwinadventure/adventure_darwin.go: -------------------------------------------------------------------------------- 1 | // +build darwin 2 | 3 | package main 4 | 5 | /* 6 | 7 | #include 8 | 9 | int NXArgc = 0; 10 | const char** NXArgv = NULL; 11 | const char** environ = NULL; 12 | const char* __progname = NULL; 13 | 14 | struct __DATA__dyld { 15 | long lazy; 16 | int (*lookup)(const char*, void**); 17 | // ProgramVars 18 | const void* mh; 19 | int* NXArgcPtr; 20 | const char*** NXArgvPtr; 21 | const char*** environPtr; 22 | const char** __prognamePtr; 23 | }; 24 | 25 | static volatile struct __DATA__dyld myDyldSection __attribute__ ((section ("__DATA,__dyld"))) 26 | = { 0, 0, NULL, &NXArgc, &NXArgv, &environ, &__progname }; 27 | 28 | 29 | uintptr_t GetAddr(const char* fnname) { 30 | void *fnp; 31 | printf("%p\n", fnp); 32 | int ec = myDyldSection.lookup(fnname, &fnp); 33 | printf("%d\n", ec); 34 | printf("%p\n", fnp); 35 | return (uintptr_t)fnp; 36 | } 37 | 38 | */ 39 | import "C" 40 | 41 | import ( 42 | "fmt" 43 | "os" 44 | 45 | "github.com/davecgh/go-spew/spew" 46 | ) 47 | 48 | func main() { 49 | if len(os.Args) != 2 { 50 | fmt.Println("must supply a function name") 51 | os.Exit(1) 52 | } 53 | fnName := os.Args[1] 54 | foo := C.GetAddr(C.CString(fnName)) 55 | spew.Dump(uintptr(foo)) 56 | } 57 | --------------------------------------------------------------------------------