Skip to content

Commit 990856a

Browse files
committed
Obfuscating assemblies with missing dependencies
ConfuserEx is now able to obfuscate assemblies without all the dependencies. It makes some worst case assumptions for missing dependencies.
1 parent dd43ff9 commit 990856a

File tree

8 files changed

+79
-78
lines changed

8 files changed

+79
-78
lines changed

Confuser.Core/Confuser.Core.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
<PackageReference Include="Microsoft.DiaSymReader.Native" Version="1.7.0" />
2020
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
2121
<PackageReference Include="System.Threading" Version="4.3.0" />
22+
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
2223
</ItemGroup>
2324

2425
<ItemGroup>

Confuser.Core/ConfuserEngine.cs

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -262,14 +262,10 @@ static void RunPipeline(ProtectionPipeline pipeline, ConfuserContext context) {
262262
static void Inspection(ConfuserContext context) {
263263
context.Logger.Info("Resolving dependencies...");
264264
foreach (var dependency in context.Modules
265-
.SelectMany(module => module.GetAssemblyRefs().Select(asmRef => Tuple.Create(asmRef, module)))) {
266-
try {
267-
context.Resolver.ResolveThrow(dependency.Item1, dependency.Item2);
268-
}
269-
catch (AssemblyResolveException ex) {
270-
context.Logger.ErrorException("Failed to resolve dependency of '" + dependency.Item2.Name + "'.", ex);
271-
throw new ConfuserException(ex);
272-
}
265+
.SelectMany(module => module.GetAssemblyRefs().Select(asmRef => (asmRef, module)))) {
266+
var assembly = context.Resolver.Resolve(dependency.asmRef, dependency.module);
267+
if (assembly is null)
268+
context.Logger.Warn("Failed to resolve dependency '" + dependency.asmRef.FullName + "'.");
273269
}
274270

275271
context.Logger.Debug("Checking Strong Name...");
@@ -311,7 +307,7 @@ static void CheckStrongName(ConfuserContext context, ModuleDef module) {
311307
else if (isKeyProvided && !moduleIsSignedOrDelayedSigned)
312308
context.Logger.WarnFormat("[{0}] SN Key or SN public Key is provided for an unsigned module, the output may not be working.", module.Name);
313309
else if (snPubKeyBytes != null && moduleIsSignedOrDelayedSigned &&
314-
!module.Assembly.PublicKey.Data.SequenceEqual(snPubKeyBytes))
310+
!module.Assembly.PublicKey.Data.SequenceEqual(snPubKeyBytes))
315311
context.Logger.WarnFormat("[{0}] Provided SN public Key and signed module's public key do not match, the output may not be working.",
316312
module.Name);
317313
}
@@ -338,23 +334,23 @@ static void BeginModule(ConfuserContext context) {
338334
if (!context.CurrentModule.IsILOnly || context.CurrentModule.VTableFixups != null)
339335
context.RequestNative();
340336

341-
var snKey = context.Annotations.Get<StrongNameKey>(context.CurrentModule, Marker.SNKey);
342-
var snPubKey = context.Annotations.Get<StrongNamePublicKey>(context.CurrentModule, Marker.SNPubKey);
343-
var snSigKey = context.Annotations.Get<StrongNameKey>(context.CurrentModule, Marker.SNSigKey);
337+
var snKey = context.Annotations.Get<StrongNameKey>(context.CurrentModule, Marker.SNKey);
338+
var snPubKey = context.Annotations.Get<StrongNamePublicKey>(context.CurrentModule, Marker.SNPubKey);
339+
var snSigKey = context.Annotations.Get<StrongNameKey>(context.CurrentModule, Marker.SNSigKey);
344340
var snSigPubKey = context.Annotations.Get<StrongNamePublicKey>(context.CurrentModule, Marker.SNSigPubKey);
345341

346-
var snDelaySig = context.Annotations.Get<bool>(context.CurrentModule, Marker.SNDelaySig, false);
347-
342+
var snDelaySig = context.Annotations.Get<bool>(context.CurrentModule, Marker.SNDelaySig, false);
343+
348344
context.CurrentModuleWriterOptions.DelaySign = snDelaySig;
349345

350346
if (snKey != null && snPubKey != null && snSigKey != null && snSigPubKey != null)
351347
context.CurrentModuleWriterOptions.InitializeEnhancedStrongNameSigning(context.CurrentModule, snSigKey, snSigPubKey, snKey, snPubKey);
352-
else if (snSigPubKey != null && snSigKey != null)
353-
context.CurrentModuleWriterOptions.InitializeEnhancedStrongNameSigning(context.CurrentModule, snSigKey, snSigPubKey);
354-
else
348+
else if (snSigPubKey != null && snSigKey != null)
349+
context.CurrentModuleWriterOptions.InitializeEnhancedStrongNameSigning(context.CurrentModule, snSigKey, snSigPubKey);
350+
else
355351
context.CurrentModuleWriterOptions.InitializeStrongNameSigning(context.CurrentModule, snKey);
356352

357-
if (snDelaySig) {
353+
if (snDelaySig) {
358354
context.CurrentModuleWriterOptions.StrongNamePublicKey = snPubKey;
359355
context.CurrentModuleWriterOptions.StrongNameKey = null;
360356
}
@@ -528,7 +524,7 @@ static void PrintEnvironmentInfo(ConfuserContext context) {
528524

529525
if (context.Resolver != null) {
530526
context.Logger.Error("Cached assemblies:");
531-
foreach (AssemblyDef asm in context.InternalResolver.GetCachedAssemblies()) {
527+
foreach (var asm in context.InternalResolver.GetCachedAssemblies().Where(a => !(a is null))) {
532528
if (string.IsNullOrEmpty(asm.ManifestModule.Location))
533529
context.Logger.ErrorFormat(" {0}", asm.FullName);
534530
else

Confuser.Core/DnlibUtils.cs

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -208,16 +208,14 @@ public static bool IsDelegate(this TypeDef type) {
208208
/// <param name="type">The type.</param>
209209
/// <param name="baseType">The full name of base type.</param>
210210
/// <returns><c>true</c> if the specified type is inherited from a base type; otherwise, <c>false</c>.</returns>
211-
public static bool InheritsFromCorlib(this TypeDef type, string baseType) {
212-
if (type.BaseType == null)
213-
return false;
214-
215-
TypeDef bas = type;
216-
do {
217-
bas = bas.BaseType.ResolveTypeDefThrow();
211+
public static bool InheritsFromCorLib(this TypeDef type, string baseType) {
212+
var bas = type.GetBaseType();
213+
while (!(bas is null) && bas.DefinitionAssembly.IsCorLib()) {
218214
if (bas.ReflectionFullName == baseType)
219215
return true;
220-
} while (bas.BaseType != null && bas.BaseType.DefinitionAssembly.IsCorLib());
216+
217+
bas = bas.GetBaseType();
218+
}
221219
return false;
222220
}
223221

@@ -228,15 +226,13 @@ public static bool InheritsFromCorlib(this TypeDef type, string baseType) {
228226
/// <param name="baseType">The full name of base type.</param>
229227
/// <returns><c>true</c> if the specified type is inherited from a base type; otherwise, <c>false</c>.</returns>
230228
public static bool InheritsFrom(this TypeDef type, string baseType) {
231-
if (type.BaseType == null)
232-
return false;
233-
234-
TypeDef bas = type;
235-
do {
236-
bas = bas.BaseType.ResolveTypeDefThrow();
229+
var bas = type.GetBaseType();
230+
while (!(bas is null)) {
237231
if (bas.ReflectionFullName == baseType)
238232
return true;
239-
} while (bas.BaseType != null);
233+
234+
bas = bas.GetBaseType();
235+
}
240236
return false;
241237
}
242238

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

256-
if (type.BaseType == null)
257-
return false;
258-
259-
type = type.BaseType.ResolveTypeDefThrow();
251+
type = type.GetBaseType() as TypeDef;
260252
} while (type != null);
261-
throw new UnreachableException();
253+
254+
return false;
262255
}
263256

264257
/// <summary>

Confuser.Renamer/AnalyzePhase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ void Analyze(NameService service, ConfuserContext context, ProtectionParameters
175175
if (parameters.GetParameter(context, type, "forceRen", false))
176176
return;
177177

178-
if (type.InheritsFromCorlib("System.Attribute")) {
178+
if (type.InheritsFromCorLib("System.Attribute")) {
179179
service.ReduceRenameMode(type, RenameMode.Reflection);
180180
}
181181

Confuser.Renamer/Analyzers/InterReferenceAnalyzer.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@ public void Analyze(ConfuserContext context, INameService service, ProtectionPar
3535
for (uint i = 1; i <= len; i++) {
3636
TypeRef typeRef = module.ResolveTypeRef(i);
3737

38-
TypeDef typeDef = typeRef.ResolveTypeDefThrow();
38+
TypeDef typeDef = typeRef.ResolveTypeDef();
39+
if (typeDef is null) continue;
40+
3941
if (typeDef.Module != module && context.Modules.Contains((ModuleDefMD)typeDef.Module)) {
4042
service.AddReference(typeDef, new TypeRefReference(typeRef, typeDef));
4143
}
@@ -51,7 +53,9 @@ void ProcessMemberRef(ConfuserContext context, INameService service, ModuleDefMD
5153
if (memberRef.DeclaringType.TryGetArraySig() != null)
5254
return;
5355

54-
TypeDef declType = memberRef.DeclaringType.ResolveTypeDefThrow();
56+
TypeDef declType = memberRef.DeclaringType.ResolveTypeDef();
57+
if (declType is null) return;
58+
5559
if (declType.Module != module && context.Modules.Contains((ModuleDefMD)declType.Module)) {
5660
var memberDef = (IMemberDef)declType.ResolveThrow(memberRef);
5761
service.AddReference(memberDef, new MemberRefReference(memberRef, memberDef));

Confuser.Renamer/Analyzers/LdtokenEnumAnalyzer.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ public void Analyze(ConfuserContext context, INameService service, ProtectionPar
3838
}
3939
else if (instr.Operand is ITypeDefOrRef) {
4040
if (!(instr.Operand is TypeSpec)) {
41-
TypeDef type = ((ITypeDefOrRef)instr.Operand).ResolveTypeDefThrow();
42-
if (context.Modules.Contains((ModuleDefMD)type.Module) &&
43-
HandleTypeOf(context, service, method, i)) {
41+
var type = ((ITypeDefOrRef)instr.Operand).ResolveTypeDef();
42+
if (!(type is null) && context.Modules.Contains((ModuleDefMD)type.Module) &&
43+
HandleTypeOf(context, service, method, i)) {
4444
var t = type;
4545
do {
4646
DisableRename(service, t, false);
@@ -108,11 +108,11 @@ void HandleEnum(ConfuserContext context, INameService service, MethodDef method,
108108
else
109109
return;
110110

111-
ITypeDefOrRef targetTypeRef = targetType.ToBasicTypeDefOrRef();
111+
var targetTypeRef = targetType.ToBasicTypeDefOrRef();
112112
if (targetTypeRef == null)
113113
return;
114114

115-
TypeDef targetTypeDef = targetTypeRef.ResolveTypeDefThrow();
115+
var targetTypeDef = targetTypeRef.ResolveTypeDef();
116116
if (targetTypeDef != null && targetTypeDef.IsEnum && context.Modules.Contains((ModuleDefMD)targetTypeDef.Module))
117117
DisableRename(service, targetTypeDef);
118118
}
@@ -183,4 +183,4 @@ void DisableRename(INameService service, TypeDef typeDef, bool memberOnly = true
183183
DisableRename(service, nested, false);
184184
}
185185
}
186-
}
186+
}

Confuser.Renamer/Analyzers/TypeBlobAnalyzer.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ public static void Analyze(INameService service, ICollection<ModuleDefMD> module
6868
foreach (CANamedArgument arg in attr.Properties)
6969
AnalyzeCAArgument(modules, service, arg.Argument);
7070

71-
TypeDef attrType = attr.AttributeType.ResolveTypeDefThrow();
72-
if (!modules.Contains((ModuleDefMD)attrType.Module))
71+
TypeDef attrType = attr.AttributeType.ResolveTypeDef();
72+
if (attrType is null || !modules.Contains((ModuleDefMD)attrType.Module))
7373
continue;
7474

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

Confuser.Renamer/VTable.cs

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,9 @@ public static VTable ConstructVTable(TypeDef typeDef, VTableStorage storage) {
214214
foreach (var impl in method.Value.Overrides) {
215215
Debug.Assert(impl.MethodBody == method.Value);
216216

217-
MethodDef targetMethod = impl.MethodDeclaration.ResolveThrow();
217+
var targetMethod = impl.MethodDeclaration.ResolveMethodDef();
218+
if (targetMethod is null) continue;
219+
218220
if (targetMethod.DeclaringType.IsInterface) {
219221
var iface = impl.MethodDeclaration.DeclaringType.ToTypeSig();
220222
CheckKeyExist(storage, vTbl.InterfaceSlots, iface, "MethodImpl Iface");
@@ -239,7 +241,7 @@ public static VTable ConstructVTable(TypeDef typeDef, VTableStorage storage) {
239241
});
240242
}
241243
else {
242-
var targetSlot = vTbl.AllSlots.Single(slot => slot.MethodDef == targetMethod);
244+
var targetSlot = vTbl.AllSlots.Single(slot => MethodEqualityComparer.CompareDeclaringTypes.Equals(slot.MethodDef, targetMethod));
243245
CheckKeyExist(storage, vTbl.SlotsMap, targetSlot.Signature, "MethodImpl Normal Sig");
244246
targetSlot = vTbl.SlotsMap[targetSlot.Signature]; // Use the most derived slot
245247
// Maybe implemented by above processes --- this process should take priority
@@ -357,35 +359,40 @@ public VTable this[TypeDef type] {
357359
}
358360

359361
VTable GetOrConstruct(TypeDef type) {
360-
VTable ret;
361-
if (!storage.TryGetValue(type, out ret))
362+
if (type is null) return null;
363+
if (!storage.TryGetValue(type, out var ret))
362364
ret = storage[type] = VTable.ConstructVTable(type, this);
363365
return ret;
364366
}
365367

366368
public VTable GetVTable(ITypeDefOrRef type) {
367-
if (type == null)
368-
return null;
369-
if (type is TypeDef)
370-
return GetOrConstruct((TypeDef)type);
371-
if (type is TypeRef)
372-
return GetOrConstruct(((TypeRef)type).ResolveThrow());
373-
if (type is TypeSpec) {
374-
TypeSig sig = ((TypeSpec)type).TypeSig;
375-
if (sig is TypeDefOrRefSig) {
376-
TypeDef typeDef = ((TypeDefOrRefSig)sig).TypeDefOrRef.ResolveTypeDefThrow();
369+
switch (type) {
370+
case null:
371+
return null;
372+
case TypeDef typeDef:
377373
return GetOrConstruct(typeDef);
374+
case TypeRef typeRef:
375+
return GetOrConstruct(typeRef.Resolve());
376+
case TypeSpec typeSpec: {
377+
var sig = typeSpec.TypeSig;
378+
switch (sig) {
379+
case TypeDefOrRefSig defOrRefSig: {
380+
var sigTypeDef = defOrRefSig.TypeDefOrRef.ResolveTypeDef();
381+
return GetOrConstruct(sigTypeDef);
382+
}
383+
case GenericInstSig genInst: {
384+
var openType = genInst.GenericType.TypeDefOrRef.ResolveTypeDef();
385+
var vTable = GetOrConstruct(openType);
386+
387+
return vTable is null ? null : ResolveGenericArgument(openType, genInst, vTable);
388+
}
389+
default:
390+
throw new NotSupportedException("Unexpected type: " + type);
391+
}
378392
}
379-
if (sig is GenericInstSig) {
380-
var genInst = (GenericInstSig)sig;
381-
TypeDef openType = genInst.GenericType.TypeDefOrRef.ResolveTypeDefThrow();
382-
VTable vTable = GetOrConstruct(openType);
383-
384-
return ResolveGenericArgument(openType, genInst, vTable);
385-
}
386-
throw new NotSupportedException("Unexpected type: " + type);
393+
default:
394+
throw new UnreachableException();
387395
}
388-
throw new UnreachableException();
389396
}
390397

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

0 commit comments

Comments
 (0)