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 Dec 23, 2020
1 parent e58a29a commit f1ccb1e
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 77 deletions.
1 change: 1 addition & 0 deletions Confuser.Core/Confuser.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
<PackageReference Include="Microsoft.DiaSymReader.Native" Version="1.7.0" />
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
<PackageReference Include="System.Threading" Version="4.3.0" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
</ItemGroup>

<ItemGroup>
Expand Down
34 changes: 15 additions & 19 deletions Confuser.Core/ConfuserEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -262,14 +262,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 {
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 @@ -311,7 +307,7 @@ static void CheckStrongName(ConfuserContext context, ModuleDef module) {
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))
!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 All @@ -338,23 +334,23 @@ static void BeginModule(ConfuserContext context) {
if (!context.CurrentModule.IsILOnly || context.CurrentModule.VTableFixups != null)
context.RequestNative();

var snKey = context.Annotations.Get<StrongNameKey>(context.CurrentModule, Marker.SNKey);
var snPubKey = context.Annotations.Get<StrongNamePublicKey>(context.CurrentModule, Marker.SNPubKey);
var snSigKey = context.Annotations.Get<StrongNameKey>(context.CurrentModule, Marker.SNSigKey);
var snKey = context.Annotations.Get<StrongNameKey>(context.CurrentModule, Marker.SNKey);
var snPubKey = context.Annotations.Get<StrongNamePublicKey>(context.CurrentModule, Marker.SNPubKey);
var snSigKey = context.Annotations.Get<StrongNameKey>(context.CurrentModule, Marker.SNSigKey);
var snSigPubKey = context.Annotations.Get<StrongNamePublicKey>(context.CurrentModule, Marker.SNSigPubKey);

var snDelaySig = context.Annotations.Get<bool>(context.CurrentModule, Marker.SNDelaySig, false);

var snDelaySig = context.Annotations.Get<bool>(context.CurrentModule, Marker.SNDelaySig, false);

context.CurrentModuleWriterOptions.DelaySign = snDelaySig;

if (snKey != null && snPubKey != null && snSigKey != null && snSigPubKey != null)
context.CurrentModuleWriterOptions.InitializeEnhancedStrongNameSigning(context.CurrentModule, snSigKey, snSigPubKey, snKey, snPubKey);
else if (snSigPubKey != null && snSigKey != null)
context.CurrentModuleWriterOptions.InitializeEnhancedStrongNameSigning(context.CurrentModule, snSigKey, snSigPubKey);
else
else if (snSigPubKey != null && snSigKey != null)
context.CurrentModuleWriterOptions.InitializeEnhancedStrongNameSigning(context.CurrentModule, snSigKey, snSigPubKey);
else
context.CurrentModuleWriterOptions.InitializeStrongNameSigning(context.CurrentModule, snKey);

if (snDelaySig) {
if (snDelaySig) {
context.CurrentModuleWriterOptions.StrongNamePublicKey = snPubKey;
context.CurrentModuleWriterOptions.StrongNameKey = null;
}
Expand Down Expand Up @@ -528,7 +524,7 @@ static void PrintEnvironmentInfo(ConfuserContext context) {

if (context.Resolver != null) {
context.Logger.Error("Cached assemblies:");
foreach (AssemblyDef asm in context.InternalResolver.GetCachedAssemblies()) {
foreach (var asm in context.InternalResolver.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
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 = (IMemberDef)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
53 changes: 30 additions & 23 deletions Confuser.Renamer/VTable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,9 @@ public static VTable ConstructVTable(TypeDef typeDef, VTableStorage storage) {
foreach (var impl in method.Value.Overrides) {
Debug.Assert(impl.MethodBody == method.Value);

MethodDef targetMethod = impl.MethodDeclaration.ResolveThrow();
var targetMethod = impl.MethodDeclaration.ResolveMethodDef();
if (targetMethod is null) continue;

if (targetMethod.DeclaringType.IsInterface) {
var iface = impl.MethodDeclaration.DeclaringType.ToTypeSig();
CheckKeyExist(storage, vTbl.InterfaceSlots, iface, "MethodImpl Iface");
Expand All @@ -239,7 +241,7 @@ public static VTable ConstructVTable(TypeDef typeDef, VTableStorage storage) {
});
}
else {
var targetSlot = vTbl.AllSlots.Single(slot => slot.MethodDef == targetMethod);
var targetSlot = vTbl.AllSlots.Single(slot => MethodEqualityComparer.CompareDeclaringTypes.Equals(slot.MethodDef, targetMethod));
CheckKeyExist(storage, vTbl.SlotsMap, targetSlot.Signature, "MethodImpl Normal Sig");
targetSlot = vTbl.SlotsMap[targetSlot.Signature]; // Use the most derived slot
// Maybe implemented by above processes --- this process should take priority
Expand Down Expand Up @@ -357,35 +359,40 @@ public VTable this[TypeDef type] {
}

VTable GetOrConstruct(TypeDef type) {
VTable ret;
if (!storage.TryGetValue(type, out ret))
if (type is null) return null;
if (!storage.TryGetValue(type, out var ret))
ret = storage[type] = VTable.ConstructVTable(type, this);
return ret;
}

public VTable GetVTable(ITypeDefOrRef type) {
if (type == null)
return null;
if (type is TypeDef)
return GetOrConstruct((TypeDef)type);
if (type is TypeRef)
return GetOrConstruct(((TypeRef)type).ResolveThrow());
if (type is TypeSpec) {
TypeSig sig = ((TypeSpec)type).TypeSig;
if (sig is TypeDefOrRefSig) {
TypeDef typeDef = ((TypeDefOrRefSig)sig).TypeDefOrRef.ResolveTypeDefThrow();
switch (type) {
case null:
return null;
case TypeDef typeDef:
return GetOrConstruct(typeDef);
case TypeRef typeRef:
return GetOrConstruct(typeRef.Resolve());
case TypeSpec typeSpec: {
var sig = typeSpec.TypeSig;
switch (sig) {
case TypeDefOrRefSig defOrRefSig: {
var sigTypeDef = defOrRefSig.TypeDefOrRef.ResolveTypeDef();
return GetOrConstruct(sigTypeDef);
}
case GenericInstSig genInst: {
var openType = genInst.GenericType.TypeDefOrRef.ResolveTypeDef();
var vTable = GetOrConstruct(openType);

return vTable is null ? null : ResolveGenericArgument(openType, genInst, vTable);
}
default:
throw new NotSupportedException("Unexpected type: " + type);
}
}
if (sig is GenericInstSig) {
var genInst = (GenericInstSig)sig;
TypeDef openType = genInst.GenericType.TypeDefOrRef.ResolveTypeDefThrow();
VTable vTable = GetOrConstruct(openType);

return ResolveGenericArgument(openType, genInst, vTable);
}
throw new NotSupportedException("Unexpected type: " + type);
default:
throw new UnreachableException();
}
throw new UnreachableException();
}

static VTableSlot ResolveSlot(TypeDef openType, VTableSlot slot, IList<TypeSig> genArgs) {
Expand Down

0 comments on commit f1ccb1e

Please sign in to comment.