├── .gitignore ├── CHANGELOG.md ├── Codecepticon.sln ├── Codecepticon ├── Codecepticon.csproj ├── Help │ ├── CSharp.txt │ ├── Global.txt │ ├── Header.txt │ ├── PowerShell.txt │ ├── Shared.txt │ ├── Sign.txt │ └── VBA.txt ├── Modules │ ├── CSharp │ │ ├── CSharpManager.cs │ │ ├── CommandLine │ │ │ ├── CSharpCommandLine.cs │ │ │ ├── OptionsParser.cs │ │ │ └── ValidateCommandLine.cs │ │ ├── DataCollector.cs │ │ ├── DataRenamer.cs │ │ ├── DataRewriter.cs │ │ ├── Profiles │ │ │ ├── BaseProfile.cs │ │ │ ├── Certify │ │ │ │ ├── Certify.cs │ │ │ │ └── Rewriters │ │ │ │ │ ├── CommandLine.cs │ │ │ │ │ └── RemoveHelpText.cs │ │ │ ├── Rubeus │ │ │ │ ├── Rewriters │ │ │ │ │ ├── CommandLine.cs │ │ │ │ │ ├── RemoveHelpText.cs │ │ │ │ │ └── Words.cs │ │ │ │ └── Rubeus.cs │ │ │ ├── Seatbelt │ │ │ │ ├── Rewriters │ │ │ │ │ ├── CommandLine.cs │ │ │ │ │ ├── CommandLine2.cs │ │ │ │ │ └── RemoveHelpText.cs │ │ │ │ └── Seatbelt.cs │ │ │ ├── SharpChrome │ │ │ │ ├── Rewriters │ │ │ │ │ ├── CommandLine.cs │ │ │ │ │ └── RemoveHelpText.cs │ │ │ │ └── SharpChrome.cs │ │ │ ├── SharpDPAPI │ │ │ │ ├── Rewriters │ │ │ │ │ ├── CommandLine.cs │ │ │ │ │ └── RemoveHelpText.cs │ │ │ │ └── SharpDPAPI.cs │ │ │ ├── SharpHound │ │ │ │ ├── Rewriters │ │ │ │ │ ├── CommandLine.cs │ │ │ │ │ ├── IsStatements.cs │ │ │ │ │ ├── OutstandingProperties.cs │ │ │ │ │ └── RemoveHelpText.cs │ │ │ │ └── SharpHound.cs │ │ │ └── SharpView │ │ │ │ ├── Rewriters │ │ │ │ ├── MethodNames.cs │ │ │ │ ├── RemoveHelpText.cs │ │ │ │ └── SwitchCases.cs │ │ │ │ └── SharpView.cs │ │ ├── Rewriters │ │ │ ├── Assemblies.cs │ │ │ ├── RemoveComments.cs │ │ │ ├── Strings.cs │ │ │ ├── SwitchExpressions.cs │ │ │ └── SwitchStatements.cs │ │ ├── SyntaxTreeHelper.cs │ │ ├── Unmapping.cs │ │ └── VisualStudioManager.cs │ ├── CommandLineData.cs │ ├── CommandLineManager.cs │ ├── CommandLineValidator.cs │ ├── DataUnmapping.cs │ ├── ModuleManager.cs │ ├── ModuleTypes.cs │ ├── PowerShell │ │ ├── CommandLine │ │ │ ├── PowerShellCommandLine.cs │ │ │ └── ValidateCommandLine.cs │ │ ├── DataCollector.cs │ │ ├── DataRenamer.cs │ │ ├── PowerShellManager.cs │ │ ├── SyntaxTreeHelper.cs │ │ └── Unmapping.cs │ ├── Sign │ │ ├── CertificateManager.cs │ │ ├── CommandLine │ │ │ ├── SignCommandLine.cs │ │ │ └── ValidateCommandLine.cs │ │ ├── MsSign │ │ │ ├── ISigningTool.cs │ │ │ ├── PortableExecutableSigningTool.cs │ │ │ ├── SignFileRequest.cs │ │ │ ├── SignFileResponse.cs │ │ │ ├── SignFileResponseFileInfo.cs │ │ │ ├── UnmanagedStruct.cs │ │ │ └── Win32SigningAPI.cs │ │ ├── SignManager.cs │ │ └── SignToolManager.cs │ └── VB6 │ │ ├── ANTLR │ │ ├── VisualBasic6.g4 │ │ ├── VisualBasic6BaseListener.cs │ │ ├── VisualBasic6BaseVisitor.cs │ │ ├── VisualBasic6Lexer.cs │ │ ├── VisualBasic6Listener.cs │ │ ├── VisualBasic6Parser.cs │ │ └── VisualBasic6Visitor.cs │ │ ├── Collectors │ │ ├── CollectorVisitor.cs │ │ └── TypeCollectorVisitor.cs │ │ ├── CommandLine │ │ ├── ValidateCommandLine.cs │ │ └── Vb6CommandLine.cs │ │ ├── DataCollector.cs │ │ ├── DataRenamer.cs │ │ ├── OfficeReservedWords.cs │ │ ├── Renamers │ │ ├── Declarations.cs │ │ ├── Identifiers.cs │ │ └── Strings.cs │ │ ├── SyntaxTreeHelper.cs │ │ ├── Unmapping.cs │ │ ├── Vb6Constants.cs │ │ └── Vb6Manager.cs ├── Program.cs ├── Properties │ ├── Settings.Designer.cs │ └── Settings.settings ├── Templates │ ├── Base64.vb6 │ ├── ExternalFile.cs │ ├── ExternalFile.vb6 │ ├── Group.cs │ ├── Group.ps1 │ ├── Group.vb6 │ ├── Mapping.html │ ├── Single.cs │ ├── Single.ps1 │ ├── Single.vb6 │ ├── XOR.cs │ ├── XOR.ps1 │ ├── XOR.vb6 │ └── markov-english-words.txt └── Utils │ ├── Logger.cs │ ├── MarkovWordGenerator │ ├── MarkovModel.cs │ └── MarkovWordGenerator.cs │ ├── NameGenerator.cs │ ├── StringEncoding.cs │ └── Templates.cs ├── CommandLineGenerator.html ├── LICENSE ├── NuGet.config ├── README.md └── docs ├── Functionality.md ├── KnownIssues.md ├── Tips.md └── images ├── CmdGenerator.png ├── Mapping-File-1.png ├── Mapping-File-2.png ├── Mapping-File-3.png ├── Mapping-File-4.png ├── MissingMethodException.png ├── SH-Hardcoded-Command.png ├── SH3-Output-Clean.png ├── SH3-Output.png ├── VS2022-NET-Roslyn.png └── VS2022-NET.png /.gitignore: -------------------------------------------------------------------------------- 1 | # User-specific files 2 | *.suo 3 | *.user 4 | *.userosscache 5 | *.sln.docstates 6 | 7 | 8 | # Build results 9 | [Dd]ebug/ 10 | [Dd]ebugPublic/ 11 | [Rr]elease/ 12 | [Rr]eleases/ 13 | x64/ 14 | x86/ 15 | bld/ 16 | [Bb]in/ 17 | [Oo]bj/ 18 | [Ll]og/ 19 | 20 | # Visual Studio 2015/2017 cache/options directory 21 | .vs/ 22 | 23 | # Visual Studio 2017 auto generated files 24 | Generated\ Files/ 25 | 26 | # MSTest test Results 27 | [Tt]est[Rr]esult*/ 28 | [Bb]uild[Ll]og.* 29 | 30 | 31 | # .NET Core 32 | project.lock.json 33 | project.fragment.lock.json 34 | artifacts/ 35 | 36 | # Misc 37 | launchSettings.json 38 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Codecepticon Changelog 2 | 3 | ## v1.2.2 4 | 5 | * `[Update]` Removed `BouncyCastle` dependency, now certificates are generated using native .NET functionality. 6 | 7 | ## v1.2.1 8 | 9 | * `[New]` C#: Added support for renaming Structs. 10 | 11 | ## v1.2.0 12 | 13 | * `[Update]` Removed the `signtool.exe` dependency and are now natively signing executables. The code was taken & customised from https://github.com/Danielku15/SigningServer, under MIT License - original author is Danielku15. 14 | 15 | ## v1.1.0 16 | 17 | * `[New]` Module: Implement the `sign` module, to enable creating self-signed certificates and using any given certificate to sign an executable. This functionality is using `signtool.exe`. 18 | 19 | ## v1.0.3 20 | 21 | * `[Fix]` C#: Ensure that Delegate function/declarations are also renamed. 22 | 23 | ## v1.0.2 24 | 25 | * `[New]` Mapping: Added checkbox to "Match Exact Word" when searching within the document. 26 | * `[Fix]` C#: Ensure that Seatbelt commands are renamed properly. 27 | 28 | ## v1.0.1 29 | 30 | * `[Fix]` PowerShell: Ensure that variables referenced as `${name}` are also expanded. 31 | * `[Fix]` C#: Ensure that SharpView commands are renamed properly. -------------------------------------------------------------------------------- /Codecepticon.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.3.32804.467 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Codecepticon", "Codecepticon\Codecepticon.csproj", "{0E7C6E56-D50A-4F1A-AD6A-C8DDD6D30DF8}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {0E7C6E56-D50A-4F1A-AD6A-C8DDD6D30DF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {0E7C6E56-D50A-4F1A-AD6A-C8DDD6D30DF8}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {0E7C6E56-D50A-4F1A-AD6A-C8DDD6D30DF8}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {0E7C6E56-D50A-4F1A-AD6A-C8DDD6D30DF8}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {FBAD0329-EB7B-4C99-B600-104EC6AD462C} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Codecepticon/Codecepticon.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net472 6 | none 7 | x64 8 | AnyCPU;x86;x64 9 | 9.0 10 | Codecepticon 11 | Codecepticon 12 | 1.2.2 13 | Pavel Tsakalidis 14 | Accenture Security 15 | Codecepticon 16 | Offensive Security Code Obfuscator 17 | https://github.com/Accenture/Codecepticon 18 | 19 | True 20 | 21 | 22 | 23 | full 24 | 25 | 26 | 27 | full 28 | 29 | 30 | 31 | full 32 | 33 | 34 | 35 | full 36 | 37 | 38 | 39 | full 40 | 41 | 42 | 43 | full 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | True 73 | True 74 | Settings.settings 75 | 76 | 77 | 78 | 79 | 80 | SettingsSingleFileGenerator 81 | Settings.Designer.cs 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /Codecepticon/Help/CSharp.txt: -------------------------------------------------------------------------------- 1 | %%_HEADER_%% 2 | 3 | Usage: Codecepticon.exe --module [csharp|cs] [OPTIONS]... 4 | 5 | --action [obfuscate|unmap] Specify the action to be executed, whether to obfuscate a solution or unmap output 6 | files back to readable data. 7 | --path [solution] Location of the *.sln project to be obfuscated. 8 | --build Whether to build the project upon completion. 9 | --build-path [path] Path to a directory where the solution will be compiled to. Only works with --build. 10 | --profile [name] Name of an application-specific profile to use. Supported profiles are: 11 | - certify 12 | - rubeus 13 | - seatbelt 14 | - sharpchrome 15 | - sharpdpapi 16 | - sharphound 17 | - sharpview 18 | 19 | --rename [all|..custom..] Specify what requires obfuscation, from below: 20 | - all Will obfuscate everything. 21 | - n Namespaces 22 | - c Classes 23 | - e Enums 24 | - f Functions 25 | - p Properties 26 | - a Parameters 27 | - v Variables 28 | - s Structs 29 | - o Command Line 30 | %%_SHARED_%% 31 | 32 | Good luck. -------------------------------------------------------------------------------- /Codecepticon/Help/Global.txt: -------------------------------------------------------------------------------- 1 | %%_HEADER_%% 2 | 3 | Usage: 4 | Codecepticon.exe --module [csharp|powershell|vba|sign] --help [OPTIONS]... 5 | Codecepticon.exe --config [XML Config File] 6 | 7 | Tip: Use the command line generator HTML file to make your life easier. -------------------------------------------------------------------------------- /Codecepticon/Help/Header.txt: -------------------------------------------------------------------------------- 1 | Codecepticon v%%_VERSION_%% [ Accenture Security ] 2 | - For more information visit https://github.com/Accenture/Codecepticon -------------------------------------------------------------------------------- /Codecepticon/Help/PowerShell.txt: -------------------------------------------------------------------------------- 1 | %%_HEADER_%% 2 | 3 | Usage: Codecepticon.exe --module [powershell|ps] [OPTIONS]... 4 | 5 | --action [obfuscate|unmap] Specify the action to be executed, whether to obfuscate a solution or unmap output 6 | files back to readable data. 7 | --path [script] Location of the *.ps1 file to be obfuscated. 8 | 9 | --rename [all|..custom..] Specify what requires obfuscation, from below: 10 | - all Will obfuscate everything. 11 | - f Functions 12 | - v Variables 13 | 14 | %%_SHARED_%% 15 | 16 | Good luck. -------------------------------------------------------------------------------- /Codecepticon/Help/Shared.txt: -------------------------------------------------------------------------------- 1 | --rename-method [opt] Specify which renaming method to utilise, from below: 2 | - random Generate random character combinations from a given character set. 3 | - notwins Prevent the same character from appearing consequently. 4 | - dict Generate combinations based on a user-defined dictionary. 5 | - markov Generate "English-sounding" random words using Markov chains. 6 | --rename-charset [set] Speficy the charset that will be used to generate obfuscated data. Works with 7 | rename method [random|notwins]. 8 | --rename-length [len] Specify the length of the generated obfuscated data. 9 | --rename-dictionary-file [path] Path to the dictionary file to be used with the [dict] rename method. Each line 10 | must contain a word, no special characters allowed other than an underscore. 11 | --rename-dictionary [w1,w2,wN] Specify a comma-separated dictionary wordlist to be used with the [dict] rename 12 | method. 13 | --markov-min-length [len] Only used with 'markov' as the --rename-method. Specifies the min/max length a 14 | --markov-max-length [len] generated word will have. Default values are 3 and 9. 15 | --markov-min-words [count] Only used with 'markov' as the --rename-method. When random words are generated 16 | --markov-max-words [count] they are also concatenated to increase the size of the output variable/name/ 17 | This behaviour is similar to the 'dict' rename method. 18 | 19 | --string-rewrite Enable string rewriting. 20 | --string-rewrite-method [opt] Specify how to rewrite strings, from below: 21 | - b64 Encode all strings using Base64. 22 | - xor Encrypt all data using XOR and randomly generated keys. 23 | - group Replace each character with a group combination of multiple 24 | characters. For instance, "a" => "qwer", "b" => "mnbv", etc. 25 | - single A basic substitution cipher. 26 | - external Encode all strings using Base64 and export them to a file. Upon 27 | execution, all strings will be loaded into memory. 28 | --string-rewrite-charset [set] Specify the charset that will be used to generate group character combinations. 29 | Used only with --string-rewrite-method group. 30 | --string-rewrite-length [len] Specify the length of each generated group. 31 | --string-rewrite-extfile [path] Specify the path where the strings will be encoded and exported to. Used only 32 | with --string-rewrite-method external. 33 | 34 | --map-file [path] Specify the path where the mapping HTML file will be written to. If no file is 35 | specified, then a ".html" file be created in the solution's directory. 36 | 37 | --unmap-directory [path] Specify the directory where the obfuscated output files are located. 38 | Only works with --action unmap. 39 | --unmap-recursive Parse all files under --unmap-directory recursively. 40 | Only works with --action unmap. 41 | --unmap-file [path] Specify an obfuscated file to unmap. Only works with --action unmap. 42 | 43 | --verbose What it says. 44 | --debug What it says. -------------------------------------------------------------------------------- /Codecepticon/Help/Sign.txt: -------------------------------------------------------------------------------- 1 | %%_HEADER_%% 2 | 3 | Usage: Codecepticon.exe --module sign [OPTIONS]... 4 | 5 | --action [cert|sign] Specify the action to be executed: 6 | cert: Generate a self-signed certificate (pfx). 7 | sign: Sign an executable using a pfx file. 8 | --subject Specify the subject for the new certificate (CN=Codecepticon,C=GB, etc). 9 | --issuer Specify the issuer for the new certificate (CN=Codecepticon Issuer,C=GB, etc). 10 | --copy-from Specify a signed file to copy the Subject/Issuer from. If --subject or --issuer are 11 | also set those will supercede this argument. 12 | --not-before Date from when the new certificate will be valid from, format is YYYY-MM-DD HH:MM:SS. 13 | --not-after Expiration date for the new certificate, format is YYYY-MM-DD HH:MM:SS. 14 | --pfx-file When used with '--action cert' this is where the pfx file will be saved as. 15 | When used with '--action sign' this is where the pfx file will be loaded from. 16 | --overwrite When used with '--action cert' this will indicate whether to rewrite the target file 17 | if it already exists. 18 | --password Password for the pfx file (either to save or load, depending on the --action) 19 | --path [executable] Location of the executable file to be signed. 20 | --algorithm When used with '--action sign', this argument will specify the signature algorithm. 21 | This can be one of: MD5, SHA1, SHA256, SHA384, SHA512. 22 | --timestamp When used with '--action sign', this is where the Timestamp Server is specified. 23 | For example 'http://timestamp.sectigo.com' or 'http://timestamp.digicert.com'. -------------------------------------------------------------------------------- /Codecepticon/Help/VBA.txt: -------------------------------------------------------------------------------- 1 | %%_HEADER_%% 2 | 3 | Usage: Codecepticon.exe --module [vb6|vba] [OPTIONS]... 4 | 5 | --action [obfuscate|unmap] Specify the action to be executed, whether to obfuscate a solution or unmap output 6 | files back to readable data. 7 | --path [module] Location of the *.bas file to be obfuscated. 8 | 9 | --rename [all|..custom..] Specify what requires obfuscation, from below: 10 | - all Will obfuscate everything. 11 | - i Identifiers 12 | %%_SHARED_%% 13 | 14 | Good luck. -------------------------------------------------------------------------------- /Codecepticon/Modules/CSharp/CommandLine/OptionsParser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Codecepticon.CommandLine; 6 | using Microsoft.CodeAnalysis; 7 | using Microsoft.CodeAnalysis.CSharp.Syntax; 8 | 9 | namespace Codecepticon.Modules.CSharp.CommandLine 10 | { 11 | class OptionsParser 12 | { 13 | protected SyntaxTreeHelper Helper = new SyntaxTreeHelper(); 14 | 15 | public async Task> ParseOptionsFile(Document document) 16 | { 17 | Dictionary commandLineData = new Dictionary(); 18 | 19 | SyntaxTree syntaxTree = await document.GetSyntaxTreeAsync(); 20 | var properties = syntaxTree.GetRoot().DescendantNodes().OfType(); 21 | foreach (var p in properties) 22 | { 23 | if (!Helper.IsOptionChild(p)) 24 | { 25 | continue; 26 | } 27 | 28 | DataCollector.CommandLine data = Helper.GetOptionData(p); 29 | if (String.IsNullOrEmpty(data.Argument)) 30 | { 31 | continue; 32 | } 33 | 34 | // Sometimes the property is different to the actual command line, so we need to add it manually. For example "CollectionMethod"'s property is "CollectionMethods". 35 | if (!DataCollector.Mapping.Properties.ContainsKey(data.Argument)) 36 | { 37 | DataCollector.Mapping.Properties.Add(data.Argument, CommandLineData.Global.NameGenerator.Generate()); 38 | } 39 | commandLineData.Add(data.PropertyName, data); 40 | } 41 | 42 | return commandLineData; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Codecepticon/Modules/CSharp/CommandLine/ValidateCommandLine.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using Codecepticon.CommandLine; 8 | using Codecepticon.Utils; 9 | 10 | namespace Codecepticon.Modules.CSharp.CommandLine 11 | { 12 | class ValidateCommandLine : CommandLineValidator 13 | { 14 | public bool Run() 15 | { 16 | if (!ValidateAction()) 17 | { 18 | return false; 19 | } 20 | 21 | if (!ProfileSpecificValidation()) 22 | { 23 | return false; 24 | } 25 | 26 | return true; 27 | } 28 | 29 | protected bool ValidateAction() 30 | { 31 | switch (CommandLineData.Global.Action) 32 | { 33 | case CommandLineData.Action.None: 34 | Logger.Error("'action' parameter not set"); 35 | return false; 36 | case CommandLineData.Action.Obfuscate: 37 | return ValidateActionObfuscate(); 38 | case CommandLineData.Action.Unmap: 39 | return ValidateActionUnmap(); 40 | } 41 | 42 | return false; 43 | } 44 | 45 | protected bool ValidateActionObfuscate() 46 | { 47 | if (!CommandLineData.CSharp.Rename.Enabled && !CommandLineData.Global.Rewrite.Strings) 48 | { 49 | Logger.Error("No rename or rewrite parameters set."); 50 | return false; 51 | } 52 | 53 | // Check if the solution exists. 54 | if (String.IsNullOrEmpty(CommandLineData.Global.Project.Path) || !File.Exists(CommandLineData.Global.Project.Path)) 55 | { 56 | Logger.Error($"Input path is empty or does not exist: {CommandLineData.Global.Project.Path}"); 57 | return false; 58 | } 59 | 60 | if (String.IsNullOrEmpty(CommandLineData.Global.Project.SaveAs)) 61 | { 62 | // Default behaviour is to replace the actual file. 63 | CommandLineData.Global.Project.SaveAs = CommandLineData.Global.Project.Path; 64 | } 65 | 66 | if (CommandLineData.CSharp.Rename.Enabled && !ValidateRename()) 67 | { 68 | return false; 69 | } 70 | 71 | if (!ValidateRewrite(ModuleTypes.CodecepticonModules.CSharp)) 72 | { 73 | return false; 74 | } 75 | 76 | if (!ValidateMappingFiles()) 77 | { 78 | return false; 79 | } 80 | 81 | if (!ValidateProjectSettings()) 82 | { 83 | return false; 84 | } 85 | 86 | return true; 87 | } 88 | 89 | protected bool ValidateProjectSettings() 90 | { 91 | // Set the default compilation configuration. 92 | CommandLineData.CSharp.Compilation.Configuration = "Release"; 93 | CommandLineData.CSharp.Compilation.Settings = new Dictionary 94 | { 95 | // These two disable the generation of *.pdb files. 96 | { "DebugType", "none" }, 97 | { "DebugSymbols", "false" } 98 | }; 99 | 100 | if (CommandLineData.CSharp.Compilation.Build) 101 | { 102 | if (!String.IsNullOrEmpty(CommandLineData.CSharp.Compilation.OutputPath)) 103 | { 104 | CommandLineData.CSharp.Compilation.Settings.Add("OutputPath", CommandLineData.CSharp.Compilation.OutputPath); 105 | } 106 | } 107 | 108 | return true; 109 | } 110 | 111 | protected bool ProfileSpecificValidation() 112 | { 113 | if (CommandLineData.CSharp.Profile != null && !CommandLineData.CSharp.Profile.ValidateCommandLine()) 114 | { 115 | Logger.Error("Command line did not meet profile requirements."); 116 | return false; 117 | } 118 | return true; 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /Codecepticon/Modules/CSharp/Profiles/BaseProfile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Codecepticon.CommandLine; 7 | using Codecepticon.Utils; 8 | using Microsoft.CodeAnalysis; 9 | using BuildEvaluation = Microsoft.Build.Evaluation; 10 | 11 | namespace Codecepticon.Modules.CSharp.Profiles 12 | { 13 | class BaseProfile 14 | { 15 | public virtual string Name { get; } = "Not Set"; 16 | 17 | public virtual async Task Before(Solution solution, Project project) 18 | { 19 | Logger.Debug("Profile does not implement Before function"); 20 | return solution; 21 | } 22 | 23 | public virtual async Task After(Solution solution, Project project) 24 | { 25 | BuildEvaluation.Project buildProject = VisualStudioManager.GetBuildProject(project); 26 | 27 | if (CommandLineData.CSharp.Rename.Namespaces || CommandLineData.CSharp.Rename.Classes) 28 | { 29 | string startupObject = buildProject.GetPropertyValue("StartupObject"); 30 | if (!String.IsNullOrEmpty(startupObject)) 31 | { 32 | Logger.Debug($"StartUp Object was: {startupObject}"); 33 | string[] elements = startupObject.Split('.'); 34 | if (elements.Length == 2) 35 | { 36 | string namespaceValue = CommandLineData.CSharp.Rename.Namespaces && DataCollector.Mapping.Namespaces.ContainsKey(elements[0]) ? DataCollector.Mapping.Namespaces[elements[0]] : elements[0]; 37 | string classValue = CommandLineData.CSharp.Rename.Classes && DataCollector.Mapping.Classes.ContainsKey(elements[1]) ? DataCollector.Mapping.Classes[elements[1]] : elements[1]; 38 | Logger.Debug($"StartUp Object is: {namespaceValue}.{classValue}"); 39 | buildProject.SetProperty("StartupObject", $"{namespaceValue}.{classValue}"); 40 | buildProject.Save(); 41 | } 42 | } 43 | } 44 | 45 | return solution; 46 | } 47 | 48 | public virtual async Task Final(Solution solution, Project project) 49 | { 50 | Logger.Debug("Profile does not implement Final function"); 51 | return solution; 52 | } 53 | 54 | public virtual bool ValidateCommandLine() 55 | { 56 | Logger.Debug("Profile does not implement ValidateCommandLine function"); 57 | return true; 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Codecepticon/Modules/CSharp/Profiles/Certify/Certify.cs: -------------------------------------------------------------------------------- 1 | using Codecepticon.CommandLine; 2 | using Codecepticon.Modules.CSharp.Profiles.Certify.Rewriters; 3 | using Codecepticon.Modules.CSharp.Rewriters; 4 | using Codecepticon.Utils; 5 | using Microsoft.CodeAnalysis; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.IO; 9 | using System.Linq; 10 | //using System.Reflection.Metadata; 11 | using System.Text; 12 | using System.Threading.Tasks; 13 | using BuildEvaluation = Microsoft.Build.Evaluation; 14 | 15 | namespace Codecepticon.Modules.CSharp.Profiles.Certify 16 | { 17 | class Certify : BaseProfile 18 | { 19 | public override string Name { get; } = "Certify"; 20 | public override async Task Before(Solution solution, Project project) 21 | { 22 | if (CommandLineData.CSharp.Rename.CommandLine) 23 | { 24 | Logger.Debug("Certify: Rewriting command line"); 25 | solution = await RewriteCommandLine(solution, project); 26 | } 27 | 28 | Logger.Debug("Certify: Removing help text"); 29 | solution = await RemoveHelpText(solution, project); 30 | 31 | Logger.Debug("Certify: Rewriting switch expressions"); 32 | solution = await RewriteSwitchExpressions(solution, project); 33 | 34 | return solution; 35 | } 36 | 37 | public override async Task After(Solution solution, Project project) 38 | { 39 | BuildEvaluation.Project buildProject = VisualStudioManager.GetBuildProject(project); 40 | 41 | if (CommandLineData.CSharp.Rename.Namespaces) 42 | { 43 | Logger.Debug("Certify: Renaming RootNamespace"); 44 | string rootNamespace = buildProject.GetPropertyValue("RootNamespace"); 45 | string newNamespace = DataCollector.Mapping.Namespaces[rootNamespace]; 46 | buildProject.SetProperty("RootNamespace", newNamespace); 47 | } 48 | 49 | Logger.Debug("Certify: Renaming Misc Properties"); 50 | buildProject.SetProperty("AssemblyName", CommandLineData.Global.NameGenerator.Generate()); 51 | buildProject.SetProperty("Company", CommandLineData.Global.NameGenerator.Generate()); 52 | buildProject.SetProperty("Product", CommandLineData.Global.NameGenerator.Generate()); 53 | buildProject.Save(); 54 | return solution; 55 | } 56 | 57 | protected async Task RewriteSwitchExpressions(Solution solution, Project project) 58 | { 59 | foreach (Document document in project.Documents) 60 | { 61 | SyntaxNode syntaxRoot = await document.GetSyntaxRootAsync(); 62 | SwitchExpressions switchExpressions = new SwitchExpressions(); 63 | switchExpressions.documentModel = await document.GetSemanticModelAsync(); 64 | syntaxRoot = switchExpressions.Visit(syntaxRoot); 65 | 66 | solution = solution.WithDocumentSyntaxRoot(document.Id, syntaxRoot); 67 | } 68 | 69 | return solution; 70 | } 71 | 72 | protected async Task RewriteCommandLine(Solution solution, Project project) 73 | { 74 | Rewriters.CommandLine rewriteCommandLine = new Rewriters.CommandLine(); 75 | 76 | project = VisualStudioManager.GetProjectByName(solution, project.Name); 77 | foreach (Document document in project.Documents) 78 | { 79 | SyntaxNode syntaxRoot = await document.GetSyntaxRootAsync(); 80 | 81 | FileInfo file = new FileInfo(document.FilePath); 82 | if (file.DirectoryName.Split('\\').Last() == "Commands") 83 | { 84 | syntaxRoot = rewriteCommandLine.Visit(syntaxRoot); 85 | } 86 | 87 | solution = solution.WithDocumentSyntaxRoot(document.Id, syntaxRoot); 88 | } 89 | return solution; 90 | } 91 | 92 | protected async Task RemoveHelpText(Solution solution, Project project) 93 | { 94 | project = VisualStudioManager.GetProjectByName(solution, project.Name); 95 | Document csInfo = VisualStudioManager.GetDocumentByName(project, "Info.cs"); 96 | 97 | SyntaxNode syntaxRoot = await csInfo.GetSyntaxRootAsync(); 98 | RemoveHelpText rewriter = new RemoveHelpText(); 99 | SyntaxNode newSyntaxRoot = rewriter.Visit(syntaxRoot); 100 | 101 | solution = solution.WithDocumentSyntaxRoot(csInfo.Id, newSyntaxRoot); 102 | 103 | return solution; 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /Codecepticon/Modules/CSharp/Profiles/Certify/Rewriters/CommandLine.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using Microsoft.CodeAnalysis.CSharp; 3 | using Microsoft.CodeAnalysis.CSharp.Syntax; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Codecepticon.Modules.CSharp.Profiles.Certify.Rewriters 11 | { 12 | class CommandLine : CSharpSyntaxRewriter 13 | { 14 | protected SyntaxTreeHelper Helper = new SyntaxTreeHelper(); 15 | 16 | public override SyntaxNode VisitLiteralExpression(LiteralExpressionSyntax node) 17 | { 18 | string text = node.GetFirstToken().ValueText.Trim(); 19 | if (text.Length > 0 && text[0] == '/') 20 | { 21 | return Helper.RewriteCommandLineArg(node, text, "/"); 22 | } 23 | 24 | if (Helper.GetPropertyDeclaration(node) == "CommandName") 25 | { 26 | return Helper.RewriteCommandLineArg(node, text, ""); 27 | } 28 | 29 | return base.VisitLiteralExpression(node); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Codecepticon/Modules/CSharp/Profiles/Certify/Rewriters/RemoveHelpText.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using Microsoft.CodeAnalysis.CSharp; 3 | using Microsoft.CodeAnalysis.CSharp.Syntax; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Codecepticon.Modules.CSharp.Profiles.Certify.Rewriters 11 | { 12 | class RemoveHelpText : CSharpSyntaxRewriter 13 | { 14 | protected SyntaxTreeHelper Helper = new SyntaxTreeHelper(); 15 | 16 | protected List HelpFunctions = new List 17 | { 18 | "showlogo", 19 | "showusage" 20 | }; 21 | 22 | public override SyntaxNode VisitBlock(BlockSyntax node) 23 | { 24 | BlockSyntax block = RewriteBlock(node); 25 | return block ?? base.VisitBlock(node); 26 | } 27 | 28 | protected BlockSyntax RewriteBlock(BlockSyntax node) 29 | { 30 | SyntaxNode pMethod = Helper.FindParentOfType(node, SyntaxKind.MethodDeclaration); 31 | if (pMethod == null) 32 | { 33 | return null; 34 | } 35 | 36 | string functionName = pMethod.ChildTokens().LastOrDefault().ValueText.ToLower(); 37 | if (String.IsNullOrEmpty(functionName)) 38 | { 39 | return null; 40 | } 41 | 42 | if (!HelpFunctions.Contains(functionName)) 43 | { 44 | return null; 45 | } 46 | return SyntaxFactory.Block(null); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Codecepticon/Modules/CSharp/Profiles/Rubeus/Rewriters/CommandLine.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Codecepticon.CommandLine; 7 | using Codecepticon.Utils; 8 | using Microsoft.CodeAnalysis; 9 | using Microsoft.CodeAnalysis.CSharp; 10 | using Microsoft.CodeAnalysis.CSharp.Syntax; 11 | 12 | namespace Codecepticon.Modules.CSharp.Profiles.Rubeus.Rewriters 13 | { 14 | class CommandLine : CSharpSyntaxRewriter 15 | { 16 | protected SyntaxTreeHelper Helper = new SyntaxTreeHelper(); 17 | 18 | public override SyntaxNode VisitLiteralExpression(LiteralExpressionSyntax node) 19 | { 20 | string text = node.GetFirstToken().ValueText.Trim(); 21 | if (text.Length > 0 && text[0] == '/') 22 | { 23 | return Helper.RewriteCommandLineArg(node, text, "/"); 24 | } 25 | 26 | if (Helper.GetPropertyDeclaration(node) == "CommandName") 27 | { 28 | return Helper.RewriteCommandLineArg(node, text, ""); 29 | } 30 | 31 | return base.VisitLiteralExpression(node); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Codecepticon/Modules/CSharp/Profiles/Rubeus/Rewriters/RemoveHelpText.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Microsoft.CodeAnalysis; 7 | using Microsoft.CodeAnalysis.CSharp; 8 | using Microsoft.CodeAnalysis.CSharp.Syntax; 9 | 10 | namespace Codecepticon.Modules.CSharp.Profiles.Rubeus.Rewriters 11 | { 12 | class RemoveHelpText : CSharpSyntaxRewriter 13 | { 14 | protected SyntaxTreeHelper Helper = new SyntaxTreeHelper(); 15 | 16 | protected List HelpFunctions = new List 17 | { 18 | "showlogo", 19 | "showusage" 20 | }; 21 | 22 | public override SyntaxNode VisitBlock(BlockSyntax node) 23 | { 24 | BlockSyntax block = RewriteBlock(node); 25 | return block ?? base.VisitBlock(node); 26 | } 27 | 28 | protected BlockSyntax RewriteBlock(BlockSyntax node) 29 | { 30 | SyntaxNode pMethod = Helper.FindParentOfType(node, SyntaxKind.MethodDeclaration); 31 | if (pMethod == null) 32 | { 33 | return null; 34 | } 35 | 36 | string functionName = pMethod.ChildTokens().LastOrDefault().ValueText.ToLower(); 37 | if (String.IsNullOrEmpty(functionName)) 38 | { 39 | return null; 40 | } 41 | 42 | if (!HelpFunctions.Contains(functionName)) 43 | { 44 | return null; 45 | } 46 | return SyntaxFactory.Block(null); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Codecepticon/Modules/CSharp/Profiles/Rubeus/Rewriters/Words.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Microsoft.CodeAnalysis; 7 | using Microsoft.CodeAnalysis.CSharp; 8 | using Microsoft.CodeAnalysis.CSharp.Syntax; 9 | 10 | namespace Codecepticon.Modules.CSharp.Profiles.Rubeus.Rewriters 11 | { 12 | class Words : CSharpSyntaxRewriter 13 | { 14 | protected SyntaxTreeHelper Helper = new SyntaxTreeHelper(); 15 | 16 | protected List RewriteWords = new List(new[] { "hashcat", "john" }); 17 | 18 | public override SyntaxNode VisitLiteralExpression(LiteralExpressionSyntax node) 19 | { 20 | string text = node.GetFirstToken().ValueText.Trim(); 21 | return RewriteWords.Contains(text) ? Helper.RewriteCommandLineArg(node, text, "") : base.VisitLiteralExpression(node); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Codecepticon/Modules/CSharp/Profiles/Rubeus/Rubeus.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using Codecepticon.CommandLine; 8 | using Codecepticon.Modules.CSharp.Profiles.Rubeus.Rewriters; 9 | using Codecepticon.Utils; 10 | using Microsoft.CodeAnalysis; 11 | using BuildEvaluation = Microsoft.Build.Evaluation; 12 | 13 | namespace Codecepticon.Modules.CSharp.Profiles.Rubeus 14 | { 15 | class Rubeus : BaseProfile 16 | { 17 | public override string Name { get; } = "Rubeus"; 18 | 19 | public override async Task Before(Solution solution, Project project) 20 | { 21 | if (CommandLineData.CSharp.Rename.CommandLine) 22 | { 23 | Logger.Debug("Rubeus: Rewriting command line"); 24 | solution = await RewriteCommandLine(solution, project); 25 | } 26 | 27 | Logger.Debug("Rubeus: Removing help text"); 28 | solution = await RemoveHelpText(solution, project); 29 | return solution; 30 | } 31 | 32 | public override async Task After(Solution solution, Project project) 33 | { 34 | BuildEvaluation.Project buildProject = VisualStudioManager.GetBuildProject(project); 35 | 36 | if (CommandLineData.CSharp.Rename.Namespaces) 37 | { 38 | Logger.Debug("Rubeus: Renaming RootNamespace"); 39 | string rootNamespace = buildProject.GetPropertyValue("RootNamespace"); 40 | string newNamespace = DataCollector.Mapping.Namespaces[rootNamespace]; 41 | buildProject.SetProperty("RootNamespace", newNamespace); 42 | } 43 | 44 | Logger.Debug("Rubeus: Renaming Misc Properties"); 45 | buildProject.SetProperty("AssemblyName", CommandLineData.Global.NameGenerator.Generate()); 46 | buildProject.SetProperty("Company", CommandLineData.Global.NameGenerator.Generate()); 47 | buildProject.SetProperty("Product", CommandLineData.Global.NameGenerator.Generate()); 48 | buildProject.Save(); 49 | return solution; 50 | } 51 | 52 | protected async Task RewriteCommandLine(Solution solution, Project project) 53 | { 54 | Rewriters.CommandLine rewriteCommandLine = new Rewriters.CommandLine(); 55 | Words rewriteWords = new Words(); 56 | 57 | project = VisualStudioManager.GetProjectByName(solution, project.Name); 58 | foreach (Document document in project.Documents) 59 | { 60 | SyntaxNode syntaxRoot = await document.GetSyntaxRootAsync(); 61 | syntaxRoot = rewriteWords.Visit(syntaxRoot); 62 | 63 | FileInfo file = new FileInfo(document.FilePath); 64 | if (file.DirectoryName.Split('\\').Last() == "Commands") 65 | { 66 | syntaxRoot = rewriteCommandLine.Visit(syntaxRoot); 67 | } 68 | 69 | solution = solution.WithDocumentSyntaxRoot(document.Id, syntaxRoot); 70 | } 71 | return solution; 72 | } 73 | 74 | protected async Task RemoveHelpText(Solution solution, Project project) 75 | { 76 | project = VisualStudioManager.GetProjectByName(solution, project.Name); 77 | Document csInfo = VisualStudioManager.GetDocumentByName(project, "Info.cs"); 78 | 79 | SyntaxNode syntaxRoot = await csInfo.GetSyntaxRootAsync(); 80 | RemoveHelpText rewriter = new RemoveHelpText(); 81 | SyntaxNode newSyntaxRoot = rewriter.Visit(syntaxRoot); 82 | 83 | solution = solution.WithDocumentSyntaxRoot(csInfo.Id, newSyntaxRoot); 84 | 85 | return solution; 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /Codecepticon/Modules/CSharp/Profiles/Seatbelt/Rewriters/CommandLine.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Microsoft.CodeAnalysis; 7 | using Microsoft.CodeAnalysis.CSharp; 8 | using Microsoft.CodeAnalysis.CSharp.Syntax; 9 | 10 | namespace Codecepticon.Modules.CSharp.Profiles.Seatbelt.Rewriters 11 | { 12 | class CommandLine : CSharpSyntaxRewriter 13 | { 14 | protected SyntaxTreeHelper Helper = new SyntaxTreeHelper(); 15 | 16 | protected List SeatbeltArgumentParsers = new List 17 | { 18 | "ParseAndRemoveSwitchArgument", 19 | "ParseAndRemoveKeyValueArgument" 20 | }; 21 | 22 | public override SyntaxNode VisitLiteralExpression(LiteralExpressionSyntax node) 23 | { 24 | string text = node.GetFirstToken().ValueText.Trim(); 25 | if (Helper.GetPropertyDeclaration(node) == "Command") 26 | { 27 | if (Helper.GetClassBaseList(node) == "CommandBase") 28 | { 29 | return Helper.RewriteCommandLineArg(node, text, ""); 30 | } 31 | } 32 | 33 | /* 34 | * This will parse the following: 35 | * var commandGroups = ParseAndRemoveKeyValueArgument("-Group"); 36 | */ 37 | if (text.Length > 0 && text.StartsWith("-")) 38 | { 39 | string functionName = Helper.GetCallingFunctionNameFromArgument(node); 40 | if (functionName.Length > 0 && SeatbeltArgumentParsers.Contains(functionName)) 41 | { 42 | return Helper.RewriteCommandLineArg(node, text, "-"); 43 | } 44 | } 45 | 46 | return base.VisitLiteralExpression(node); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Codecepticon/Modules/CSharp/Profiles/Seatbelt/Rewriters/CommandLine2.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using Microsoft.CodeAnalysis.CSharp; 3 | using Microsoft.CodeAnalysis.CSharp.Syntax; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Codecepticon.Modules.CSharp.Profiles.Seatbelt.Rewriters 11 | { 12 | class CommandLine2 : CSharpSyntaxRewriter 13 | { 14 | public override SyntaxNode VisitLiteralExpression(LiteralExpressionSyntax node) 15 | { 16 | string text = node.GetFirstToken().ValueText.Trim(); 17 | if (text == "all") 18 | { 19 | return SyntaxFactory.ParseExpression($"\"{DataCollector.Mapping.Enums["All"].ToLower()}\""); 20 | } 21 | return base.VisitLiteralExpression(node); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Codecepticon/Modules/CSharp/Profiles/Seatbelt/Rewriters/RemoveHelpText.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Microsoft.CodeAnalysis; 7 | using Microsoft.CodeAnalysis.CSharp; 8 | using Microsoft.CodeAnalysis.CSharp.Syntax; 9 | 10 | namespace Codecepticon.Modules.CSharp.Profiles.Seatbelt.Rewriters 11 | { 12 | class RemoveHelpText : CSharpSyntaxRewriter 13 | { 14 | protected SyntaxTreeHelper Helper = new SyntaxTreeHelper(); 15 | 16 | protected List HelpFunctions = new List 17 | { 18 | "printlogo", 19 | "usage" 20 | }; 21 | 22 | public override SyntaxNode VisitBlock(BlockSyntax node) 23 | { 24 | BlockSyntax block = RewriteBlock(node); 25 | return block ?? base.VisitBlock(node); 26 | } 27 | 28 | protected BlockSyntax RewriteBlock(BlockSyntax node) 29 | { 30 | SyntaxNode pMethod = Helper.FindParentOfType(node, SyntaxKind.MethodDeclaration); 31 | if (pMethod == null) 32 | { 33 | return null; 34 | } 35 | 36 | string functionName = pMethod.ChildTokens().LastOrDefault().ValueText.ToLower(); 37 | if (String.IsNullOrEmpty(functionName)) 38 | { 39 | return null; 40 | } 41 | 42 | if (!HelpFunctions.Contains(functionName)) 43 | { 44 | return null; 45 | } 46 | return SyntaxFactory.Block(null); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Codecepticon/Modules/CSharp/Profiles/Seatbelt/Seatbelt.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using Codecepticon.CommandLine; 8 | using System.IO; 9 | using Codecepticon.Modules.CSharp.Profiles.Seatbelt.Rewriters; 10 | using Codecepticon.Utils; 11 | 12 | namespace Codecepticon.Modules.CSharp.Profiles.Seatbelt 13 | { 14 | class Seatbelt : BaseProfile 15 | { 16 | public override string Name { get; } = "Seatbelt"; 17 | public override async Task Before(Solution solution, Project project) 18 | { 19 | if (CommandLineData.CSharp.Rename.CommandLine) 20 | { 21 | Logger.Debug("Seatbelt: Rewriting command line"); 22 | solution = await RewriteCommandLine(solution, project); 23 | } 24 | 25 | Logger.Debug("Seatbelt: Removing help text"); 26 | solution = await RemoveHelpText(solution, project); 27 | return solution; 28 | } 29 | 30 | protected async Task RewriteCommandLine(Solution solution, Project project) 31 | { 32 | Rewriters.CommandLine rewriteCommandLine = new Rewriters.CommandLine(); 33 | 34 | project = VisualStudioManager.GetProjectByName(solution, project.Name); 35 | SyntaxNode syntaxRoot; 36 | foreach (Document document in project.Documents) 37 | { 38 | syntaxRoot = await document.GetSyntaxRootAsync(); 39 | 40 | FileInfo file = new FileInfo(document.FilePath); 41 | if (file.DirectoryName.IndexOf(@"\Commands\") >= 0) 42 | { 43 | syntaxRoot = rewriteCommandLine.Visit(syntaxRoot); 44 | } 45 | else if (file.Name == "SeatbeltArgumentParser.cs") 46 | { 47 | syntaxRoot = rewriteCommandLine.Visit(syntaxRoot); 48 | } 49 | 50 | solution = solution.WithDocumentSyntaxRoot(document.Id, syntaxRoot); 51 | } 52 | 53 | // Now we need to update the final references to the "all" command argument. 54 | Document csRuntime = VisualStudioManager.GetDocumentByName(project, "Runtime.cs"); 55 | syntaxRoot = await csRuntime.GetSyntaxRootAsync(); 56 | CommandLine2 rewriteCommandLine2 = new CommandLine2(); 57 | syntaxRoot = rewriteCommandLine2.Visit(syntaxRoot); 58 | solution = solution.WithDocumentSyntaxRoot(csRuntime.Id, syntaxRoot); 59 | 60 | return solution; 61 | } 62 | 63 | protected async Task RemoveHelpText(Solution solution, Project project) 64 | { 65 | project = VisualStudioManager.GetProjectByName(solution, project.Name); 66 | Document csInfo = VisualStudioManager.GetDocumentByName(project, "Seatbelt.cs"); 67 | 68 | SyntaxNode syntaxRoot = await csInfo.GetSyntaxRootAsync(); 69 | RemoveHelpText rewriter = new RemoveHelpText(); 70 | SyntaxNode newSyntaxRoot = rewriter.Visit(syntaxRoot); 71 | 72 | solution = solution.WithDocumentSyntaxRoot(csInfo.Id, newSyntaxRoot); 73 | 74 | return solution; 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /Codecepticon/Modules/CSharp/Profiles/SharpChrome/Rewriters/CommandLine.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis.CSharp.Syntax; 2 | using Microsoft.CodeAnalysis.CSharp; 3 | using Microsoft.CodeAnalysis; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Codecepticon.Modules.CSharp.Profiles.SharpChrome.Rewriters 11 | { 12 | class CommandLine : CSharpSyntaxRewriter 13 | { 14 | protected SyntaxTreeHelper Helper = new SyntaxTreeHelper(); 15 | 16 | public override SyntaxNode VisitLiteralExpression(LiteralExpressionSyntax node) 17 | { 18 | string text = node.GetFirstToken().ValueText.Trim(); 19 | if (text.Length > 0 && text[0] == '/') 20 | { 21 | return Helper.RewriteCommandLineArg(node, text, "/"); 22 | } 23 | 24 | if (Helper.GetPropertyDeclaration(node) == "CommandName") 25 | { 26 | return Helper.RewriteCommandLineArg(node, text, ""); 27 | } 28 | 29 | return base.VisitLiteralExpression(node); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Codecepticon/Modules/CSharp/Profiles/SharpChrome/Rewriters/RemoveHelpText.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis.CSharp.Syntax; 2 | using Microsoft.CodeAnalysis.CSharp; 3 | using Microsoft.CodeAnalysis; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Codecepticon.Modules.CSharp.Profiles.SharpChrome.Rewriters 11 | { 12 | class RemoveHelpText : CSharpSyntaxRewriter 13 | { 14 | protected SyntaxTreeHelper Helper = new SyntaxTreeHelper(); 15 | 16 | protected List HelpFunctions = new List 17 | { 18 | "showlogo", 19 | "showusage" 20 | }; 21 | 22 | public override SyntaxNode VisitBlock(BlockSyntax node) 23 | { 24 | BlockSyntax block = RewriteBlock(node); 25 | return block ?? base.VisitBlock(node); 26 | } 27 | 28 | protected BlockSyntax RewriteBlock(BlockSyntax node) 29 | { 30 | SyntaxNode pMethod = Helper.FindParentOfType(node, SyntaxKind.MethodDeclaration); 31 | if (pMethod == null) 32 | { 33 | return null; 34 | } 35 | 36 | string functionName = pMethod.ChildTokens().LastOrDefault().ValueText.ToLower(); 37 | if (String.IsNullOrEmpty(functionName)) 38 | { 39 | return null; 40 | } 41 | 42 | if (!HelpFunctions.Contains(functionName)) 43 | { 44 | return null; 45 | } 46 | return SyntaxFactory.Block(null); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Codecepticon/Modules/CSharp/Profiles/SharpChrome/SharpChrome.cs: -------------------------------------------------------------------------------- 1 | using Codecepticon.CommandLine; 2 | using Codecepticon.Modules.CSharp.Profiles.SharpChrome.Rewriters; 3 | using Codecepticon.Utils; 4 | using Microsoft.CodeAnalysis; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.IO; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | using BuildEvaluation = Microsoft.Build.Evaluation; 12 | 13 | namespace Codecepticon.Modules.CSharp.Profiles.SharpChrome 14 | { 15 | class SharpChrome : BaseProfile 16 | { 17 | public override string Name { get; } = "SharpChrome"; 18 | 19 | public override async Task Before(Solution solution, Project project) 20 | { 21 | if (CommandLineData.CSharp.Rename.CommandLine) 22 | { 23 | Logger.Debug("SharpChrome: Rewriting command line"); 24 | solution = await RewriteCommandLine(solution, project); 25 | } 26 | 27 | Logger.Debug("SharpChrome: Removing help text"); 28 | solution = await RemoveHelpText(solution, project); 29 | return solution; 30 | } 31 | 32 | public override async Task After(Solution solution, Project project) 33 | { 34 | BuildEvaluation.Project buildProject = VisualStudioManager.GetBuildProject(project); 35 | 36 | if (CommandLineData.CSharp.Rename.Namespaces) 37 | { 38 | Logger.Debug("SharpChrome: Renaming RootNamespace"); 39 | string rootNamespace = buildProject.GetPropertyValue("RootNamespace"); 40 | string newNamespace = DataCollector.Mapping.Namespaces[rootNamespace]; 41 | buildProject.SetProperty("RootNamespace", newNamespace); 42 | } 43 | 44 | Logger.Debug("SharpDPAPI: Renaming Misc Properties"); 45 | buildProject.SetProperty("AssemblyName", CommandLineData.Global.NameGenerator.Generate()); 46 | buildProject.SetProperty("Company", CommandLineData.Global.NameGenerator.Generate()); 47 | buildProject.SetProperty("Product", CommandLineData.Global.NameGenerator.Generate()); 48 | buildProject.Save(); 49 | return solution; 50 | } 51 | 52 | protected async Task RewriteCommandLine(Solution solution, Project project) 53 | { 54 | Rewriters.CommandLine rewriteCommandLine = new Rewriters.CommandLine(); 55 | 56 | project = VisualStudioManager.GetProjectByName(solution, project.Name); 57 | foreach (Document document in project.Documents) 58 | { 59 | SyntaxNode syntaxRoot = await document.GetSyntaxRootAsync(); 60 | 61 | FileInfo file = new FileInfo(document.FilePath); 62 | if (file.DirectoryName.Split('\\').Last() == "Commands") 63 | { 64 | syntaxRoot = rewriteCommandLine.Visit(syntaxRoot); 65 | } 66 | 67 | solution = solution.WithDocumentSyntaxRoot(document.Id, syntaxRoot); 68 | } 69 | return solution; 70 | } 71 | 72 | protected async Task RemoveHelpText(Solution solution, Project project) 73 | { 74 | project = VisualStudioManager.GetProjectByName(solution, project.Name); 75 | Document csInfo = VisualStudioManager.GetDocumentByName(project, "Info.cs"); 76 | 77 | SyntaxNode syntaxRoot = await csInfo.GetSyntaxRootAsync(); 78 | RemoveHelpText rewriter = new RemoveHelpText(); 79 | SyntaxNode newSyntaxRoot = rewriter.Visit(syntaxRoot); 80 | 81 | solution = solution.WithDocumentSyntaxRoot(csInfo.Id, newSyntaxRoot); 82 | 83 | return solution; 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /Codecepticon/Modules/CSharp/Profiles/SharpDPAPI/Rewriters/CommandLine.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using Microsoft.CodeAnalysis.CSharp; 3 | using Microsoft.CodeAnalysis.CSharp.Syntax; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Codecepticon.Modules.CSharp.Profiles.SharpDPAPI.Rewriters 11 | { 12 | class CommandLine : CSharpSyntaxRewriter 13 | { 14 | protected SyntaxTreeHelper Helper = new SyntaxTreeHelper(); 15 | 16 | public override SyntaxNode VisitLiteralExpression(LiteralExpressionSyntax node) 17 | { 18 | string text = node.GetFirstToken().ValueText.Trim(); 19 | if (text.Length > 0 && text[0] == '/') 20 | { 21 | return Helper.RewriteCommandLineArg(node, text, "/"); 22 | } 23 | 24 | if (Helper.GetPropertyDeclaration(node) == "CommandName") 25 | { 26 | return Helper.RewriteCommandLineArg(node, text, ""); 27 | } 28 | 29 | return base.VisitLiteralExpression(node); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Codecepticon/Modules/CSharp/Profiles/SharpDPAPI/Rewriters/RemoveHelpText.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using Microsoft.CodeAnalysis.CSharp; 3 | using Microsoft.CodeAnalysis.CSharp.Syntax; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Codecepticon.Modules.CSharp.Profiles.SharpDPAPI.Rewriters 11 | { 12 | class RemoveHelpText : CSharpSyntaxRewriter 13 | { 14 | protected SyntaxTreeHelper Helper = new SyntaxTreeHelper(); 15 | 16 | protected List HelpFunctions = new List 17 | { 18 | "showlogo", 19 | "showusage" 20 | }; 21 | 22 | public override SyntaxNode VisitBlock(BlockSyntax node) 23 | { 24 | BlockSyntax block = RewriteBlock(node); 25 | return block ?? base.VisitBlock(node); 26 | } 27 | 28 | protected BlockSyntax RewriteBlock(BlockSyntax node) 29 | { 30 | SyntaxNode pMethod = Helper.FindParentOfType(node, SyntaxKind.MethodDeclaration); 31 | if (pMethod == null) 32 | { 33 | return null; 34 | } 35 | 36 | string functionName = pMethod.ChildTokens().LastOrDefault().ValueText.ToLower(); 37 | if (String.IsNullOrEmpty(functionName)) 38 | { 39 | return null; 40 | } 41 | 42 | if (!HelpFunctions.Contains(functionName)) 43 | { 44 | return null; 45 | } 46 | return SyntaxFactory.Block(null); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Codecepticon/Modules/CSharp/Profiles/SharpDPAPI/SharpDPAPI.cs: -------------------------------------------------------------------------------- 1 | using Codecepticon.CommandLine; 2 | using Codecepticon.Modules.CSharp.Profiles.SharpDPAPI.Rewriters; 3 | using Codecepticon.Utils; 4 | using Microsoft.CodeAnalysis; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.IO; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | using BuildEvaluation = Microsoft.Build.Evaluation; 12 | 13 | namespace Codecepticon.Modules.CSharp.Profiles.SharpDPAPI 14 | { 15 | class SharpDPAPI : BaseProfile 16 | { 17 | public override string Name { get; } = "SharpDPAPI"; 18 | public override async Task Before(Solution solution, Project project) 19 | { 20 | if (CommandLineData.CSharp.Rename.CommandLine) 21 | { 22 | Logger.Debug("SharpDPAPI: Rewriting command line"); 23 | solution = await RewriteCommandLine(solution, project); 24 | } 25 | 26 | Logger.Debug("SharpDPAPI: Removing help text"); 27 | solution = await RemoveHelpText(solution, project); 28 | return solution; 29 | } 30 | 31 | public override async Task After(Solution solution, Project project) 32 | { 33 | BuildEvaluation.Project buildProject = VisualStudioManager.GetBuildProject(project); 34 | 35 | if (CommandLineData.CSharp.Rename.Namespaces) 36 | { 37 | Logger.Debug("SharpDPAPI: Renaming RootNamespace"); 38 | string rootNamespace = buildProject.GetPropertyValue("RootNamespace"); 39 | string newNamespace = DataCollector.Mapping.Namespaces[rootNamespace]; 40 | buildProject.SetProperty("RootNamespace", newNamespace); 41 | } 42 | 43 | Logger.Debug("SharpDPAPI: Renaming Misc Properties"); 44 | buildProject.SetProperty("AssemblyName", CommandLineData.Global.NameGenerator.Generate()); 45 | buildProject.SetProperty("Company", CommandLineData.Global.NameGenerator.Generate()); 46 | buildProject.SetProperty("Product", CommandLineData.Global.NameGenerator.Generate()); 47 | buildProject.Save(); 48 | return solution; 49 | } 50 | 51 | protected async Task RewriteCommandLine(Solution solution, Project project) 52 | { 53 | Rewriters.CommandLine rewriteCommandLine = new Rewriters.CommandLine(); 54 | 55 | project = VisualStudioManager.GetProjectByName(solution, project.Name); 56 | foreach (Document document in project.Documents) 57 | { 58 | SyntaxNode syntaxRoot = await document.GetSyntaxRootAsync(); 59 | 60 | FileInfo file = new FileInfo(document.FilePath); 61 | if (file.DirectoryName.Split('\\').Last() == "Commands") 62 | { 63 | syntaxRoot = rewriteCommandLine.Visit(syntaxRoot); 64 | } 65 | 66 | solution = solution.WithDocumentSyntaxRoot(document.Id, syntaxRoot); 67 | } 68 | return solution; 69 | } 70 | 71 | protected async Task RemoveHelpText(Solution solution, Project project) 72 | { 73 | project = VisualStudioManager.GetProjectByName(solution, project.Name); 74 | Document csInfo = VisualStudioManager.GetDocumentByName(project, "Info.cs"); 75 | 76 | SyntaxNode syntaxRoot = await csInfo.GetSyntaxRootAsync(); 77 | RemoveHelpText rewriter = new RemoveHelpText(); 78 | SyntaxNode newSyntaxRoot = rewriter.Visit(syntaxRoot); 79 | 80 | solution = solution.WithDocumentSyntaxRoot(csInfo.Id, newSyntaxRoot); 81 | 82 | return solution; 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Codecepticon/Modules/CSharp/Profiles/SharpHound/Rewriters/CommandLine.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Codecepticon.CommandLine; 7 | using Microsoft.CodeAnalysis; 8 | using Microsoft.CodeAnalysis.CSharp; 9 | using Microsoft.CodeAnalysis.CSharp.Syntax; 10 | 11 | namespace Codecepticon.Modules.CSharp.Profiles.SharpHound.Rewriters 12 | { 13 | class CommandLine : CSharpSyntaxRewriter 14 | { 15 | protected SyntaxTreeHelper Helper = new SyntaxTreeHelper(); 16 | 17 | public override SyntaxNode VisitLiteralExpression(LiteralExpressionSyntax node) 18 | { 19 | if (Helper.IsOptionParent(node)) 20 | { 21 | string value = node.GetFirstToken().ValueText; 22 | string newValue = GetReplacementString(value); 23 | if (newValue.Length > 0) 24 | { 25 | return SyntaxFactory.ParseExpression($"\"{newValue}\""); 26 | } 27 | 28 | // We also need to replace the "Default" collection method, if Enums have been renamed. 29 | if (CommandLineData.CSharp.Rename.Enums && value == "Default") 30 | { 31 | newValue = DataCollector.Mapping.Enums[value]; 32 | return SyntaxFactory.ParseExpression($"\"{newValue}\""); 33 | } 34 | } 35 | return base.VisitLiteralExpression(node); 36 | } 37 | 38 | protected string GetReplacementString(string text) 39 | { 40 | string output = ""; 41 | foreach (KeyValuePair mapping in DataCollector.Mapping.CommandLine) 42 | { 43 | if (text == mapping.Value.Argument) 44 | { 45 | output = mapping.Value.NewName; 46 | break; 47 | } 48 | } 49 | 50 | return output; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Codecepticon/Modules/CSharp/Profiles/SharpHound/Rewriters/IsStatements.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Microsoft.CodeAnalysis; 7 | using Microsoft.CodeAnalysis.CSharp; 8 | using Microsoft.CodeAnalysis.CSharp.Syntax; 9 | 10 | namespace Codecepticon.Modules.CSharp.Profiles.SharpHound.Rewriters 11 | { 12 | class IsStatements : CSharpSyntaxRewriter 13 | { 14 | protected SyntaxTreeHelper Helper = new SyntaxTreeHelper(); 15 | 16 | public override SyntaxNode VisitIsPatternExpression(IsPatternExpressionSyntax node) 17 | { 18 | string ifStatement = RewriteIsStatement(node); 19 | if (ifStatement.Length > 0) 20 | { 21 | return SyntaxFactory.ParseExpression(ifStatement); 22 | } 23 | return base.VisitIsPatternExpression(node); 24 | } 25 | 26 | protected string RewriteIsStatement(SyntaxNode node) 27 | { 28 | SyntaxNode nodeIdentifier = Helper.FindChildOfType(node, SyntaxKind.IdentifierName); 29 | if (nodeIdentifier == null) 30 | { 31 | return ""; 32 | } 33 | 34 | SyntaxNode nodeOrPattern = Helper.FindChildOfType(node, SyntaxKind.OrPattern); 35 | if (nodeOrPattern == null) 36 | { 37 | return ""; 38 | } 39 | 40 | List nodeConstants = Helper.FindChildrenOfType(nodeOrPattern, SyntaxKind.ConstantPattern); 41 | if (nodeConstants.Count == 0) 42 | { 43 | return ""; 44 | } 45 | 46 | string ifStatement = ""; 47 | foreach (SyntaxNode pNode in nodeConstants) 48 | { 49 | if (ifStatement.Length > 0) 50 | { 51 | ifStatement += " || "; 52 | } 53 | ifStatement += $"{nodeIdentifier.GetText()} == {pNode.GetText()}"; 54 | } 55 | 56 | return $"({ifStatement})"; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Codecepticon/Modules/CSharp/Profiles/SharpHound/Rewriters/OutstandingProperties.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Microsoft.CodeAnalysis; 7 | using Microsoft.CodeAnalysis.CSharp; 8 | using Microsoft.CodeAnalysis.CSharp.Syntax; 9 | 10 | namespace Codecepticon.Modules.CSharp.Profiles.SharpHound.Rewriters 11 | { 12 | class OutstandingProperties : CSharpSyntaxRewriter 13 | { 14 | public override SyntaxNode VisitIdentifierName(IdentifierNameSyntax node) 15 | { 16 | /* 17 | * For some reason these aren't renamed in a few instances, such as: 18 | * var restrictedMemberOfSets = actions.Where(x => x.Target == GroupActionTarget.RestrictedMemberOf) 19 | .Select(x => (x.TargetRid, x.TargetSid, x.TargetType)).GroupBy(x => x.TargetRid); <== This last one is not renamed automatically. 20 | */ 21 | 22 | switch (node.Identifier.ValueText) 23 | { 24 | case "TargetRid": 25 | case "TargetSid": 26 | case "TargetType": 27 | if (DataCollector.Mapping.Properties.ContainsKey(node.Identifier.ValueText)) 28 | { 29 | return SyntaxFactory.IdentifierName(DataCollector.Mapping.Properties[node.Identifier.ValueText]); 30 | } 31 | break; 32 | case "computer_name": 33 | case "lan_group": 34 | if (DataCollector.Mapping.Variables.ContainsKey(node.Identifier.ValueText)) 35 | { 36 | return SyntaxFactory.IdentifierName(DataCollector.Mapping.Variables[node.Identifier.ValueText]); 37 | } 38 | break; 39 | } 40 | 41 | return base.VisitIdentifierName(node); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Codecepticon/Modules/CSharp/Profiles/SharpHound/Rewriters/RemoveHelpText.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Microsoft.CodeAnalysis; 7 | using Microsoft.CodeAnalysis.CSharp; 8 | using Microsoft.CodeAnalysis.CSharp.Syntax; 9 | 10 | namespace Codecepticon.Modules.CSharp.Profiles.SharpHound.Rewriters 11 | { 12 | class RemoveHelpText : CSharpSyntaxRewriter 13 | { 14 | protected SyntaxTreeHelper Helper = new SyntaxTreeHelper(); 15 | 16 | public override SyntaxNode VisitLiteralExpression(LiteralExpressionSyntax node) 17 | { 18 | if (Helper.IsOptionParent(node)) 19 | { 20 | string argName = Helper.GetArgumentName(node); 21 | if (argName == "HelpText") 22 | { 23 | return SyntaxFactory.ParseExpression("\"\""); 24 | } 25 | } 26 | return base.VisitLiteralExpression(node); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Codecepticon/Modules/CSharp/Profiles/SharpView/Rewriters/MethodNames.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Microsoft.CodeAnalysis; 7 | using Microsoft.CodeAnalysis.CSharp; 8 | using Microsoft.CodeAnalysis.CSharp.Syntax; 9 | 10 | namespace Codecepticon.Modules.CSharp.Profiles.SharpView.Rewriters 11 | { 12 | class MethodNames : CSharpSyntaxRewriter 13 | { 14 | protected SyntaxTreeHelper Helper = new SyntaxTreeHelper(); 15 | 16 | public override SyntaxNode VisitLiteralExpression(LiteralExpressionSyntax node) 17 | { 18 | if (!node.IsKind(SyntaxKind.StringLiteralExpression)) 19 | { 20 | return base.VisitLiteralExpression(node); 21 | } 22 | 23 | string text = node.Token.Value.ToString(); 24 | if (DataCollector.Mapping.Functions.ContainsKey(text)) 25 | { 26 | SyntaxNode nParent = Helper.FindParentOfType(node, SyntaxKind.SimpleAssignmentExpression); 27 | if (nParent != null) 28 | { 29 | (string variable, string value) = Helper.GetAssignmentData(nParent); 30 | if (variable == "methodName") 31 | { 32 | return SyntaxFactory.ParseExpression($"\"{DataCollector.Mapping.Functions[text]}\""); 33 | } 34 | } 35 | } 36 | 37 | return base.VisitLiteralExpression(node); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Codecepticon/Modules/CSharp/Profiles/SharpView/Rewriters/RemoveHelpText.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Microsoft.CodeAnalysis; 7 | using Microsoft.CodeAnalysis.CSharp; 8 | using Microsoft.CodeAnalysis.CSharp.Syntax; 9 | 10 | namespace Codecepticon.Modules.CSharp.Profiles.SharpView.Rewriters 11 | { 12 | class RemoveHelpText : CSharpSyntaxRewriter 13 | { 14 | protected SyntaxTreeHelper Helper = new SyntaxTreeHelper(); 15 | 16 | public override SyntaxNode VisitLiteralExpression(LiteralExpressionSyntax node) 17 | { 18 | if (!node.IsKind(SyntaxKind.StringLiteralExpression)) 19 | { 20 | return base.VisitLiteralExpression(node); 21 | } 22 | 23 | SyntaxNode ifStatement = Helper.FindParentOfType(node, SyntaxKind.IfStatement); 24 | if (ifStatement != null) 25 | { 26 | SyntaxNode equalStatement = Helper.FindChildOfType(ifStatement, SyntaxKind.EqualsExpression); 27 | if (equalStatement != null) 28 | { 29 | if (equalStatement.GetText().ToString() == "args.Length == 0") 30 | { 31 | return SyntaxFactory.ParseExpression($"\"\""); 32 | } 33 | } 34 | } 35 | 36 | return base.VisitLiteralExpression(node); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Codecepticon/Modules/CSharp/Profiles/SharpView/Rewriters/SwitchCases.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Microsoft.CodeAnalysis; 7 | using Microsoft.CodeAnalysis.CSharp; 8 | using Microsoft.CodeAnalysis.CSharp.Syntax; 9 | 10 | namespace Codecepticon.Modules.CSharp.Profiles.SharpView.Rewriters 11 | { 12 | class SwitchCases : CSharpSyntaxRewriter 13 | { 14 | protected SyntaxTreeHelper Helper = new SyntaxTreeHelper(); 15 | 16 | public override SyntaxNode VisitLiteralExpression(LiteralExpressionSyntax node) 17 | { 18 | if (!node.IsKind(SyntaxKind.StringLiteralExpression)) 19 | { 20 | return base.VisitLiteralExpression(node); 21 | } 22 | 23 | if (node.Parent.IsKind(SyntaxKind.CaseSwitchLabel)) 24 | { 25 | SyntaxNode nParent = Helper.FindParentOfType(node, SyntaxKind.SwitchSection); 26 | if (nParent != null) 27 | { 28 | string methodName = Helper.GetMethodMappedName(nParent); 29 | if (methodName.Length > 0) 30 | { 31 | return SyntaxFactory.ParseExpression($"\"{methodName.ToLower()}\""); 32 | } 33 | } 34 | } 35 | 36 | return base.VisitLiteralExpression(node); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Codecepticon/Modules/CSharp/Profiles/SharpView/SharpView.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Codecepticon.CommandLine; 7 | using Codecepticon.Modules.CSharp.Profiles.SharpView.Rewriters; 8 | using Codecepticon.Utils; 9 | using Microsoft.CodeAnalysis; 10 | 11 | namespace Codecepticon.Modules.CSharp.Profiles.SharpView 12 | { 13 | class SharpView : BaseProfile 14 | { 15 | public override string Name { get; } = "SharpView"; 16 | 17 | public override async Task Before(Solution solution, Project project) 18 | { 19 | if (CommandLineData.CSharp.Rename.CommandLine) 20 | { 21 | Logger.Debug("SharpView: Rewriting command line"); 22 | solution = await RewriteCommandLine(solution, project); 23 | } 24 | 25 | // Remove Help usage (when running without any command line arguments). 26 | Logger.Debug("SharpView: Removing help text"); 27 | solution = await RemoveHelpText(solution, project); 28 | return solution; 29 | } 30 | 31 | public override async Task After(Solution solution, Project project) 32 | { 33 | Dictionary projectConfiguration; 34 | 35 | if (CommandLineData.CSharp.Rename.Namespaces) 36 | { 37 | Logger.Debug("SharpView: Renaming project AssemblyName and RootNamespace"); 38 | projectConfiguration = new Dictionary 39 | { 40 | { "AssemblyName", DataCollector.Mapping.Namespaces["SharpView"] }, 41 | { "RootNamespace", DataCollector.Mapping.Namespaces["SharpView"] }, 42 | }; 43 | 44 | VisualStudioManager.SetProjectConfiguration(solution, projectConfiguration); 45 | } 46 | 47 | if (CommandLineData.CSharp.Rename.Namespaces || CommandLineData.CSharp.Rename.Classes) 48 | { 49 | Logger.Debug("SharpView: Renaming StartupObject"); 50 | string startUpObject = ""; 51 | startUpObject += CommandLineData.CSharp.Rename.Namespaces ? DataCollector.Mapping.Namespaces["SharpView"] : "SharpView"; 52 | startUpObject += "."; 53 | startUpObject += CommandLineData.CSharp.Rename.Classes ? DataCollector.Mapping.Classes["Program"] : "Program"; 54 | 55 | projectConfiguration = new Dictionary 56 | { 57 | { "StartupObject", startUpObject } 58 | }; 59 | 60 | VisualStudioManager.SetProjectConfiguration(solution, projectConfiguration); 61 | } 62 | 63 | return solution; 64 | } 65 | 66 | public override bool ValidateCommandLine() 67 | { 68 | if ((CommandLineData.CSharp.Rename.CommandLine && !CommandLineData.CSharp.Rename.Functions) || (!CommandLineData.CSharp.Rename.CommandLine && CommandLineData.CSharp.Rename.Functions)) 69 | { 70 | Logger.Error("SharpView Profile Error: You cannot obfuscate the command line without obfuscating the functions, and vice versa. Please update your arguments to include both, and try again."); 71 | return false; 72 | } 73 | return true; 74 | } 75 | 76 | protected async Task RewriteCommandLine(Solution solution, Project project) 77 | { 78 | project = VisualStudioManager.GetProjectByName(solution, project.Name); 79 | Document csProgram = VisualStudioManager.GetDocumentByName(project, "Program.cs"); 80 | 81 | SyntaxNode syntaxRoot = await csProgram.GetSyntaxRootAsync(); 82 | MethodNames rewriterMethods = new MethodNames(); 83 | SyntaxNode newSyntaxRoot = rewriterMethods.Visit(syntaxRoot); 84 | 85 | SwitchCases rewriterSwitchCases = new SwitchCases(); 86 | newSyntaxRoot = rewriterSwitchCases.Visit(newSyntaxRoot); 87 | 88 | solution = solution.WithDocumentSyntaxRoot(csProgram.Id, newSyntaxRoot); 89 | return solution; 90 | } 91 | 92 | protected async Task RemoveHelpText(Solution solution, Project project) 93 | { 94 | project = VisualStudioManager.GetProjectByName(solution, project.Name); 95 | Document csProgram = VisualStudioManager.GetDocumentByName(project, "Program.cs"); 96 | if (csProgram == null) 97 | { 98 | Logger.Error("SharpView Profile: Could not find Program.cs"); 99 | return solution; 100 | } 101 | SyntaxNode syntaxRoot = await csProgram.GetSyntaxRootAsync(); 102 | RemoveHelpText rewriterHelpUsage = new RemoveHelpText(); 103 | SyntaxNode newSyntaxRoot = rewriterHelpUsage.Visit(syntaxRoot); 104 | 105 | solution = solution.WithDocumentSyntaxRoot(csProgram.Id, newSyntaxRoot); 106 | return solution; 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /Codecepticon/Modules/CSharp/Rewriters/Assemblies.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Codecepticon.CommandLine; 7 | using Microsoft.CodeAnalysis; 8 | using Microsoft.CodeAnalysis.CSharp; 9 | using Microsoft.CodeAnalysis.CSharp.Syntax; 10 | 11 | namespace Codecepticon.Modules.CSharp.Rewriters 12 | { 13 | class Assemblies : CSharpSyntaxRewriter 14 | { 15 | protected SyntaxTreeHelper Helper = new SyntaxTreeHelper(); 16 | 17 | protected Random Rnd = new Random(); 18 | 19 | public override SyntaxNode VisitLiteralExpression(LiteralExpressionSyntax node) 20 | { 21 | return Helper.IsAssemblyAttribute(node) ? RewriteAssemblyInfo(node) : base.VisitLiteralExpression(node); 22 | } 23 | 24 | protected ExpressionSyntax RewriteAssemblyInfo(SyntaxNode node) 25 | { 26 | List companies = new List 27 | { 28 | "Microsoft", 29 | "Adobe", 30 | "Google", 31 | "Dell", 32 | "Intel", 33 | "Sony", 34 | "HP", 35 | "Cisco", 36 | "NVIDIA", 37 | "Broadcom", 38 | "Oracle", 39 | "AMD", 40 | "Vmware", 41 | "Autodesk", 42 | "Zoom", 43 | "CrowdStrike", 44 | "CarbonBlack", 45 | "McAfee", 46 | "Sophos", 47 | "Symantec", 48 | "Avast", 49 | "Avira", 50 | "Windows Defender", 51 | "Eset", 52 | "Kaspersky", 53 | "F-Secure", 54 | "Fireeye", 55 | "Ivanti", 56 | "Tanium" 57 | }; 58 | string assemblyPropertyName = Helper.GetAssemblyPropertyName(node); 59 | string value = node.GetText().ToString(); 60 | switch (assemblyPropertyName) 61 | { 62 | case "AssemblyCompany": 63 | value = $"\"{companies[Rnd.Next(companies.Count)]}\""; 64 | break; 65 | case "AssemblyCopyright": 66 | int year = Rnd.Next(2014, DateTime.Now.Year); 67 | value = $"\"Copyright {year}\""; 68 | break; 69 | case "AssemblyTitle": 70 | case "AssemblyDescription": 71 | case "AssemblyProduct": 72 | case "AssemblyTrademark": 73 | value = "\"\""; 74 | break; 75 | case "AssemblyVersion": 76 | case "AssemblyFileVersion": 77 | int major = Rnd.Next(1, 9); 78 | int minor = Rnd.Next(0, 20); 79 | int revision = Rnd.Next(0, 20); 80 | int patch = Rnd.Next(1000, 3000); 81 | value = $"\"{major}.{minor}.{revision}.{patch}\""; 82 | break; 83 | case "Guid": 84 | value = $"\"{CommandLineData.Global.Project.Guid.ToString().ToLower()}\""; 85 | break; 86 | } 87 | return SyntaxFactory.ParseExpression(value); 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /Codecepticon/Modules/CSharp/Rewriters/RemoveComments.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Microsoft.CodeAnalysis; 7 | using Microsoft.CodeAnalysis.CSharp; 8 | 9 | namespace Codecepticon.Modules.CSharp.Rewriters 10 | { 11 | class RemoveComments : CSharpSyntaxRewriter 12 | { 13 | public override SyntaxTrivia VisitTrivia(SyntaxTrivia trivia) 14 | { 15 | if (trivia.IsKind(SyntaxKind.SingleLineCommentTrivia) || trivia.IsKind(SyntaxKind.MultiLineCommentTrivia) || trivia.IsKind(SyntaxKind.MultiLineDocumentationCommentTrivia) || trivia.IsKind(SyntaxKind.SingleLineDocumentationCommentTrivia)) 16 | { 17 | return default(SyntaxTrivia); 18 | } 19 | return base.VisitTrivia(trivia); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Codecepticon/Modules/CSharp/Rewriters/Strings.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using Microsoft.CodeAnalysis.CSharp; 3 | using Microsoft.CodeAnalysis.CSharp.Syntax; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using Codecepticon.CommandLine; 10 | using Codecepticon.Utils; 11 | 12 | namespace Codecepticon.Modules.CSharp.Rewriters 13 | { 14 | class Strings : CSharpSyntaxRewriter 15 | { 16 | protected SyntaxTreeHelper Helper = new SyntaxTreeHelper(); 17 | 18 | protected NameGenerator NameGenerator = new NameGenerator(NameGenerator.RandomNameGeneratorMethods.RandomCombinations, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 32); 19 | 20 | public override SyntaxNode VisitLiteralExpression(LiteralExpressionSyntax node) 21 | { 22 | if (!node.IsKind(SyntaxKind.StringLiteralExpression)) 23 | { 24 | return base.VisitLiteralExpression(node); 25 | } 26 | 27 | if (Helper.IsAssemblyAttribute(node)) 28 | { 29 | // Assemblies are re-written in a separate step. 30 | return base.VisitLiteralExpression(node); 31 | } 32 | 33 | if (!Helper.CanReplaceString(node)) 34 | { 35 | return base.VisitLiteralExpression(node); 36 | } 37 | 38 | return RewriteString(node.Token.Value.ToString()); 39 | } 40 | 41 | public override SyntaxNode VisitInterpolatedStringExpression(InterpolatedStringExpressionSyntax node) 42 | { 43 | // First check if the interpolation has a custom format, and if it does, skip it. 44 | if (Helper.HasInterpolationFormat(node)) 45 | { 46 | return base.VisitInterpolatedStringExpression(node); 47 | } 48 | 49 | string format = ""; 50 | string vars = ""; 51 | int varCount = 0; 52 | 53 | foreach (SyntaxNode n in node.ChildNodes()) 54 | { 55 | switch (n.Kind()) 56 | { 57 | case SyntaxKind.InterpolatedStringText: 58 | format += n.ChildTokens().First().ValueText; 59 | break; 60 | case SyntaxKind.Interpolation: 61 | if (vars.Length > 0) { vars += ","; } 62 | vars += $"{n.ChildNodes().First().GetText()}"; 63 | 64 | format += $"{{{varCount}}}"; 65 | varCount++; 66 | 67 | break; 68 | } 69 | } 70 | 71 | string encodedString = GetEncodedString(format); 72 | if (varCount > 0) 73 | { 74 | encodedString = $"System.String.Format({encodedString}, {vars})"; 75 | } 76 | 77 | return SyntaxFactory.ParseExpression(encodedString); 78 | } 79 | 80 | protected ExpressionSyntax RewriteString(string text) 81 | { 82 | return SyntaxFactory.ParseExpression(GetEncodedString(text)); 83 | } 84 | 85 | protected string GetEncodedString(string text) 86 | { 87 | string code = ""; 88 | switch (CommandLineData.Global.Rewrite.EncodingMethod) 89 | { 90 | case StringEncoding.StringEncodingMethods.Base64: 91 | text = Convert.ToBase64String(Encoding.UTF8.GetBytes(text)); 92 | code = $"System.Text.Encoding.UTF8.GetString(System.Convert.FromBase64String(\"{text}\"))"; 93 | break; 94 | case StringEncoding.StringEncodingMethods.XorEncrypt: 95 | string key = NameGenerator.Generate(); 96 | text = StringEncoding.Xor(text, key, false, false); 97 | code = $"{CommandLineData.Global.Rewrite.Template.Namespace}.{CommandLineData.Global.Rewrite.Template.Class}.{CommandLineData.Global.Rewrite.Template.Function}(\"{text}\", \"{key}\")"; 98 | break; 99 | case StringEncoding.StringEncodingMethods.SingleCharacterSubstitution: 100 | text = StringEncoding.SingleCharacter(text, CommandLineData.Global.Rewrite.SingleMapping); 101 | code = $"{CommandLineData.Global.Rewrite.Template.Namespace}.{CommandLineData.Global.Rewrite.Template.Class}.{CommandLineData.Global.Rewrite.Template.Function}(\"{text}\")"; 102 | break; 103 | case StringEncoding.StringEncodingMethods.GroupCharacterSubstitution: 104 | text = StringEncoding.GroupCharacter(text, CommandLineData.Global.Rewrite.GroupMapping); 105 | code = $"{CommandLineData.Global.Rewrite.Template.Namespace}.{CommandLineData.Global.Rewrite.Template.Class}.{CommandLineData.Global.Rewrite.Template.Function}(\"{text}\")"; 106 | break; 107 | case StringEncoding.StringEncodingMethods.ExternalFile: 108 | int index = StringEncoding.GetExternalFileIndex(text); 109 | code = $"{CommandLineData.Global.Rewrite.Template.Namespace}.{CommandLineData.Global.Rewrite.Template.Class}.{CommandLineData.Global.Rewrite.Template.Function}({index})"; 110 | break; 111 | } 112 | 113 | return code; 114 | } 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /Codecepticon/Modules/CSharp/Rewriters/SwitchExpressions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using Microsoft.CodeAnalysis.CSharp; 3 | using Microsoft.CodeAnalysis.CSharp.Syntax; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Codecepticon.Modules.CSharp.Rewriters 11 | { 12 | class SwitchExpressions : CSharpSyntaxRewriter 13 | { 14 | protected SyntaxTreeHelper Helper = new SyntaxTreeHelper(); 15 | 16 | public SemanticModel documentModel = null; 17 | 18 | public override SyntaxNode VisitSwitchExpression(SwitchExpressionSyntax node) 19 | { 20 | /* 21 | * This is a switch expression, for example the following snippet from Certify: 22 | * 23 | * private string? ConvertGuidToName(string guid) 24 | { 25 | return guid switch 26 | { 27 | "0e10c968-78fb-11d2-90d4-00c04f79dc55" => "Enrollment", 28 | "a05b8cc2-17bc-4802-a710-e7c15ab866a2" => "AutoEnrollment", 29 | "00000000-0000-0000-0000-000000000000" => "All", 30 | _ => null 31 | }; 32 | } 33 | * 34 | * And needs to be rewritten in order to be able to obfuscate it: 35 | * 36 | * if (guid == "0e10c968-78fb-11d2-90d4-00c04f79dc55") { 37 | * return "Enrollment" 38 | * } else if (guid == "a05b8cc2-17bc-4802-a710-e7c15ab866a2") { 39 | * return "AutoEnrollment" 40 | * } else if (guid == "00000000-0000-0000-0000-000000000000") { 41 | * return "All" 42 | * } else { 43 | * return null 44 | * } 45 | * 46 | * However, as it's inline it's difficult to go back and start changing things, 47 | * so we'll use an inline function like: 48 | * 49 | * return ((Func)((guid) => { return guid; }))(guid); 50 | * 51 | * We need to collect the following: 52 | * 1. Name of the variable that is compared against values = "guid" 53 | * 2. Type of that variable, as we'll need to define it and pass it as a parameter = "string" 54 | * 3. Type of the value that is being returned, in this case it's the function type = "string" 55 | */ 56 | 57 | // First we need to get the identifier name. 58 | SyntaxNode identifierNode = Helper.FindChildOfType(node, SyntaxKind.IdentifierName); 59 | if (identifierNode != null) 60 | { 61 | // Get #1 62 | string identifierName = identifierNode.GetFirstToken().ValueText; 63 | 64 | // Get #2 65 | // ISymbol identifierSymbol = documentModel.GetSymbolInfo(identifierNode).Symbol; 66 | string identifierType = documentModel.GetSymbolInfo(identifierNode).Symbol.ToString(); 67 | 68 | // Get #3 69 | string expressionType = documentModel.GetTypeInfo(node).Type.ToString(); 70 | 71 | // Collect all comparisons. 72 | Dictionary expressions = new Dictionary(); 73 | foreach (SyntaxNode switchArm in node.ChildNodes()) 74 | { 75 | // Just to confirm we have the right node. 76 | if (!switchArm.IsKind(SyntaxKind.SwitchExpressionArm)) 77 | { 78 | continue; 79 | } 80 | 81 | string constantPattern = switchArm.ChildNodes().ElementAt(0).GetText().ToString().Trim(); 82 | string returnValue = switchArm.ChildNodes().ElementAt(1).GetText().ToString().Trim(); 83 | expressions.Add(constantPattern, returnValue); 84 | } 85 | 86 | // Build function. 87 | string sourceCodeIfStatement = ""; 88 | foreach (KeyValuePair comparison in expressions) 89 | { 90 | if (sourceCodeIfStatement == "") 91 | { 92 | sourceCodeIfStatement += $"if ({identifierName} == {comparison.Key})" + " {\r\n"; 93 | } 94 | else 95 | { 96 | if (comparison.Key == "_") 97 | { 98 | sourceCodeIfStatement += " else {\r\n"; 99 | } 100 | else 101 | { 102 | sourceCodeIfStatement += $" else if ({identifierName} == {comparison.Key})" + " {\r\n"; 103 | } 104 | } 105 | 106 | sourceCodeIfStatement += $"return {comparison.Value};"; 107 | 108 | sourceCodeIfStatement += "}\r\n"; 109 | } 110 | 111 | string code = $"((Func<{identifierType}, {expressionType}>)(({identifierName}) => "; 112 | code += "{ " + sourceCodeIfStatement + " }"; 113 | code += $"))({identifierName});"; 114 | 115 | return SyntaxFactory.ParseExpression(code); 116 | } 117 | 118 | return base.VisitSwitchExpression(node); 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /Codecepticon/Modules/CSharp/Rewriters/SwitchStatements.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Microsoft.CodeAnalysis; 7 | using Microsoft.CodeAnalysis.CSharp; 8 | using Microsoft.CodeAnalysis.CSharp.Syntax; 9 | 10 | namespace Codecepticon.Modules.CSharp.Rewriters 11 | { 12 | class SwitchStatements : CSharpSyntaxRewriter 13 | { 14 | protected SyntaxTreeHelper Helper = new SyntaxTreeHelper(); 15 | 16 | public override SyntaxNode VisitSwitchStatement(SwitchStatementSyntax node) 17 | { 18 | /* 19 | * This is a typical switch statement. 20 | */ 21 | SyntaxNode switchCondition = Helper.FindChildOfType(node, new[] { SyntaxKind.InvocationExpression, SyntaxKind.IdentifierName, SyntaxKind.SimpleMemberAccessExpression }); 22 | if (switchCondition == null) 23 | { 24 | return base.VisitSwitchStatement(node); 25 | } 26 | 27 | string sourceCodeIfStatement = ""; 28 | foreach (SyntaxNode switchSection in node.ChildNodes()) 29 | { 30 | // Just to confirm we have the right node. 31 | if (!switchSection.IsKind(SyntaxKind.SwitchSection)) 32 | { 33 | continue; 34 | } 35 | 36 | if (Helper.HasChildOfType(switchSection, SyntaxKind.CasePatternSwitchLabel)) 37 | { 38 | sourceCodeIfStatement = ""; 39 | break; 40 | } 41 | 42 | string ifLeft = switchCondition.GetText().ToString().Trim(); 43 | 44 | List conditions = Helper.GetSwitchCaseConditions(switchSection); 45 | string ifCondition = BuildIfCondition(conditions, ifLeft); 46 | 47 | if (sourceCodeIfStatement == "") 48 | { 49 | sourceCodeIfStatement += $"if ({ifCondition})" + " {\r\n"; 50 | } 51 | else 52 | { 53 | if (ifCondition == "") 54 | { 55 | sourceCodeIfStatement += " else {\r\n"; 56 | } 57 | else 58 | { 59 | sourceCodeIfStatement += $" else if ({ifCondition})" + " {\r\n"; 60 | } 61 | } 62 | 63 | sourceCodeIfStatement += Helper.GetSwitchCaseSourceCode(switchSection); 64 | 65 | sourceCodeIfStatement += "\r\n}"; 66 | } 67 | 68 | return sourceCodeIfStatement != "" ? SyntaxFactory.ParseStatement(sourceCodeIfStatement) : base.VisitSwitchStatement(node); 69 | } 70 | 71 | protected string BuildIfCondition(List conditions, string ifLeft) 72 | { 73 | string output = ""; 74 | foreach (string condition in conditions) 75 | { 76 | if (output != "") 77 | { 78 | output += " || "; 79 | 80 | } 81 | output += ifLeft + " == " + condition; 82 | } 83 | return output; 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /Codecepticon/Modules/CSharp/Unmapping.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using Codecepticon.CommandLine; 8 | using Codecepticon.Utils; 9 | 10 | 11 | namespace Codecepticon.Modules.CSharp 12 | { 13 | class Unmapping : DataUnmapping 14 | { 15 | public static void GenerateMapFile(string saveAs) 16 | { 17 | Dictionary data = new Dictionary 18 | { 19 | ["namespaces"] = "", 20 | ["classes"] = "", 21 | ["functions"] = "", 22 | ["enums"] = "", 23 | ["properties"] = "", 24 | ["variables"] = "", 25 | ["parameters"] = "", 26 | ["structs"] = "", 27 | ["cmdline"] = "", 28 | }; 29 | 30 | if (CommandLineData.CSharp.Rename.Namespaces) 31 | { 32 | data["namespaces"] = ConcatData(DataCollector.Mapping.Namespaces); 33 | } 34 | 35 | if (CommandLineData.CSharp.Rename.Classes) 36 | { 37 | data["classes"] = ConcatData(DataCollector.Mapping.Classes); 38 | } 39 | 40 | if (CommandLineData.CSharp.Rename.Functions) 41 | { 42 | data["functions"] = ConcatData(DataCollector.Mapping.Functions); 43 | } 44 | 45 | if (CommandLineData.CSharp.Rename.Enums) 46 | { 47 | data["enums"] = ConcatData(DataCollector.Mapping.Enums); 48 | } 49 | 50 | if (CommandLineData.CSharp.Rename.Properties) 51 | { 52 | data["properties"] = ConcatData(DataCollector.Mapping.Properties); 53 | } 54 | 55 | if (CommandLineData.CSharp.Rename.Variables) 56 | { 57 | data["variables"] = ConcatData(DataCollector.Mapping.Variables); 58 | } 59 | 60 | if (CommandLineData.CSharp.Rename.Parameters) 61 | { 62 | data["parameters"] = ConcatData(DataCollector.Mapping.Parameters); 63 | } 64 | 65 | if (CommandLineData.CSharp.Rename.Structs) 66 | { 67 | data["structs"] = ConcatData(DataCollector.Mapping.Structs); 68 | } 69 | 70 | if (CommandLineData.CSharp.Rename.CommandLine) 71 | { 72 | data["cmdline"] = DataCollector.ConcatCommandLineData(DataCollector.Mapping.CommandLine); 73 | } 74 | 75 | WriteTemplateFile(saveAs, data); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /Codecepticon/Modules/CommandLineData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Codecepticon.Modules.CSharp.Profiles; 7 | using Codecepticon.Utils; 8 | using Codecepticon.Utils.MarkovWordGenerator; 9 | using Microsoft.PowerShell.Commands; 10 | 11 | namespace Codecepticon.CommandLine 12 | { 13 | class CommandLineData 14 | { 15 | public enum Action 16 | { 17 | None = 0, 18 | Obfuscate = 1, 19 | Unmap = 2, 20 | GenerateCertificate = 3, 21 | Sign = 4, 22 | } 23 | 24 | public struct ProjectStruct 25 | { 26 | public string Path; 27 | public bool Verbose; 28 | public bool Debug; 29 | public Guid Guid; 30 | public string SaveAs; 31 | } 32 | 33 | public struct CharacterSetStruct 34 | { 35 | public string Value; 36 | public int Length; 37 | } 38 | 39 | public struct DictionaryStruct 40 | { 41 | public List Words; 42 | } 43 | 44 | public struct NameGeneratorStruct 45 | { 46 | public CharacterSetStruct CharacterSet; 47 | public DictionaryStruct Dictionary; 48 | } 49 | 50 | public struct VSBuildStruct 51 | { 52 | public bool Build; 53 | public string Configuration; 54 | public Dictionary Settings; 55 | public string OutputPath; 56 | public bool Precompile; 57 | } 58 | 59 | public struct CSharpRenamingStruct 60 | { 61 | public bool Enabled; 62 | public bool Namespaces; 63 | public bool Classes; 64 | public bool Functions; 65 | public bool Enums; 66 | public bool Properties; 67 | public bool Variables; 68 | public bool Parameters; 69 | public bool CommandLine; 70 | public bool Structs; 71 | } 72 | 73 | public struct RewriteTemplateStruct 74 | { 75 | public string File; 76 | public string Namespace; 77 | public string Class; 78 | public string Function; 79 | public string Mapping; 80 | public string AddedFile; 81 | } 82 | 83 | public struct StringRewriteStruct 84 | { 85 | public bool Strings; 86 | 87 | public StringEncoding.StringEncodingMethods EncodingMethod; 88 | public CharacterSetStruct CharacterSet; 89 | public RewriteTemplateStruct Template; 90 | 91 | public Dictionary SingleMapping; 92 | public Dictionary GroupMapping; 93 | public string ExternalFile; 94 | } 95 | 96 | public struct MarkovGenerationStruct 97 | { 98 | public MarkovWordGenerator Generator; 99 | public int MinWords; 100 | public int MaxWords; 101 | public int MinLength; 102 | public int MaxLength; 103 | } 104 | 105 | public struct DataUnmap 106 | { 107 | public string MapFile; 108 | public string Directory; 109 | public string File; 110 | public bool Recursive; 111 | } 112 | 113 | public struct CSharpSettings 114 | { 115 | public CSharpRenamingStruct Rename; 116 | public VSBuildStruct Compilation; 117 | public BaseProfile Profile; 118 | } 119 | 120 | public struct PowerShellRenamingStruct 121 | { 122 | public bool Enabled; 123 | public bool Functions; 124 | public bool Variables; 125 | public bool Parameters; 126 | } 127 | 128 | public struct Vb6RenamingStruct 129 | { 130 | public bool Enabled; 131 | public bool Identifiers; 132 | } 133 | 134 | public struct PowerShellSettings 135 | { 136 | public PowerShellRenamingStruct Rename; 137 | } 138 | 139 | public struct Vb6Settings 140 | { 141 | public Vb6RenamingStruct Rename; 142 | } 143 | 144 | public struct SignNewCertificate 145 | { 146 | public string Subject; 147 | public string Issuer; 148 | public DateTime NotBefore; 149 | public DateTime NotAfter; 150 | public string Password; 151 | public bool Overwrite; 152 | public string PfxFile; 153 | public string CopyFrom; 154 | } 155 | 156 | public struct SignSettings 157 | { 158 | public SignNewCertificate NewCertificate; 159 | public string TimestampServer; 160 | public string SignatureAlgorithm; 161 | } 162 | 163 | public struct RenameGeneratorStruct 164 | { 165 | public NameGenerator.RandomNameGeneratorMethods Method; 166 | public NameGeneratorStruct Data; 167 | } 168 | 169 | public struct GlobalSettings 170 | { 171 | public Action Action; 172 | public ProjectStruct Project; 173 | public NameGenerator NameGenerator; 174 | public DataUnmap Unmap; 175 | public StringRewriteStruct Rewrite; 176 | public RenameGeneratorStruct RenameGenerator; 177 | public string ConfigFile; 178 | public bool IsHelp; 179 | public string[] RawCmdLineArgs; 180 | public string RawConfigFile; 181 | public string Version; 182 | public MarkovGenerationStruct Markov; 183 | } 184 | 185 | // Below this line are the variables that are used to access live data. 186 | public static GlobalSettings Global = new GlobalSettings(); 187 | public static CSharpSettings CSharp = new CSharpSettings(); 188 | public static PowerShellSettings PowerShell = new PowerShellSettings(); 189 | public static Vb6Settings Vb6 = new Vb6Settings(); 190 | public static SignSettings Sign = new SignSettings(); 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /Codecepticon/Modules/ModuleManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Codecepticon.Utils; 7 | 8 | namespace Codecepticon.Modules 9 | { 10 | class ModuleManager 11 | { 12 | protected static async Task GenerateName(NameGenerator nameGenerator, Func isMappingUnique) 13 | { 14 | string name; 15 | int duplicateAttempts = 0; 16 | int attemptLimit = 100; 17 | do 18 | { 19 | name = nameGenerator.Generate(); 20 | if (isMappingUnique(name)) 21 | { 22 | break; 23 | } 24 | } while (++duplicateAttempts < attemptLimit); 25 | 26 | if (duplicateAttempts >= attemptLimit) 27 | { 28 | Logger.Error($"Failed {attemptLimit} times to generate a unique string that is not already a mapping. Increase your character set / length / dictionary, and try again."); 29 | return ""; 30 | } 31 | 32 | return name; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Codecepticon/Modules/ModuleTypes.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Codecepticon.Modules 8 | { 9 | class ModuleTypes 10 | { 11 | public enum CodecepticonModules 12 | { 13 | None = -1, 14 | Unknown = 0, 15 | CSharp = 1, 16 | Powershell = 2, 17 | Vb6 = 3, 18 | Sign = 101 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Codecepticon/Modules/PowerShell/CommandLine/PowerShellCommandLine.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using Codecepticon.CommandLine; 6 | using Codecepticon.Utils; 7 | 8 | namespace Codecepticon.Modules.PowerShell.CommandLine 9 | { 10 | class PowerShellCommandLine : CommandLineManager 11 | { 12 | public PowerShellCommandLine(string[] args) : base(args) 13 | { 14 | Arguments = new Dictionary(); 15 | MergeArguments(); 16 | } 17 | 18 | protected override bool Parse(Dictionary arguments) 19 | { 20 | if (!ParseGlobalArguments(arguments)) 21 | { 22 | return false; 23 | } 24 | 25 | foreach (KeyValuePair argument in arguments) 26 | { 27 | switch (argument.Key.ToLower()) 28 | { 29 | case "rename": 30 | CommandLineData.PowerShell.Rename.Enabled = (argument.Value.Length > 0); 31 | ParseRenameOptions(argument.Value.ToLower()); 32 | break; 33 | //default: 34 | // Logger.Error($"Code error: Not supported parameter - {argument.Key}"); 35 | // return false; 36 | } 37 | } 38 | 39 | ValidateCommandLine validate = new ValidateCommandLine(); 40 | return validate.Run(); 41 | } 42 | 43 | protected void ParseRenameOptions(string value) 44 | { 45 | if (value == "all") 46 | { 47 | SetRenameValue(true); 48 | } 49 | else 50 | { 51 | SetRenameValue(false); 52 | foreach (char c in value.ToLower().ToArray()) 53 | { 54 | switch (c.ToString()) 55 | { 56 | case "f": 57 | CommandLineData.PowerShell.Rename.Functions = true; 58 | break; 59 | case "v": 60 | CommandLineData.PowerShell.Rename.Variables = true; 61 | CommandLineData.PowerShell.Rename.Parameters = true; 62 | break; 63 | } 64 | } 65 | } 66 | } 67 | 68 | protected override void SetRenameValue(bool value) 69 | { 70 | CommandLineData.PowerShell.Rename.Functions = value; 71 | CommandLineData.PowerShell.Rename.Variables = value; 72 | CommandLineData.PowerShell.Rename.Parameters = value; 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /Codecepticon/Modules/PowerShell/CommandLine/ValidateCommandLine.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using Codecepticon.CommandLine; 8 | using Codecepticon.Utils; 9 | 10 | namespace Codecepticon.Modules.PowerShell.CommandLine 11 | { 12 | class ValidateCommandLine : CommandLineValidator 13 | { 14 | public bool Run() 15 | { 16 | if (!ValidateAction()) 17 | { 18 | return false; 19 | } 20 | 21 | return true; 22 | } 23 | 24 | protected bool ValidateAction() 25 | { 26 | switch (CommandLineData.Global.Action) 27 | { 28 | case CommandLineData.Action.None: 29 | Logger.Error("'action' parameter not set"); 30 | return false; 31 | case CommandLineData.Action.Obfuscate: 32 | return ValidateActionObfuscate(); 33 | case CommandLineData.Action.Unmap: 34 | return ValidateActionUnmap(); 35 | } 36 | 37 | return false; 38 | } 39 | 40 | protected bool ValidateActionObfuscate() 41 | { 42 | if (!CommandLineData.PowerShell.Rename.Enabled && !CommandLineData.Global.Rewrite.Strings) 43 | { 44 | Logger.Error("No rename or rewrite parameters set."); 45 | return false; 46 | } 47 | 48 | // Check if the solution exists. 49 | if (String.IsNullOrEmpty(CommandLineData.Global.Project.Path) || !File.Exists(CommandLineData.Global.Project.Path)) 50 | { 51 | Logger.Error($"Path is empty or does not exist: {CommandLineData.Global.Project.Path}"); 52 | return false; 53 | } 54 | 55 | if (String.IsNullOrEmpty(CommandLineData.Global.Project.SaveAs)) 56 | { 57 | // Default behaviour is to replace the actual file. 58 | CommandLineData.Global.Project.SaveAs = CommandLineData.Global.Project.Path + ".obfuscated.ps1"; 59 | } 60 | 61 | if (CommandLineData.PowerShell.Rename.Enabled && !ValidateRename()) 62 | { 63 | return false; 64 | } 65 | 66 | if (!ValidateRewrite(ModuleTypes.CodecepticonModules.Powershell)) 67 | { 68 | return false; 69 | } 70 | 71 | if (!ValidateMappingFiles()) 72 | { 73 | return false; 74 | } 75 | 76 | return true; 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /Codecepticon/Modules/PowerShell/DataCollector.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Management.Automation.Language; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Codecepticon.Modules.PowerShell 9 | { 10 | class DataCollector 11 | { 12 | public static SyntaxTreeHelper Helper = new SyntaxTreeHelper(); 13 | 14 | public static List AllFunctions = new List(); 15 | public static List AllVariables = new List(); 16 | 17 | public struct MappingStruct 18 | { 19 | public Dictionary Functions; 20 | public Dictionary Variables; 21 | } 22 | 23 | public static MappingStruct Mapping = new MappingStruct 24 | { 25 | Functions = new Dictionary(), 26 | Variables = new Dictionary(), 27 | }; 28 | 29 | public static bool IsMappingUnique(string name) 30 | { 31 | string item = Mapping.Functions.FirstOrDefault(s => s.Value == name.ToLower()).Key; 32 | if (item != null) 33 | { 34 | return false; 35 | } 36 | 37 | item = Mapping.Variables.FirstOrDefault(s => s.Value == name.ToLower()).Key; 38 | return item == null; 39 | } 40 | 41 | public static async Task CollectFunctions(Token[] psTokens) 42 | { 43 | for (int i = 0; i < psTokens.Length; i++) 44 | { 45 | Token prevToken = (i == 0) ? null : psTokens[i - 1]; 46 | Token currToken = psTokens[i]; 47 | 48 | if (Helper.IsFunction(prevToken)) 49 | { 50 | // Using .ToLower() because PowerShell isn't case-sensitive. 51 | if (!currToken.Text.Contains(":") && !AllFunctions.Contains(currToken.Text.ToLower())) 52 | { 53 | AllFunctions.Add(currToken.Text.ToLower()); 54 | } 55 | } 56 | } 57 | AllFunctions.Sort(); 58 | } 59 | 60 | public static async Task CollectVariables(Token[] psTokens) 61 | { 62 | foreach (Token currToken in psTokens) 63 | { 64 | if (Helper.IsVariable(currToken)) 65 | { 66 | // Using .ToLower() because PowerShell isn't case-sensitive. 67 | string name = currToken.Text.Substring(1).ToLower(); // Remove the $ from the beginning. 68 | if (!name.Contains(":") && !AllVariables.Contains(name)) 69 | { 70 | AllVariables.Add(name); 71 | } 72 | } 73 | } 74 | AllVariables.Sort(); 75 | } 76 | 77 | public static async Task CollectParameters(Token[] psTokens) 78 | { 79 | for (int i = 0; i < psTokens.Length; i++) 80 | { 81 | Token currToken = psTokens[i]; 82 | 83 | if (Helper.IsParameter(currToken)) 84 | { 85 | if (Helper.IsCallingFunctionBuiltIn(psTokens, i)) 86 | { 87 | continue; 88 | } 89 | 90 | // Using .ToLower() because PowerShell isn't case-sensitive. 91 | string name = currToken.Text.Substring(1).ToLower(); // Remove the $ from the beginning. 92 | if (!name.Contains(":") && !AllVariables.Contains(name)) 93 | { 94 | AllVariables.Add(name); 95 | } 96 | } 97 | } 98 | AllVariables.Sort(); 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /Codecepticon/Modules/PowerShell/Unmapping.cs: -------------------------------------------------------------------------------- 1 | using Codecepticon.CommandLine; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Codecepticon.Modules.PowerShell 9 | { 10 | class Unmapping : DataUnmapping 11 | { 12 | public static void GenerateMapFile(string saveAs) 13 | { 14 | Dictionary data = new Dictionary 15 | { 16 | ["namespaces"] = "", 17 | ["classes"] = "", 18 | ["functions"] = "", 19 | ["enums"] = "", 20 | ["properties"] = "", 21 | ["variables"] = "", 22 | ["parameters"] = "", 23 | ["cmdline"] = "", 24 | }; 25 | 26 | if (CommandLineData.PowerShell.Rename.Functions) 27 | { 28 | data["functions"] = ConcatData(DataCollector.Mapping.Functions); 29 | } 30 | 31 | if (CommandLineData.PowerShell.Rename.Variables || CommandLineData.PowerShell.Rename.Parameters) 32 | { 33 | data["variables"] = ConcatData(DataCollector.Mapping.Variables); 34 | } 35 | 36 | WriteTemplateFile(saveAs, data); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Codecepticon/Modules/Sign/CertificateManager.cs: -------------------------------------------------------------------------------- 1 | using Codecepticon.Utils; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Security.Cryptography; 6 | using System.Security.Cryptography.X509Certificates; 7 | 8 | namespace Codecepticon.Modules.Sign 9 | { 10 | class CertificateManager 11 | { 12 | private const int KeyLength = 2048; 13 | 14 | public bool GenerateCertificate(string Subject, string Issuer, DateTime NotBefore, DateTime NotAfter, string Password, string PfxOutput) 15 | { 16 | // https://stackoverflow.com/a/48210587/2445959 17 | RSA keyPair = RSA.Create(KeyLength); 18 | 19 | Logger.Verbose("Generating issuer certificate..."); 20 | Logger.Verbose("Issuer is " + Issuer); 21 | X509Certificate2 certificateIssuer = GenerateIssuerCertificate(Issuer, NotBefore, NotAfter); 22 | 23 | Logger.Info("Generating signing certificate..."); 24 | Logger.Verbose("Subject is " + Subject); 25 | CertificateRequest certRequest = new(Subject, keyPair, HashAlgorithmName.SHA512, RSASignaturePadding.Pkcs1); 26 | certRequest.CertificateExtensions.Add(new X509BasicConstraintsExtension(false, false, 0, false)); 27 | //certRequest.CertificateExtensions.Add(new X509EnhancedKeyUsageExtension(new OidCollection { new Oid("1.3.6.1.5.5.7.3.8") }, true)); 28 | certRequest.CertificateExtensions.Add(new X509SubjectKeyIdentifierExtension(certRequest.PublicKey, false)); 29 | X509Certificate2 cert = certRequest.Create(certificateIssuer, NotBefore, NotAfter, new byte[] { 1, 2, 3, 4 }); 30 | 31 | // Add the private key back to the certificate. 32 | X509Certificate2 certificate = cert.CopyWithPrivateKey(keyPair); 33 | 34 | Logger.Info("Exporting certificate to file..."); 35 | File.WriteAllBytes(PfxOutput, certificate.Export(X509ContentType.Pfx, Password)); 36 | 37 | return true; 38 | } 39 | 40 | private X509Certificate2 GenerateIssuerCertificate(string Issuer, DateTime NotBefore, DateTime NotAfter) 41 | { 42 | RSA keyPair = RSA.Create(KeyLength); 43 | 44 | CertificateRequest issuerRequest = new(Issuer, keyPair, HashAlgorithmName.SHA512, RSASignaturePadding.Pkcs1); 45 | issuerRequest.CertificateExtensions.Add(new X509BasicConstraintsExtension(true, false, 0, true)); 46 | issuerRequest.CertificateExtensions.Add(new X509SubjectKeyIdentifierExtension(issuerRequest.PublicKey, false)); 47 | return issuerRequest.CreateSelfSigned(NotBefore, NotAfter); 48 | } 49 | 50 | public bool CheckPfxPassword(string pfxFile, string password) 51 | { 52 | try 53 | { 54 | X509Certificate2 certificate = new(pfxFile, password); 55 | } 56 | catch (Exception e) 57 | { 58 | return false; 59 | } 60 | 61 | return true; 62 | } 63 | 64 | public X509Certificate GetCertificateFromFile(string signedFile) 65 | { 66 | return X509Certificate.CreateFromSignedFile(signedFile); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Codecepticon/Modules/Sign/CommandLine/SignCommandLine.cs: -------------------------------------------------------------------------------- 1 | using Codecepticon.CommandLine; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Codecepticon.Modules.Sign.CommandLine 9 | { 10 | class SignCommandLine : CommandLineManager 11 | { 12 | public SignCommandLine(string[] args) : base(args) 13 | { 14 | Arguments = new Dictionary 15 | { 16 | { "issuer", "" }, 17 | { "subject", "" }, 18 | { "copy-from", "" }, 19 | { "not-before", "" }, 20 | { "not-after", "" }, 21 | { "password", "" }, 22 | { "pfx-file", "" }, 23 | { "overwrite", "switch" }, 24 | { "algorithm", "" }, 25 | { "timestamp", "" } 26 | }; 27 | MergeArguments(); 28 | } 29 | 30 | protected override bool Parse(Dictionary arguments) 31 | { 32 | if (!ParseGlobalArguments(arguments)) 33 | { 34 | return false; 35 | } 36 | 37 | foreach (KeyValuePair argument in arguments) 38 | { 39 | switch (argument.Key.ToLower()) 40 | { 41 | case "subject": 42 | CommandLineData.Sign.NewCertificate.Subject = argument.Value; 43 | break; 44 | case "issuer": 45 | CommandLineData.Sign.NewCertificate.Issuer = argument.Value; 46 | break; 47 | case "copy-from": 48 | CommandLineData.Sign.NewCertificate.CopyFrom = argument.Value; 49 | break; 50 | case "not-after": 51 | try 52 | { 53 | CommandLineData.Sign.NewCertificate.NotAfter = DateTime.ParseExact(argument.Value, "yyyy-MM-dd HH:mm:ss", System.Globalization.CultureInfo.InvariantCulture); 54 | } 55 | catch (Exception e) 56 | { 57 | // Nothing. 58 | } 59 | break; 60 | case "not-before": 61 | try 62 | { 63 | CommandLineData.Sign.NewCertificate.NotBefore = DateTime.ParseExact(argument.Value, "yyyy-MM-dd HH:mm:ss", System.Globalization.CultureInfo.InvariantCulture); 64 | } 65 | catch (Exception e) 66 | { 67 | // Nothing. 68 | } 69 | break; 70 | case "password": 71 | CommandLineData.Sign.NewCertificate.Password = argument.Value; 72 | break; 73 | case "pfx-file": 74 | CommandLineData.Sign.NewCertificate.PfxFile = argument.Value; 75 | break; 76 | case "overwrite": 77 | if (argument.Value.ToLower() != "false") 78 | { 79 | CommandLineData.Sign.NewCertificate.Overwrite = (argument.Value.Length > 0); 80 | } 81 | break; 82 | case "algorithm": 83 | CommandLineData.Sign.SignatureAlgorithm = argument.Value.ToUpper(); 84 | break; 85 | case "timestamp": 86 | CommandLineData.Sign.TimestampServer = argument.Value; 87 | break; 88 | } 89 | } 90 | 91 | ValidateCommandLine validate = new ValidateCommandLine(); 92 | return validate.Run(); 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /Codecepticon/Modules/Sign/MsSign/ISigningTool.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Codecepticon.Modules.Sign.MsSign 8 | { 9 | public interface ISigningTool 10 | { 11 | /// 12 | /// Gets the name of the format the signing tool offers to sign. 13 | /// 14 | string FormatName { get; } 15 | 16 | /// 17 | /// Gets the list of hash algorithms supported by this signing tool. 18 | /// 19 | IReadOnlyList SupportedHashAlgorithms { get; } 20 | 21 | /// 22 | /// Performs the signing of the given file through the request. 23 | /// Might throw any exceptions describing the error during signing. 24 | /// 25 | /// The request describing what to sign. 26 | /// A token to support cancellation. 27 | /// The result of the signing operation. 28 | SignFileResponse SignFile(SignFileRequest signFileRequest); 29 | 30 | /// 31 | /// Checks whether the given file is signed. 32 | /// 33 | /// The path to the file on disk. 34 | /// A token to support cancellation. 35 | /// true if the file is considered signed, otherwise false. 36 | /// 37 | /// Some tools might only do a very basic check and not a full validation on whether 38 | /// all aspects of the signing are in place and valid. 39 | /// 40 | bool IsFileSigned(string inputFileName); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Codecepticon/Modules/Sign/MsSign/SignFileRequest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Security.Cryptography.X509Certificates; 5 | using System.Security.Cryptography; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Codecepticon.Modules.Sign.MsSign 10 | { 11 | public class SignFileRequest 12 | { 13 | /// 14 | /// Gets or sets the absolute path to the file being signed. 15 | /// 16 | public string InputFilePath { get; set; } 17 | 18 | /// 19 | /// Gets or sets the certificate used during the signing operation. 20 | /// Typically embedded into the signed file (without private keys). 21 | /// 22 | public X509Certificate2 Certificate { get; set; } 23 | 24 | /// 25 | /// Gets or sets the private key used for performing the signing operations. 26 | /// This key must match the to avoid corrupt signatures. 27 | /// 28 | public AsymmetricAlgorithm PrivateKey { get; set; } 29 | 30 | /// 31 | /// Gets or sets the original name of the file being signed. 32 | /// might point to a temporarily name while is the name of 33 | /// the file as provided by the client. Might be used to generate auxiliary files. 34 | /// 35 | public string OriginalFileName { get; set; } 36 | 37 | /// 38 | /// Gets or sets the timestamping server which should be used for timestamping the signatures. 39 | /// 40 | public string TimestampServer { get; set; } 41 | 42 | /// 43 | /// Gets or sets the name of the hash algorithm to be used for the signatures. 44 | /// 45 | public string HashAlgorithm { get; set; } 46 | 47 | /// 48 | /// Gets or sets whether any existing signatures should be overwritten. 49 | /// If this is not set, and a file is already signed, the signing operation will fail. 50 | /// 51 | public bool OverwriteSignature { get; set; } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Codecepticon/Modules/Sign/MsSign/SignFileResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Codecepticon.Modules.Sign.MsSign 8 | { 9 | public enum SignFileResponseStatus 10 | { 11 | /// 12 | /// File was successfully signed 13 | /// 14 | FileSigned, 15 | 16 | /// 17 | /// Files was successfully signed, an existing signature was removed 18 | /// 19 | FileResigned, 20 | 21 | /// 22 | /// The file was already signed and therefore signing was skipped. 23 | /// 24 | FileAlreadySigned, 25 | 26 | /// 27 | /// The file was not signed because the given file format cannot be signed or is not supported. 28 | /// 29 | FileNotSignedUnsupportedFormat, 30 | 31 | /// 32 | /// The file was not signed because an unexpected error happened. 33 | /// 34 | FileNotSignedError, 35 | 36 | /// 37 | /// The file was not signed because the singing request was noth authorized. 38 | /// 39 | FileNotSignedUnauthorized 40 | } 41 | 42 | public class SignFileResponse 43 | { 44 | /// 45 | /// The result status of the signing 46 | /// 47 | public SignFileResponseStatus Status { get; set; } 48 | 49 | /// 50 | /// The detailed error message in case is set to 51 | /// 52 | public string ErrorMessage { get; set; } 53 | 54 | /// 55 | /// The result files consisting typically of the signed file. 56 | /// In some scenarios additional files might be provided (e.g. Android v4 idsig) 57 | /// 58 | public IList ResultFiles { get; set; } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Codecepticon/Modules/Sign/MsSign/SignFileResponseFileInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Codecepticon.Modules.Sign.MsSign 8 | { 9 | public class SignFileResponseFileInfo 10 | { 11 | /// 12 | /// The name of the output file as it should be named on the client side. 13 | /// 14 | public string FileName { get; } 15 | 16 | /// 17 | /// The full path to the disk holding the output file which should be sent to the client. 18 | /// 19 | public string OutputFilePath { get; } 20 | 21 | public SignFileResponseFileInfo(string fileName, string outputFilePath) 22 | { 23 | FileName = fileName; 24 | OutputFilePath = outputFilePath; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Codecepticon/Modules/Sign/MsSign/UnmanagedStruct.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.InteropServices; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Codecepticon.Modules.Sign.MsSign 9 | { 10 | internal sealed class UnmanagedStruct : IDisposable 11 | where T : struct 12 | { 13 | public IntPtr Pointer { get; private set; } 14 | 15 | public UnmanagedStruct() 16 | { 17 | Pointer = Marshal.AllocHGlobal(Marshal.SizeOf()); 18 | } 19 | 20 | public void Fill(T value) 21 | { 22 | Marshal.StructureToPtr(value, Pointer, false); 23 | } 24 | 25 | public UnmanagedStruct(T v) : this() 26 | { 27 | Marshal.StructureToPtr(v, Pointer, false); 28 | } 29 | 30 | public void Dispose() 31 | { 32 | if (Pointer != IntPtr.Zero) 33 | { 34 | Marshal.FreeHGlobal(Pointer); 35 | Pointer = IntPtr.Zero; 36 | } 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Codecepticon/Modules/Sign/SignManager.cs: -------------------------------------------------------------------------------- 1 | using Codecepticon.CommandLine; 2 | using Codecepticon.Modules.Sign.MsSign; 3 | using Codecepticon.Utils; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.IO; 7 | using System.Linq; 8 | using System.Security.Cryptography.X509Certificates; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | 12 | namespace Codecepticon.Modules.Sign 13 | { 14 | class SignManager : ModuleManager 15 | { 16 | public async Task Run() 17 | { 18 | switch (CommandLineData.Global.Action) 19 | { 20 | case CommandLineData.Action.GenerateCertificate: 21 | GenerateCertificate(); 22 | break; 23 | case CommandLineData.Action.Sign: 24 | SignExecutable(); 25 | break; 26 | } 27 | } 28 | 29 | protected bool GenerateCertificate() 30 | { 31 | CertificateManager certificateManager = new CertificateManager(); 32 | Logger.Info("Generating certificate..."); 33 | try 34 | { 35 | bool result = certificateManager.GenerateCertificate(CommandLineData.Sign.NewCertificate.Subject, CommandLineData.Sign.NewCertificate.Issuer, CommandLineData.Sign.NewCertificate.NotBefore, CommandLineData.Sign.NewCertificate.NotAfter, CommandLineData.Sign.NewCertificate.Password, CommandLineData.Sign.NewCertificate.PfxFile); 36 | if (!result) 37 | { 38 | Logger.Error("Could not generate self-signed certificate"); 39 | return false; 40 | } 41 | } 42 | catch (Exception e) 43 | { 44 | Logger.Error(e.Message); 45 | return false; 46 | } 47 | Logger.Info("Certificate generated"); 48 | return true; 49 | } 50 | 51 | protected bool SignExecutable() 52 | { 53 | Logger.Info("Loading certificate..."); 54 | 55 | X509Certificate2 certificate; 56 | try 57 | { 58 | certificate = new(CommandLineData.Sign.NewCertificate.PfxFile, CommandLineData.Sign.NewCertificate.Password); 59 | } catch (Exception e) 60 | { 61 | Logger.Error("Could not load PFX file: " + CommandLineData.Sign.NewCertificate.PfxFile); 62 | Logger.Error(e.Message); 63 | return false; 64 | } 65 | 66 | try 67 | { 68 | Logger.Info("Signing executable..."); 69 | SignFileRequest request = new() 70 | { 71 | Certificate = certificate, 72 | PrivateKey = certificate.GetRSAPrivateKey(), 73 | OverwriteSignature = true, 74 | InputFilePath = CommandLineData.Global.Project.Path, 75 | HashAlgorithm = CommandLineData.Sign.SignatureAlgorithm, 76 | TimestampServer = CommandLineData.Sign.TimestampServer, 77 | }; 78 | 79 | PortableExecutableSigningTool signingTool = new(); 80 | SignFileResponse response = signingTool.SignFile(request); 81 | if (response.Status != SignFileResponseStatus.FileSigned && response.Status != SignFileResponseStatus.FileResigned) 82 | { 83 | return false; 84 | } 85 | } catch (Exception e) 86 | { 87 | Logger.Error("Could not sign executable"); 88 | Logger.Error(e.Message); 89 | return false; 90 | } 91 | 92 | 93 | Logger.Success("Executable signed"); 94 | return true; 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /Codecepticon/Modules/Sign/SignToolManager.cs: -------------------------------------------------------------------------------- 1 | using Codecepticon.Utils; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Diagnostics; 5 | using System.Linq; 6 | using System.Runtime.InteropServices; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Codecepticon.Modules.Sign 11 | { 12 | class SignToolManager 13 | { 14 | [DllImport("shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)] 15 | static extern int SHGetSpecialFolderPath(IntPtr hwndOwner, IntPtr lpszPath, int nFolder, int fCreate); 16 | 17 | private const int CSIDL_PROGRAM_FILES = 0x0026; 18 | private const int CSIDL_PROGRAM_FILESX86 = 0x002a; 19 | 20 | public string Find() 21 | { 22 | List systemPaths = new List 23 | { 24 | GetSpecialFolder(CSIDL_PROGRAM_FILES).ToLower(), 25 | GetSpecialFolder(CSIDL_PROGRAM_FILESX86).ToLower() 26 | }.Distinct().ToList(); // If Codecepticon is compiled as x86 it will get the same folder twice. 27 | 28 | List foundFiles = SearchInFolders(systemPaths); 29 | if (foundFiles.Count == 0) 30 | { 31 | return ""; 32 | } 33 | else if (foundFiles.Count == 1) 34 | { 35 | return foundFiles.First(); 36 | } 37 | 38 | string path = ""; 39 | 40 | Logger.Info(""); 41 | Logger.Info("Multiple instances of signtool.exe were found, please select which one you would like to use:"); 42 | Logger.Info(""); 43 | for (int i = 0; i < foundFiles.Count; i++) 44 | { 45 | Logger.Info("\t[" + (i + 1) + "] " + foundFiles[i]); 46 | } 47 | Logger.Info(""); 48 | 49 | while (true) 50 | { 51 | Logger.Info("Please enter the number of your selection: ", false); 52 | var userResponse = Console.ReadLine(); 53 | if (int.TryParse(userResponse, out int fileNumber) && fileNumber > 0 && fileNumber <= foundFiles.Count()) 54 | { 55 | path = foundFiles[fileNumber - 1]; 56 | break; 57 | } 58 | } 59 | 60 | return path; 61 | } 62 | 63 | private string GetSpecialFolder(int folder) 64 | { 65 | IntPtr path = Marshal.AllocHGlobal(260 * 2); // Unicode. 66 | SHGetSpecialFolderPath(IntPtr.Zero, path, folder, 0); 67 | string result = Marshal.PtrToStringUni(path); 68 | Marshal.FreeHGlobal(path); 69 | return result; 70 | } 71 | 72 | private List SearchInFolders(List paths) 73 | { 74 | List files = new List(); 75 | foreach (string path in paths) 76 | { 77 | string commandOutput = RunSearch(path); 78 | 79 | string[] lines = commandOutput.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); 80 | 81 | foreach (string line in lines) 82 | { 83 | if (!line.ToLower().StartsWith(path)) 84 | { 85 | continue; 86 | } 87 | else if (files.Contains(line)) 88 | { 89 | continue; 90 | } 91 | files.Add(line); 92 | } 93 | } 94 | return files; 95 | } 96 | 97 | private string RunSearch(string path) 98 | { 99 | Logger.Info("Running: cd \"" + path + "\" && dir /s /b signtool.exe"); 100 | Process process = new Process(); 101 | process.StartInfo.FileName = "cmd.exe"; 102 | process.StartInfo.Arguments = "/c cd \"" + path + "\" && dir /s /b signtool.exe"; 103 | process.StartInfo.RedirectStandardOutput = true; 104 | process.StartInfo.UseShellExecute = false; 105 | process.StartInfo.CreateNoWindow = true; 106 | process.Start(); 107 | return process.StandardOutput.ReadToEnd(); 108 | } 109 | 110 | public bool SignExecutable(string signToolPath, string executable, string pfxFile, string password, ref string stdOutput, ref string stdError) 111 | { 112 | // signtool.exe sign /f C:\data\tmp\self-signed.pfx /p Hello /fd SHA256 /tr http://localhost:8888/ C:\data\tmp\SignCerts\SignCerts\bin\Debug\net6.0\SignCerts2.exe 113 | string commandLineArguments = $"sign /f \"{pfxFile}\" /p \"{password}\" /fd SHA256 \"{executable}\""; 114 | Logger.Info($"Running: {signToolPath} {commandLineArguments}"); 115 | 116 | Process process = new Process(); 117 | process.StartInfo.FileName = signToolPath; 118 | process.StartInfo.Arguments = commandLineArguments; 119 | process.StartInfo.RedirectStandardOutput = true; 120 | process.StartInfo.RedirectStandardError= true; 121 | process.StartInfo.UseShellExecute = false; 122 | process.StartInfo.CreateNoWindow = true; 123 | process.Start(); 124 | 125 | stdOutput = process.StandardOutput.ReadToEnd().Trim(); 126 | stdError = process.StandardError.ReadToEnd().Trim(); 127 | 128 | return stdError.Length == 0; 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /Codecepticon/Modules/VB6/Collectors/CollectorVisitor.cs: -------------------------------------------------------------------------------- 1 | using Antlr4.Runtime.Misc; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Codecepticon.Modules.VB6.Collectors 9 | { 10 | class CollectorVisitor : VisualBasic6BaseListener 11 | { 12 | public static SyntaxTreeHelper Helper = new SyntaxTreeHelper(); 13 | 14 | public override void EnterType(VisualBasic6Parser.TypeContext context) 15 | { 16 | // As String, Worksheet, etc - including non-VB types like Worksheet etc. 17 | string customVariableType = Helper.GetCustomVariableType(context); 18 | if (customVariableType.Length > 0 && (DataCollector.AllTypes.Contains(customVariableType) || DataCollector.AllEnums.Contains(customVariableType))) 19 | { 20 | DataCollector.AllIdentifiers.Add(customVariableType); 21 | } 22 | base.EnterType(context); 23 | } 24 | 25 | public override void EnterTypeStmt(VisualBasic6Parser.TypeStmtContext context) 26 | { 27 | DataCollector.AllIdentifiers.Add(Helper.GetStatementIdentifier(context)); 28 | base.EnterTypeStmt(context); 29 | } 30 | 31 | public override void EnterEnumerationStmt(VisualBasic6Parser.EnumerationStmtContext context) 32 | { 33 | DataCollector.AllIdentifiers.Add(Helper.GetStatementIdentifier(context)); 34 | base.EnterEnumerationStmt(context); 35 | } 36 | 37 | public override void EnterEnumerationStmt_Constant(VisualBasic6Parser.EnumerationStmt_ConstantContext context) 38 | { 39 | DataCollector.AllIdentifiers.Add(Helper.GetStatementIdentifier(context)); 40 | base.EnterEnumerationStmt_Constant(context); 41 | } 42 | 43 | public override void EnterTypeStmt_Element(VisualBasic6Parser.TypeStmt_ElementContext context) 44 | { 45 | DataCollector.AllIdentifiers.Add(Helper.GetStatementIdentifier(context)); 46 | base.EnterTypeStmt_Element(context); 47 | } 48 | 49 | public override void EnterVariableSubStmt(VisualBasic6Parser.VariableSubStmtContext context) 50 | { 51 | DataCollector.AllIdentifiers.Add(Helper.GetStatementIdentifier(context)); 52 | base.EnterVariableSubStmt(context); 53 | } 54 | 55 | public override void EnterConstSubStmt(VisualBasic6Parser.ConstSubStmtContext context) 56 | { 57 | DataCollector.AllIdentifiers.Add(Helper.GetStatementIdentifier(context)); 58 | base.EnterConstSubStmt(context); 59 | } 60 | 61 | public override void EnterFunctionStmt(VisualBasic6Parser.FunctionStmtContext context) 62 | { 63 | if (!Helper.IsReserved(Helper.GetStatementIdentifier(context))) 64 | { 65 | DataCollector.AllIdentifiers.Add(Helper.GetStatementIdentifier(context)); 66 | } 67 | base.EnterFunctionStmt(context); 68 | } 69 | 70 | public override void EnterSubStmt(VisualBasic6Parser.SubStmtContext context) 71 | { 72 | if (!Helper.IsReserved(Helper.GetStatementIdentifier(context))) 73 | { 74 | DataCollector.AllIdentifiers.Add(Helper.GetStatementIdentifier(context)); 75 | } 76 | base.EnterSubStmt(context); 77 | } 78 | 79 | public override void EnterDeclareStmt([NotNull] VisualBasic6Parser.DeclareStmtContext context) 80 | { 81 | DataCollector.AllIdentifiers.Add(Helper.GetStatementIdentifier(context)); 82 | base.EnterDeclareStmt(context); 83 | } 84 | 85 | public override void EnterArg([NotNull] VisualBasic6Parser.ArgContext context) 86 | { 87 | DataCollector.AllIdentifiers.Add(Helper.GetStatementIdentifier(context)); 88 | base.EnterArg(context); 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /Codecepticon/Modules/VB6/Collectors/TypeCollectorVisitor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Codecepticon.Modules.VB6.Collectors 8 | { 9 | class TypeCollectorVisitor : VisualBasic6BaseListener 10 | { 11 | public static SyntaxTreeHelper Helper = new SyntaxTreeHelper(); 12 | 13 | public override void EnterTypeStmt(VisualBasic6Parser.TypeStmtContext context) 14 | { 15 | DataCollector.AllTypes.Add(Helper.GetStatementIdentifier(context)); 16 | base.EnterTypeStmt(context); 17 | } 18 | 19 | public override void EnterEnumerationStmt(VisualBasic6Parser.EnumerationStmtContext context) 20 | { 21 | DataCollector.AllEnums.Add(Helper.GetStatementIdentifier(context)); 22 | base.EnterEnumerationStmt(context); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Codecepticon/Modules/VB6/CommandLine/ValidateCommandLine.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using Codecepticon.CommandLine; 8 | using Codecepticon.Utils; 9 | 10 | namespace Codecepticon.Modules.VB6.CommandLine 11 | { 12 | class ValidateCommandLine : CommandLineValidator 13 | { 14 | public bool Run() 15 | { 16 | if (!ValidateAction()) 17 | { 18 | return false; 19 | } 20 | 21 | return true; 22 | } 23 | 24 | protected bool ValidateAction() 25 | { 26 | switch (CommandLineData.Global.Action) 27 | { 28 | case CommandLineData.Action.None: 29 | Logger.Error("'action' parameter not set"); 30 | return false; 31 | case CommandLineData.Action.Obfuscate: 32 | return ValidateActionObfuscate(); 33 | case CommandLineData.Action.Unmap: 34 | return ValidateActionUnmap(); 35 | } 36 | 37 | return false; 38 | } 39 | 40 | protected bool ValidateActionObfuscate() 41 | { 42 | // Check if the solution exists. 43 | if (String.IsNullOrEmpty(CommandLineData.Global.Project.Path) || !File.Exists(CommandLineData.Global.Project.Path)) 44 | { 45 | Logger.Error($"Input path is empty or does not exist: {CommandLineData.Global.Project.Path}"); 46 | return false; 47 | } 48 | 49 | if (String.IsNullOrEmpty(CommandLineData.Global.Project.SaveAs)) 50 | { 51 | // Default behaviour is to replace the actual file. 52 | CommandLineData.Global.Project.SaveAs = CommandLineData.Global.Project.Path + ".obfuscated.vba"; 53 | } 54 | 55 | if (CommandLineData.Vb6.Rename.Enabled && !ValidateRename()) 56 | { 57 | return false; 58 | } 59 | 60 | if (!ValidateRewrite(ModuleTypes.CodecepticonModules.Vb6)) 61 | { 62 | return false; 63 | } 64 | 65 | if (!ValidateMappingFiles()) 66 | { 67 | return false; 68 | } 69 | 70 | return true; 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Codecepticon/Modules/VB6/CommandLine/Vb6CommandLine.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using Codecepticon.CommandLine; 6 | using Codecepticon.Utils; 7 | 8 | namespace Codecepticon.Modules.VB6.CommandLine 9 | { 10 | class Vb6CommandLine : CommandLineManager 11 | { 12 | public Vb6CommandLine(string[] args) : base(args) 13 | { 14 | Arguments = new Dictionary(); 15 | MergeArguments(); 16 | } 17 | 18 | protected override void SetRenameValue(bool value) 19 | { 20 | CommandLineData.Vb6.Rename.Identifiers = value; 21 | } 22 | 23 | protected override bool Parse(Dictionary arguments) 24 | { 25 | if (!ParseGlobalArguments(arguments)) 26 | { 27 | return false; 28 | } 29 | 30 | foreach (KeyValuePair argument in arguments) 31 | { 32 | switch (argument.Key.ToLower()) 33 | { 34 | case "rename": 35 | CommandLineData.Vb6.Rename.Enabled = (argument.Value.Length > 0); 36 | ParseRenameOptions(argument.Value.ToLower()); 37 | break; 38 | //default: 39 | // Logger.Error($"Code error: Not supported parameter - {argument.Key}"); 40 | // return false; 41 | } 42 | } 43 | 44 | ValidateCommandLine validate = new ValidateCommandLine(); 45 | return validate.Run(); 46 | } 47 | 48 | protected void ParseRenameOptions(string value) 49 | { 50 | if (value == "all") 51 | { 52 | SetRenameValue(true); 53 | } 54 | else 55 | { 56 | SetRenameValue(false); 57 | foreach (char c in value.ToLower().ToArray()) 58 | { 59 | switch (c.ToString()) 60 | { 61 | case "i": 62 | CommandLineData.Vb6.Rename.Identifiers = true; 63 | break; 64 | } 65 | } 66 | } 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Codecepticon/Modules/VB6/DataCollector.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Antlr4.Runtime.Tree; 7 | using Codecepticon.Modules.VB6.Collectors; 8 | 9 | namespace Codecepticon.Modules.VB6 10 | { 11 | class DataCollector 12 | { 13 | public static List AllIdentifiers = new List(); 14 | public static List AllTypes = new List(); 15 | public static List AllEnums = new List(); 16 | 17 | public struct MappingStruct 18 | { 19 | public Dictionary Identifiers; 20 | } 21 | 22 | public static MappingStruct Mapping = new MappingStruct 23 | { 24 | Identifiers = new Dictionary() 25 | }; 26 | 27 | public void CollectData(IParseTree tree) 28 | { 29 | TypeCollectorVisitor typeVisitor = new TypeCollectorVisitor(); 30 | CollectorVisitor visitor = new CollectorVisitor(); 31 | 32 | // First we need to collect custom types and enums. This way if something is defined as "Worksheet", it won't be replaced. 33 | ParseTreeWalker.Default.Walk(typeVisitor, tree); 34 | ParseTreeWalker.Default.Walk(visitor, tree); 35 | 36 | AllIdentifiers = AllIdentifiers.Distinct().ToList(); 37 | // We need to remove any keywords that exist in the list but don't exist in types. 38 | AllIdentifiers.Sort(); 39 | } 40 | 41 | public static bool IsMappingUnique(string name) 42 | { 43 | // VB6 is NOT case-sensitive, so everything has to be unique. 44 | string item = Mapping.Identifiers.FirstOrDefault(s => s.Value.ToLower() == name.ToLower()).Key; 45 | return item == null; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Codecepticon/Modules/VB6/DataRenamer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Text.RegularExpressions; 7 | using System.Threading.Tasks; 8 | using Antlr4.Runtime; 9 | using Antlr4.Runtime.Tree; 10 | using Codecepticon.Modules.VB6.Renamers; 11 | using Codecepticon.CommandLine; 12 | using Codecepticon.Utils; 13 | 14 | namespace Codecepticon.Modules.VB6 15 | { 16 | class DataRenamer 17 | { 18 | protected NameGenerator NameGenerator = new NameGenerator(NameGenerator.RandomNameGeneratorMethods.RandomCombinations, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 32); 19 | 20 | public async Task RenameIdentifiers(Vb6Manager.ParsedFileStruct parsedFile) 21 | { 22 | Identifiers renameIdentifiers = new Identifiers(parsedFile.Stream); 23 | ParseTreeWalker.Default.Walk(renameIdentifiers, parsedFile.Tree); 24 | 25 | return new Vb6Manager.ParsedFileStruct(renameIdentifiers.GetText()); 26 | } 27 | 28 | public async Task RewriteStrings(Vb6Manager.ParsedFileStruct parsedFile) 29 | { 30 | Strings rewriteStrings = new Strings(parsedFile.Stream); 31 | ParseTreeWalker.Default.Walk(rewriteStrings, parsedFile.Tree); 32 | 33 | return new Vb6Manager.ParsedFileStruct(rewriteStrings.GetText()); 34 | } 35 | 36 | public async Task RewriteDeclarations(Vb6Manager.ParsedFileStruct parsedFile) 37 | { 38 | Declarations rewriteDeclarations = new Declarations(parsedFile.Stream); 39 | ParseTreeWalker.Default.Walk(rewriteDeclarations, parsedFile.Tree); 40 | 41 | return new Vb6Manager.ParsedFileStruct(rewriteDeclarations.GetText()); 42 | } 43 | 44 | public string AddStringHelperFunction() 45 | { 46 | string code = File.ReadAllText(CommandLineData.Global.Rewrite.Template.File); 47 | string mapping; 48 | 49 | // Find all variables that look like %_NAME_% 50 | Regex regex = new Regex(@"(%_[A-Za-z0-9_]+_%)"); 51 | var matches = regex.Matches(code).Cast().Select(m => m.Value).ToArray().Distinct(); 52 | 53 | // And now replace them all. We only need to keep track of the Namespace, Class, and Function names. 54 | foreach (var match in matches) 55 | { 56 | string name = NameGenerator.Generate(); 57 | switch (match.ToLower()) 58 | { 59 | case "%_function_%": 60 | Logger.Debug($"StringHelperClass - Replace %_function_% with {name}"); 61 | CommandLineData.Global.Rewrite.Template.Function = name; 62 | break; 63 | case "%_mapping_var_%": 64 | Logger.Debug($"StringHelperClass - Replace %_mapping_var_% with {name}"); 65 | CommandLineData.Global.Rewrite.Template.Mapping = name; 66 | break; 67 | } 68 | 69 | code = code.Replace(match, name); 70 | } 71 | 72 | switch (CommandLineData.Global.Rewrite.EncodingMethod) 73 | { 74 | case StringEncoding.StringEncodingMethods.SingleCharacterSubstitution: 75 | mapping = StringEncoding.ExportSingleCharacterMap(CommandLineData.Global.Rewrite.SingleMapping, ModuleTypes.CodecepticonModules.Vb6); 76 | code = code.Replace("%MAPPING%", mapping); 77 | break; 78 | case StringEncoding.StringEncodingMethods.GroupCharacterSubstitution: 79 | mapping = StringEncoding.ExportGroupCharacterMap(CommandLineData.Global.Rewrite.GroupMapping, ModuleTypes.CodecepticonModules.Vb6); 80 | code = code.Replace("%MAPPING%", mapping); 81 | break; 82 | case StringEncoding.StringEncodingMethods.ExternalFile: 83 | code = code.Replace("%MAPPING%", Path.GetFileName(CommandLineData.Global.Rewrite.ExternalFile)); 84 | break; 85 | } 86 | 87 | return code; 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /Codecepticon/Modules/VB6/OfficeReservedWords.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Codecepticon.Modules.VB6 8 | { 9 | class OfficeReservedWords 10 | { 11 | public static List FileMacroFunctions = new List 12 | { 13 | /* Word */ 14 | "autoopen", 15 | "autonew", 16 | "autoclose", 17 | "autoexec", 18 | "autoexit", 19 | /* Excel */ 20 | "auto_open", 21 | "auto_close", 22 | "auto_activate", 23 | "auto_deactivate" 24 | }; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Codecepticon/Modules/VB6/Renamers/Declarations.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Antlr4.Runtime; 7 | using Antlr4.Runtime.Misc; 8 | 9 | namespace Codecepticon.Modules.VB6.Renamers 10 | { 11 | class Declarations : VisualBasic6BaseListener 12 | { 13 | public static SyntaxTreeHelper Helper = new SyntaxTreeHelper(); 14 | 15 | private TokenStreamRewriter Rewriter { get; } 16 | 17 | public Declarations(CommonTokenStream stream) 18 | { 19 | Rewriter = new TokenStreamRewriter(stream); 20 | } 21 | 22 | public string GetText() 23 | { 24 | return Rewriter.GetText(); 25 | } 26 | 27 | public override void EnterDeclareStmt([NotNull] VisualBasic6Parser.DeclareStmtContext context) 28 | { 29 | if (!Helper.DeclarationHasAlias(context)) 30 | { 31 | string newDeclaration = Helper.DeclarationAddAlias(context); 32 | Rewriter.Replace(context.Start, context.Stop, newDeclaration); 33 | } 34 | base.EnterDeclareStmt(context); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Codecepticon/Modules/VB6/Renamers/Identifiers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Antlr4.Runtime; 7 | using Antlr4.Runtime.Misc; 8 | 9 | namespace Codecepticon.Modules.VB6.Renamers 10 | { 11 | class Identifiers : VisualBasic6BaseListener 12 | { 13 | private TokenStreamRewriter Rewriter { get; } 14 | 15 | public Identifiers(CommonTokenStream stream) 16 | { 17 | Rewriter = new TokenStreamRewriter(stream); 18 | } 19 | 20 | public string GetText() 21 | { 22 | return Rewriter.GetText(); 23 | } 24 | 25 | public override void EnterAmbiguousIdentifier(VisualBasic6Parser.AmbiguousIdentifierContext context) 26 | { 27 | string text = context.GetText(); 28 | if (DataCollector.Mapping.Identifiers.ContainsKey(text)) 29 | { 30 | Rewriter.Replace(context.Start, context.Stop, DataCollector.Mapping.Identifiers[text]); 31 | } 32 | base.EnterAmbiguousIdentifier(context); 33 | } 34 | 35 | public override void EnterCertainIdentifier([NotNull] VisualBasic6Parser.CertainIdentifierContext context) 36 | { 37 | string text = context.GetText(); 38 | if (DataCollector.Mapping.Identifiers.ContainsKey(text)) 39 | { 40 | Rewriter.Replace(context.Start, context.Stop, DataCollector.Mapping.Identifiers[text]); 41 | } 42 | base.EnterCertainIdentifier(context); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Codecepticon/Modules/VB6/Renamers/Strings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Antlr4.Runtime; 7 | using Antlr4.Runtime.Misc; 8 | using Codecepticon.CommandLine; 9 | using Codecepticon.Utils; 10 | 11 | namespace Codecepticon.Modules.VB6.Renamers 12 | { 13 | class Strings : VisualBasic6BaseListener 14 | { 15 | public static SyntaxTreeHelper Helper = new SyntaxTreeHelper(); 16 | private TokenStreamRewriter Rewriter { get; } 17 | 18 | protected NameGenerator NameGenerator = new NameGenerator(NameGenerator.RandomNameGeneratorMethods.RandomCombinations, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 32); 19 | 20 | public Strings(CommonTokenStream stream) 21 | { 22 | Rewriter = new TokenStreamRewriter(stream); 23 | } 24 | 25 | public string GetText() 26 | { 27 | return Rewriter.GetText(); 28 | } 29 | 30 | public override void EnterLiteral([NotNull] VisualBasic6Parser.LiteralContext context) 31 | { 32 | string text = context.GetText(); 33 | if (text.Length > 2 && text.Substring(0, 1) == "\"") 34 | { 35 | // If length == 2 it could be an empty string, ie "". Also check if it's a constant. 36 | if (!Helper.IsStringConstant(context)) 37 | { 38 | Rewriter.Replace(context.Start, context.Stop, RewriteString(text.Trim('"'))); 39 | } 40 | } 41 | base.EnterLiteral(context); 42 | } 43 | 44 | protected string RewriteString(string text) 45 | { 46 | string code = ""; 47 | switch (CommandLineData.Global.Rewrite.EncodingMethod) 48 | { 49 | case StringEncoding.StringEncodingMethods.Base64: 50 | text = Convert.ToBase64String(Encoding.UTF8.GetBytes(text)); 51 | code = CommandLineData.Global.Rewrite.Template.Function + "(\""+ text +"\")"; 52 | break; 53 | case StringEncoding.StringEncodingMethods.XorEncrypt: 54 | string key = NameGenerator.Generate(); 55 | text = StringEncoding.Xor(text, key, false, false); 56 | code = CommandLineData.Global.Rewrite.Template.Function + "(\"" + text + "\", \"" + key + "\")"; 57 | break; 58 | case StringEncoding.StringEncodingMethods.SingleCharacterSubstitution: 59 | text = StringEncoding.SingleCharacter(text, CommandLineData.Global.Rewrite.SingleMapping); 60 | code = CommandLineData.Global.Rewrite.Template.Function + "(\"" + text + "\")"; 61 | break; 62 | case StringEncoding.StringEncodingMethods.GroupCharacterSubstitution: 63 | text = StringEncoding.GroupCharacter(text, CommandLineData.Global.Rewrite.GroupMapping); 64 | code = CommandLineData.Global.Rewrite.Template.Function + "(\"" + text + "\")"; 65 | break; 66 | case StringEncoding.StringEncodingMethods.ExternalFile: 67 | int index = StringEncoding.GetExternalFileIndex(text); 68 | code = CommandLineData.Global.Rewrite.Template.Function + "(" + index + ")"; 69 | break; 70 | } 71 | 72 | return code; 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /Codecepticon/Modules/VB6/SyntaxTreeHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Data.SqlClient; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using Antlr4.Runtime; 8 | using Antlr4.Runtime.Tree; 9 | using Codecepticon.Utils; 10 | 11 | namespace Codecepticon.Modules.VB6 12 | { 13 | class SyntaxTreeHelper 14 | { 15 | public string GetStatementIdentifier(ParserRuleContext context) 16 | { 17 | string name = ""; 18 | foreach (var child in context.children) 19 | { 20 | if ((int)GetObjectPropertyValue(child, "RuleIndex", 0) == VisualBasic6Parser.RULE_ambiguousIdentifier) 21 | { 22 | name = child.GetText(); 23 | break; 24 | } 25 | } 26 | return name; 27 | } 28 | 29 | public string GetCustomVariableType(VisualBasic6Parser.TypeContext context) 30 | { 31 | return Vb6Constants.DataTypes.Contains(context.GetText().ToLower()) ? "" : context.GetText(); 32 | } 33 | 34 | public bool IsReserved(string name) 35 | { 36 | name = name.ToLower(); 37 | if (name.StartsWith("document_")) 38 | { 39 | Logger.Debug($"Skipping rename of {name}"); 40 | // Functions like Document_Open, Document_XMLAfterInsert, etc. 41 | return true; 42 | } else if (name.StartsWith("worksheet_")) 43 | { 44 | Logger.Debug($"Skipping rename of {name}"); 45 | // Functions like Workbook_Activate, Workbook_BeforeSave, etc. 46 | return true; 47 | } 48 | return OfficeReservedWords.FileMacroFunctions.Contains(name.ToLower()); 49 | } 50 | 51 | public bool ObjectHasProperty(IParseTree context, string propertyName) 52 | { 53 | return context.GetType().GetProperty(propertyName) != null; 54 | } 55 | 56 | public object GetObjectPropertyValue(IParseTree context, string propertyName, object defaultValue) 57 | { 58 | return ObjectHasProperty(context, propertyName) ? context.GetType().GetProperty(propertyName).GetValue(context, null) : defaultValue; 59 | } 60 | 61 | public bool DeclarationHasAlias(ParserRuleContext context) 62 | { 63 | bool hasAlias = false; 64 | foreach (var child in context.children) 65 | { 66 | if (child.GetText().ToLower() == "alias") 67 | { 68 | hasAlias = true; 69 | break; 70 | } 71 | } 72 | 73 | return hasAlias; 74 | } 75 | 76 | public bool ChildObjectHasProperty(IParseTree context, string propertyName) 77 | { 78 | return context.Payload.GetType().GetProperty(propertyName) != null; 79 | } 80 | 81 | public object GetChildObjectPropertyValue(IParseTree context, string propertyName, object defaultValue) 82 | { 83 | return ChildObjectHasProperty(context, propertyName) ? context.Payload.GetType().GetProperty(propertyName).GetValue(context.Payload, null) : defaultValue; 84 | } 85 | 86 | public int GetChildType(IParseTree context) 87 | { 88 | var type = GetChildObjectPropertyValue(context, "Type", 0); 89 | if (type == null) 90 | { 91 | return 0; 92 | } 93 | return Int32.Parse(type.ToString()); 94 | } 95 | 96 | public bool IsDeclarationLibName(IList children, int index) 97 | { 98 | bool isLibName = false; 99 | for (int i = 0; i < index; i++) 100 | { 101 | if (GetChildType(children[i]) == VisualBasic6Parser.LIB) 102 | { 103 | isLibName = true; 104 | break; 105 | } 106 | } 107 | return isLibName; 108 | } 109 | 110 | public string DeclarationAddAlias(ParserRuleContext context) 111 | { 112 | string newDeclaration = ""; 113 | for (int i = 0; i < context.ChildCount; i++) 114 | { 115 | var child = context.children[i]; 116 | if (GetChildType(child) == VisualBasic6Parser.STRINGLITERAL) 117 | { 118 | if (IsDeclarationLibName(context.children, i)) 119 | { 120 | newDeclaration += child.GetText() + " Alias \""+ GetStatementIdentifier(context) +"\""; 121 | continue; 122 | } 123 | } 124 | newDeclaration += child.GetText(); 125 | } 126 | return newDeclaration; 127 | } 128 | 129 | public bool IsStringConstant(ParserRuleContext context) 130 | { 131 | // Go up to 5 parents to see if we hit a const statement. 132 | RuleContext original = context; 133 | bool result = false; 134 | for (int i = 0; i < 5; i++) 135 | { 136 | original = original.Parent != null ? original.Parent : null; 137 | if (original != null && (int)GetObjectPropertyValue(original, "RuleIndex", 0) == VisualBasic6Parser.RULE_constStmt) 138 | { 139 | result = true; 140 | break; 141 | } 142 | } 143 | return result; 144 | } 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /Codecepticon/Modules/VB6/Unmapping.cs: -------------------------------------------------------------------------------- 1 | using Codecepticon.CommandLine; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Codecepticon.Modules.VB6 9 | { 10 | class Unmapping : DataUnmapping 11 | { 12 | public static void GenerateMapFile(string saveAs) 13 | { 14 | Dictionary data = new Dictionary 15 | { 16 | ["namespaces"] = "", 17 | ["classes"] = "", 18 | ["functions"] = "", 19 | ["enums"] = "", 20 | ["properties"] = "", 21 | ["variables"] = "", 22 | ["parameters"] = "", 23 | ["cmdline"] = "", 24 | }; 25 | 26 | if (CommandLineData.Vb6.Rename.Identifiers) 27 | { 28 | data["functions"] = ConcatData(DataCollector.Mapping.Identifiers); 29 | } 30 | 31 | WriteTemplateFile(saveAs, data); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Codecepticon/Program.cs: -------------------------------------------------------------------------------- 1 | using Codecepticon.CommandLine; 2 | using Codecepticon.Modules.CSharp; 3 | using Codecepticon.Utils; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.IO; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using Codecepticon.Modules.PowerShell; 11 | using Codecepticon.Modules.VB6; 12 | using static Codecepticon.Modules.ModuleTypes; 13 | using Newtonsoft.Json; 14 | using Codecepticon.Modules.Sign; 15 | 16 | namespace Codecepticon 17 | { 18 | class Program 19 | { 20 | static async Task Main(string[] args) 21 | { 22 | if (args.Length == 0) 23 | { 24 | Logger.Info("Run --help for more, or use the Command Line Generator HTML file to generate a command", true, false); 25 | return; 26 | } 27 | 28 | CommandLineManager cmdManager = new CommandLineManager(args); 29 | if (cmdManager.IsHelp()) 30 | { 31 | Logger.Info(cmdManager.LoadHelp(CodecepticonModules.None), true, false); 32 | return; 33 | } 34 | 35 | CodecepticonModules module = cmdManager.GetModule(); 36 | if (module == CodecepticonModules.None || module == CodecepticonModules.Unknown) 37 | { 38 | Logger.Error("No module is defined or module is invalid.", true, false); 39 | return; 40 | } 41 | 42 | Logger.Info($"Codecepticon v{CommandLineData.Global.Version} is starting..."); 43 | if (!cmdManager.LoadCommandLineArguments(module)) 44 | { 45 | if (CommandLineData.Global.IsHelp) 46 | { 47 | Logger.Info(cmdManager.LoadHelp(module), true, false); 48 | return; 49 | } 50 | Logger.Error("Could not parse command line."); 51 | return; 52 | } 53 | 54 | Logger.Debug("Global Command Line Data"); 55 | Logger.Debug(JsonConvert.SerializeObject(CommandLineData.Global)); 56 | 57 | Logger.Debug("C# Command Line Data"); 58 | Logger.Debug(JsonConvert.SerializeObject(CommandLineData.CSharp)); 59 | 60 | Logger.Debug("VB6 Command Line Data"); 61 | Logger.Debug(JsonConvert.SerializeObject(CommandLineData.Vb6)); 62 | 63 | Logger.Debug("PowerShell Command Line Data"); 64 | Logger.Debug(JsonConvert.SerializeObject(CommandLineData.PowerShell)); 65 | 66 | switch (module) 67 | { 68 | case CodecepticonModules.CSharp: 69 | CSharpManager CSharpManager = new CSharpManager(); 70 | await CSharpManager.Run(); 71 | break; 72 | case CodecepticonModules.Powershell: 73 | PowerShellManager PowerShellManager = new PowerShellManager(); 74 | await PowerShellManager.Run(); 75 | break; 76 | case CodecepticonModules.Vb6: 77 | Vb6Manager vb6Manager = new Vb6Manager(); 78 | await vb6Manager.Run(); 79 | break; 80 | case CodecepticonModules.Sign: 81 | SignManager signManager = new SignManager(); 82 | await signManager.Run(); 83 | break; 84 | default: 85 | Logger.Error("Code error: Module manager not implemented."); 86 | return; 87 | } 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /Codecepticon/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace Codecepticon.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.3.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Codecepticon/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Codecepticon/Templates/Base64.vb6: -------------------------------------------------------------------------------- 1 | Function %_FUNCTION_%(b64) 2 | Dim b 3 | With CreateObject("Microsoft.XMLDOM").createElement("b64") 4 | .DataType = "bin.base64": .text = b64 5 | b = .nodeTypedValue 6 | With CreateObject("ADODB.Stream") 7 | .Open: .Type = 1: .Write b: .Position = 0: .Type = 2: .Charset = "utf-8" 8 | %_FUNCTION_% = .ReadText 9 | .Close 10 | End With 11 | End With 12 | End Function 13 | -------------------------------------------------------------------------------- /Codecepticon/Templates/ExternalFile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | 7 | namespace %_NAMESPACE_% 8 | { 9 | class %_CLASS_% 10 | { 11 | public static List StringMapping = new List(); 12 | 13 | public static string %_FUNCTION_%(int index) 14 | { 15 | if (StringMapping.Count == 0) { 16 | StringMapping = File.ReadAllLines("%MAPPING%").ToList().Select(v => Encoding.UTF8.GetString(Convert.FromBase64String(v))).ToList(); 17 | } 18 | 19 | return StringMapping[index]; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Codecepticon/Templates/ExternalFile.vb6: -------------------------------------------------------------------------------- 1 | Function %_FUNCTION_%(ByVal %_INDEX_% As Long) As String 2 | Dim %_VAR_BDATA_%() As Byte 3 | Dim %_VAR_DATA_%() As String 4 | Dim %_VAR_B64_% 5 | 6 | Open "%MAPPING%" For Binary As #1 7 | ReDim %_VAR_BDATA_%(LOF(1) - 1) As Byte 8 | Get #1, , %_VAR_BDATA_%() 9 | Close #1 10 | 11 | %_VAR_DATA_%() = Split(StrConv(%_VAR_BDATA_%(), vbUnicode), vbCrLf) 12 | 13 | With CreateObject("Microsoft.XMLDOM").createElement("b64") 14 | .DataType = "bin.base64": .text = %_VAR_DATA_%(%_INDEX_%) 15 | %_VAR_B64_% = .nodeTypedValue 16 | With CreateObject("ADODB.Stream") 17 | .Open: .Type = 1: .Write %_VAR_B64_%: .Position = 0: .Type = 2: .Charset = "utf-8" 18 | %_FUNCTION_% = .ReadText 19 | .Close 20 | End With 21 | End With 22 | End Function 23 | -------------------------------------------------------------------------------- /Codecepticon/Templates/Group.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace %_NAMESPACE_% 5 | { 6 | class %_CLASS_% 7 | { 8 | public static Dictionary mapping = new Dictionary() { 9 | %MAPPING% 10 | }; 11 | 12 | public static string %_FUNCTION_%(string text) 13 | { 14 | string output = ""; 15 | int mapLength = mapping.First().Key.Length; 16 | for (int i = 0; i < text.Length; i += mapLength) 17 | { 18 | output += (char)mapping[text.Substring(i, mapLength)]; 19 | } 20 | return output; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Codecepticon/Templates/Group.ps1: -------------------------------------------------------------------------------- 1 | function %_FUNCTION_% { 2 | param( 3 | [string] $%_TEXT_% 4 | ) 5 | 6 | $%_MAPPING_VAR_% = New-Object System.Collections.Hashtable 7 | %MAPPING% 8 | 9 | $%_OUTPUT_% = "" 10 | 11 | $%_MAPLENGTH_% = $($%_MAPPING_VAR_%.Keys)[0].length 12 | for ($%_i_% = 0; $%_i_% -lt $%_TEXT_%.length; $%_i_% += $%_MAPLENGTH_%) { 13 | $%_OUTPUT_% += [char]$%_MAPPING_VAR_%[$%_TEXT_%.SubString($%_i_%, $%_MAPLENGTH_%)] 14 | } 15 | 16 | $%_OUTPUT_% 17 | } 18 | -------------------------------------------------------------------------------- /Codecepticon/Templates/Group.vb6: -------------------------------------------------------------------------------- 1 | Function %_FUNCTION_%(ByVal %_TEXT_% As String) 2 | Dim %_MAPPING_VAR_% 3 | Dim %_VAR_I_% As Long 4 | Dim %_VAR_OUTPUT_% As String 5 | dim %_VAR_ITEMS_% 6 | 7 | Set %_MAPPING_VAR_% = CreateObject("Scripting.Dictionary") 8 | 9 | %MAPPING% 10 | 11 | %_VAR_ITEMS_% = %_MAPPING_VAR_%.Keys 12 | 13 | For %_VAR_I_% = 1 To Len(%_TEXT_%) Step Len(%_VAR_ITEMS_%(0)) 14 | %_VAR_OUTPUT_% = %_VAR_OUTPUT_% & Chr(%_MAPPING_VAR_%(Mid(%_TEXT_%, %_VAR_I_%, Len(%_VAR_ITEMS_%(0))))) 15 | Next %_VAR_I_% 16 | %_FUNCTION_% = %_VAR_OUTPUT_% 17 | End Function 18 | -------------------------------------------------------------------------------- /Codecepticon/Templates/Single.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace %_NAMESPACE_% 4 | { 5 | class %_CLASS_% 6 | { 7 | public static Dictionary mapping = new Dictionary() { 8 | %MAPPING% 9 | }; 10 | 11 | public static string %_FUNCTION_%(string text) 12 | { 13 | string output = ""; 14 | foreach (char c in text) 15 | { 16 | if (mapping.ContainsKey(c.ToString())) 17 | { 18 | output += mapping[c.ToString()]; 19 | } 20 | else 21 | { 22 | output += c.ToString(); 23 | } 24 | } 25 | 26 | return output; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Codecepticon/Templates/Single.ps1: -------------------------------------------------------------------------------- 1 | function %_FUNCTION_% { 2 | param( 3 | [string] $%_TEXT_% 4 | ) 5 | 6 | $%_MAPPING_VAR_% = New-Object System.Collections.Hashtable 7 | %MAPPING% 8 | 9 | $%_OUTPUT_% = "" 10 | for ($%_i_% = 0; $%_i_% -lt $%_TEXT_%.length; $%_i_%++) { 11 | $%_c_% = $%_TEXT_%.SubString($%_i_%, 1) 12 | if ($%_MAPPING_VAR_%.ContainsKey($%_c_%)) { 13 | $%_OUTPUT_% += $%_MAPPING_VAR_%[$%_c_%] 14 | } else { 15 | $%_OUTPUT_% += $%_c_% 16 | } 17 | } 18 | 19 | $%_OUTPUT_% 20 | } 21 | -------------------------------------------------------------------------------- /Codecepticon/Templates/Single.vb6: -------------------------------------------------------------------------------- 1 | Function %_FUNCTION_%(ByVal %_TEXT_% As String) 2 | Dim %_MAPPING_VAR_% 3 | Dim %_VAR_I_% As Long 4 | Dim %_VAR_OUTPUT_% As String 5 | 6 | Set %_MAPPING_VAR_% = CreateObject("Scripting.Dictionary") 7 | 8 | %MAPPING% 9 | 10 | For %_VAR_I_% = 1 To Len(%_TEXT_%) 11 | %_VAR_OUTPUT_% = %_VAR_OUTPUT_% & %_MAPPING_VAR_%(Mid(%_TEXT_%, %_VAR_I_%, 1)) 12 | Next %_VAR_I_% 13 | %_FUNCTION_% = %_VAR_OUTPUT_% 14 | End Function 15 | -------------------------------------------------------------------------------- /Codecepticon/Templates/XOR.cs: -------------------------------------------------------------------------------- 1 | namespace %_NAMESPACE_% 2 | { 3 | class %_CLASS_% 4 | { 5 | public static string %_FUNCTION_%(string text, string key) 6 | { 7 | byte[] data = System.Convert.FromBase64String(text); 8 | byte[] k = System.Text.Encoding.UTF8.GetBytes(key); 9 | byte[] output = new byte[data.Length]; 10 | 11 | for (int i = 0; i < data.Length; i++) 12 | { 13 | output[i] = (byte)(data[i] ^ k[i % k.Length]); 14 | } 15 | return System.Text.Encoding.UTF8.GetString(output); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Codecepticon/Templates/XOR.ps1: -------------------------------------------------------------------------------- 1 | function %_FUNCTION_% { 2 | param( 3 | [string] $%_text_%, 4 | [string] $%_key_% 5 | ) 6 | 7 | $%_data_% = [System.Convert]::FromBase64String($%_text_%) 8 | $%_output_% = @() 9 | for ($%_i_% = 0; $%_i_% -lt $%_data_%.length; $%_i_%++) { 10 | $%_output_% += $%_data_%[$%_i_%] -bxor ([byte]($%_key_%[$%_i_% % $%_key_%.length])) 11 | } 12 | 13 | [System.Text.Encoding]::UTF8.GetString($%_output_%) 14 | } -------------------------------------------------------------------------------- /Codecepticon/Templates/XOR.vb6: -------------------------------------------------------------------------------- 1 | Function %_FUNCTION_%(ByVal %_TEXT_% As String, ByVal %_KEY_% As String) As String 2 | Dim %_VAR_BTEXT_%() As Byte 3 | Dim %_VAR_BKEY_%() As Byte 4 | Dim %_VAR_TEXTPOS_% As Long 5 | Dim %_VAR_KEYPOS_% As Long 6 | Dim %_VAR_B64_% 7 | 8 | With CreateObject("Microsoft.XMLDOM").createElement("b64") 9 | .DataType = "bin.base64": .text = %_TEXT_% 10 | %_VAR_B64_% = .nodeTypedValue 11 | With CreateObject("ADODB.Stream") 12 | .Open: .Type = 1: .Write %_VAR_B64_%: .Position = 0: .Type = 2: .Charset = "utf-8" 13 | %_TEXT_% = .ReadText 14 | .Close 15 | End With 16 | End With 17 | 18 | %_VAR_BTEXT_% = StrConv(%_TEXT_%, vbFromUnicode) 19 | %_VAR_BKEY_% = StrConv(%_KEY_%, vbFromUnicode) 20 | For %_VAR_TEXTPOS_% = 0 To UBound(%_VAR_BTEXT_%) 21 | %_VAR_BTEXT_%(%_VAR_TEXTPOS_%) = %_VAR_BTEXT_%(%_VAR_TEXTPOS_%) Xor %_VAR_BKEY_%(%_VAR_KEYPOS_%) 22 | If %_VAR_KEYPOS_% < UBound(%_VAR_BKEY_%) Then 23 | %_VAR_KEYPOS_% = %_VAR_KEYPOS_% + 1 24 | Else 25 | %_VAR_KEYPOS_% = 0 26 | End If 27 | Next %_VAR_TEXTPOS_% 28 | %_FUNCTION_% = StrConv(%_VAR_BTEXT_%, vbUnicode) 29 | End Function -------------------------------------------------------------------------------- /Codecepticon/Utils/Logger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Reflection; 7 | using System.IO; 8 | 9 | namespace Codecepticon.Utils 10 | { 11 | class Logger 12 | { 13 | public static bool IsVerbose = false; 14 | 15 | public static bool IsDebug = false; 16 | 17 | public static string ConsoleLogFile = ""; 18 | 19 | public static void Verbose(string message, bool newLine = true, bool showTime = true) 20 | { 21 | if (!IsVerbose) 22 | { 23 | return; 24 | } 25 | 26 | Write(message, newLine, showTime); 27 | } 28 | 29 | public static void Debug(string message, bool newLine = true, bool showTime = true) 30 | { 31 | if (!IsDebug) 32 | { 33 | return; 34 | } 35 | 36 | Console.ForegroundColor = ConsoleColor.Blue; 37 | Write("[DEBUG] " + message, newLine, showTime); 38 | Console.ResetColor(); 39 | } 40 | 41 | public static void Error(string message, bool newLine = true, bool showTime = true) 42 | { 43 | Console.ForegroundColor = ConsoleColor.Red; 44 | Write(message, newLine, showTime); 45 | Console.ResetColor(); 46 | } 47 | 48 | public static void Info(string message, bool newLine = true, bool showTime = true) 49 | { 50 | Write(message, newLine, showTime); 51 | } 52 | 53 | public static void Warning(string message, bool newLine = true, bool showTime = true) 54 | { 55 | Console.ForegroundColor = ConsoleColor.Yellow; 56 | Write(message, newLine, showTime); 57 | Console.ResetColor(); 58 | } 59 | 60 | public static void Success(string message, bool newLine = true, bool showTime = true) 61 | { 62 | Console.ForegroundColor = ConsoleColor.Green; 63 | Write(message, newLine, showTime); 64 | Console.ResetColor(); 65 | } 66 | 67 | protected static string FormatString(string message) 68 | { 69 | return $"[{DateTime.Now:HH:mm:ss}] {message}"; 70 | } 71 | 72 | protected static void Write(string message, bool newLine = true, bool showTime = true) 73 | { 74 | message = showTime ? FormatString(message) : message; 75 | message += newLine ? Environment.NewLine : ""; 76 | Console.Write(message); 77 | WriteToLogFile(message); 78 | } 79 | 80 | protected static void WriteToLogFile(string message) 81 | { 82 | // Write to file too. 83 | if (ConsoleLogFile == "") 84 | { 85 | ConsoleLogFile = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\codecepticon.log"; 86 | if (!File.Exists(ConsoleLogFile)) 87 | { 88 | File.Create(ConsoleLogFile).Dispose(); 89 | } 90 | } 91 | 92 | using (StreamWriter w = File.AppendText(ConsoleLogFile)) 93 | { 94 | w.Write(message); 95 | } 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Codecepticon/Utils/MarkovWordGenerator/MarkovModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Codecepticon.Utils.MarkovWordGenerator 8 | { 9 | /* 10 | * Taken from https://github.com/MagicMau/ProceduralNameGenerator 11 | */ 12 | class MarkovModel 13 | { 14 | private int order; 15 | private double smoothing; 16 | private List alphabet; 17 | private Dictionary> observations; 18 | private Dictionary> chains; 19 | 20 | public MarkovModel(IEnumerable trainingData, int order, double smoothing, List alphabet) 21 | { 22 | this.order = order; 23 | this.smoothing = smoothing; 24 | this.alphabet = alphabet; 25 | 26 | observations = new Dictionary>(); 27 | Retrain(trainingData); 28 | } 29 | 30 | public char Generate(string context, Random rnd) 31 | { 32 | List chain; 33 | if (chains.TryGetValue(context, out chain)) 34 | { 35 | return alphabet[SelectIndex(chain, rnd)]; 36 | } 37 | 38 | return '\0'; 39 | } 40 | 41 | public void Retrain(IEnumerable trainingData) 42 | { 43 | Train(trainingData); 44 | BuildChains(); 45 | } 46 | 47 | private void Train(IEnumerable trainingData) 48 | { 49 | foreach (var d in trainingData) 50 | { 51 | string data = new string('#', order) + d + '#'; 52 | for (int i = 0; i < data.Length - order; i++) 53 | { 54 | string key = data.Substring(i, order); 55 | List value; 56 | if (!observations.TryGetValue(key, out value)) 57 | { 58 | value = new List(); 59 | observations[key] = value; 60 | } 61 | value.Add(data[i + order]); 62 | } 63 | } 64 | } 65 | 66 | private void BuildChains() 67 | { 68 | chains = new Dictionary>(); 69 | 70 | foreach (string context in observations.Keys) 71 | { 72 | foreach (char prediction in alphabet) 73 | { 74 | List chain; 75 | if (!chains.TryGetValue(context, out chain)) 76 | { 77 | chain = new List(); 78 | chains[context] = chain; 79 | } 80 | int count = 0; 81 | List observation; 82 | if (observations.TryGetValue(context, out observation)) 83 | { 84 | count = observation.Count(c => c == prediction); 85 | } 86 | 87 | chain.Add(smoothing + count); 88 | } 89 | } 90 | } 91 | 92 | private int SelectIndex(List chain, Random rnd) 93 | { 94 | var totals = new List(); 95 | double accumulator = 0f; 96 | 97 | foreach (var weight in chain) 98 | { 99 | accumulator += weight; 100 | totals.Add(accumulator); 101 | } 102 | 103 | var rand = rnd.NextDouble() * accumulator; 104 | 105 | for (int i = 0; i < totals.Count; i++) 106 | { 107 | if (rand < totals[i]) 108 | { 109 | return i; 110 | } 111 | } 112 | 113 | return 0; 114 | } 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /Codecepticon/Utils/MarkovWordGenerator/MarkovWordGenerator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Codecepticon.Utils.MarkovWordGenerator 9 | { 10 | /* 11 | * Taken from https://github.com/MagicMau/ProceduralNameGenerator 12 | */ 13 | class MarkovWordGenerator 14 | { 15 | public int order { get; set; } 16 | public double smoothing { get; set; } 17 | 18 | private List models; 19 | 20 | public MarkovWordGenerator(string trainingDataFile, int order, double smoothing) 21 | { 22 | string[] words = File.ReadAllLines(trainingDataFile).ToArray(); 23 | Init(words, order, smoothing); 24 | } 25 | 26 | protected void Init(IEnumerable trainingData, int order, double smoothing) 27 | { 28 | this.order = order; 29 | this.smoothing = smoothing; 30 | this.models = new List(); 31 | 32 | // Identify and sort the alphabet used in the training data 33 | var letters = new HashSet(); 34 | foreach (var word in trainingData) 35 | { 36 | foreach (char c in word) 37 | { 38 | letters.Add(c); 39 | } 40 | } 41 | var domain = letters.OrderBy(c => c).ToList(); 42 | domain.Insert(0, '#'); 43 | 44 | // create models 45 | for (int i = 0; i < order; i++) 46 | { 47 | this.models.Add(new MarkovModel(trainingData, order - i, smoothing, domain)); 48 | } 49 | } 50 | 51 | public MarkovWordGenerator(IEnumerable trainingData, int order, double smoothing) 52 | { 53 | Init(trainingData, order, smoothing); 54 | } 55 | 56 | private string Generate(Random rnd) 57 | { 58 | string name = new string('#', this.order); 59 | char letter = GetLetter(name, rnd); 60 | while (letter != '#' && letter != '\0') 61 | { 62 | name += letter; 63 | letter = GetLetter(name, rnd); 64 | } 65 | return name; 66 | } 67 | 68 | private char GetLetter(string name, Random rnd) 69 | { 70 | char letter = '\0'; 71 | string context = name.Substring(name.Length - this.order); 72 | foreach (var model in this.models) 73 | { 74 | letter = model.Generate(context, rnd); 75 | if (letter == '\0') 76 | { 77 | context = context.Substring(1); 78 | } 79 | else 80 | { 81 | break; 82 | } 83 | } 84 | return letter; 85 | } 86 | 87 | public List GenerateWords(int count, int minLength, int maxLength, Random rnd) 88 | { 89 | int invalidCount = 0; 90 | List words = new List(); 91 | while (words.Count < count) 92 | { 93 | string word = GenerateWord(minLength, maxLength, rnd); 94 | if (word == null) 95 | { 96 | if (++invalidCount == 100) 97 | { 98 | // We've tried 100 times to find a valid word, and couldn't. Return an empty dataset. 99 | // We're not returning the "words" variable because it would contain less words than "count". 100 | return new List(); 101 | } 102 | continue; 103 | } 104 | invalidCount = 0; 105 | words.Add(word); 106 | } 107 | return words; 108 | } 109 | 110 | private string GenerateWord(int minLength, int maxLength, Random rnd) 111 | { 112 | string word = Generate(rnd).Replace("#", ""); 113 | if (word.Length < minLength || word.Length > maxLength) 114 | { 115 | return null; 116 | } 117 | 118 | return word; 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /Codecepticon/Utils/NameGenerator.cs: -------------------------------------------------------------------------------- 1 | using Codecepticon.CommandLine; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Globalization; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Codecepticon.Utils 10 | { 11 | class NameGenerator 12 | { 13 | public enum RandomNameGeneratorMethods 14 | { 15 | None = 0, 16 | RandomCombinations = 1, 17 | AvoidTwinCharacters = 2, 18 | DictionaryWords = 3, 19 | Markov = 4 20 | } 21 | 22 | private static readonly Random RandomSeed = new Random(); 23 | 24 | private readonly RandomNameGeneratorMethods _generationMethod; 25 | 26 | private readonly string _characterSet; 27 | 28 | private readonly int _length; 29 | 30 | private readonly List _dictionaryWords; 31 | 32 | public NameGenerator(RandomNameGeneratorMethods generationMethod, string characterSet) 33 | { 34 | 35 | _generationMethod = generationMethod; 36 | _characterSet = characterSet; 37 | _length = 0; 38 | _dictionaryWords = new List(); 39 | } 40 | 41 | public NameGenerator(RandomNameGeneratorMethods generationMethod, string characterSet, int length) 42 | { 43 | 44 | _generationMethod = generationMethod; 45 | _characterSet = characterSet; 46 | _length = length; 47 | _dictionaryWords = new List(); 48 | } 49 | 50 | public NameGenerator(RandomNameGeneratorMethods generationMethod, string characterSet, int length, List dictionaryWords) 51 | { 52 | _generationMethod = generationMethod; 53 | _characterSet = characterSet; 54 | _length = length; 55 | _dictionaryWords = dictionaryWords; 56 | } 57 | 58 | public string Generate() 59 | { 60 | switch (_generationMethod) 61 | { 62 | case RandomNameGeneratorMethods.RandomCombinations: 63 | return GenerateRandomString(); 64 | case RandomNameGeneratorMethods.AvoidTwinCharacters: 65 | return GenerateNoTwinString(); 66 | case RandomNameGeneratorMethods.DictionaryWords: 67 | return GenerateDictionaryString(); 68 | case RandomNameGeneratorMethods.Markov: 69 | return GenerateMarkovWords(); 70 | 71 | } 72 | return ""; 73 | } 74 | 75 | protected string GenerateRandomString() 76 | { 77 | int l = (_length > 0) ? _length : RandomSeed.Next(2, 16); 78 | return new string(Enumerable.Repeat(_characterSet, l).Select(s => s[RandomSeed.Next(s.Length)]).ToArray()); 79 | } 80 | 81 | protected string GenerateNoTwinString() 82 | { 83 | int l = (_length > 0) ? _length : RandomSeed.Next(2, 16); 84 | char[] value = new char[l]; 85 | int attemptLimit = 100; 86 | // Set the first char. 87 | value[0] = _characterSet[RandomSeed.Next(_characterSet.Length)]; 88 | 89 | for (int i = 1; i < l; i++) 90 | { 91 | char c; 92 | int attemptCount = 0; 93 | do 94 | { 95 | c = _characterSet[RandomSeed.Next(_characterSet.Length)]; 96 | } while (c == value[i - 1] && ++attemptCount < attemptLimit); 97 | 98 | if (attemptCount >= attemptLimit) 99 | { 100 | return ""; 101 | } 102 | 103 | value[i] = c; 104 | } 105 | 106 | return new string(value); 107 | } 108 | 109 | protected string GenerateDictionaryString() 110 | { 111 | int l = (_length > 0) ? _length : RandomSeed.Next(2, 16); 112 | string value = ""; 113 | for (int i = 0; i < l; i++) 114 | { 115 | value += _dictionaryWords[RandomSeed.Next(_dictionaryWords.Count)]; 116 | } 117 | return value; 118 | } 119 | 120 | protected string GenerateMarkovWords() 121 | { 122 | CultureInfo culture = System.Threading.Thread.CurrentThread.CurrentCulture; 123 | int count = RandomSeed.Next(CommandLineData.Global.Markov.MinWords, CommandLineData.Global.Markov.MaxWords); 124 | List words = CommandLineData.Global.Markov.Generator.GenerateWords(count, CommandLineData.Global.Markov.MinLength, CommandLineData.Global.Markov.MaxLength, RandomSeed); 125 | words = words.Select(w => culture.TextInfo.ToTitleCase(w.ToLower())).ToList(); 126 | return String.Join("", words); 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /Codecepticon/Utils/Templates.cs: -------------------------------------------------------------------------------- 1 | using Codecepticon.Modules; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Codecepticon.Utils 10 | { 11 | class Templates 12 | { 13 | protected Dictionary TemplateNames = new Dictionary 14 | { 15 | { StringEncoding.StringEncodingMethods.Base64, "Base64" }, 16 | { StringEncoding.StringEncodingMethods.XorEncrypt, "XOR" }, 17 | { StringEncoding.StringEncodingMethods.SingleCharacterSubstitution, "Single" }, 18 | { StringEncoding.StringEncodingMethods.GroupCharacterSubstitution, "Group" }, 19 | { StringEncoding.StringEncodingMethods.ExternalFile, "ExternalFile" } 20 | }; 21 | 22 | protected Dictionary TemplateExtensions = new Dictionary 23 | { 24 | { ModuleTypes.CodecepticonModules.CSharp, "cs" }, 25 | { ModuleTypes.CodecepticonModules.Powershell, "ps1" }, 26 | { ModuleTypes.CodecepticonModules.Vb6, "vb6" }, 27 | }; 28 | 29 | public string GetTemplateFile(string fileName) 30 | { 31 | return Path.GetFullPath(@"Templates\" + fileName); 32 | } 33 | 34 | public string GetTemplateFile(ModuleTypes.CodecepticonModules module, StringEncoding.StringEncodingMethods method) 35 | { 36 | if (!TemplateNames.ContainsKey(method) || !TemplateExtensions.ContainsKey(module)) 37 | { 38 | return ""; 39 | } 40 | 41 | string fileName = TemplateNames[method] + "." + TemplateExtensions[module]; 42 | fileName = Path.GetFullPath(@"Templates\" + fileName); 43 | return fileName; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Accenture Security 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /NuGet.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /docs/KnownIssues.md: -------------------------------------------------------------------------------- 1 | # Codecepticon Known Issues 2 | 3 | ## C# Obfuscation 4 | 5 | ### Solutions with Multiple Projects 6 | 7 | Codecepticon does not work when a solution has more than 1 project included. An example of this is the [SharpDPAPI](https://github.com/GhostPack/SharpDPAPI) project which also includes `SharpChrome`. In order to obfuscate it, you will have to remove one or the other. Codecepticon will catch this and will prompt you for action (continue/exit). 8 | 9 | ### Roslyn Version 10 | 11 | Currently C# obfuscation only works with Roslyn v3.9.0, as there is a but which affects renaming namespaces/functions: https://github.com/dotnet/roslyn/issues/58463 12 | 13 | When this issue is resolved, Codecepticon and its documentation will be updated. Codecepticon will catch this and will prompt you for action (continue/exit). 14 | 15 | ## PowerShell Obfuscation 16 | 17 | Due to the nature and complexity of PowerShell scripts, obfuscation of large/complex scripts may or may not work. 18 | 19 | ## VBA/VB6 20 | 21 | ### Documents 22 | 23 | Codecepticon cannot obfuscate an office document such as Word/Excel. You will have to obfuscate each `*.bas` file and then manually insert into your document. -------------------------------------------------------------------------------- /docs/Tips.md: -------------------------------------------------------------------------------- 1 | # Codecepticon Tips 2 | 3 | This is a collection of tips to make your life easier. 4 | 5 | ## Command Line Generator 6 | 7 | As mentioned multiple times, use the [Command Line Generator](../CommandLineGenerator.html) 8 | 9 | ## Always Test First 10 | 11 | After obfuscating a project or a script, make sure you test locally to see that everything works. Just because it compiled does not mean that it also works like it should. 12 | 13 | ## Never Double-Obfuscate 14 | 15 | Avoid obfuscating already obfuscated code. It may or may not work, but if you choose to go that way you're on your own! 16 | 17 | ## Git is Your Friend 18 | 19 | Use `git` functionality to restore a project into its original state. 20 | 21 | Clone the project you wish to obfuscate: 22 | 23 | ``` 24 | git clone https://github.com/GhostPack/Rubeus 25 | ``` 26 | 27 | Obfuscate it and check against AV/EDR. If you need to restore to its original version and obfuscate again, there is no need to clone the repo again as you can simply run the following command: 28 | 29 | ``` 30 | git clean -fd && git reset HEAD --hard 31 | ``` 32 | 33 | ## Profiles 34 | 35 | Just because you selected an obfuscation profile (like `Rubeus` or `SharpView`) does not mean you do not have to specify everything else (what and how to rename identifiers etc). Profiles are there to add the cherry on top and make tool-specific changes to ensure the end result works properly. 36 | 37 | "Does Codecepticon only work for tools that have a profile?" - No, Codecepticon will work with any project - it's just that some projects may need one last push to get them over the line, and this is where profiles (existing or future) come in. 38 | 39 | ## Include Command Line in Target 40 | 41 | If you find yourself in a situation where you can run an executable but you cannot use `cmd` or `powershell` to pass arguments to it, include them in the source and compile: 42 | 43 | ![Hardcoded SharpHound Command](images/SH-Hardcoded-Command.png "Hardcoded SharpHound Command") 44 | 45 | ## Get Rid of Unused Code 46 | 47 | Usually you will not need the entire functionality that tools like `Rubeus`, `SharpHound`, or `SharpView` have to offer, however the larger the codebase is the easier it is to fingerprint different aspects of it. Therefore, consider trimming down a project until you are left with only the required functionality. 48 | 49 | [JetBrains Resharper](https://www.jetbrains.com/resharper/) offers functionality to identify unused methods, classes, declarations, etc, to assist with this. 50 | 51 | ## Sign Your Executables 52 | 53 | It's quite suprising that by simply signing an executable can bypass some AV vendors, even if the certificate is invalid. -------------------------------------------------------------------------------- /docs/images/CmdGenerator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Accenture/Codecepticon/296a646eca3d5137425d80f6286c94d12f6e272b/docs/images/CmdGenerator.png -------------------------------------------------------------------------------- /docs/images/Mapping-File-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Accenture/Codecepticon/296a646eca3d5137425d80f6286c94d12f6e272b/docs/images/Mapping-File-1.png -------------------------------------------------------------------------------- /docs/images/Mapping-File-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Accenture/Codecepticon/296a646eca3d5137425d80f6286c94d12f6e272b/docs/images/Mapping-File-2.png -------------------------------------------------------------------------------- /docs/images/Mapping-File-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Accenture/Codecepticon/296a646eca3d5137425d80f6286c94d12f6e272b/docs/images/Mapping-File-3.png -------------------------------------------------------------------------------- /docs/images/Mapping-File-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Accenture/Codecepticon/296a646eca3d5137425d80f6286c94d12f6e272b/docs/images/Mapping-File-4.png -------------------------------------------------------------------------------- /docs/images/MissingMethodException.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Accenture/Codecepticon/296a646eca3d5137425d80f6286c94d12f6e272b/docs/images/MissingMethodException.png -------------------------------------------------------------------------------- /docs/images/SH-Hardcoded-Command.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Accenture/Codecepticon/296a646eca3d5137425d80f6286c94d12f6e272b/docs/images/SH-Hardcoded-Command.png -------------------------------------------------------------------------------- /docs/images/SH3-Output-Clean.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Accenture/Codecepticon/296a646eca3d5137425d80f6286c94d12f6e272b/docs/images/SH3-Output-Clean.png -------------------------------------------------------------------------------- /docs/images/SH3-Output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Accenture/Codecepticon/296a646eca3d5137425d80f6286c94d12f6e272b/docs/images/SH3-Output.png -------------------------------------------------------------------------------- /docs/images/VS2022-NET-Roslyn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Accenture/Codecepticon/296a646eca3d5137425d80f6286c94d12f6e272b/docs/images/VS2022-NET-Roslyn.png -------------------------------------------------------------------------------- /docs/images/VS2022-NET.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Accenture/Codecepticon/296a646eca3d5137425d80f6286c94d12f6e272b/docs/images/VS2022-NET.png --------------------------------------------------------------------------------