-
-
Save xpn/002087ce54bcfd9132240f10212f6707 to your computer and use it in GitHub Desktop.
Code obfuscator using Roslyn.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Threading.Tasks; | |
using Microsoft.CodeAnalysis; | |
using Microsoft.CodeAnalysis.CSharp; | |
using Microsoft.CodeAnalysis.CSharp.Syntax; | |
using Microsoft.CodeAnalysis.MSBuild; | |
using Microsoft.CodeAnalysis.Rename; | |
namespace Rewriter | |
{ | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
Console.WriteLine("Roslyn Renamer example by @_xpn_\n"); | |
Program p = new Program(); | |
if (args.Length != 1) | |
{ | |
Console.WriteLine("[*] Error: No solution path provided"); | |
return; | |
} | |
p.Run(args[0]).Wait(); | |
} | |
// via SO: https://stackoverflow.com/questions/1344221/how-can-i-generate-random-alphanumeric-strings | |
public static string RandomString(int length) | |
{ | |
var random = new Random(); | |
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; | |
return new string(Enumerable.Repeat(chars, length) | |
.Select(s => s[random.Next(s.Length)]).ToArray()); | |
} | |
MSBuildWorkspace m_workspace; | |
public async Task Run(string solutionPath) | |
{ | |
// Create a workspace to allow loading our solution | |
m_workspace = MSBuildWorkspace.Create(); | |
// Load our target solution | |
Solution solution = await m_workspace.OpenSolutionAsync(solutionPath); | |
// Find all projects in the solution | |
var projects = solution.Projects; | |
// Get the first project | |
var project = projects.FirstOrDefault(); | |
// Enumerate through documents in the project | |
foreach (var document in project.Documents) | |
{ | |
// Get our syntax tree representation of the document | |
var syntaxTree = await document.GetSyntaxTreeAsync(); | |
// Find all classes and pass them to be renamed | |
var classes = syntaxTree.GetRoot().DescendantNodes().OfType<ClassDeclarationSyntax>(); | |
foreach (var c in classes) | |
{ | |
solution = await Replace<ClassDeclarationSyntax>(solution, project.Name, document.Name, c.Identifier.ToString(), RandomString(10)); | |
} | |
// Find all enums and pass them to be renamed | |
var enums = syntaxTree.GetRoot().DescendantNodes().OfType<EnumDeclarationSyntax>(); | |
foreach (var e in enums) | |
{ | |
solution = await Replace<EnumDeclarationSyntax>(solution, project.Name, document.Name, e.Identifier.ToString(), RandomString(10)); | |
} | |
// Find all namespaces and pass them to be renamed | |
var namespaces = syntaxTree.GetRoot().DescendantNodes().OfType<NamespaceDeclarationSyntax>(); | |
foreach (var n in namespaces) | |
{ | |
solution = await Replace<NamespaceDeclarationSyntax>(solution, project.Name, document.Name, n.Name.ToString(), RandomString(10)); | |
} | |
} | |
// When completed, apply changes to our solution | |
m_workspace.TryApplyChanges(solution); | |
} | |
public async Task<Solution> Replace<T>(Solution solution, string projectName, string documentName, string oldName, string newName) | |
{ | |
ISymbol symbol; | |
IEnumerable<T> nodes; | |
var project = solution.Projects.Where(s => s.Name == projectName).FirstOrDefault(); | |
var document = project.Documents.Where(s => s.Name == documentName).FirstOrDefault(); | |
var semanticModel = await document.GetSemanticModelAsync(); | |
var syntaxTree = await document.GetSyntaxTreeAsync(); | |
// Check if we have a namespace as this has a different property to search for | |
if (typeof(T) == typeof(NamespaceDeclarationSyntax)) | |
{ | |
nodes = (IEnumerable<T>)syntaxTree.GetRoot().DescendantNodes().OfType<T>(); | |
var node = ((IEnumerable<NamespaceDeclarationSyntax>)nodes).Where(s => s.Name.ToString() == oldName).FirstOrDefault(); | |
if (node == null) | |
{ | |
return solution; | |
} | |
// Get a symbol for our namespace | |
symbol = semanticModel.GetDeclaredSymbol(node); | |
} | |
else | |
{ | |
nodes = (IEnumerable<T>)syntaxTree.GetRoot().DescendantNodes().OfType<T>(); | |
var node = ((IEnumerable<BaseTypeDeclarationSyntax>)nodes).Where(s => s.Identifier.ToString() == oldName).FirstOrDefault(); | |
if (node == null) | |
{ | |
return solution; | |
} | |
// Get a symbol for our class/enum | |
symbol = semanticModel.GetDeclaredSymbol(node); | |
} | |
// Use Roslyn to rename throughout our solution | |
solution = await Renamer.RenameSymbolAsync(solution, symbol, newName, solution.Workspace.Options); | |
return solution; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment