TypeScrambler
Add generic type scrambling protection
This commit is contained in:
Родитель
cbd2c7669c
Коммит
d8a40d4e23
Двоичный файл не отображается.
|
@ -39,7 +39,7 @@ public static class Program {
|
|||
Console.WriteLine("error when executing git describe.");
|
||||
}
|
||||
}
|
||||
tag = tag ?? "v" + ver + "-custom";
|
||||
tag = tag ?? "v" + ver;
|
||||
|
||||
string template = Path.Combine(dir, "GlobalAssemblyInfo.Template.cs");
|
||||
string output = Path.Combine(dir, "GlobalAssemblyInfo.cs");
|
||||
|
|
|
@ -117,6 +117,28 @@
|
|||
<Compile Include="Resources\NormalMode.cs" />
|
||||
<Compile Include="Resources\REContext.cs" />
|
||||
<Compile Include="Resources\ResourceProtection.cs" />
|
||||
<Compile Include="TypeScrambler\AnalyzePhase.cs" />
|
||||
<Compile Include="TypeScrambler\ScramblePhase.cs" />
|
||||
<Compile Include="TypeScrambler\Scrambler\Analyzers\ContextAnalyzer.cs" />
|
||||
<Compile Include="TypeScrambler\Scrambler\Analyzers\ContextAnalyzerFactory.cs" />
|
||||
<Compile Include="TypeScrambler\Scrambler\Analyzers\MemberRefAnalyzer.cs" />
|
||||
<Compile Include="TypeScrambler\Scrambler\Analyzers\MethodDefAnalyzer.cs" />
|
||||
<Compile Include="TypeScrambler\Scrambler\Analyzers\MethodSpecAnalyzer.cs" />
|
||||
<Compile Include="TypeScrambler\Scrambler\Analyzers\TypeRefAnalyzer.cs" />
|
||||
<Compile Include="TypeScrambler\Scrambler\Rewriter\EmbeddedCode\ObjectCreationFactory.cs" />
|
||||
<Compile Include="TypeScrambler\Scrambler\Rewriter\Instructions\InstructionRewriter.cs" />
|
||||
<Compile Include="TypeScrambler\Scrambler\Rewriter\Instructions\InstructionRewriterFactory.cs" />
|
||||
<Compile Include="TypeScrambler\Scrambler\Rewriter\Instructions\MemberRefInstructionRewriter.cs" />
|
||||
<Compile Include="TypeScrambler\Scrambler\Rewriter\Instructions\MethodDefInstructionRewriter.cs" />
|
||||
<Compile Include="TypeScrambler\Scrambler\Rewriter\Instructions\MethodSpecInstructionRewriter.cs" />
|
||||
<Compile Include="TypeScrambler\Scrambler\Rewriter\Instructions\TypeDefInstructionRewriter.cs" />
|
||||
<Compile Include="TypeScrambler\Scrambler\Rewriter\Instructions\TypeRefInstructionRewriter.cs" />
|
||||
<Compile Include="TypeScrambler\Scrambler\ScannedItem.cs" />
|
||||
<Compile Include="TypeScrambler\Scrambler\ScannedMethod.cs" />
|
||||
<Compile Include="TypeScrambler\Scrambler\ScannedType.cs" />
|
||||
<Compile Include="TypeScrambler\Scrambler\TypeRewriter.cs" />
|
||||
<Compile Include="TypeScrambler\TypeScrambleProtection.cs" />
|
||||
<Compile Include="TypeScrambler\TypeService.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\ConfuserEx.snk">
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
using Confuser.Core;
|
||||
using Confuser.Protections.TypeScramble.Scrambler;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Confuser.Protections.TypeScramble {
|
||||
class AnalyzePhase : ProtectionPhase {
|
||||
|
||||
public AnalyzePhase(TypeScrambleProtection parent) : base(parent){
|
||||
}
|
||||
|
||||
public override ProtectionTargets Targets => ProtectionTargets.Types | ProtectionTargets.Methods;
|
||||
|
||||
public override string Name => "Type scanner";
|
||||
|
||||
protected override void Execute(ConfuserContext context, ProtectionParameters parameters) {
|
||||
|
||||
//CreateGenericsForTypes(context, parameters.Targets.OfType<TypeDef>().WithProgress(context.Logger));
|
||||
|
||||
CreateGenericsForMethods(context, parameters.Targets.OfType<MethodDef>()
|
||||
.OrderBy(x =>
|
||||
x?.Parameters?.Count ?? 0 +
|
||||
x.Body?.Variables?.Count ?? 0)
|
||||
.WithProgress(context.Logger));
|
||||
}
|
||||
|
||||
|
||||
private void CreateGenericsForTypes(ConfuserContext context, IEnumerable<TypeDef> types) {
|
||||
TypeService service = context.Registry.GetService<TypeService>();
|
||||
|
||||
foreach (TypeDef type in types) {
|
||||
if(type.Module.EntryPoint.DeclaringType != type) {
|
||||
service.AddScannedItem(new ScannedType(type));
|
||||
context.CheckCancellation();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateGenericsForMethods(ConfuserContext context, IEnumerable<MethodDef> methods) {
|
||||
TypeService service = context.Registry.GetService<TypeService>();
|
||||
|
||||
foreach(MethodDef method in methods) {
|
||||
|
||||
/*
|
||||
context.Logger.DebugFormat("[{0}]", method.Name);
|
||||
if (method.HasBody) {
|
||||
foreach(var i in method.Body.Instructions) {
|
||||
context.Logger.DebugFormat("{0} - {1} : {2}", i.OpCode, i?.Operand?.GetType().ToString() ?? "NULL", i.Operand);
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
if(method.Module.EntryPoint != method && !(method.HasOverrides || method.IsAbstract || method.IsConstructor || method.IsGetter) ) {
|
||||
service.AddScannedItem(new ScannedMethod(service, method));
|
||||
context.CheckCancellation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
using Confuser.Core;
|
||||
using Confuser.Protections.TypeScramble.Scrambler;
|
||||
using dnlib.DotNet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Confuser.Protections.TypeScramble {
|
||||
class ScramblePhase : ProtectionPhase {
|
||||
|
||||
public ScramblePhase(TypeScrambleProtection parent) : base(parent){
|
||||
}
|
||||
|
||||
public override ProtectionTargets Targets => ProtectionTargets.Types | ProtectionTargets.Methods | ProtectionTargets.Modules;
|
||||
|
||||
public override string Name =>"Type scrambler";
|
||||
|
||||
protected override void Execute(ConfuserContext context, ProtectionParameters parameters) {
|
||||
|
||||
var rewriter = new TypeRewriter(context);
|
||||
rewriter.ApplyGeterics();
|
||||
|
||||
foreach (IDnlibDef def in parameters.Targets.WithProgress(context.Logger)) {
|
||||
|
||||
switch (def) {
|
||||
|
||||
case MethodDef md:
|
||||
if (md.HasBody) {
|
||||
rewriter.Process(md);
|
||||
}
|
||||
break;
|
||||
case ModuleDef mod:
|
||||
rewriter.ImportCode(mod);
|
||||
break;
|
||||
}
|
||||
|
||||
context.CheckCancellation();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Confuser.Protections.TypeScramble.Scrambler.Analyzers {
|
||||
public abstract class ContextAnalyzer {
|
||||
|
||||
public abstract Type TargetType();
|
||||
|
||||
public abstract void ProcessOperand(ScannedMethod m, object o);
|
||||
}
|
||||
|
||||
|
||||
public abstract class ContextAnalyzer<T> : ContextAnalyzer {
|
||||
public override Type TargetType() => typeof(T);
|
||||
public abstract void Process(ScannedMethod m, T o);
|
||||
public override void ProcessOperand(ScannedMethod m, object o) {
|
||||
Process(m, (T)o);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Confuser.Protections.TypeScramble.Scrambler.Analyzers {
|
||||
public class ContextAnalyzerFactory : IEnumerable {
|
||||
|
||||
public Dictionary<Type, ContextAnalyzer> Analyzers = new Dictionary<Type, ContextAnalyzer>();
|
||||
private ScannedMethod targetMethod;
|
||||
public ContextAnalyzerFactory(ScannedMethod m) {
|
||||
targetMethod = m;
|
||||
}
|
||||
|
||||
public void Add(ContextAnalyzer a) {
|
||||
Analyzers.Add(a.TargetType(), a);
|
||||
}
|
||||
|
||||
public void Analyze(object o) {
|
||||
ContextAnalyzer a;
|
||||
Analyzers.TryGetValue(o.GetType().BaseType, out a);
|
||||
a?.ProcessOperand(targetMethod, o);
|
||||
}
|
||||
|
||||
public IEnumerator GetEnumerator() {
|
||||
return Analyzers.Values.GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
using dnlib.DotNet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Confuser.Protections.TypeScramble.Scrambler.Analyzers {
|
||||
class MemberRefAnalyzer : ContextAnalyzer<MemberRef> {
|
||||
public override void Process(ScannedMethod m, MemberRef o) {
|
||||
|
||||
TypeSig sig = null;
|
||||
|
||||
if (o.Class is TypeRef) {
|
||||
sig = (o.Class as TypeRef)?.ToTypeSig();
|
||||
|
||||
}
|
||||
|
||||
if (o.Class is TypeSpec) {
|
||||
sig = (o.Class as TypeSpec)?.ToTypeSig();
|
||||
}
|
||||
if (sig != null) {
|
||||
m.RegisterGeneric(sig);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
using dnlib.DotNet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Confuser.Protections.TypeScramble.Scrambler.Analyzers {
|
||||
class MethodDefAnalyzer : ContextAnalyzer<MethodDef> {
|
||||
private TypeService service;
|
||||
|
||||
public MethodDefAnalyzer(TypeService _service) {
|
||||
service = _service;
|
||||
}
|
||||
public override void Process(ScannedMethod m, MethodDef o) {
|
||||
var sc = service.GetItem(o.MDToken) as ScannedMethod;
|
||||
if(sc != null) {
|
||||
|
||||
foreach (var regTypes in sc.TrueTypes) {
|
||||
m.RegisterGeneric(regTypes);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
using dnlib.DotNet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Confuser.Protections.TypeScramble.Scrambler.Analyzers {
|
||||
class MethodSpecAnalyzer : ContextAnalyzer<MethodSpec> {
|
||||
public override void Process(ScannedMethod m, MethodSpec o) {
|
||||
|
||||
foreach (var t in o.GenericInstMethodSig.GenericArguments) {
|
||||
m.RegisterGeneric(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
using dnlib.DotNet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Confuser.Protections.TypeScramble.Scrambler.Analyzers {
|
||||
class TypeRefAnalyzer : ContextAnalyzer<TypeRef> {
|
||||
public override void Process(ScannedMethod m, TypeRef o) {
|
||||
|
||||
m.RegisterGeneric(o.ToTypeSig());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
using dnlib.DotNet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Confuser.Protections.TypeScramble.Scrambler.Rewriter.EmbeddedCode {
|
||||
public class ObjectCreationFactory {
|
||||
|
||||
public static void Import(ModuleDef mod) {
|
||||
|
||||
var curMod = ModuleDefMD.Load(typeof(ObjectCreationFactory).Module);
|
||||
|
||||
var t = curMod.Find(typeof(ObjectCreationFactory).FullName, true);
|
||||
curMod.Types.Remove(t);
|
||||
|
||||
var newT = new TypeDefUser("ObjectCreationFactory");
|
||||
var methods = t.Methods.ToArray();
|
||||
foreach (var m in methods) {
|
||||
m.DeclaringType = null;
|
||||
newT.Methods.Add(m);
|
||||
}
|
||||
|
||||
mod.Types.Add(t);
|
||||
// return newT;
|
||||
}
|
||||
|
||||
public static T Create<T>() {
|
||||
return Activator.CreateInstance<T>();
|
||||
}
|
||||
public static TR Create<TR, T0>(T0 p0) {
|
||||
return (TR)Activator.CreateInstance(typeof(TR), new object[] { p0 });
|
||||
}
|
||||
|
||||
public static TR Create<TR, T0, T1>(T0 p0, T1 p1) {
|
||||
return (TR)Activator.CreateInstance(typeof(TR), new object[] { p0, p1 });
|
||||
}
|
||||
|
||||
public static TR Create<TR, T0, T1, T2>(T0 p0, T1 p1, T2 p2) {
|
||||
return (TR)Activator.CreateInstance(typeof(TR), new object[] { p0, p1, p2 });
|
||||
}
|
||||
|
||||
public static TR Create<TR, T0, T1, T2, T3>(T0 p0, T1 p1, T2 p2, T3 p3) {
|
||||
return (TR)Activator.CreateInstance(typeof(TR), new object[] { p0, p1, p2, p3 });
|
||||
}
|
||||
|
||||
public static TR Create<TR, T0, T1, T2, T3, T4>(T0 p0, T1 p1, T2 p2, T3 p3, T4 p4) {
|
||||
return (TR)Activator.CreateInstance(typeof(TR), new object[] { p0, p1, p2, p3, p4 });
|
||||
}
|
||||
|
||||
public static TR Create<TR, T0, T1, T2, T3, T4, T5>(T0 p0, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5) {
|
||||
return (TR)Activator.CreateInstance(typeof(TR), new object[] { p0, p1, p2, p3, p4, p5 });
|
||||
}
|
||||
|
||||
public static TR Create<TR, T0, T1, T2, T3, T4, T5, T6>(T0 p0, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6) {
|
||||
return (TR)Activator.CreateInstance(typeof(TR), new object[] { p0, p1, p2, p3, p4, p5, p6 });
|
||||
}
|
||||
|
||||
public static TR Create<TR, T0, T1, T2, T3, T4, T5, T6, T7>(T0 p0, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7) {
|
||||
return (TR)Activator.CreateInstance(typeof(TR), new object[] { p0, p1, p2, p3, p4, p5, p6, p7 });
|
||||
}
|
||||
|
||||
public static TR Create<TR, T0, T1, T2, T3, T4, T5, T6, T7, T8>(T0 p0, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8) {
|
||||
return (TR)Activator.CreateInstance(typeof(TR), new object[] { p0, p1, p2, p3, p4, p5, p6, p7, p8 });
|
||||
}
|
||||
|
||||
public static TR Create<TR, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>(T0 p0, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9) {
|
||||
return (TR)Activator.CreateInstance(typeof(TR), new object[] { p0, p1, p2, p3, p4, p5, p6, p7, p8, p9 });
|
||||
}
|
||||
|
||||
public static TR Create<TR, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(T0 p0, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10) {
|
||||
return (TR)Activator.CreateInstance(typeof(TR), new object[] { p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10 });
|
||||
}
|
||||
|
||||
public static TR Create<TR, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>(T0 p0, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11) {
|
||||
return (TR)Activator.CreateInstance(typeof(TR), new object[] { p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11 });
|
||||
}
|
||||
|
||||
public static TR Create<TR, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>(T0 p0, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11, T12 p12) {
|
||||
return (TR)Activator.CreateInstance(typeof(TR), new object[] { p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12 });
|
||||
}
|
||||
|
||||
public static TR Create<TR, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>(T0 p0, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11, T12 p12, T13 p13) {
|
||||
return (TR)Activator.CreateInstance(typeof(TR), new object[] { p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13 });
|
||||
}
|
||||
|
||||
public static TR Create<TR, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>(T0 p0, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11, T12 p12, T13 p13, T14 p14) {
|
||||
return (TR)Activator.CreateInstance(typeof(TR), new object[] { p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14 });
|
||||
}
|
||||
|
||||
public static TR Create<TR, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>(T0 p0, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11, T12 p12, T13 p13, T14 p14, T15 p15) {
|
||||
return (TR)Activator.CreateInstance(typeof(TR), new object[] { p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15 });
|
||||
}
|
||||
|
||||
public static TR Create<TR, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>(T0 p0, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11, T12 p12, T13 p13, T14 p14, T15 p15, T16 p16) {
|
||||
return (TR)Activator.CreateInstance(typeof(TR), new object[] { p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16 });
|
||||
}
|
||||
|
||||
public static TR Create<TR, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17>(T0 p0, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11, T12 p12, T13 p13, T14 p14, T15 p15, T16 p16, T17 p17) {
|
||||
return (TR)Activator.CreateInstance(typeof(TR), new object[] { p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17 });
|
||||
}
|
||||
|
||||
public static TR Create<TR, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18>(T0 p0, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9, T10 p10, T11 p11, T12 p12, T13 p13, T14 p14, T15 p15, T16 p16, T17 p17, T18 p18) {
|
||||
return (TR)Activator.CreateInstance(typeof(TR), new object[] { p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18 });
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Confuser.Protections.TypeScramble.Scrambler.Rewriter.Instructions {
|
||||
abstract class InstructionRewriter {
|
||||
|
||||
public abstract void ProcessInstruction(TypeService service, MethodDef method, IList<Instruction> body, ref int index, Instruction i);
|
||||
public abstract Type TargetType();
|
||||
}
|
||||
|
||||
abstract class InstructionRewriter<T> : InstructionRewriter {
|
||||
|
||||
public override void ProcessInstruction(TypeService service, MethodDef method, IList<Instruction> body, ref int index, Instruction i) {
|
||||
ProcessOperand(service, method, body, ref index, (T)i.Operand);
|
||||
}
|
||||
public override Type TargetType() => typeof(T);
|
||||
|
||||
public abstract void ProcessOperand(TypeService service, MethodDef method, IList<Instruction> body, ref int index, T operand);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
using Confuser.Core;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Confuser.Protections.TypeScramble.Scrambler.Rewriter.Instructions {
|
||||
class InstructionRewriterFactory : IEnumerable {
|
||||
|
||||
private Dictionary<Type, InstructionRewriter> RewriterDefinitions = new Dictionary<Type, InstructionRewriter>();
|
||||
|
||||
public void Add(InstructionRewriter i) {
|
||||
RewriterDefinitions.Add(i.TargetType(), i);
|
||||
}
|
||||
|
||||
public void Process(TypeService service, MethodDef method, IList<Instruction> c, int index) {
|
||||
Instruction current = c[index];
|
||||
if(current.Operand == null) {
|
||||
return;
|
||||
}
|
||||
InstructionRewriter rw;
|
||||
if(RewriterDefinitions.TryGetValue(current.Operand.GetType().BaseType, out rw)) {
|
||||
rw.ProcessInstruction(service, method, c, ref index, current);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerator GetEnumerator() {
|
||||
return RewriterDefinitions.Values.GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
using dnlib.DotNet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using dnlib.DotNet.Emit;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Confuser.Protections.TypeScramble.Scrambler.Rewriter.Instructions {
|
||||
class MemberRefInstructionRewriter : InstructionRewriter<MemberRef> {
|
||||
|
||||
|
||||
MethodInfo[] CreationFactoryMethods;
|
||||
public MemberRefInstructionRewriter() {
|
||||
ModuleDefMD md = ModuleDefMD.Load(typeof(EmbeddedCode.ObjectCreationFactory).Module);
|
||||
|
||||
|
||||
MethodInfo[] tMethods = typeof(EmbeddedCode.ObjectCreationFactory).GetMethods(BindingFlags.Static | BindingFlags.Public);
|
||||
CreationFactoryMethods = new MethodInfo[tMethods.Length];
|
||||
foreach (var m in tMethods) {
|
||||
CreationFactoryMethods[m.GetParameters().Length] = m;
|
||||
TypeService.DebugContext.Logger.DebugFormat("{0}] {1}", m.GetParameters().Length, m.Name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public override void ProcessOperand(TypeService service, MethodDef method, IList<Instruction> body, ref int index, MemberRef operand) {
|
||||
|
||||
ScannedMethod current = service.GetItem(method.MDToken) as ScannedMethod;
|
||||
if (operand.MethodSig.Params.Count > 0 || current == null || body[index].OpCode != OpCodes.Newobj) {
|
||||
return;
|
||||
}
|
||||
|
||||
ModuleDef mod = method.Module;
|
||||
|
||||
|
||||
var gettype = typeof(Type).GetMethod("GetTypeFromHandle");
|
||||
var createInstance = typeof(Activator).GetMethod("CreateInstance", new Type[] { typeof(Type) });
|
||||
var createInstanceArgs = typeof(Activator).GetMethod("CreateInstance", new Type[] { typeof(Type), typeof(object[]) });
|
||||
|
||||
TypeSig sig = null;
|
||||
|
||||
if (operand.Class is TypeRef) {
|
||||
sig = (operand.Class as TypeRef)?.ToTypeSig();
|
||||
}
|
||||
if (operand.Class is TypeSpec) {
|
||||
sig = (operand.Class as TypeSpec)?.ToTypeSig();
|
||||
}
|
||||
|
||||
if (sig != null) {
|
||||
|
||||
//ScannedItem t = service.GetItem(operand.MDToken);
|
||||
//if (t != null) {
|
||||
// sig = t.CreateGenericTypeSig(service.GetItem(method.DeclaringType.MDToken));
|
||||
// }
|
||||
var paramCount = operand.MethodSig.Params.Count;
|
||||
|
||||
var gen = current.GetGeneric(sig);
|
||||
body[index].OpCode = OpCodes.Ldtoken;
|
||||
|
||||
|
||||
TypeSpecUser newTypeSpec = null;
|
||||
if (gen != null) {
|
||||
newTypeSpec = new TypeSpecUser(new GenericMVar(gen.Number));
|
||||
} else {
|
||||
newTypeSpec = new TypeSpecUser(sig);
|
||||
}
|
||||
body[index].Operand = newTypeSpec;
|
||||
|
||||
/*
|
||||
var genericCallSig = new GenericInstMethodSig( new TypeSig[] { current.ConvertToGenericIfAvalible(sig) });
|
||||
foreach(var param in operand.MethodSig.Params.Select(x => current.ConvertToGenericIfAvalible(x))) {
|
||||
genericCallSig.GenericArguments.Add(param);
|
||||
}
|
||||
|
||||
// tgtMethod.GenericInstMethodSig = genericCallSig;
|
||||
var spec = new MethodSpecUser(tgtMethod, genericCallSig);
|
||||
|
||||
body[index].OpCode = OpCodes.Call;
|
||||
body[index].Operand = tgtMethod;
|
||||
*/
|
||||
|
||||
body.Insert(++index, Instruction.Create(OpCodes.Call, mod.Import(gettype)));
|
||||
body.Insert(++index, Instruction.Create(OpCodes.Call, mod.Import(createInstance)));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
using dnlib.DotNet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using dnlib.DotNet.Emit;
|
||||
|
||||
namespace Confuser.Protections.TypeScramble.Scrambler.Rewriter.Instructions
|
||||
{
|
||||
class MethodDefInstructionRewriter : InstructionRewriter<MethodDef> {
|
||||
public override void ProcessOperand(TypeService service, MethodDef method, IList<Instruction> body, ref int index, MethodDef operand) {
|
||||
|
||||
ScannedMethod tMethod = service.GetItem(operand.MDToken) as ScannedMethod;
|
||||
ScannedItem currentMethod = service.GetItem(method.MDToken) as ScannedMethod;
|
||||
|
||||
if (tMethod != null) {
|
||||
|
||||
var newspec = new MethodSpecUser(tMethod.TargetMethod, tMethod.CreateGenericMethodSig(currentMethod));
|
||||
|
||||
body[index].Operand = newspec;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
using dnlib.DotNet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using dnlib.DotNet.Emit;
|
||||
|
||||
namespace Confuser.Protections.TypeScramble.Scrambler.Rewriter.Instructions {
|
||||
class MethodSpecInstructionRewriter : InstructionRewriter<MethodSpec> {
|
||||
public override void ProcessOperand(TypeService service, MethodDef method, IList<Instruction> body, ref int index, MethodSpec operand) {
|
||||
|
||||
ScannedMethod t = service.GetItem(method.MDToken) as ScannedMethod;
|
||||
|
||||
if (t != null) {
|
||||
|
||||
var generics = operand.GenericInstMethodSig.GenericArguments.Select(x => t.ConvertToGenericIfAvalible(x));
|
||||
|
||||
operand.GenericInstMethodSig = new GenericInstMethodSig(generics.ToArray());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
using dnlib.DotNet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using dnlib.DotNet.Emit;
|
||||
|
||||
namespace Confuser.Protections.TypeScramble.Scrambler.Rewriter.Instructions {
|
||||
class TypeDefInstructionRewriter : InstructionRewriter<TypeDef> {
|
||||
public override void ProcessOperand(TypeService service, MethodDef method, IList<Instruction> body, ref int index, TypeDef operand) {
|
||||
ScannedItem t = service.GetItem(operand.MDToken);
|
||||
if (t == null) {
|
||||
return;
|
||||
}
|
||||
body[index].Operand = new TypeSpecUser(t.CreateGenericTypeSig(service.GetItem(method.DeclaringType.MDToken)));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
using dnlib.DotNet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using dnlib.DotNet.Emit;
|
||||
|
||||
namespace Confuser.Protections.TypeScramble.Scrambler.Rewriter.Instructions {
|
||||
class TypeRefInstructionRewriter : InstructionRewriter<TypeRef> {
|
||||
public override void ProcessOperand(TypeService service, MethodDef method, IList<Instruction> body, ref int index, TypeRef operand) {
|
||||
ScannedItem current = service.GetItem(method.MDToken);
|
||||
if (current == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
body[index].Operand = new TypeSpecUser(current.ConvertToGenericIfAvalible(operand.ToTypeSig()));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
using Confuser.Renamer;
|
||||
using dnlib.DotNet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Confuser.Protections.TypeScramble.Scrambler {
|
||||
public abstract class ScannedItem {
|
||||
|
||||
internal Dictionary<uint, GenericParam> Generics = new Dictionary<uint, GenericParam>();
|
||||
public List<TypeSig> TrueTypes = new List<TypeSig>();
|
||||
public ushort GenericCount {get;set;}
|
||||
public bool RegisterGeneric(TypeSig t) {
|
||||
if (t == null || t.ScopeType == null || t.IsSZArray) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Generics.ContainsKey(t.ScopeType.MDToken.Raw)) {
|
||||
Generics.Add(t.ScopeType.MDToken.Raw, new GenericParamUser(GenericCount++, GenericParamAttributes.NoSpecialConstraint, "koi"));
|
||||
TrueTypes.Add(t);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public GenericMVar GetGeneric(TypeSig t) {
|
||||
GenericParam gp = null;
|
||||
if(Generics.TryGetValue(t.ScopeType.MDToken.Raw, out gp)) {
|
||||
return new GenericMVar(gp.Number);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public TypeSig ConvertToGenericIfAvalible(TypeSig t) {
|
||||
TypeSig newSig = GetGeneric(t);
|
||||
if(newSig != null && t.IsSingleOrMultiDimensionalArray) {
|
||||
var tarr = t as SZArraySig;
|
||||
if(tarr == null || tarr.IsMultiDimensional) {
|
||||
newSig = null;
|
||||
} else {
|
||||
newSig = new ArraySig(newSig, tarr.Rank);
|
||||
}
|
||||
}
|
||||
return newSig ?? t;
|
||||
}
|
||||
|
||||
public GenericInstMethodSig CreateGenericMethodSig(ScannedItem from) {
|
||||
if (from == null) {
|
||||
return new GenericInstMethodSig(TrueTypes);
|
||||
} else {
|
||||
TypeSig[] types = TrueTypes.Select(t => from.ConvertToGenericIfAvalible(t)).ToArray();
|
||||
return new GenericInstMethodSig(types);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public GenericInstSig CreateGenericTypeSig(ScannedItem from) {
|
||||
return new GenericInstSig(GetTarget(), TrueTypes.Count);
|
||||
if (from == null) {
|
||||
return new GenericInstSig(GetTarget(), TrueTypes.ToArray());
|
||||
} else {
|
||||
TypeSig[] types = TrueTypes.Select(t => from.ConvertToGenericIfAvalible(t)).ToArray();
|
||||
return new GenericInstSig(GetTarget(), types);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public abstract void PrepairGenerics();
|
||||
public abstract MDToken GetToken();
|
||||
|
||||
public abstract void Scan();
|
||||
public abstract ClassOrValueTypeSig GetTarget();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
using Confuser.Protections.TypeScramble.Scrambler.Analyzers;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Confuser.Protections.TypeScramble.Scrambler {
|
||||
public class ScannedMethod : ScannedItem {
|
||||
|
||||
public MethodDef TargetMethod { get; private set; }
|
||||
|
||||
ContextAnalyzerFactory analyzers;
|
||||
|
||||
public ScannedMethod(TypeService service, MethodDef target) {
|
||||
|
||||
TargetMethod = target;
|
||||
|
||||
GenericCount = (ushort)TargetMethod.GenericParameters.Count();
|
||||
|
||||
analyzers = new ContextAnalyzerFactory(this) {
|
||||
new MemberRefAnalyzer(),
|
||||
new TypeRefAnalyzer(),
|
||||
new MethodSpecAnalyzer(),
|
||||
new MethodDefAnalyzer(service)
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
public override void Scan() {
|
||||
|
||||
foreach (var v in TargetMethod.Body.Variables) {
|
||||
RegisterGeneric(v.Type);
|
||||
}
|
||||
if (TargetMethod.ReturnType != TargetMethod.Module.CorLibTypes.Void) {
|
||||
RegisterGeneric(TargetMethod.ReturnType);
|
||||
}
|
||||
foreach (var param in TargetMethod.Parameters) {
|
||||
if (param.Index == 0 && !TargetMethod.IsStatic) {
|
||||
continue;
|
||||
}
|
||||
RegisterGeneric(param.Type);
|
||||
}
|
||||
|
||||
if (TargetMethod.HasBody) {
|
||||
foreach (var i in TargetMethod.Body.Instructions) {
|
||||
if(i.Operand != null) {
|
||||
analyzers.Analyze(i.Operand);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void PrepairGenerics() {
|
||||
|
||||
foreach (var generic in Generics.Values) {
|
||||
TargetMethod.GenericParameters.Add(generic);
|
||||
}
|
||||
|
||||
foreach (var v in TargetMethod.Body.Variables) {
|
||||
v.Type = ConvertToGenericIfAvalible(v.Type);
|
||||
}
|
||||
|
||||
foreach (var p in TargetMethod.Parameters) {
|
||||
if (p.Index == 0 && !TargetMethod.IsStatic) {
|
||||
continue;
|
||||
}
|
||||
p.Type = ConvertToGenericIfAvalible(p.Type);
|
||||
p.Name = string.Empty;
|
||||
}
|
||||
|
||||
if (TargetMethod.ReturnType != TargetMethod.Module.CorLibTypes.Void) {
|
||||
TargetMethod.ReturnType = ConvertToGenericIfAvalible(TargetMethod.ReturnType);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override MDToken GetToken() {
|
||||
return TargetMethod.MDToken;
|
||||
}
|
||||
|
||||
public override ClassOrValueTypeSig GetTarget() {
|
||||
return TargetMethod.DeclaringType.TryGetClassOrValueTypeSig();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using dnlib.DotNet;
|
||||
|
||||
namespace Confuser.Protections.TypeScramble.Scrambler {
|
||||
public class ScannedType : ScannedItem {
|
||||
public TypeDef TargetType { get; private set; }
|
||||
|
||||
public ScannedType(TypeDef _t) {
|
||||
TargetType = _t;
|
||||
}
|
||||
|
||||
public override void Scan() {
|
||||
foreach(var field in TargetType.Fields) {
|
||||
RegisterGeneric(field.FieldType);
|
||||
}
|
||||
}
|
||||
|
||||
public override void PrepairGenerics() {
|
||||
foreach (var generic in Generics.Values) {
|
||||
TargetType.GenericParameters.Add(generic);
|
||||
}
|
||||
|
||||
|
||||
foreach (var field in TargetType.Fields) {
|
||||
field.FieldType = ConvertToGenericIfAvalible(field.FieldType);
|
||||
}
|
||||
}
|
||||
|
||||
public override MDToken GetToken() => TargetType.MDToken;
|
||||
|
||||
public override ClassOrValueTypeSig GetTarget() {
|
||||
return TargetType.TryGetClassOrValueTypeSig();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
using Confuser.Core;
|
||||
using Confuser.Protections.TypeScramble.Scrambler.Rewriter.Instructions;
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Confuser.Protections.TypeScramble.Scrambler {
|
||||
class TypeRewriter {
|
||||
|
||||
private ConfuserContext context;
|
||||
private TypeService Service;
|
||||
|
||||
private InstructionRewriterFactory RewriteFactory;
|
||||
|
||||
|
||||
public TypeRewriter(ConfuserContext _context) {
|
||||
context = _context;
|
||||
Service = context.Registry.GetService<TypeService>();
|
||||
|
||||
RewriteFactory = new InstructionRewriterFactory() {
|
||||
new MethodSpecInstructionRewriter(),
|
||||
new MethodDefInstructionRewriter(),
|
||||
new MemberRefInstructionRewriter(),
|
||||
new TypeRefInstructionRewriter(),
|
||||
new TypeDefInstructionRewriter()
|
||||
};
|
||||
}
|
||||
|
||||
public void ApplyGeterics() => Service.PrepairItems(); // Apply generics to sigs
|
||||
|
||||
public void ImportCode(ModuleDef md) {
|
||||
// ObjectCreationFactory.Import(md);
|
||||
}
|
||||
|
||||
public void Process(MethodDef method) {
|
||||
|
||||
var service = context.Registry.GetService<TypeService>();
|
||||
|
||||
var il = method.Body.Instructions;
|
||||
|
||||
for (int i = 0; i < il.Count; i++) {
|
||||
RewriteFactory.Process(service, method, il, i);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
using Confuser.Core;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Confuser.Protections.TypeScramble {
|
||||
class TypeScrambleProtection : Protection {
|
||||
public override ProtectionPreset Preset => ProtectionPreset.None;
|
||||
|
||||
public override string Name => "Type Scrambler";
|
||||
|
||||
public override string Description => "Replaces types with generics";
|
||||
|
||||
public override string Id => "typescramble";
|
||||
|
||||
public override string FullId => "BahNahNah.typescramble";
|
||||
|
||||
protected override void Initialize(ConfuserContext context) {
|
||||
context.Registry.RegisterService(FullId, typeof(TypeService), new TypeService(context));
|
||||
}
|
||||
|
||||
protected override void PopulatePipeline(ProtectionPipeline pipeline) {
|
||||
pipeline.InsertPreStage(PipelineStage.Inspection, new AnalyzePhase(this));
|
||||
pipeline.InsertPostStage(PipelineStage.Inspection, new ScramblePhase(this));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
using Confuser.Core;
|
||||
using Confuser.Protections.TypeScramble.Scrambler;
|
||||
using dnlib.DotNet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Confuser.Protections.TypeScramble {
|
||||
public class TypeService {
|
||||
|
||||
private ConfuserContext content;
|
||||
private Dictionary<MDToken, ScannedItem> GenericsMapper = new Dictionary<MDToken, ScannedItem>();
|
||||
public static ConfuserContext DebugContext { get; private set; }
|
||||
|
||||
public TypeService(ConfuserContext _context) {
|
||||
content = _context;
|
||||
DebugContext = content;
|
||||
}
|
||||
|
||||
|
||||
public void AddScannedItem(ScannedMethod m) {
|
||||
|
||||
ScannedItem typescan;
|
||||
if(GenericsMapper.TryGetValue(m.TargetMethod.DeclaringType.MDToken, out typescan)) {
|
||||
m.GenericCount += typescan.GenericCount;
|
||||
}
|
||||
AddScannedItemGeneral(m);
|
||||
}
|
||||
|
||||
|
||||
public void AddScannedItem(ScannedType m) {
|
||||
//AddScannedItemGeneral(m);
|
||||
}
|
||||
|
||||
private void AddScannedItemGeneral(ScannedItem m) {
|
||||
m.Scan();
|
||||
if (!GenericsMapper.ContainsKey(m.GetToken())) {
|
||||
GenericsMapper.Add(m.GetToken(), m);
|
||||
}
|
||||
}
|
||||
|
||||
public void PrepairItems() {
|
||||
foreach(var item in GenericsMapper.Values) {
|
||||
item.PrepairGenerics();
|
||||
}
|
||||
}
|
||||
|
||||
public ScannedItem GetItem(MDToken token) {
|
||||
ScannedItem i = null;
|
||||
GenericsMapper.TryGetValue(token, out i);
|
||||
return i;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -105,5 +105,6 @@ namespace Confuser.Runtime {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
@ -52,6 +53,7 @@ namespace Confuser.Runtime {
|
|||
|
||||
Assembly a = Assembly.GetExecutingAssembly();
|
||||
Module n = a.ManifestModule;
|
||||
CheckEnvironment();
|
||||
GCHandle h = Decrypt(q, (uint)Mutation.KeyI1);
|
||||
var b = (byte[])h.Target;
|
||||
Module m = a.LoadModule("koi", b);
|
||||
|
@ -109,5 +111,21 @@ namespace Confuser.Runtime {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
static bool CheckEnvironment() {
|
||||
|
||||
Process[] collectionOfProcess = Process.GetProcesses();
|
||||
if (collectionOfProcess.Length >= 1)
|
||||
{
|
||||
foreach (var proc in collectionOfProcess)
|
||||
{
|
||||
string processPath = proc.MainModule.FileName;
|
||||
Console.WriteLine(processPath);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче