Skip to content

Commit

Permalink
Obfuscating assemblies with missing dependencies
Browse files Browse the repository at this point in the history
ConfuserEx is now able to obfuscate assemblies without all the dependencies.
It makes some worst case assumptions for missing dependencies.
  • Loading branch information
mkaring committed Jun 28, 2020
1 parent b4a67cb commit e79b8ab
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 109 deletions.
1 change: 1 addition & 0 deletions Confuser.Core/Confuser.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
<ItemGroup Label="Nuget Dependencies">
<PackageReference Include="Microsoft.Win32.Registry" Version="4.*" />
<PackageReference Include="System.Threading" Version="4.*" />
<PackageReference Include="System.ValueTuple" Version="4.*" />
</ItemGroup>

<ItemGroup Label="Project Dependencies">
Expand Down
96 changes: 46 additions & 50 deletions Confuser.Core/ConfuserEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@
using MethodImplAttributes = dnlib.DotNet.MethodImplAttributes;
using TypeAttributes = dnlib.DotNet.TypeAttributes;

namespace Confuser.Core {
namespace Confuser.Core {
/// <summary>
/// The processing engine of ConfuserEx.
/// </summary>
public static class ConfuserEngine {
public static class ConfuserEngine {
/// <summary>
/// The version of ConfuserEx.
/// </summary>
Expand Down Expand Up @@ -50,8 +50,8 @@ static ConfuserEngine() {
return null;
}
};
}

}

/// <summary>
/// Runs the engine with the specified parameters.
/// </summary>
Expand All @@ -67,15 +67,15 @@ public static Task Run(ConfuserParameters parameters, CancellationToken? token =
if (token == null)
token = new CancellationTokenSource().Token;
return Task.Factory.StartNew(() => RunInternal(parameters, token.Value), token.Value);
}

}

/// <summary>
/// Runs the engine.
/// </summary>
/// <param name="parameters">The parameters.</param>
/// <param name="token">The cancellation token.</param>
static void RunInternal(ConfuserParameters parameters, CancellationToken token) {
// 1. Setup context
static void RunInternal(ConfuserParameters parameters, CancellationToken token) {
// 1. Setup context
var context = new ConfuserContext();
context.Logger = parameters.GetLogger();
context.Project = parameters.Project.Clone();
Expand All @@ -85,8 +85,8 @@ static void RunInternal(ConfuserParameters parameters, CancellationToken token)
PrintInfo(context);

bool ok = false;
try {
// Enable watermarking by default
try {
// Enable watermarking by default
context.Project.Rules.Insert(0, new Rule {
new SettingItem<Protection>(WatermarkingProtection._Id),
new SettingItem<Protection>("harden")
Expand All @@ -103,9 +103,9 @@ static void RunInternal(ConfuserParameters parameters, CancellationToken token)

context.CheckCancellation();

Marker marker = parameters.GetMarker();

// 2. Discover plugins
Marker marker = parameters.GetMarker();

// 2. Discover plugins
context.Logger.Debug("Discovering plugins...");

IList<Protection> prots;
Expand All @@ -115,9 +115,9 @@ static void RunInternal(ConfuserParameters parameters, CancellationToken token)

context.Logger.InfoFormat("Discovered {0} protections, {1} packers.", prots.Count, packers.Count);

context.CheckCancellation();

// 3. Resolve dependency
context.CheckCancellation();

// 3. Resolve dependency
context.Logger.Debug("Resolving component dependency...");
try {
var resolver = new DependencyResolver(prots);
Expand All @@ -134,9 +134,9 @@ static void RunInternal(ConfuserParameters parameters, CancellationToken token)
foreach (Packer packer in packers)
components.Add(packer);

context.CheckCancellation();

// 4. Load modules
context.CheckCancellation();

// 4. Load modules
context.Logger.Info("Loading input modules...");
marker.Initalize(prots, packers);
MarkerResult markings = marker.MarkProject(parameters.Project, context);
Expand All @@ -149,9 +149,9 @@ static void RunInternal(ConfuserParameters parameters, CancellationToken token)
context.Packer = markings.Packer;
context.ExternalModules = markings.ExternalModules;

context.CheckCancellation();

// 5. Initialize components
context.CheckCancellation();

// 5. Initialize components
context.Logger.Info("Initializing...");
foreach (ConfuserComponent comp in components) {
try {
Expand All @@ -164,19 +164,19 @@ static void RunInternal(ConfuserParameters parameters, CancellationToken token)
context.CheckCancellation();
}

context.CheckCancellation();

// 6. Build pipeline
context.CheckCancellation();

// 6. Build pipeline
context.Logger.Debug("Building pipeline...");
var pipeline = new ProtectionPipeline();
context.Pipeline = pipeline;
foreach (ConfuserComponent comp in components) {
comp.PopulatePipeline(pipeline);
}

context.CheckCancellation();

//7. Run pipeline
context.CheckCancellation();

//7. Run pipeline
RunPipeline(pipeline, context);

ok = true;
Expand All @@ -199,8 +199,8 @@ static void RunInternal(ConfuserParameters parameters, CancellationToken token)
catch (OperationCanceledException) {
context.Logger.Error("Operation cancelled.");
}
catch (ConfuserException) {
// Exception is already handled/logged, so just ignore and report failure
catch (ConfuserException) {
// Exception is already handled/logged, so just ignore and report failure
}
catch (Exception ex) {
context.Logger.ErrorException("Unknown error occurred.", ex);
Expand All @@ -210,8 +210,8 @@ static void RunInternal(ConfuserParameters parameters, CancellationToken token)
context.Resolver.Clear();
context.Logger.Finish(ok);
}
}

}

/// <summary>
/// Runs the protection pipeline.
/// </summary>
Expand Down Expand Up @@ -264,14 +264,10 @@ static void RunPipeline(ProtectionPipeline pipeline, ConfuserContext context) {
static void Inspection(ConfuserContext context) {
context.Logger.Info("Resolving dependencies...");
foreach (var dependency in context.Modules
.SelectMany(module => module.GetAssemblyRefs().Select(asmRef => Tuple.Create(asmRef, module)))) {
try {
AssemblyDef assembly = context.Resolver.ResolveThrow(dependency.Item1, dependency.Item2);
}
catch (AssemblyResolveException ex) {
context.Logger.ErrorException("Failed to resolve dependency of '" + dependency.Item2.Name + "'.", ex);
throw new ConfuserException(ex);
}
.SelectMany(module => module.GetAssemblyRefs().Select(asmRef => (asmRef, module)))) {
var assembly = context.Resolver.Resolve(dependency.asmRef, dependency.module);
if (assembly is null)
context.Logger.Warn("Failed to resolve dependency '" + dependency.asmRef.FullName + "'.");
}

context.Logger.Debug("Checking Strong Name...");
Expand Down Expand Up @@ -312,8 +308,8 @@ static void CheckStrongName(ConfuserContext context, ModuleDef module) {
context.Logger.WarnFormat("[{0}] SN Key or SN public Key is not provided for a signed module, the output may not be working.", module.Name);
else if (isKeyProvided && !moduleIsSignedOrDelayedSigned)
context.Logger.WarnFormat("[{0}] SN Key or SN public Key is provided for an unsigned module, the output may not be working.", module.Name);
else if (snPubKeyBytes != null && moduleIsSignedOrDelayedSigned &&
!module.Assembly.PublicKey.Data.SequenceEqual(snPubKeyBytes))
else if (snPubKeyBytes != null && moduleIsSignedOrDelayedSigned &&
!module.Assembly.PublicKey.Data.SequenceEqual(snPubKeyBytes))
context.Logger.WarnFormat("[{0}] Provided SN public Key and signed module's public key do not match, the output may not be working.",
module.Name);
}
Expand Down Expand Up @@ -444,8 +440,8 @@ static void SaveModules(ConfuserContext context) {
context.Logger.DebugFormat("Saving to '{0}'...", path);
File.WriteAllBytes(path, context.OutputModules[i]);
}
}

}

/// <summary>
/// Prints the copyright stuff and environment information.
/// </summary>
Expand All @@ -467,9 +463,9 @@ static void PrintInfo(ConfuserContext context) {
}
}

static IEnumerable<string> GetFrameworkVersions() {
// http://msdn.microsoft.com/en-us/library/hh925568.aspx

static IEnumerable<string> GetFrameworkVersions() {
// http://msdn.microsoft.com/en-us/library/hh925568.aspx

using (RegistryKey ndpKey =
RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, "").
OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP\")) {
Expand Down Expand Up @@ -510,8 +506,8 @@ static IEnumerable<string> GetFrameworkVersions() {
var releaseKey = (int)ndpKey.GetValue("Release");
yield return "v4.5 " + releaseKey;
}
}

}

/// <summary>
/// Prints the environment information when error occurred.
/// </summary>
Expand All @@ -530,7 +526,7 @@ static void PrintEnvironmentInfo(ConfuserContext context) {

if (context.Resolver != null) {
context.Logger.Error("Cached assemblies:");
foreach (AssemblyDef asm in context.Resolver.GetCachedAssemblies()) {
foreach (var asm in context.Resolver.GetCachedAssemblies().Where(a => !(a is null))) {
if (string.IsNullOrEmpty(asm.ManifestModule.Location))
context.Logger.ErrorFormat(" {0}", asm.FullName);
else
Expand Down
39 changes: 16 additions & 23 deletions Confuser.Core/DnlibUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -208,16 +208,14 @@ public static bool IsDelegate(this TypeDef type) {
/// <param name="type">The type.</param>
/// <param name="baseType">The full name of base type.</param>
/// <returns><c>true</c> if the specified type is inherited from a base type; otherwise, <c>false</c>.</returns>
public static bool InheritsFromCorlib(this TypeDef type, string baseType) {
if (type.BaseType == null)
return false;

TypeDef bas = type;
do {
bas = bas.BaseType.ResolveTypeDefThrow();
public static bool InheritsFromCorLib(this TypeDef type, string baseType) {
var bas = type.GetBaseType();
while (!(bas is null) && bas.DefinitionAssembly.IsCorLib()) {
if (bas.ReflectionFullName == baseType)
return true;
} while (bas.BaseType != null && bas.BaseType.DefinitionAssembly.IsCorLib());

bas = bas.GetBaseType();
}
return false;
}

Expand All @@ -228,15 +226,13 @@ public static bool InheritsFromCorlib(this TypeDef type, string baseType) {
/// <param name="baseType">The full name of base type.</param>
/// <returns><c>true</c> if the specified type is inherited from a base type; otherwise, <c>false</c>.</returns>
public static bool InheritsFrom(this TypeDef type, string baseType) {
if (type.BaseType == null)
return false;

TypeDef bas = type;
do {
bas = bas.BaseType.ResolveTypeDefThrow();
var bas = type.GetBaseType();;
while (!(bas is null)) {
if (bas.ReflectionFullName == baseType)
return true;
} while (bas.BaseType != null);

bas = bas.GetBaseType();
}
return false;
}

Expand All @@ -248,17 +244,14 @@ public static bool InheritsFrom(this TypeDef type, string baseType) {
/// <returns><c>true</c> if the specified type implements the interface; otherwise, <c>false</c>.</returns>
public static bool Implements(this TypeDef type, string fullName) {
do {
foreach (InterfaceImpl iface in type.Interfaces) {
if (iface.Interface.ReflectionFullName == fullName)
return true;
if (type.Interfaces.Any(iFace => iFace.Interface.ReflectionFullName == fullName)) {
return true;
}

if (type.BaseType == null)
return false;

type = type.BaseType.ResolveTypeDefThrow();
type = type.GetBaseType() as TypeDef;
} while (type != null);
throw new UnreachableException();

return false;
}

/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion Confuser.Renamer/AnalyzePhase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ void Analyze(NameService service, ConfuserContext context, ProtectionParameters
if (parameters.GetParameter(context, type, "forceRen", false))
return;

if (type.InheritsFromCorlib("System.Attribute")) {
if (type.InheritsFromCorLib("System.Attribute")) {
service.ReduceRenameMode(type, RenameMode.ASCII);
}

Expand Down
8 changes: 6 additions & 2 deletions Confuser.Renamer/Analyzers/InterReferenceAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ public void Analyze(ConfuserContext context, INameService service, ProtectionPar
for (uint i = 1; i <= len; i++) {
TypeRef typeRef = module.ResolveTypeRef(i);

TypeDef typeDef = typeRef.ResolveTypeDefThrow();
TypeDef typeDef = typeRef.ResolveTypeDef();
if (typeDef is null) continue;

if (typeDef.Module != module && context.Modules.Contains((ModuleDefMD)typeDef.Module)) {
service.AddReference(typeDef, new TypeRefReference(typeRef, typeDef));
}
Expand All @@ -51,7 +53,9 @@ void ProcessMemberRef(ConfuserContext context, INameService service, ModuleDefMD
if (memberRef.DeclaringType.TryGetArraySig() != null)
return;

TypeDef declType = memberRef.DeclaringType.ResolveTypeDefThrow();
TypeDef declType = memberRef.DeclaringType.ResolveTypeDef();
if (declType is null) return;

if (declType.Module != module && context.Modules.Contains((ModuleDefMD)declType.Module)) {
var memberDef = (IDnlibDef)declType.ResolveThrow(memberRef);
service.AddReference(memberDef, new MemberRefReference(memberRef, memberDef));
Expand Down
12 changes: 6 additions & 6 deletions Confuser.Renamer/Analyzers/LdtokenEnumAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ public void Analyze(ConfuserContext context, INameService service, ProtectionPar
}
else if (instr.Operand is ITypeDefOrRef) {
if (!(instr.Operand is TypeSpec)) {
TypeDef type = ((ITypeDefOrRef)instr.Operand).ResolveTypeDefThrow();
if (context.Modules.Contains((ModuleDefMD)type.Module) &&
HandleTypeOf(context, service, method, i)) {
var type = ((ITypeDefOrRef)instr.Operand).ResolveTypeDef();
if (!(type is null) && context.Modules.Contains((ModuleDefMD)type.Module) &&
HandleTypeOf(context, service, method, i)) {
var t = type;
do {
DisableRename(service, t, false);
Expand Down Expand Up @@ -108,11 +108,11 @@ void HandleEnum(ConfuserContext context, INameService service, MethodDef method,
else
return;

ITypeDefOrRef targetTypeRef = targetType.ToBasicTypeDefOrRef();
var targetTypeRef = targetType.ToBasicTypeDefOrRef();
if (targetTypeRef == null)
return;

TypeDef targetTypeDef = targetTypeRef.ResolveTypeDefThrow();
var targetTypeDef = targetTypeRef.ResolveTypeDef();
if (targetTypeDef != null && targetTypeDef.IsEnum && context.Modules.Contains((ModuleDefMD)targetTypeDef.Module))
DisableRename(service, targetTypeDef);
}
Expand Down Expand Up @@ -183,4 +183,4 @@ void DisableRename(INameService service, TypeDef typeDef, bool memberOnly = true
DisableRename(service, nested, false);
}
}
}
}
8 changes: 4 additions & 4 deletions Confuser.Renamer/Analyzers/TypeBlobAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ public static void Analyze(INameService service, ICollection<ModuleDefMD> module
foreach (CANamedArgument arg in attr.Properties)
AnalyzeCAArgument(modules, service, arg.Argument);

TypeDef attrType = attr.AttributeType.ResolveTypeDefThrow();
if (!modules.Contains((ModuleDefMD)attrType.Module))
TypeDef attrType = attr.AttributeType.ResolveTypeDef();
if (attrType is null || !modules.Contains((ModuleDefMD)attrType.Module))
continue;

foreach (var arg in attr.NamedArguments) {
Expand Down Expand Up @@ -159,8 +159,8 @@ private static void AnalyzeMemberRef(ICollection<ModuleDefMD> modules, INameServ
if (sig is GenericInstSig) {
var inst = (GenericInstSig)sig;
Debug.Assert(!(inst.GenericType.TypeDefOrRef is TypeSpec));
TypeDef openType = inst.GenericType.TypeDefOrRef.ResolveTypeDefThrow();
if (!modules.Contains((ModuleDefMD)openType.Module) ||
TypeDef openType = inst.GenericType.TypeDefOrRef.ResolveTypeDef();
if (openType is null || !modules.Contains((ModuleDefMD)openType.Module) ||
memberRef.IsArrayAccessors())
return;

Expand Down
Loading

0 comments on commit e79b8ab

Please sign in to comment.