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