Conflicts:
	Confuser.Core/ConfuserEngine.cs
	Confuser.Core/Marker.cs
	Confuser.Renamer/AnalyzePhase.cs
This commit is contained in:
yck1509 2014-06-23 01:39:21 +08:00
Родитель 4be2740723 5969669215
Коммит 479b7e3975
93 изменённых файлов: 4215 добавлений и 117 удалений

1
.gitignore поставляемый
Просмотреть файл

@ -28,7 +28,6 @@ obj/
_ReSharper*/
[Tt]est[Rr]esult*
/docs
!packages/*/build/
packages/
/Confuser.Test

Просмотреть файл

@ -128,9 +128,9 @@ namespace Confuser.CLI {
WriteLineWithColor(ConsoleColor.Red, "Exception: " + ex);
}
public void Progress(int overall, int progress) {
WriteLineWithColor(ConsoleColor.Gray, string.Format("{0}/{1}", progress, overall));
}
public void Progress(int progress, int overall) { }
public void EndProgress() { }
public void Finish(bool successful) {
DateTime now = DateTime.Now;

Просмотреть файл

@ -67,20 +67,21 @@ namespace Confuser.Core {
context.PackerInitiated = parameters.PackerInitiated;
context.token = token;
var asmResolver = new AssemblyResolver();
asmResolver.EnableTypeDefCache = true;
asmResolver.DefaultModuleContext = new ModuleContext(asmResolver);
context.Resolver = asmResolver;
context.BaseDirectory = Path.Combine(Environment.CurrentDirectory, parameters.Project.BaseDirectory + "\\");
context.OutputDirectory = Path.Combine(parameters.Project.BaseDirectory, parameters.Project.OutputDirectory + "\\");
foreach (string probePath in parameters.Project.ProbePaths)
asmResolver.PostSearchPaths.Add(Path.Combine(context.BaseDirectory, probePath));
PrintInfo(context);
bool ok = false;
try {
var asmResolver = new AssemblyResolver();
asmResolver.EnableTypeDefCache = true;
asmResolver.DefaultModuleContext = new ModuleContext(asmResolver);
context.Resolver = asmResolver;
context.BaseDirectory = Path.Combine(Environment.CurrentDirectory, parameters.Project.BaseDirectory + "\\");
context.OutputDirectory = Path.Combine(parameters.Project.BaseDirectory, parameters.Project.OutputDirectory + "\\");
foreach (string probePath in parameters.Project.ProbePaths)
asmResolver.PostSearchPaths.Add(Path.Combine(context.BaseDirectory, probePath));
context.CheckCancellation();
Marker marker = parameters.GetMarker();
// 2. Discover plugins
@ -93,13 +94,14 @@ namespace Confuser.Core {
context.Logger.InfoFormat("Discovered {0} protections, {1} packers.", prots.Count, packers.Count);
context.CheckCancellation();
// 3. Resolve dependency
context.Logger.Debug("Resolving component dependency...");
try {
var resolver = new DependencyResolver(prots);
prots = resolver.SortDependency();
}
catch (CircularDependencyException ex) {
} catch (CircularDependencyException ex) {
context.Logger.ErrorException("", ex);
throw new ConfuserException(ex);
}
@ -110,6 +112,8 @@ namespace Confuser.Core {
foreach (Packer packer in packers)
components.Add(packer);
context.CheckCancellation();
// 4. Load modules
context.Logger.Info("Loading input modules...");
marker.Initalize(prots, packers);
@ -122,19 +126,22 @@ namespace Confuser.Core {
asmResolver.AddToCache(module);
context.Packer = markings.Packer;
context.CheckCancellation();
// 5. Initialize components
context.Logger.Info("Initializing...");
foreach (ConfuserComponent comp in components) {
try {
comp.Initialize(context);
}
catch (Exception ex) {
} catch (Exception ex) {
context.Logger.ErrorException("Error occured during initialization of '" + comp.Name + "'.", ex);
throw new ConfuserException(ex);
}
context.CheckCancellation();
}
context.CheckCancellation();
// 6. Build pipeline
context.Logger.Debug("Building pipeline...");
var pipeline = new ProtectionPipeline();
@ -142,35 +149,28 @@ namespace Confuser.Core {
foreach (ConfuserComponent comp in components) {
comp.PopulatePipeline(pipeline);
}
context.CheckCancellation();
//7. Run pipeline
RunPipeline(pipeline, context);
ok = true;
}
catch (AssemblyResolveException ex) {
} catch (AssemblyResolveException ex) {
context.Logger.ErrorException("Failed to resolve a assembly, check if all dependencies are of correct version.", ex);
}
catch (TypeResolveException ex) {
} catch (TypeResolveException ex) {
context.Logger.ErrorException("Failed to resolve a type, check if all dependencies are of correct version.", ex);
}
catch (MemberRefResolveException ex) {
} catch (MemberRefResolveException ex) {
context.Logger.ErrorException("Failed to resolve a member, check if all dependencies are of correct version.", ex);
}
catch (IOException ex) {
} catch (IOException ex) {
context.Logger.ErrorException("An IO error occured, check if all input/output locations are read/writable.", ex);
}
catch (OperationCanceledException) {
} catch (OperationCanceledException) {
context.Logger.Error("Operation is canceled.");
}
catch (ConfuserException) {
} catch (ConfuserException) {
// Exception is already handled/logged, so just ignore and report failure
}
catch (Exception ex) {
} catch (Exception ex) {
context.Logger.ErrorException("Unknown error occured.", ex);
}
finally {
} finally {
context.Logger.Finish(ok);
}
}
@ -234,8 +234,7 @@ namespace Confuser.Core {
.SelectMany(module => module.GetAssemblyRefs().Select(asmRef => Tuple.Create(asmRef, module)))) {
try {
AssemblyDef assembly = context.Resolver.ResolveThrow(dependency.Item1, dependency.Item2);
}
catch (AssemblyResolveException ex) {
} catch (AssemblyResolveException ex) {
context.Logger.ErrorException("Failed to resolve dependency of '" + dependency.Item2.Name + "'.", ex);
throw new ConfuserException(ex);
}
@ -300,6 +299,7 @@ namespace Confuser.Core {
context.Logger.InfoFormat("Processing module '{0}'...", context.CurrentModule.Name);
context.CurrentModuleWriterListener = new ModuleWriterListener();
context.CurrentModuleWriterListener.OnWriterEvent += (sender, e) => context.CheckCancellation();
context.CurrentModuleWriterOptions = new ModuleWriterOptions(context.CurrentModule, context.CurrentModuleWriterListener);
var snKey = context.Annotations.Get<StrongNameKey>(context.CurrentModule, Marker.SNKey);
context.CurrentModuleWriterOptions.InitializeStrongNameSigning(context.CurrentModule, snKey);
@ -388,8 +388,7 @@ namespace Confuser.Core {
private static void PrintInfo(ConfuserContext context) {
if (context.PackerInitiated) {
context.Logger.Info("Protecting packer stub...");
}
else {
} else {
context.Logger.InfoFormat("{0} {1}", Version, Copyright);
Type mono = Type.GetType("Mono.Runtime");

Просмотреть файл

@ -74,9 +74,26 @@ namespace Confuser.Core {
/// <summary>
/// Logs the progress of protection.
/// </summary>
/// <remarks>
/// This method is intended to be used with <see cref="EndProgress" />.
/// </remarks>
/// <example>
/// <code>
/// for (int i = 0; i &lt; defs.Length; i++) {
/// logger.Progress(i + 1, defs.Length);
/// }
/// logger.EndProgress();
/// </code>
/// </example>
/// <param name="overall">The total work amount .</param>
/// <param name="progress">The amount of work done.</param>
void Progress(int overall, int progress);
void Progress(int progress, int overall);
/// <summary>
/// End the progress of protection.
/// </summary>
/// <seealso cref="Progress" />
void EndProgress();
/// <summary>
/// Logs the finish of protection.

Просмотреть файл

@ -110,6 +110,8 @@ namespace Confuser.Core {
context.Logger.InfoFormat("Loading '{0}'...", module.Path);
ModuleDefMD modDef = module.Resolve(proj.BaseDirectory, context.Resolver.DefaultModuleContext);
context.CheckCancellation();
if (proj.Debug)
modDef.LoadPdb();
@ -118,8 +120,10 @@ namespace Confuser.Core {
context.Annotations.Set(modDef, SNKey, LoadSNKey(context, module.SNKeyPath == null ? null : Path.Combine(proj.BaseDirectory, module.SNKeyPath), module.SNKeyPassword));
context.Annotations.Set(modDef, RulesKey, rules);
foreach (IDnlibDef def in modDef.FindDefinitions())
foreach (IDnlibDef def in modDef.FindDefinitions()) {
ApplyRules(context, def, rules);
context.CheckCancellation();
}
// Packer parameters are stored in modules
if (packerParams != null)

Просмотреть файл

@ -49,6 +49,9 @@ namespace Confuser.Core {
/// <inheritdoc />
public void Progress(int overall, int progress) { }
/// <inheritdoc />
public void EndProgress() { }
/// <inheritdoc />
public void Finish(bool successful) { }

Просмотреть файл

@ -124,8 +124,12 @@ namespace Confuser.Core {
baseLogger.ErrorException(msg, ex);
}
public void Progress(int overall, int progress) {
baseLogger.Progress(overall, progress);
public void Progress(int progress, int overall) {
baseLogger.Progress(progress, overall);
}
public void EndProgress() {
baseLogger.EndProgress();
}
public void Finish(bool successful) {

Просмотреть файл

@ -32,7 +32,12 @@ namespace Confuser.Core {
GetPluginsInternal(context, protections, packers, components);
}
private static bool HasAccessibleDefConstructor(Type type) {
/// <summary>
/// Determines whether the specified type has an accessible default constructor.
/// </summary>
/// <param name="type">The type.</param>
/// <returns><c>true</c> if the specified type has an accessible default constructor; otherwise, <c>false</c>.</returns>
public static bool HasAccessibleDefConstructor(Type type) {
ConstructorInfo ctor = type.GetConstructor(Type.EmptyTypes);
if (ctor == null) return false;
return ctor.IsPublic;

Просмотреть файл

@ -61,7 +61,7 @@
<xs:sequence>
<xs:element name="rule" type="rule" minOccurs="0" maxOccurs="unbounded" />
<xs:element name="packer" type="objSettings" minOccurs="0" maxOccurs="1" />
<xs:element name="module" type="module" minOccurs="1" maxOccurs="unbounded" />
<xs:element name="module" type="module" minOccurs="0" maxOccurs="unbounded" />
<xs:element name="probePath" type="xs:string" minOccurs="0" maxOccurs="unbounded" />
<xs:element name="plugin" type="xs:string" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>

Просмотреть файл

@ -23,6 +23,12 @@
/// <value>The protection targets.</value>
public abstract ProtectionTargets Targets { get; }
/// <summary>
/// Gets the name of the phase.
/// </summary>
/// <value>The name of phase.</value>
public abstract string Name { get; }
/// <summary>
/// Gets a value indicating whether this phase process all targets, not just the targets that requires the component.
/// </summary>

Просмотреть файл

@ -120,12 +120,15 @@ namespace Confuser.Core {
/// <param name="context">The working context.</param>
internal void ExecuteStage(PipelineStage stage, Action<ConfuserContext> func, Func<IList<IDnlibDef>> targets, ConfuserContext context) {
foreach (ProtectionPhase pre in preStage[stage]) {
pre.Execute(context, new ProtectionParameters(pre.Parent, Filter(context, targets(), pre)));
context.CheckCancellation();
context.Logger.DebugFormat("Executing '{0}' phase...", pre.Name);
pre.Execute(context, new ProtectionParameters(pre.Parent, Filter(context, targets(), pre)));
}
context.CheckCancellation();
func(context);
context.CheckCancellation();
foreach (ProtectionPhase post in postStage[stage]) {
context.Logger.DebugFormat("Executing '{0}' phase...", post.Name);
post.Execute(context, new ProtectionParameters(post.Parent, Filter(context, targets(), post)));
context.CheckCancellation();
}

Просмотреть файл

@ -24,42 +24,41 @@ namespace Confuser.Core.Services {
/// <inheritdoc />
public MethodDef GetRuntimeDecompressor(ModuleDef module, Action<IDnlibDef> init) {
Tuple<MethodDef, List<IDnlibDef>> decompressor = context.Annotations.GetOrCreate(module, Decompressor, m => {
var rt = context.Registry.GetService<IRuntimeService>();
var rt = context.Registry.GetService<IRuntimeService>();
List<IDnlibDef> members = InjectHelper.Inject(rt.GetRuntimeType("Confuser.Runtime.Lzma"), module.GlobalType, module).ToList();
MethodDef decomp = null;
foreach (IDnlibDef member in members) {
if (member is MethodDef) {
var method = (MethodDef)member;
if (method.Access == MethodAttributes.Public)
method.Access = MethodAttributes.Assembly;
if (!method.IsConstructor)
method.IsSpecialName = false;
List<IDnlibDef> members = InjectHelper.Inject(rt.GetRuntimeType("Confuser.Runtime.Lzma"), module.GlobalType, module).ToList();
MethodDef decomp = null;
foreach (IDnlibDef member in members) {
if (member is MethodDef) {
var method = (MethodDef)member;
if (method.Access == MethodAttributes.Public)
method.Access = MethodAttributes.Assembly;
if (!method.IsConstructor)
method.IsSpecialName = false;
if (method.Name == "Decompress")
decomp = method;
}
else if (member is FieldDef) {
var field = (FieldDef)member;
if (field.Access == FieldAttributes.Public)
field.Access = FieldAttributes.Assembly;
if (field.IsLiteral) {
field.DeclaringType.Fields.Remove(field);
}
}
}
members.RemoveWhere(def => def is FieldDef && ((FieldDef)def).IsLiteral);
if (method.Name == "Decompress")
decomp = method;
} else if (member is FieldDef) {
var field = (FieldDef)member;
if (field.Access == FieldAttributes.Public)
field.Access = FieldAttributes.Assembly;
if (field.IsLiteral) {
field.DeclaringType.Fields.Remove(field);
}
}
}
members.RemoveWhere(def => def is FieldDef && ((FieldDef)def).IsLiteral);
Debug.Assert(decomp != null);
return Tuple.Create(decomp, members);
});
Debug.Assert(decomp != null);
return Tuple.Create(decomp, members);
});
foreach (IDnlibDef member in decompressor.Item2)
init(member);
return decompressor.Item1;
}
/// <inheritdoc />
public byte[] Compress(byte[] data) {
public byte[] Compress(byte[] data, Action<double> progressFunc = null) {
CoderPropID[] propIDs = {
CoderPropID.DictionarySize,
CoderPropID.PosStateBits,
@ -89,9 +88,29 @@ namespace Confuser.Core.Services {
fileSize = data.Length;
for (int i = 0; i < 8; i++)
x.WriteByte((Byte)(fileSize >> (8 * i)));
encoder.Code(new MemoryStream(data), x, -1, -1, null);
ICodeProgress progress = null;
if (progressFunc != null)
progress = new CompressionLogger(progressFunc, data.Length);
encoder.Code(new MemoryStream(data), x, -1, -1, progress);
return x.ToArray();
}
private class CompressionLogger : ICodeProgress {
private readonly Action<double> progressFunc;
private readonly int size;
public CompressionLogger(Action<double> progressFunc, int size) {
this.progressFunc = progressFunc;
this.size = size;
}
public void SetProgress(long inSize, long outSize) {
double precentage = (double)inSize / size;
progressFunc(precentage);
}
}
}
/// <summary>
@ -110,7 +129,8 @@ namespace Confuser.Core.Services {
/// Compresses the specified data.
/// </summary>
/// <param name="data">The buffer storing the data.</param>
/// <param name="progressFunc">The function that receive the progress of compression.</param>
/// <returns>The compressed data.</returns>
byte[] Compress(byte[] data);
byte[] Compress(byte[] data, Action<double> progressFunc = null);
}
}

Просмотреть файл

@ -68,7 +68,7 @@ namespace Confuser.Core {
}
/// <summary>
/// OBtains the relative path from the specified base path.
/// Obtains the relative path from the specified base path.
/// </summary>
/// <param name="filespec">The file path.</param>
/// <param name="folder">The base path.</param>
@ -181,5 +181,23 @@ namespace Confuser.Core {
}
return self;
}
/// <summary>
/// Returns a <see cref="IEnumerable{T}" /> that log the progress of iterating the specified list.
/// </summary>
/// <typeparam name="T">The type of list element</typeparam>
/// <param name="enumerable">The list.</param>
/// <param name="logger">The logger.</param>
/// <returns>A wrapper of the list.</returns>
public static IEnumerable<T> WithProgress<T>(this IEnumerable<T> enumerable, ILogger logger) {
var list = new List<T>(enumerable);
int i;
for (i = 0; i < list.Count; i++) {
logger.Progress(i, list.Count);
yield return list[i];
}
logger.Progress(i, list.Count);
logger.EndProgress();
}
}
}

Просмотреть файл

@ -49,6 +49,10 @@ namespace Confuser.Protections {
get { return ProtectionTargets.Modules; }
}
public override string Name {
get { return "Anti-debug injection"; }
}
protected override void Execute(ConfuserContext context, ProtectionParameters parameters) {
var rt = context.Registry.GetService<IRuntimeService>();
var marker = context.Registry.GetService<IMarkerService>();

Просмотреть файл

@ -49,6 +49,10 @@ namespace Confuser.Protections {
get { return ProtectionTargets.Modules; }
}
public override string Name {
get { return "Anti-dump injection"; }
}
protected override void Execute(ConfuserContext context, ProtectionParameters parameters) {
TypeDef rtType = context.Registry.GetService<IRuntimeService>().GetRuntimeType("Confuser.Runtime.AntiDump");

Просмотреть файл

@ -43,6 +43,10 @@ namespace Confuser.Protections {
get { return ProtectionTargets.Modules; }
}
public override string Name {
get { return "Anti-ILDasm marking"; }
}
protected override void Execute(ConfuserContext context, ProtectionParameters parameters) {
foreach (ModuleDef module in parameters.Targets.OfType<ModuleDef>()) {
TypeRef attrRef = module.CorLibTypes.GetTypeRef("System.Runtime.CompilerServices", "SuppressIldasmAttribute");

Просмотреть файл

@ -53,6 +53,10 @@ namespace Confuser.Protections {
get { return ProtectionTargets.Methods; }
}
public override string Name {
get { return "Anti-tamper helpers injection"; }
}
protected override void Execute(ConfuserContext context, ProtectionParameters parameters) {
if (!parameters.Targets.Any())
return;
@ -82,6 +86,10 @@ namespace Confuser.Protections {
get { return ProtectionTargets.Methods; }
}
public override string Name {
get { return "Anti-tamper metadata preparation"; }
}
protected override void Execute(ConfuserContext context, ProtectionParameters parameters) {
if (!parameters.Targets.Any())
return;

Просмотреть файл

@ -24,6 +24,7 @@ namespace Confuser.Protections.AntiTamper {
private uint c;
private MethodDef cctor;
private MethodDef cctorRepl;
private ConfuserContext context;
private IKeyDeriver deriver;
private byte[] fieldLayout;
@ -37,6 +38,7 @@ namespace Confuser.Protections.AntiTamper {
private uint z;
public void HandleInject(AntiTamperProtection parent, ConfuserContext context, ProtectionParameters parameters) {
this.context = context;
random = context.Registry.GetService<IRandomService>().GetRandomGenerator(parent.FullId);
z = random.NextUInt32();
x = random.NextUInt32();
@ -77,8 +79,7 @@ namespace Confuser.Protections.AntiTamper {
Instruction instr = instrs[i];
if (instr.OpCode == OpCodes.Ldtoken) {
instr.Operand = context.CurrentModule.GlobalType;
}
else if (instr.OpCode == OpCodes.Call) {
} else if (instr.OpCode == OpCodes.Call) {
var method = (IMethod)instr.Operand;
if (method.DeclaringType.Name == "Mutation" &&
method.Name == "Crypt") {
@ -144,9 +145,10 @@ namespace Confuser.Protections.AntiTamper {
private void OnWriterEvent(object sender, ModuleWriterListenerEventArgs e) {
var writer = (ModuleWriter)sender;
if (e.WriterEvent == ModuleWriterEvent.MDBeginWriteMethodBodies) {
context.Logger.Debug("Extracting method bodies...");
CreateSection(writer);
}
else if (e.WriterEvent == ModuleWriterEvent.BeginStrongNameSign) {
} else if (e.WriterEvent == ModuleWriterEvent.BeginStrongNameSign) {
context.Logger.Debug("Encrypting method section...");
EncryptSection(writer);
}
}
@ -202,7 +204,7 @@ namespace Confuser.Protections.AntiTamper {
cctor.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
// save methods
foreach (MethodDef method in methods) {
foreach (MethodDef method in methods.WithProgress(context.Logger)) {
if (!method.HasBody)
continue;
@ -216,6 +218,7 @@ namespace Confuser.Protections.AntiTamper {
method.Body = NopBody;
writer.MetaData.TablesHeap.MethodTable[token.Rid].ImplFlags |= (ushort)MethodImplAttributes.NoInlining;
context.CheckCancellation();
}
bodyIndex.PopulateSection(newSection);
@ -242,8 +245,7 @@ namespace Confuser.Protections.AntiTamper {
if (nameHash == name1 * name2) {
encSize = reader.ReadUInt32();
encLoc = reader.ReadUInt32();
}
else if (nameHash != 0) {
} else if (nameHash != 0) {
uint sectSize = reader.ReadUInt32();
uint sectLoc = reader.ReadUInt32();
Hash(stream, reader, sectLoc, sectSize);

Просмотреть файл

@ -50,7 +50,7 @@ namespace Confuser.Protections {
protected override void Pack(ConfuserContext context, ProtectionParameters parameters) {
var ctx = context.Annotations.Get<CompressorContext>(context, ContextKey);
if (ctx == null) {
context.Logger.Error("No main module specified!");
context.Logger.Error("No executable module!");
throw new ConfuserException(null);
}
@ -77,6 +77,7 @@ namespace Confuser.Protections {
stubModule.Write(ms, new ModuleWriterOptions(stubModule, new KeyInjector(ctx)) {
StrongNameKey = snKey
});
context.CheckCancellation();
base.ProtectStub(context, context.OutputPaths[ctx.ModuleIndex], ms.ToArray(), snKey, new StubProtection(ctx));
}
}
@ -105,6 +106,7 @@ namespace Confuser.Protections {
key[i] |= 1;
compCtx.KeySig = key;
int moduleIndex = 0;
foreach (var entry in modules) {
byte[] name = Encoding.UTF8.GetBytes(entry.Key);
for (int i = 0; i < name.Length; i++)
@ -113,11 +115,17 @@ namespace Confuser.Protections {
uint state = 0x6fff61;
foreach (byte chr in name)
state = state * 0x5e3f1f + chr;
byte[] encrypted = compCtx.Encrypt(comp, entry.Value, state);
byte[] encrypted = compCtx.Encrypt(comp, entry.Value, state, progress => {
progress = (progress + moduleIndex) / modules.Count;
context.Logger.Progress((int)(progress * 10000), 10000);
});
context.CheckCancellation();
var resource = new EmbeddedResource(Convert.ToBase64String(name), encrypted, ManifestResourceAttributes.Private);
stubModule.Resources.Add(resource);
moduleIndex++;
}
context.Logger.EndProgress();
}
private void InjectData(ModuleDef stubModule, MethodDef method, byte[] data) {
@ -137,14 +145,14 @@ namespace Confuser.Protections {
stubModule.GlobalType.Fields.Add(dataField);
MutationHelper.ReplacePlaceholder(method, arg => {
var repl = new List<Instruction>();
repl.AddRange(arg);
repl.Add(Instruction.Create(OpCodes.Dup));
repl.Add(Instruction.Create(OpCodes.Ldtoken, dataField));
repl.Add(Instruction.Create(OpCodes.Call, stubModule.Import(
typeof (RuntimeHelpers).GetMethod("InitializeArray"))));
return repl.ToArray();
});
var repl = new List<Instruction>();
repl.AddRange(arg);
repl.Add(Instruction.Create(OpCodes.Dup));
repl.Add(Instruction.Create(OpCodes.Ldtoken, dataField));
repl.Add(Instruction.Create(OpCodes.Call, stubModule.Import(
typeof (RuntimeHelpers).GetMethod("InitializeArray"))));
return repl.ToArray();
});
}
private void InjectStub(ConfuserContext context, CompressorContext compCtx, ProtectionParameters parameters, ModuleDef stubModule) {
@ -165,13 +173,20 @@ namespace Confuser.Protections {
}
compCtx.Deriver.Init(context, random);
context.Logger.Debug("Encrypting modules...");
// Main
MethodDef entryPoint = defs.OfType<MethodDef>().Single(method => method.Name == "Main");
stubModule.EntryPoint = entryPoint;
uint seed = random.NextUInt32();
compCtx.OriginModule = context.OutputModules[compCtx.ModuleIndex];
byte[] encryptedModule = compCtx.Encrypt(comp, compCtx.OriginModule, seed);
byte[] encryptedModule = compCtx.Encrypt(comp, compCtx.OriginModule, seed,
progress => context.Logger.Progress((int)(progress * 10000), 10000));
context.Logger.EndProgress();
context.CheckCancellation();
compCtx.EncryptedModule = encryptedModule;
MutationHelper.InjectKeys(entryPoint,
@ -196,9 +211,8 @@ namespace Confuser.Protections {
instrs.RemoveAt(i - 1);
instrs.RemoveAt(i - 2);
instrs.InsertRange(i - 2, compCtx.Deriver.EmitDerivation(decrypter, context, (Local)ldDst.Operand, (Local)ldSrc.Operand));
}
else if (method.DeclaringType.Name == "Lzma" &&
method.Name == "Decompress") {
} else if (method.DeclaringType.Name == "Lzma" &&
method.Name == "Decompress") {
MethodDef decomp = comp.GetRuntimeDecompressor(stubModule, member => { });
instr.Operand = decomp;
}
@ -228,8 +242,7 @@ namespace Confuser.Protections {
uint sigToken = 0x11000000 | sigRid;
ctx.KeyToken = sigToken;
MutationHelper.InjectKey(writer.Module.EntryPoint, 2, (int)sigToken);
}
else if (evt == ModuleWriterEvent.MDBeginAddResources) {
} else if (evt == ModuleWriterEvent.MDBeginAddResources) {
// Compute hash
byte[] hash = SHA1.Create().ComputeHash(ctx.OriginModule);
uint hashBlob = writer.MetaData.BlobHeap.Add(hash);

Просмотреть файл

@ -19,7 +19,7 @@ namespace Confuser.Protections.Compress {
public string ModuleName;
public byte[] OriginModule;
public byte[] Encrypt(ICompressionService compress, byte[] data, uint seed) {
public byte[] Encrypt(ICompressionService compress, byte[] data, uint seed, Action<double> progressFunc) {
data = (byte[])data.Clone();
var dst = new uint[0x10];
var src = new uint[0x10];
@ -37,7 +37,7 @@ namespace Confuser.Protections.Compress {
if ((i & 0xff) == 0)
state = (state * state) % 0x8a5cb7;
}
data = compress.Compress(data);
data = compress.Compress(data, progressFunc);
Array.Resize(ref data, (data.Length + 3) & ~3);
var encryptedData = new byte[data.Length];

Просмотреть файл

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Confuser.Core;
@ -14,15 +15,26 @@ namespace Confuser.Protections.Compress {
get { return ProtectionTargets.Modules; }
}
public override string Name {
get { return "Packer info extraction"; }
}
protected override void Execute(ConfuserContext context, ProtectionParameters parameters) {
if (context.Packer == null)
return;
if (context.Annotations.Get<CompressorContext>(context, Compressor.ContextKey) != null)
return;
bool isExe = context.CurrentModule.Kind == ModuleKind.Windows ||
context.CurrentModule.Kind == ModuleKind.Console;
var mainModule = parameters.GetParameter<string>(context, null, "main");
if (context.CurrentModule.Name == mainModule) {
if (context.Annotations.Get<CompressorContext>(context, Compressor.ContextKey) != null) {
if (isExe) {
context.Logger.Error("Too many executable modules!");
throw new ConfuserException(null);
}
return;
}
if (isExe) {
var ctx = new CompressorContext {
ModuleIndex = context.CurrentModuleIndex,
Assembly = context.CurrentModule.Assembly

Просмотреть файл

@ -49,6 +49,10 @@ namespace Confuser.Protections.Compress {
get { return ProtectionTargets.Modules; }
}
public override string Name {
get { return "Packer info encoding"; }
}
protected override void Execute(ConfuserContext context, ProtectionParameters parameters) {
context.CurrentModuleWriterListener.OnWriterEvent += (sender, e) => {
if (e.WriterEvent == ModuleWriterEvent.MDBeginCreateTables) {

Просмотреть файл

@ -20,6 +20,10 @@ namespace Confuser.Protections.Constants {
get { return ProtectionTargets.Methods; }
}
public override string Name {
get { return "Constants encoding"; }
}
protected override void Execute(ConfuserContext context, ProtectionParameters parameters) {
var moduleCtx = context.Annotations.Get<CEContext>(context.CurrentModule, ConstantProtection.ContextKey);
if (!parameters.Targets.Any() || moduleCtx == null)
@ -33,11 +37,12 @@ namespace Confuser.Protections.Constants {
// encode
moduleCtx.EncodedBuffer = new List<uint>();
foreach (var entry in ldInit) // Ensure the array length haven't been encoded yet
foreach (var entry in ldInit.WithProgress(context.Logger)) // Ensure the array length haven't been encoded yet
{
EncodeInitializer(moduleCtx, entry.Key, entry.Value);
context.CheckCancellation();
}
foreach (var entry in ldc) {
foreach (var entry in ldc.WithProgress(context.Logger)) {
if (entry.Key is string) {
EncodeString(moduleCtx, (string)entry.Key, entry.Value);
}
@ -59,6 +64,7 @@ namespace Confuser.Protections.Constants {
}
else
throw new UnreachableException();
context.CheckCancellation();
}
// compress
@ -72,6 +78,7 @@ namespace Confuser.Protections.Constants {
}
Debug.Assert(buffIndex == encodedBuff.Length);
encodedBuff = context.Registry.GetService<ICompressionService>().Compress(encodedBuff);
context.CheckCancellation();
uint compressedLen = (uint)(encodedBuff.Length + 3) / 4;
compressedLen = (compressedLen + 0xfu) & ~0xfu;
@ -214,7 +221,7 @@ namespace Confuser.Protections.Constants {
ConfuserContext context, ProtectionParameters parameters, CEContext moduleCtx,
Dictionary<object, List<Tuple<MethodDef, Instruction>>> ldc,
Dictionary<byte[], List<Tuple<MethodDef, Instruction>>> ldInit) {
foreach (MethodDef method in parameters.Targets.OfType<MethodDef>()) {
foreach (MethodDef method in parameters.Targets.OfType<MethodDef>().WithProgress(context.Logger)) {
if (!method.HasBody)
continue;
@ -319,6 +326,8 @@ namespace Confuser.Protections.Constants {
if (eligible)
ldc.AddListEntry(instr.Operand, Tuple.Create(method, instr));
}
context.CheckCancellation();
}
}

Просмотреть файл

@ -18,6 +18,10 @@ namespace Confuser.Protections.Constants {
get { return ProtectionTargets.Methods; }
}
public override string Name {
get { return "Constant encryption helpers injection"; }
}
protected override void Execute(ConfuserContext context, ProtectionParameters parameters) {
if (parameters.Targets.Any()) {
var compression = context.Registry.GetService<ICompressionService>();

Просмотреть файл

@ -20,6 +20,10 @@ namespace Confuser.Protections.ControlFlow {
get { return ProtectionTargets.Methods; }
}
public override string Name {
get { return "Control flow mangling"; }
}
private static CFContext ParseParameters(MethodDef method, ConfuserContext context, ProtectionParameters parameters, RandomGenerator random, bool disableOpti) {
var ret = new CFContext();
ret.Type = parameters.GetParameter(context, method, "type", CFType.Switch);
@ -67,9 +71,10 @@ namespace Confuser.Protections.ControlFlow {
bool disabledOpti = DisabledOptimization(context.CurrentModule);
RandomGenerator random = context.Registry.GetService<IRandomService>().GetRandomGenerator(ControlFlowProtection._FullId);
foreach (MethodDef method in parameters.Targets.OfType<MethodDef>())
foreach (MethodDef method in parameters.Targets.OfType<MethodDef>().WithProgress(context.Logger))
if (method.HasBody && method.Body.Instructions.Count > 0) {
ProcessMethod(method.Body, ParseParameters(method, context, parameters, random, disabledOpti));
context.CheckCancellation();
}
}

Просмотреть файл

@ -49,6 +49,10 @@ namespace Confuser.Protections {
get { return ProtectionTargets.Modules; }
}
public override string Name {
get { return "Invalid metadata addition"; }
}
protected override void Execute(ConfuserContext context, ProtectionParameters parameters) {
if (parameters.Targets.Contains(context.CurrentModule)) {
random = context.Registry.GetService<IRandomService>().GetRandomGenerator(_FullId);

Просмотреть файл

@ -16,6 +16,10 @@ namespace Confuser.Protections.ReferenceProxy {
get { return ProtectionTargets.Methods; }
}
public override string Name {
get { return "Encoding reference proxies"; }
}
private static RPContext ParseParameters(MethodDef method, ConfuserContext context, ProtectionParameters parameters, RPStore store) {
var ret = new RPContext();
ret.Mode = parameters.GetParameter(context, method, "mode", Mode.Mild);
@ -96,9 +100,10 @@ namespace Confuser.Protections.ReferenceProxy {
var store = new RPStore { random = random };
foreach (MethodDef method in parameters.Targets.OfType<MethodDef>())
foreach (MethodDef method in parameters.Targets.OfType<MethodDef>().WithProgress(context.Logger))
if (method.HasBody && method.Body.Instructions.Count > 0) {
ProcessMethod(ParseParameters(method, context, parameters, store));
context.CheckCancellation();
}
RPContext ctx = ParseParameters(context.CurrentModule, context, parameters, store);

Просмотреть файл

@ -19,6 +19,10 @@ namespace Confuser.Protections.Resources {
get { return ProtectionTargets.Methods; }
}
public override string Name {
get { return "Resource encryption helpers injection"; }
}
protected override void Execute(ConfuserContext context, ProtectionParameters parameters) {
if (parameters.Targets.Any()) {
var compression = context.Registry.GetService<ICompressionService>();

Просмотреть файл

@ -26,6 +26,9 @@ namespace Confuser.Protections.Resources {
private void OnWriterEvent(object sender, ModuleWriterListenerEventArgs e) {
var writer = (ModuleWriter)sender;
if (e.WriterEvent == ModuleWriterEvent.MDBeginAddResources) {
ctx.Context.CheckCancellation();
ctx.Context.Logger.Debug("Encrypting resources...");
List<EmbeddedResource> resources = ctx.Module.Resources.OfType<EmbeddedResource>().ToList();
ctx.Module.Resources.RemoveWhere(res => res is EmbeddedResource);
@ -51,7 +54,11 @@ namespace Confuser.Protections.Resources {
}
// compress
moduleBuff = ctx.Context.Registry.GetService<ICompressionService>().Compress(moduleBuff);
moduleBuff = ctx.Context.Registry.GetService<ICompressionService>().Compress(
moduleBuff,
progress => ctx.Context.Logger.Progress((int)(progress * 10000), 10000));
ctx.Context.Logger.EndProgress();
ctx.Context.CheckCancellation();
uint compressedLen = (uint)(moduleBuff.Length + 3) / 4;
compressedLen = (compressedLen + 0xfu) & ~0xfu;
@ -91,8 +98,7 @@ namespace Confuser.Protections.Resources {
MutationHelper.InjectKeys(ctx.InitMethod,
new[] { 0, 1 },
new[] { (int)(size / 4), (int)(keySeed) });
}
else if (e.WriterEvent == ModuleWriterEvent.EndCalculateRvasAndFileOffsets) {
} else if (e.WriterEvent == ModuleWriterEvent.EndCalculateRvasAndFileOffsets) {
TablesHeap tblHeap = writer.MetaData.TablesHeap;
tblHeap.FieldRVATable[writer.MetaData.GetFieldRVARid(ctx.DataField)].RVA = (uint)encryptedResource.RVA;
}

Просмотреть файл

@ -15,6 +15,10 @@ namespace Confuser.Renamer {
get { return ProtectionTargets.AllDefinitions; }
}
public override string Name {
get { return "Name analysis"; }
}
private void ParseParameters(IDnlibDef def, ConfuserContext context, NameService service, ProtectionParameters parameters) {
var mode = parameters.GetParameter<RenameMode?>(context, def, "mode", null);
if (mode != null)
@ -24,7 +28,7 @@ namespace Confuser.Renamer {
protected override void Execute(ConfuserContext context, ProtectionParameters parameters) {
var service = (NameService)context.Registry.GetService<INameService>();
context.Logger.Debug("Building VTables & identifier list...");
foreach (IDnlibDef def in parameters.Targets) {
foreach (IDnlibDef def in parameters.Targets.WithProgress(context.Logger)) {
ParseParameters(def, context, service, parameters);
if (def is ModuleDef) {
@ -39,12 +43,14 @@ namespace Confuser.Renamer {
service.GetVTables().GetVTable((TypeDef)def);
service.SetOriginalNamespace(def, ((TypeDef)def).Namespace);
}
context.CheckCancellation();
}
context.Logger.Debug("Analyzing...");
IList<IRenamer> renamers = service.Renamers;
foreach (IDnlibDef def in parameters.Targets) {
foreach (IDnlibDef def in parameters.Targets.WithProgress(context.Logger)) {
Analyze(service, context, parameters, def, true);
context.CheckCancellation();
}
}

Просмотреть файл

@ -14,12 +14,17 @@ namespace Confuser.Renamer {
get { return ProtectionTargets.AllDefinitions; }
}
public override string Name {
get { return "Post-renaming"; }
}
protected override void Execute(ConfuserContext context, ProtectionParameters parameters) {
var service = (NameService)context.Registry.GetService<INameService>();
foreach (IRenamer renamer in service.Renamers) {
foreach (IDnlibDef def in parameters.Targets)
renamer.PostRename(context, service, def);
context.CheckCancellation();
}
}
}

Просмотреть файл

@ -12,6 +12,10 @@ namespace Confuser.Renamer {
get { return ProtectionTargets.AllDefinitions; }
}
public override string Name {
get { return "Renaming"; }
}
protected override void Execute(ConfuserContext context, ProtectionParameters parameters) {
var service = (NameService)context.Registry.GetService<INameService>();
@ -19,9 +23,10 @@ namespace Confuser.Renamer {
foreach (IRenamer renamer in service.Renamers) {
foreach (IDnlibDef def in parameters.Targets)
renamer.PreRename(context, service, def);
context.CheckCancellation();
}
foreach (IDnlibDef def in parameters.Targets) {
foreach (IDnlibDef def in parameters.Targets.WithProgress(context.Logger)) {
if (def is MethodDef)
if (parameters.GetParameter(context, def, "renameArgs", true)) {
foreach (ParamDef param in ((MethodDef)def).ParamDefs)
@ -62,6 +67,7 @@ namespace Confuser.Renamer {
throw new ConfuserException(null);
}
}
context.CheckCancellation();
}
}
}

Просмотреть файл

@ -24,6 +24,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Confuser.Runtime", "Confuse
{BEB67A6E-4C54-4DE5-8C6B-2C12F44A7B92} = {BEB67A6E-4C54-4DE5-8C6B-2C12F44A7B92}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConfuserEx", "ConfuserEx\ConfuserEx.csproj", "{B5205EBA-EC32-4C53-86A0-FAEEE7393EC0}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -58,6 +60,10 @@ Global
{A45C184F-F98F-4258-A928-BFF437034791}.Debug|Any CPU.Build.0 = Release|Any CPU
{A45C184F-F98F-4258-A928-BFF437034791}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A45C184F-F98F-4258-A928-BFF437034791}.Release|Any CPU.Build.0 = Release|Any CPU
{B5205EBA-EC32-4C53-86A0-FAEEE7393EC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B5205EBA-EC32-4C53-86A0-FAEEE7393EC0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B5205EBA-EC32-4C53-86A0-FAEEE7393EC0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B5205EBA-EC32-4C53-86A0-FAEEE7393EC0}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

18
ConfuserEx/App.xaml Normal file
Просмотреть файл

@ -0,0 +1,18 @@
<Application x:Class="ConfuserEx.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Skin.xaml" />
<ResourceDictionary Source="Views.xaml" />
</ResourceDictionary.MergedDictionaries>
<BitmapImage x:Key="New" UriSource="Resources/New.png" />
<BitmapImage x:Key="Open" UriSource="Resources/Open.png" />
<BitmapImage x:Key="Save" UriSource="Resources/Save.png" />
<BitmapImage x:Key="Tools" UriSource="Resources/Tools.png" />
<BitmapImage x:Key="Decode" UriSource="Resources/Decode.png" />
<BitmapImage x:Key="Error" UriSource="Resources/Error.png" />
<FontFamily x:Key="FontAwesome">Resources/#FontAwesome</FontFamily>
</ResourceDictionary>
</Application.Resources>
</Application>

6
ConfuserEx/App.xaml.cs Normal file
Просмотреть файл

@ -0,0 +1,6 @@
using System;
using System.Windows;
namespace ConfuserEx {
public partial class App : Application { }
}

Просмотреть файл

@ -0,0 +1,22 @@
using System;
using System.Globalization;
using System.Windows.Data;
using System.Windows.Media;
namespace ConfuserEx {
public class BrushToColorConverter : IValueConverter {
public static readonly BrushToColorConverter Instance = new BrushToColorConverter();
private BrushToColorConverter() { }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
var brush = value as SolidColorBrush;
if (brush != null)
return brush.Color;
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
throw new NotImplementedException();
}
}
}

Просмотреть файл

@ -0,0 +1,43 @@
<UserControl x:Class="ConfuserEx.CompComboBox"
x:Name="Root"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:core="clr-namespace:Confuser.Core;assembly=Confuser.Core">
<ComboBox ItemsSource="{Binding Components, ElementName=Root}"
SelectedItem="{Binding SelectedComponent, ElementName=Root}"
DisplayMemberPath="Id" FontFamily="Consolas"
ScrollViewer.CanContentScroll="False">
<ComboBox.ItemContainerStyle>
<Style TargetType="{x:Type ComboBoxItem}">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBoxItem}">
<Border Width="350" BorderBrush="{StaticResource Foreground}"
Background="{TemplateBinding Background}" BorderThickness="1" Margin="5">
<Grid Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Label Grid.Row="0" Content="{Binding Name}" HorizontalAlignment="Left" />
<Label Grid.Row="0" Content="{Binding Id}" HorizontalAlignment="Right" />
<Label Grid.Row="1">
<TextBlock Text="{Binding Description}" TextTrimming="WordEllipsis"
FontSize="10" Foreground="Gray" />
</Label>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{StaticResource HighlightBackground}" />
<Setter Property="Foreground" Value="{StaticResource SelectedForeground}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ComboBox.ItemContainerStyle>
</ComboBox>
</UserControl>

Просмотреть файл

@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using Confuser.Core;
namespace ConfuserEx {
public partial class CompComboBox : UserControl {
public static readonly DependencyProperty ComponentsProperty = DependencyProperty.Register("Components", typeof (IEnumerable<ConfuserComponent>), typeof (CompComboBox), new UIPropertyMetadata(null));
public static readonly DependencyProperty SelectedComponentProperty = DependencyProperty.Register("SelectedComponent", typeof (ConfuserComponent), typeof (CompComboBox), new UIPropertyMetadata(null));
public static readonly DependencyProperty ArgumentsProperty = DependencyProperty.Register("Arguments", typeof (Dictionary<string, string>), typeof (CompComboBox), new UIPropertyMetadata(null));
public CompComboBox() {
InitializeComponent();
}
public IEnumerable<ConfuserComponent> Components {
get { return (IEnumerable<ConfuserComponent>)GetValue(ComponentsProperty); }
set { SetValue(ComponentsProperty, value); }
}
public ConfuserComponent SelectedComponent {
get { return (ConfuserComponent)GetValue(SelectedComponentProperty); }
set { SetValue(SelectedComponentProperty, value); }
}
public Dictionary<string, string> Arguments {
get { return (Dictionary<string, string>)GetValue(ArgumentsProperty); }
set { SetValue(ArgumentsProperty, value); }
}
}
}

Просмотреть файл

@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Data;
using Confuser.Core;
namespace ConfuserEx {
internal class ComponentConverter : Freezable, IValueConverter {
public static readonly DependencyProperty ComponentsProperty = DependencyProperty.Register("Components", typeof (IList<ConfuserComponent>), typeof (ComponentConverter), new UIPropertyMetadata(null));
public IList<ConfuserComponent> Components {
get { return (IList<ConfuserComponent>)GetValue(ComponentsProperty); }
set { SetValue(ComponentsProperty, value); }
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
Debug.Assert(value is string || value == null);
Debug.Assert(targetType == typeof (ConfuserComponent));
Debug.Assert(Components != null);
if (value == null) return null;
return Components.Single(comp => comp.Id == (string)value);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
Debug.Assert(value is ConfuserComponent || value == null);
Debug.Assert(targetType == typeof (string));
if (value == null) return null;
return ((ConfuserComponent)value).Id;
}
protected override Freezable CreateInstanceCore() {
return new ComponentConverter();
}
}
}

Просмотреть файл

@ -0,0 +1,113 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using Confuser.Core;
namespace ConfuserEx {
internal class ComponentDiscovery {
private static void CrossDomainLoadComponents() {
var ctx = (CrossDomainContext)AppDomain.CurrentDomain.GetData("ctx");
Assembly assembly = Assembly.LoadFile(ctx.PluginPath);
foreach (Type i in assembly.GetTypes()) {
if (i.IsAbstract || !PluginDiscovery.HasAccessibleDefConstructor(i))
continue;
if (typeof (Protection).IsAssignableFrom(i)) {
var prot = (Protection)Activator.CreateInstance(i);
ctx.AddProtection(Info.FromComponent(prot, ctx.PluginPath));
} else if (typeof (Packer).IsAssignableFrom(i)) {
var packer = (Packer)Activator.CreateInstance(i);
ctx.AddPacker(Info.FromComponent(packer, ctx.PluginPath));
}
}
}
public static void LoadComponents(IList<ConfuserComponent> protections, IList<ConfuserComponent> packers, string pluginPath) {
var ctx = new CrossDomainContext(protections, packers, pluginPath);
AppDomain appDomain = AppDomain.CreateDomain("");
appDomain.SetData("ctx", ctx);
appDomain.DoCallBack(CrossDomainLoadComponents);
AppDomain.Unload(appDomain);
}
public static void RemoveComponents(IList<ConfuserComponent> protections, IList<ConfuserComponent> packers, string pluginPath) {
protections.RemoveWhere(comp => comp is InfoComponent && ((InfoComponent)comp).info.path == pluginPath);
packers.RemoveWhere(comp => comp is InfoComponent && ((InfoComponent)comp).info.path == pluginPath);
}
private class CrossDomainContext : MarshalByRefObject {
private readonly IList<ConfuserComponent> packers;
private readonly string pluginPath;
private readonly IList<ConfuserComponent> protections;
public CrossDomainContext(IList<ConfuserComponent> protections, IList<ConfuserComponent> packers, string pluginPath) {
this.protections = protections;
this.packers = packers;
this.pluginPath = pluginPath;
}
public string PluginPath {
get { return pluginPath; }
}
public void AddProtection(Info info) {
protections.Add(new InfoComponent(info));
}
public void AddPacker(Info info) {
packers.Add(new InfoComponent(info));
}
}
[Serializable]
private class Info {
public string desc;
public string fullId;
public string id;
public string name;
public string path;
public static Info FromComponent(ConfuserComponent component, string pluginPath) {
var ret = new Info();
ret.name = component.Name;
ret.desc = component.Description;
ret.id = component.Id;
ret.fullId = component.FullId;
ret.path = pluginPath;
return ret;
}
}
private class InfoComponent : ConfuserComponent {
public readonly Info info;
public InfoComponent(Info info) {
this.info = info;
}
public override string Name {
get { return info.name; }
}
public override string Description {
get { return info.desc; }
}
public override string Id {
get { return info.id; }
}
public override string FullId {
get { return info.fullId; }
}
protected override void Initialize(ConfuserContext context) {
throw new NotSupportedException();
}
protected override void PopulatePipeline(ProtectionPipeline pipeline) {
throw new NotSupportedException();
}
}
}
}

Просмотреть файл

@ -0,0 +1,247 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{B5205EBA-EC32-4C53-86A0-FAEEE7393EC0}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>ConfuserEx</RootNamespace>
<AssemblyName>ConfuserEx</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
<Utf8Output>true</Utf8Output>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
<RestorePackages>true</RestorePackages>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>..\Debug\bin\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
<OutputPath>..\Release\bin\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>ConfuserEx.ico</ApplicationIcon>
</PropertyGroup>
<PropertyGroup>
<SignAssembly>true</SignAssembly>
</PropertyGroup>
<PropertyGroup>
<AssemblyOriginatorKeyFile>..\ConfuserEx.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="GalaSoft.MvvmLight.Extras.WPF4">
<HintPath>..\packages\MvvmLightLibs.4.3.31.1\lib\net40\GalaSoft.MvvmLight.Extras.WPF4.dll</HintPath>
</Reference>
<Reference Include="GalaSoft.MvvmLight.WPF4">
<HintPath>..\packages\MvvmLightLibs.4.3.31.1\lib\net40\GalaSoft.MvvmLight.WPF4.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Practices.ServiceLocation">
<HintPath>..\packages\CommonServiceLocator.1.2\lib\portable-windows8+net40+sl5+windowsphone8\Microsoft.Practices.ServiceLocation.dll</HintPath>
</Reference>
<Reference Include="Ookii.Dialogs.Wpf">
<HintPath>..\deps\Ookii.Dialogs.Wpf.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Threading, Version=1.0.2856.102, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<HintPath>..\packages\TaskParallelLibrary.1.0.2856.0\lib\Net35\System.Threading.dll</HintPath>
</Reference>
<Reference Include="System.Windows.Interactivity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\MvvmLightLibs.4.3.31.1\lib\net40\System.Windows.Interactivity.dll</HintPath>
</Reference>
<Reference Include="System.Xaml" />
<Reference Include="System.Xml" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="..\GlobalAssemblyInfo.cs">
<Link>Properties\GlobalAssemblyInfo.cs</Link>
</Compile>
<Compile Include="BrushToColorConverter.cs" />
<Compile Include="CompComboBox.xaml.cs">
<DependentUpon>CompComboBox.xaml</DependentUpon>
</Compile>
<Compile Include="ComponentConverter.cs" />
<Compile Include="ComponentDiscovery.cs" />
<Compile Include="EnumValuesExtension.cs" />
<Compile Include="FileDragDrop.cs" />
<Compile Include="InvertBoolConverter.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Skin.cs" />
<Compile Include="ViewModel\Project\ProjectRuleVM.cs" />
<Compile Include="ViewModel\Project\ProjectSettingVM.cs" />
<Compile Include="ViewModel\StringItem.cs" />
<Compile Include="ViewModel\UI\AppVM.cs" />
<Compile Include="ViewModel\IViewModel.cs" />
<Compile Include="ViewModel\Project\ProjectModuleVM.cs" />
<Compile Include="ViewModel\UI\ProjectTabVM.cs" />
<Compile Include="ViewModel\Project\ProjectVM.cs" />
<Compile Include="ViewModel\UI\ProtectTabVM.cs" />
<Compile Include="ViewModel\UI\SettingsTabVM.cs" />
<Compile Include="ViewModel\UI\TabViewModel.cs" />
<Compile Include="ViewModel\Utils.cs" />
<Compile Include="ViewModel\ViewModelBase.cs" />
<Compile Include="Views\ProjectModuleView.xaml.cs">
<DependentUpon>ProjectModuleView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\ProjectRuleView.xaml.cs">
<DependentUpon>ProjectRuleView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\ProjectTabAdvancedView.xaml.cs">
<DependentUpon>ProjectTabAdvancedView.xaml</DependentUpon>
</Compile>
<Page Include="CompComboBox.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="MainWindow.xaml.cs">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Page Include="Skin.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\ProtectTabView.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\ProjectRuleView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\SettingsTabView.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\ProjectModuleView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\ProjectTabAdvancedView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\ProjectTabView.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
</ItemGroup>
<ItemGroup>
<AppDesigner Include="Properties\" />
</ItemGroup>
<ItemGroup>
<Resource Include="ConfuserEx.ico" />
</ItemGroup>
<ItemGroup>
<None Include="..\ConfuserEx.snk">
<Link>Properties\ConfuserEx.snk</Link>
</None>
<None Include="app.config" />
<None Include="packages.config" />
<None Include="Resources\CREDITS" />
<Resource Include="Resources\FontAwesome.otf" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Confuser.Core\Confuser.Core.csproj">
<Project>{BEB67A6E-4C54-4DE5-8C6B-2C12F44A7B92}</Project>
<Name>Confuser.Core</Name>
</ProjectReference>
<ProjectReference Include="..\Confuser.DynCipher\Confuser.DynCipher.csproj">
<Project>{E832E9B8-2158-4FC0-89A1-56C6ECC10F6B}</Project>
<Name>Confuser.DynCipher</Name>
</ProjectReference>
<ProjectReference Include="..\Confuser.Protections\Confuser.Protections.csproj">
<Project>{3EAB01B5-9B49-48D8-BFA1-5493B26CCB71}</Project>
<Name>Confuser.Protections</Name>
</ProjectReference>
<ProjectReference Include="..\Confuser.Renamer\Confuser.Renamer.csproj">
<Project>{862DA0DA-52E1-47CD-B9C2-46B106031B28}</Project>
<Name>Confuser.Renamer</Name>
</ProjectReference>
<ProjectReference Include="..\Confuser.Runtime\Confuser.Runtime.csproj">
<Project>{A45C184F-F98F-4258-A928-BFF437034791}</Project>
<Name>Confuser.Runtime</Name>
</ProjectReference>
<ProjectReference Include="..\dnlib\src\dnlib.csproj">
<Project>{FDFC1237-143F-4919-8318-4926901F4639}</Project>
<Name>dnlib</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\Decode.png" />
<Resource Include="Resources\New.png" />
<Resource Include="Resources\Open.png" />
<Resource Include="Resources\Save.png" />
<Resource Include="Resources\Tools.png" />
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\Error.png" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
<Target Name="solveAliasProblem" >
<ConvertToAbsolutePath Paths="..\packages\TaskParallelLibrary.1.0.2856.0\lib\Net35\System.Threading.dll">
<Output TaskParameter="AbsolutePaths" PropertyName="FullPathOriginal" />
</ConvertToAbsolutePath>
<ItemGroup>
<ReferencePath Remove="$(FullPathOriginal)"/>
<ReferencePath Include="$(FullPathOriginal)">
<Aliases>PTL</Aliases>
</ReferencePath>
</ItemGroup>
</Target>
<PropertyGroup>
<CoreCompileDependsOn>solveAliasProblem;$(PrepareResourcesDependsOn)</CoreCompileDependsOn>
</PropertyGroup>
</Project>

Двоичные данные
ConfuserEx/ConfuserEx.ico Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 37 KiB

Просмотреть файл

@ -0,0 +1,16 @@
using System;
using System.Windows.Markup;
namespace ConfuserEx {
public class EnumValuesExtension : MarkupExtension {
private readonly Type enumType;
public EnumValuesExtension(Type enumType) {
this.enumType = enumType;
}
public override object ProvideValue(IServiceProvider serviceProvider) {
return Enum.GetValues(enumType);
}
}
}

112
ConfuserEx/FileDragDrop.cs Normal file
Просмотреть файл

@ -0,0 +1,112 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using ConfuserEx.ViewModel;
using GalaSoft.MvvmLight.Command;
namespace ConfuserEx {
public class FileDragDrop {
public static readonly DependencyProperty CommandProperty =
DependencyProperty.RegisterAttached("Command", typeof (ICommand), typeof (FileDragDrop), new UIPropertyMetadata(null, OnCommandChanged));
public static ICommand FileCmd = new DragDropCommand(
data => {
Debug.Assert(data.Item2.GetDataPresent(DataFormats.FileDrop));
if (data.Item1 is TextBox) {
string file = ((string[])data.Item2.GetData(DataFormats.FileDrop))[0];
Debug.Assert(File.Exists(file));
((TextBox)data.Item1).Text = file;
} else if (data.Item1 is ListBox) {
var files = (string[])data.Item2.GetData(DataFormats.FileDrop);
Debug.Assert(files.All(file => File.Exists(file)));
var list = (IList<StringItem>)((ListBox)data.Item1).ItemsSource;
foreach (string file in files)
list.Add(new StringItem(file));
} else
throw new NotSupportedException();
}, data => {
if (!data.Item2.GetDataPresent(DataFormats.FileDrop))
return false;
return ((string[])data.Item2.GetData(DataFormats.FileDrop)).All(file => File.Exists(file));
});
public static ICommand DirectoryCmd = new DragDropCommand(
data => {
Debug.Assert(data.Item2.GetDataPresent(DataFormats.FileDrop));
if (data.Item1 is TextBox) {
string dir = ((string[])data.Item2.GetData(DataFormats.FileDrop))[0];
Debug.Assert(Directory.Exists(dir));
((TextBox)data.Item1).Text = dir;
} else if (data.Item1 is ListBox) {
var dirs = (string[])data.Item2.GetData(DataFormats.FileDrop);
Debug.Assert(dirs.All(dir => Directory.Exists(dir)));
var list = (IList<StringItem>)((ListBox)data.Item1).ItemsSource;
foreach (string dir in dirs)
list.Add(new StringItem(dir));
} else
throw new NotSupportedException();
}, data => {
if (!data.Item2.GetDataPresent(DataFormats.FileDrop))
return false;
return ((string[])data.Item2.GetData(DataFormats.FileDrop)).All(dir => Directory.Exists(dir));
});
public static ICommand GetCommand(DependencyObject obj) {
return (ICommand)obj.GetValue(CommandProperty);
}
public static void SetCommand(DependencyObject obj, ICommand value) {
obj.SetValue(CommandProperty, value);
}
private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
var elem = (UIElement)d;
if (e.NewValue != null) {
elem.AllowDrop = true;
elem.PreviewDragOver += OnDragOver;
elem.PreviewDrop += OnDrop;
} else {
elem.AllowDrop = false;
elem.PreviewDragOver -= OnDragOver;
elem.PreviewDrop -= OnDrop;
}
}
private static void OnDragOver(object sender, DragEventArgs e) {
ICommand cmd = GetCommand((DependencyObject)sender);
e.Effects = DragDropEffects.None;
if (cmd is DragDropCommand) {
if (cmd.CanExecute(Tuple.Create((UIElement)sender, e.Data)))
e.Effects = DragDropEffects.Link;
} else {
if (cmd.CanExecute(e.Data))
e.Effects = DragDropEffects.Link;
}
e.Handled = true;
}
private static void OnDrop(object sender, DragEventArgs e) {
ICommand cmd = GetCommand((DependencyObject)sender);
if (cmd is DragDropCommand) {
if (cmd.CanExecute(Tuple.Create((UIElement)sender, e.Data)))
cmd.Execute(Tuple.Create((UIElement)sender, e.Data));
} else {
if (cmd.CanExecute(e.Data))
cmd.Execute(e.Data);
}
e.Handled = true;
}
private class DragDropCommand : RelayCommand<Tuple<UIElement, IDataObject>> {
public DragDropCommand(Action<Tuple<UIElement, IDataObject>> execute, Func<Tuple<UIElement, IDataObject>, bool> canExecute)
: base(execute, canExecute) { }
}
}
}

Просмотреть файл

@ -0,0 +1,21 @@
using System;
using System.Diagnostics;
using System.Globalization;
using System.Windows.Data;
namespace ConfuserEx {
internal class InvertBoolConverter : IValueConverter {
public static readonly InvertBoolConverter Instance = new InvertBoolConverter();
private InvertBoolConverter() { }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
Debug.Assert(value is bool);
Debug.Assert(targetType == typeof (bool));
return !(bool)value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
throw new NotSupportedException();
}
}
}

Просмотреть файл

@ -0,0 +1,60 @@
<Window x:Class="ConfuserEx.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ConfuserEx"
Title="{Binding Title}" Width="800" Height="600" Style="{StaticResource DarkWindow}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ToolBar Grid.Row="0" Grid.ColumnSpan="2" ToolBarTray.IsLocked="True" ToolBar.OverflowMode="Never"
KeyboardNavigation.TabNavigation="Continue">
<Button Command="{Binding NewProject}">
<StackPanel Orientation="Horizontal">
<Image Source="{StaticResource New}" Margin="0,0,4,0" />
<TextBlock Text="New project" VerticalAlignment="Center" />
</StackPanel>
</Button>
<Button Command="{Binding OpenProject}">
<StackPanel Orientation="Horizontal">
<Image Source="{StaticResource Open}" Margin="0,0,4,0" />
<TextBlock Text="Open project" VerticalAlignment="Center" />
</StackPanel>
</Button>
<Button Command="{Binding SaveProject}">
<StackPanel Orientation="Horizontal">
<Image Source="{StaticResource Save}" Margin="0,0,4,0" />
<TextBlock Text="Save project" VerticalAlignment="Center" />
</StackPanel>
</Button>
<Button ContextMenuService.IsEnabled="False" Click="OpenMenu">
<StackPanel Orientation="Horizontal">
<Image Source="{StaticResource Tools}" Margin="0,0,4,0" />
<TextBlock Text="Tools" VerticalAlignment="Center" />
<Path Data="M 0.5 4 L 6.5 4 L 3.5 9 Z" Fill="{StaticResource Foreground}" Margin="4,0,0,0"
VerticalAlignment="Center" />
</StackPanel>
<Button.ContextMenu>
<ContextMenu
DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
<MenuItem Header="Stack Trace Decoder" Command="{Binding Decode}">
<MenuItem.Icon>
<Image Source="{StaticResource Decode}" />
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</Button.ContextMenu>
</Button>
</ToolBar>
<TabControl Grid.Row="1" Grid.ColumnSpan="2" Margin="10" ItemsSource="{Binding Tabs}" Padding="5"
SelectedIndex="0" local:Skin.TabsDisabled="{Binding NavigationDisabled}">
<TabControl.ItemContainerStyle>
<Style TargetType="{x:Type TabItem}" BasedOn="{StaticResource {x:Type TabItem}}">
<Setter Property="Width" Value="80" />
<Setter Property="Header" Value="{Binding Header}" />
</Style>
</TabControl.ItemContainerStyle>
</TabControl>
</Grid>
</Window>

Просмотреть файл

@ -0,0 +1,38 @@
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using Confuser.Core.Project;
using ConfuserEx.ViewModel;
namespace ConfuserEx {
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
var app = new AppVM();
app.Project = new ProjectVM(new ConfuserProject());
app.FileName = "Unnamed.crproj";
app.Tabs.Add(new ProjectTabVM(app));
app.Tabs.Add(new SettingsTabVM(app));
app.Tabs.Add(new ProtectTabVM(app));
DataContext = app;
}
private void OpenMenu(object sender, RoutedEventArgs e) {
var btn = (Button)sender;
ContextMenu menu = btn.ContextMenu;
menu.PlacementTarget = btn;
menu.Placement = PlacementMode.MousePoint;
menu.IsOpen = true;
}
protected override void OnClosing(CancelEventArgs e) {
base.OnClosing(e);
e.Cancel = !((AppVM)DataContext).OnWindowClosing();
}
}
}

Просмотреть файл

@ -0,0 +1,5 @@
using System;
using System.Reflection;
[assembly: AssemblyTitle("ConfuserEx")]
[assembly: AssemblyDescription("ConfuserEx GUI")]

Просмотреть файл

@ -0,0 +1 @@
Icons adapted from http://flaticons.net

Двоичные данные
ConfuserEx/Resources/Decode.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.1 KiB

Двоичные данные
ConfuserEx/Resources/Error.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 536 B

Двоичные данные
ConfuserEx/Resources/FontAwesome.otf Normal file

Двоичный файл не отображается.

Двоичные данные
ConfuserEx/Resources/New.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.1 KiB

Двоичные данные
ConfuserEx/Resources/Open.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.1 KiB

Двоичные данные
ConfuserEx/Resources/Save.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.1 KiB

Двоичные данные
ConfuserEx/Resources/Tools.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.1 KiB

51
ConfuserEx/Skin.cs Normal file
Просмотреть файл

@ -0,0 +1,51 @@
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
namespace ConfuserEx {
public class Skin {
public static readonly DependencyProperty EmptyPromptProperty =
DependencyProperty.RegisterAttached("EmptyPrompt", typeof (string), typeof (Skin), new UIPropertyMetadata(null));
public static readonly DependencyProperty TabsDisabledProperty =
DependencyProperty.RegisterAttached("TabsDisabled", typeof (bool), typeof (Skin), new UIPropertyMetadata(false));
public static readonly DependencyProperty RTBDocumentProperty =
DependencyProperty.RegisterAttached("RTBDocument", typeof (FlowDocument), typeof (Skin), new FrameworkPropertyMetadata(null, OnRTBDocumentChanged));
public static string GetEmptyPrompt(DependencyObject obj) {
return (string)obj.GetValue(EmptyPromptProperty);
}
public static void SetEmptyPrompt(DependencyObject obj, string value) {
obj.SetValue(EmptyPromptProperty, value);
}
public static bool GetTabsDisabled(DependencyObject obj) {
return (bool)obj.GetValue(TabsDisabledProperty);
}
public static void SetTabsDisabled(DependencyObject obj, bool value) {
obj.SetValue(TabsDisabledProperty, value);
}
public static void OnRTBDocumentChanged(DependencyObject d, DependencyPropertyChangedEventArgs dpe) {
var rtb = (RichTextBox)d;
if (dpe.NewValue != null) {
rtb.Document = (FlowDocument)dpe.NewValue;
rtb.TextChanged += (sender, e) => rtb.ScrollToEnd();
}
else
rtb.Document = new FlowDocument();
}
public static FlowDocument GetRTBDocument(DependencyObject obj) {
return (FlowDocument)obj.GetValue(RTBDocumentProperty);
}
public static void SetRTBDocument(DependencyObject obj, FlowDocument value) {
obj.SetValue(RTBDocumentProperty, value);
}
}
}

1501
ConfuserEx/Skin.xaml Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,7 @@
using System;
namespace ConfuserEx.ViewModel {
public interface IViewModel<TModel> {
TModel Model { get; }
}
}

Просмотреть файл

@ -0,0 +1,87 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Reflection;
using System.Threading;
using Confuser.Core.Project;
namespace ConfuserEx.ViewModel {
public class ProjectModuleVM : ViewModelBase, IViewModel<ProjectModule>, IRuleContainer {
private readonly ProjectModule module;
private readonly ProjectVM parent;
private string asmName = "Unknown";
private string simpleName;
public ProjectModuleVM(ProjectVM parent, ProjectModule module) {
this.parent = parent;
this.module = module;
ObservableCollection<ProjectRuleVM> rules = Utils.Wrap(module.Rules, rule => new ProjectRuleVM(parent, rule));
rules.CollectionChanged += (sender, e) => parent.IsModified = true;
Rules = rules;
SimpleName = System.IO.Path.GetFileName(module.Path);
LoadAssemblyName();
}
public ProjectModule Module {
get { return module; }
}
public string Path {
get { return module.Path; }
set {
if (SetProperty(module.Path != value, val => module.Path = val, value, "Path")) {
parent.IsModified = true;
SimpleName = System.IO.Path.GetFileName(module.Path);
LoadAssemblyName();
}
}
}
public string SimpleName {
get { return simpleName; }
private set { SetProperty(ref simpleName, value, "SimpleName"); }
}
public string AssemblyName {
get { return asmName; }
private set { SetProperty(ref asmName, value, "AssemblyName"); }
}
public string SNKeyPath {
get { return module.SNKeyPath; }
set {
if (SetProperty(module.SNKeyPath != value, val => module.SNKeyPath = val, value, "SNKeyPath"))
parent.IsModified = true;
}
}
public string SNKeyPassword {
get { return module.SNKeyPassword; }
set {
if (SetProperty(module.SNKeyPassword != value, val => module.SNKeyPassword = val, value, "SNKeyPassword"))
parent.IsModified = true;
}
}
public IList<ProjectRuleVM> Rules { get; private set; }
ProjectModule IViewModel<ProjectModule>.Model {
get { return module; }
}
private void LoadAssemblyName() {
AssemblyName = "Loading...";
ThreadPool.QueueUserWorkItem(_ => {
try {
string path = System.IO.Path.Combine(parent.BaseDirectory, Path);
AssemblyName name = System.Reflection.AssemblyName.GetAssemblyName(path);
AssemblyName = name.FullName;
} catch {
AssemblyName = "Unknown";
}
});
}
}
}

Просмотреть файл

@ -0,0 +1,88 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Confuser.Core;
using Confuser.Core.Project;
using Confuser.Core.Project.Patterns;
namespace ConfuserEx.ViewModel {
internal interface IRuleContainer {
IList<ProjectRuleVM> Rules { get; }
}
public class ProjectRuleVM : ViewModelBase, IViewModel<Rule> {
private readonly ProjectVM parent;
private readonly Rule rule;
private string error;
private PatternExpression exp;
public ProjectRuleVM(ProjectVM parent, Rule rule) {
this.parent = parent;
this.rule = rule;
ObservableCollection<ProjectSettingVM<Protection>> protections = Utils.Wrap(rule, setting => new ProjectSettingVM<Protection>(parent, setting));
protections.CollectionChanged += (sender, e) => parent.IsModified = true;
Protections = protections;
ParseExpression();
}
public ProjectVM Project {
get { return parent; }
}
public string Pattern {
get { return rule.Pattern; }
set {
if (SetProperty(rule.Pattern != value, val => rule.Pattern = val, value, "Pattern")) {
parent.IsModified = true;
ParseExpression();
}
}
}
public PatternExpression Expression {
get { return exp; }
set { SetProperty(ref exp, value, "Expression"); }
}
public string ExpressionError {
get { return error; }
set { SetProperty(ref error, value, "ExpressionError"); }
}
public ProtectionPreset Preset {
get { return rule.Preset; }
set {
if (SetProperty(rule.Preset != value, val => rule.Preset = val, value, "Preset"))
parent.IsModified = true;
}
}
public bool Inherit {
get { return rule.Inherit; }
set {
if (SetProperty(rule.Inherit != value, val => rule.Inherit = val, value, "Inherit"))
parent.IsModified = true;
}
}
public IList<ProjectSettingVM<Protection>> Protections { get; private set; }
Rule IViewModel<Rule>.Model {
get { return rule; }
}
private void ParseExpression() {
PatternExpression expression;
try {
expression = new PatternParser().Parse(Pattern);
ExpressionError = null;
} catch (Exception e) {
ExpressionError = e.Message;
expression = null;
}
Expression = expression;
}
}
}

Просмотреть файл

@ -0,0 +1,34 @@
using System;
using Confuser.Core.Project;
namespace ConfuserEx.ViewModel {
public class ProjectSettingVM<T> : ViewModelBase, IViewModel<SettingItem<T>> {
private readonly ProjectVM parent;
private readonly SettingItem<T> setting;
public ProjectSettingVM(ProjectVM parent, SettingItem<T> setting) {
this.parent = parent;
this.setting = setting;
}
public string Id {
get { return setting.Id; }
set {
if (SetProperty(setting.Id != value, val => setting.Id = val, value, "Id"))
parent.IsModified = true;
}
}
public SettingItemAction Action {
get { return setting.Action; }
set {
if (SetProperty(setting.Action != value, val => setting.Action = val, value, "Action"))
parent.IsModified = true;
}
}
SettingItem<T> IViewModel<SettingItem<T>>.Model {
get { return setting; }
}
}
}

Просмотреть файл

@ -0,0 +1,101 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Reflection;
using Confuser.Core;
using Confuser.Core.Project;
namespace ConfuserEx.ViewModel {
public class ProjectVM : ViewModelBase, IViewModel<ConfuserProject>, IRuleContainer {
private readonly ConfuserProject proj;
private bool modified;
private ProjectSettingVM<Packer> packer;
public ProjectVM(ConfuserProject proj) {
this.proj = proj;
ObservableCollection<ProjectModuleVM> modules = Utils.Wrap(proj, module => new ProjectModuleVM(this, module));
modules.CollectionChanged += (sender, e) => IsModified = true;
Modules = modules;
ObservableCollection<StringItem> plugins = Utils.Wrap(proj.PluginPaths, path => new StringItem(path));
plugins.CollectionChanged += (sender, e) => IsModified = true;
Plugins = plugins;
ObservableCollection<StringItem> probePaths = Utils.Wrap(proj.ProbePaths, path => new StringItem(path));
probePaths.CollectionChanged += (sender, e) => IsModified = true;
ProbePaths = probePaths;
ObservableCollection<ProjectRuleVM> rules = Utils.Wrap(proj.Rules, rule => new ProjectRuleVM(this, rule));
rules.CollectionChanged += (sender, e) => IsModified = true;
Rules = rules;
Protections = new ObservableCollection<ConfuserComponent>();
Packers = new ObservableCollection<ConfuserComponent>();
ComponentDiscovery.LoadComponents(Protections, Packers, Assembly.Load("Confuser.Protections").Location);
ComponentDiscovery.LoadComponents(Protections, Packers, Assembly.Load("Confuser.Renamer").Location);
}
public ConfuserProject Project {
get { return proj; }
}
public bool IsModified {
get { return modified; }
set { SetProperty(ref modified, value, "IsModified"); }
}
public string Seed {
get { return proj.Seed; }
set { SetProperty(proj.Seed != value, val => proj.Seed = val, value, "Seed"); }
}
public bool Debug {
get { return proj.Debug; }
set { SetProperty(proj.Debug != value, val => proj.Debug = val, value, "Debug"); }
}
public string BaseDirectory {
get { return proj.BaseDirectory; }
set { SetProperty(proj.BaseDirectory != value, val => proj.BaseDirectory = val, value, "BaseDirectory"); }
}
public string OutputDirectory {
get { return proj.OutputDirectory; }
set { SetProperty(proj.OutputDirectory != value, val => proj.OutputDirectory = val, value, "OutputDirectory"); }
}
public ProjectSettingVM<Packer> Packer {
get {
if (proj.Packer == null)
packer = null;
else
packer = new ProjectSettingVM<Packer>(this, proj.Packer);
return packer;
}
set {
var vm = (IViewModel<SettingItem<Packer>>)value;
bool changed = (vm == null && proj.Packer != null) || (vm != null && proj.Packer != vm.Model);
SetProperty(changed, val => proj.Packer = val == null ? null : val.Model, vm, "Packer");
}
}
public IList<ProjectModuleVM> Modules { get; private set; }
public IList<StringItem> Plugins { get; private set; }
public IList<StringItem> ProbePaths { get; private set; }
public ObservableCollection<ConfuserComponent> Protections { get; private set; }
public ObservableCollection<ConfuserComponent> Packers { get; private set; }
public IList<ProjectRuleVM> Rules { get; private set; }
ConfuserProject IViewModel<ConfuserProject>.Model {
get { return proj; }
}
protected override void OnPropertyChanged(string property) {
base.OnPropertyChanged(property);
if (property != "IsModified")
IsModified = true;
}
}
}

Просмотреть файл

@ -0,0 +1,19 @@
using System;
namespace ConfuserEx.ViewModel {
public class StringItem : IViewModel<string> {
public StringItem(string item) {
Item = item;
}
public string Item { get; private set; }
string IViewModel<string>.Model {
get { return Item; }
}
public override string ToString() {
return Item;
}
}
}

Просмотреть файл

@ -0,0 +1,144 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Windows;
using System.Windows.Input;
using System.Xml;
using Confuser.Core;
using Confuser.Core.Project;
using GalaSoft.MvvmLight.Command;
using Ookii.Dialogs.Wpf;
namespace ConfuserEx.ViewModel {
public class AppVM : ViewModelBase {
private readonly IList<TabViewModel> tabs = new ObservableCollection<TabViewModel>();
private string fileName;
private bool navDisabled;
private ProjectVM proj;
public bool NavigationDisabled {
get { return navDisabled; }
set { SetProperty(ref navDisabled, value, "NavigationDisabled"); }
}
public ProjectVM Project {
get { return proj; }
set {
if (proj != null)
proj.PropertyChanged -= OnProjectPropertyChanged;
SetProperty(ref proj, value, "Project");
if (proj != null)
proj.PropertyChanged += OnProjectPropertyChanged;
}
}
public string FileName {
get { return fileName; }
set {
SetProperty(ref fileName, value, "Project");
OnPropertyChanged("Title");
}
}
public string Title {
get {
return string.Format("{0}{1} - {2}",
Path.GetFileName(fileName),
(proj.IsModified ? "*" : ""),
ConfuserEngine.Version);
}
}
public IList<TabViewModel> Tabs {
get { return tabs; }
}
public ICommand NewProject {
get { return new RelayCommand(NewProj, () => !NavigationDisabled); }
}
public ICommand OpenProject {
get { return new RelayCommand(OpenProj, () => !NavigationDisabled); }
}
public ICommand SaveProject {
get { return new RelayCommand(() => SaveProj(), () => !NavigationDisabled); }
}
public ICommand Decode {
get { return new RelayCommand(() => { MessageBox.Show("Not yet implemented!", "ConfuserEx", MessageBoxButton.OK, MessageBoxImage.Information); }, () => !NavigationDisabled); }
}
public bool OnWindowClosing() {
return PromptSave();
}
private bool SaveProj() {
if (File.Exists(FileName)) {
var sfd = new VistaSaveFileDialog();
sfd.FileName = FileName;
sfd.Filter = "ConfuserEx Projects (*.crproj)|*.crproj|All Files (*.*)|*.*";
if (!(sfd.ShowDialog(Application.Current.MainWindow) ?? false) || sfd.FileName == null)
return false;
FileName = sfd.FileName;
}
ConfuserProject proj = ((IViewModel<ConfuserProject>)Project).Model;
proj.Save().Save(FileName);
Project.IsModified = false;
return true;
}
private bool PromptSave() {
if (!Project.IsModified)
return true;
switch (MessageBox.Show("The current project has unsaved changes. Do you want to save them?", "ConfuserEx", MessageBoxButton.YesNoCancel, MessageBoxImage.Question)) {
case MessageBoxResult.Yes:
return SaveProj();
case MessageBoxResult.No:
return true;
case MessageBoxResult.Cancel:
return false;
}
return false;
}
private void NewProj() {
if (!PromptSave())
return;
Project = new ProjectVM(new ConfuserProject());
FileName = "Unnamed.crproj";
}
private void OpenProj() {
if (!PromptSave())
return;
var ofd = new VistaOpenFileDialog();
ofd.Filter = "ConfuserEx Projects (*.crproj)|*.crproj|All Files (*.*)|*.*";
if ((ofd.ShowDialog(Application.Current.MainWindow) ?? false) && ofd.FileName != null) {
string fileName = ofd.FileName;
try {
var xmlDoc = new XmlDocument();
xmlDoc.Load(fileName);
var proj = new ConfuserProject();
proj.Load(xmlDoc);
Project = new ProjectVM(proj);
FileName = fileName;
} catch {
MessageBox.Show("Invalid project!", "ConfuserEx", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
}
private void OnProjectPropertyChanged(object sender, PropertyChangedEventArgs e) {
if (e.PropertyName == "IsModified" && proj.IsModified)
OnPropertyChanged("Title");
}
}
}

Просмотреть файл

@ -0,0 +1,131 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Input;
using Confuser.Core.Project;
using ConfuserEx.Views;
using GalaSoft.MvvmLight.Command;
using Ookii.Dialogs.Wpf;
namespace ConfuserEx.ViewModel {
public class ProjectTabVM : TabViewModel {
private int selIndex = -1;
public ProjectTabVM(AppVM app)
: base(app, "Project") { }
public ICommand DragDrop {
get {
return new RelayCommand<IDataObject>(data => {
foreach (string file in (string[])data.GetData(DataFormats.FileDrop))
AddModule(file);
}, data => {
if (!data.GetDataPresent(DataFormats.FileDrop))
return false;
var files = (string[])data.GetData(DataFormats.FileDrop);
bool ret = files.All(file => File.Exists(file));
return ret;
});
}
}
public int SelectedIndex {
get { return selIndex; }
set { SetProperty(ref selIndex, value, "SelectedIndex"); }
}
public ICommand ChooseBaseDir {
get {
return new RelayCommand(() => {
var fbd = new VistaFolderBrowserDialog();
fbd.SelectedPath = App.Project.BaseDirectory;
if (fbd.ShowDialog() ?? false) {
App.Project.BaseDirectory = fbd.SelectedPath;
App.Project.OutputDirectory = Path.Combine(App.Project.BaseDirectory, "Confused");
}
});
}
}
public ICommand ChooseOutputDir {
get {
return new RelayCommand(() => {
var fbd = new VistaFolderBrowserDialog();
fbd.SelectedPath = App.Project.OutputDirectory;
if (fbd.ShowDialog() ?? false) {
App.Project.OutputDirectory = fbd.SelectedPath;
}
});
}
}
public ICommand Add {
get {
return new RelayCommand(() => {
var ofd = new VistaOpenFileDialog();
ofd.Filter = ".NET assemblies (*.exe, *.dll)|*.exe;*.dll|All Files (*.*)|*.*";
if (ofd.ShowDialog() ?? false) {
AddModule(ofd.FileName);
}
});
}
}
public ICommand Remove {
get {
return new RelayCommand(() => {
int selIndex = SelectedIndex;
Debug.Assert(selIndex != -1);
ProjectModuleVM module = App.Project.Modules[selIndex];
string msg = string.Format("Are you sure to remove module '{0}'?\r\nAll settings specific to it would be lost!", module.Path);
if (MessageBox.Show(msg, "ConfuserEx", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes) {
App.Project.Modules.RemoveAt(selIndex);
SelectedIndex = selIndex >= App.Project.Modules.Count ? App.Project.Modules.Count - 1 : selIndex;
}
}, () => SelectedIndex != -1);
}
}
public ICommand Edit {
get {
return new RelayCommand(() => {
Debug.Assert(SelectedIndex != -1);
var dialog = new ProjectModuleView(App.Project.Modules[SelectedIndex]);
dialog.Owner = Application.Current.MainWindow;
dialog.ShowDialog();
}, () => SelectedIndex != -1);
}
}
public ICommand Advanced {
get {
return new RelayCommand(() => {
var dialog = new ProjectTabAdvancedView(App.Project);
dialog.Owner = Application.Current.MainWindow;
dialog.ShowDialog();
});
}
}
private void AddModule(string file) {
if (!File.Exists(file)) {
MessageBox.Show(string.Format("File '{0}' does not exists!", file), "ConfuserEx", MessageBoxButton.OK, MessageBoxImage.Error);
return;
}
if (string.IsNullOrEmpty(App.Project.BaseDirectory)) {
string directory = Path.GetDirectoryName(file);
App.Project.BaseDirectory = directory;
App.Project.OutputDirectory = Path.Combine(directory, "Confused");
}
var module = new ProjectModuleVM(App.Project, new ProjectModule());
try {
module.Path = Confuser.Core.Utils.GetRelativePath(file, App.Project.BaseDirectory);
} catch {
module.Path = file;
}
App.Project.Modules.Add(module);
}
}
}

Просмотреть файл

@ -0,0 +1,151 @@
extern alias PTL;
using System;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using Confuser.Core;
using Confuser.Core.Project;
using GalaSoft.MvvmLight.Command;
using PTL::System.Threading;
// http://connect.microsoft.com/VisualStudio/feedback/details/615953/
namespace ConfuserEx.ViewModel {
internal class ProtectTabVM : TabViewModel, ILogger {
private readonly Paragraph documentContent;
private double? progress = 0;
private bool? result;
public ProtectTabVM(AppVM app)
: base(app, "Protect!") {
documentContent = new Paragraph();
LogDocument = new FlowDocument();
LogDocument.Blocks.Add(documentContent);
}
public ICommand ProtectCmd {
get { return new RelayCommand(DoProtect, () => !App.NavigationDisabled); }
}
public ICommand CancelCmd {
get { return new RelayCommand(DoCancel, () => App.NavigationDisabled); }
}
public double? Progress {
get { return progress; }
set { SetProperty(ref progress, value, "Progress"); }
}
public FlowDocument LogDocument { get; private set; }
public bool? Result {
get { return result; }
set { SetProperty(ref result, value, "Result"); }
}
CancellationTokenSource cancelSrc;
private void DoProtect() {
var parameters = new ConfuserParameters();
parameters.Project = ((IViewModel<ConfuserProject>)App.Project).Model;
parameters.Logger = this;
documentContent.Inlines.Clear();
cancelSrc = new CancellationTokenSource();
Result = null;
Progress = null;
begin = DateTime.Now;
App.NavigationDisabled = true;
ConfuserEngine.Run(parameters, cancelSrc.Token)
.ContinueWith(_ =>
Application.Current.Dispatcher.BeginInvoke(new Action(() => {
Progress = 0;
App.NavigationDisabled = false;
CommandManager.InvalidateRequerySuggested();
})));
}
private void DoCancel() {
cancelSrc.Cancel();
}
private void AppendLine(string format, Brush foreground, params object[] args) {
Application.Current.Dispatcher.BeginInvoke(new Action(() => {
documentContent.Inlines.Add(new Run(string.Format(format, args)) { Foreground = foreground });
documentContent.Inlines.Add(new LineBreak());
}));
}
#region Logger Impl
private DateTime begin;
void ILogger.Debug(string msg) {
AppendLine("[DEBUG] {0}", Brushes.Gray, msg);
}
void ILogger.DebugFormat(string format, params object[] args) {
AppendLine("[DEBUG] {0}", Brushes.Gray, string.Format(format, args));
}
void ILogger.Info(string msg) {
AppendLine(" [INFO] {0}", Brushes.White, msg);
}
void ILogger.InfoFormat(string format, params object[] args) {
AppendLine(" [INFO] {0}", Brushes.White, string.Format(format, args));
}
void ILogger.Warn(string msg) {
AppendLine(" [WARN] {0}", Brushes.Yellow, msg);
}
void ILogger.WarnFormat(string format, params object[] args) {
AppendLine(" [WARN] {0}", Brushes.Yellow, string.Format(format, args));
}
void ILogger.WarnException(string msg, Exception ex) {
AppendLine(" [WARN] {0}", Brushes.Yellow, msg);
AppendLine("Exception: {0}", Brushes.Yellow, ex);
}
void ILogger.Error(string msg) {
AppendLine("[ERROR] {0}", Brushes.Red, msg);
}
void ILogger.ErrorFormat(string format, params object[] args) {
AppendLine("[ERROR] {0}", Brushes.Red, string.Format(format, args));
}
void ILogger.ErrorException(string msg, Exception ex) {
AppendLine("[ERROR] {0}", Brushes.Red, msg);
AppendLine("Exception: {0}", Brushes.Red, ex);
}
void ILogger.Progress(int progress, int overall) {
Progress = (double)progress / overall;
}
void ILogger.EndProgress() {
Progress = null;
}
void ILogger.Finish(bool successful) {
DateTime now = DateTime.Now;
string timeString = string.Format(
"at {0}, {1}:{2:d2} elapsed.",
now.ToShortTimeString(),
(int)now.Subtract(begin).TotalMinutes,
now.Subtract(begin).Seconds);
if (successful)
AppendLine("Finished {0}", Brushes.Lime, timeString);
else
AppendLine("Failed {0}", Brushes.Red, timeString);
Result = successful;
}
#endregion
}
}

Просмотреть файл

@ -0,0 +1,105 @@
using System;
using System.Collections;
using System.Diagnostics;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;
using Confuser.Core;
using Confuser.Core.Project;
using ConfuserEx.Views;
using GalaSoft.MvvmLight.Command;
namespace ConfuserEx.ViewModel {
internal class SettingsTabVM : TabViewModel {
private bool hasPacker;
private IRuleContainer selectedList;
private int selectedRuleIndex;
public SettingsTabVM(AppVM app)
: base(app, "Settings") {
app.PropertyChanged += (sender, e) => {
if (e.PropertyName == "Project")
InitProject();
};
InitProject();
}
public bool HasPacker {
get { return hasPacker; }
set { SetProperty(ref hasPacker, value, "HasPacker"); }
}
public IList ModulesView { get; private set; }
public IRuleContainer SelectedList {
get { return selectedList; }
set {
if (SetProperty(ref selectedList, value, "SelectedList"))
SelectedRuleIndex = -1;
}
}
public int SelectedRuleIndex {
get { return selectedRuleIndex; }
set { SetProperty(ref selectedRuleIndex, value, "SelectedRuleIndex"); }
}
public ICommand Add {
get {
return new RelayCommand(() => {
Debug.Assert(SelectedList != null);
var rule = new ProjectRuleVM(App.Project, new Rule());
rule.Pattern = "true";
SelectedList.Rules.Add(rule);
SelectedRuleIndex = SelectedList.Rules.Count - 1;
}, () => SelectedList != null);
}
}
public ICommand Remove {
get {
return new RelayCommand(() => {
int selIndex = SelectedRuleIndex;
Debug.Assert(SelectedList != null);
Debug.Assert(selIndex != -1);
ProjectRuleVM rule = SelectedList.Rules[selIndex];
SelectedList.Rules.RemoveAt(selIndex);
SelectedRuleIndex = selIndex >= SelectedList.Rules.Count ? SelectedList.Rules.Count - 1 : selIndex;
}, () => SelectedRuleIndex != -1 && SelectedList != null);
}
}
public ICommand Edit {
get {
return new RelayCommand(() => {
Debug.Assert(SelectedRuleIndex != -1);
var dialog = new ProjectRuleView(App.Project, SelectedList.Rules[SelectedRuleIndex]);
dialog.Owner = Application.Current.MainWindow;
dialog.ShowDialog();
dialog.Cleanup();
}, () => SelectedRuleIndex != -1 && SelectedList != null);
}
}
private void InitProject() {
ModulesView = new CompositeCollection {
App.Project,
new CollectionContainer { Collection = App.Project.Modules }
};
OnPropertyChanged("ModulesView");
HasPacker = App.Project.Packer != null;
}
protected override void OnPropertyChanged(string property) {
if (property == "HasPacker") {
if (hasPacker)
App.Project.Packer = new ProjectSettingVM<Packer>(App.Project, new SettingItem<Packer> { Id = App.Project.Packers[0].Id });
else
App.Project.Packer = null;
}
base.OnPropertyChanged(property);
}
}
}

Просмотреть файл

@ -0,0 +1,13 @@
using System;
namespace ConfuserEx.ViewModel {
public abstract class TabViewModel : ViewModelBase {
protected TabViewModel(AppVM app, string header) {
App = app;
Header = header;
}
public AppVM App { get; private set; }
public string Header { get; private set; }
}
}

Просмотреть файл

@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
namespace ConfuserEx.ViewModel {
public static class Utils {
public static ObservableCollection<T> Wrap<T>(IList<T> list) {
var ret = new ObservableCollection<T>(list);
ret.CollectionChanged += (sender, e) => {
var collection = (ObservableCollection<T>)sender;
switch (e.Action) {
case NotifyCollectionChangedAction.Reset:
list.Clear();
foreach (T item in collection)
list.Add(item);
break;
case NotifyCollectionChangedAction.Add:
for (int i = 0; i < e.NewItems.Count; i++)
list.Insert(e.NewStartingIndex + i, (T)e.NewItems[i]);
break;
case NotifyCollectionChangedAction.Remove:
for (int i = 0; i < e.OldItems.Count; i++)
list.RemoveAt(e.OldStartingIndex);
break;
case NotifyCollectionChangedAction.Move:
list.RemoveAt(e.OldStartingIndex);
list.Insert(e.NewStartingIndex, (T)e.NewItems[0]);
break;
case NotifyCollectionChangedAction.Replace:
list[e.NewStartingIndex] = (T)e.NewItems[0];
break;
}
};
return ret;
}
public static ObservableCollection<TViewModel> Wrap<TModel, TViewModel>(IList<TModel> list, Func<TModel, TViewModel> transform) where TViewModel : IViewModel<TModel> {
var ret = new ObservableCollection<TViewModel>(list.Select(item => transform(item)));
ret.CollectionChanged += (sender, e) => {
var collection = (ObservableCollection<TViewModel>)sender;
switch (e.Action) {
case NotifyCollectionChangedAction.Reset:
list.Clear();
foreach (TViewModel item in collection)
list.Add(item.Model);
break;
case NotifyCollectionChangedAction.Add:
for (int i = 0; i < e.NewItems.Count; i++)
list.Insert(e.NewStartingIndex + i, ((TViewModel)e.NewItems[i]).Model);
break;
case NotifyCollectionChangedAction.Remove:
for (int i = 0; i < e.OldItems.Count; i++)
list.RemoveAt(e.OldStartingIndex);
break;
case NotifyCollectionChangedAction.Move:
list.RemoveAt(e.OldStartingIndex);
list.Insert(e.NewStartingIndex, ((TViewModel)e.NewItems[0]).Model);
break;
case NotifyCollectionChangedAction.Replace:
list[e.NewStartingIndex] = ((TViewModel)e.NewItems[0]).Model;
break;
}
};
return ret;
}
}
}

Просмотреть файл

@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
namespace ConfuserEx.ViewModel {
public class ViewModelBase : INotifyPropertyChanged {
// http://stackoverflow.com/a/1316417/462805
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string property) {
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
protected bool SetProperty<T>(ref T field, T value, string property) {
if (!EqualityComparer<T>.Default.Equals(field, value)) {
field = value;
OnPropertyChanged(property);
return true;
}
return false;
}
protected bool SetProperty<T>(bool changed, Action<T> setter, T value, string property) {
if (changed) {
setter(value);
OnPropertyChanged(property);
return true;
}
return false;
}
}
}

8
ConfuserEx/Views.xaml Normal file
Просмотреть файл

@ -0,0 +1,8 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Views\ProjectTabView.xaml" />
<ResourceDictionary Source="Views\SettingsTabView.xaml" />
<ResourceDictionary Source="Views\ProtectTabView.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

Просмотреть файл

@ -0,0 +1,46 @@
<Window x:Class="ConfuserEx.Views.ProjectModuleView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ConfuserEx"
Title="{Binding Path, StringFormat=Edit module \'{0}\'...}" Style="{StaticResource DarkWindow}"
SizeToContent="WidthAndHeight" ShowInTaskbar="False" ResizeMode="NoResize">
<Grid Margin="5">
<Grid.RowDefinitions>
<RowDefinition Height="36px" />
<RowDefinition Height="36px" />
<RowDefinition Height="36px" />
<RowDefinition Height="36px" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150px" />
<ColumnDefinition Width="250px" />
<ColumnDefinition Width="35px" />
</Grid.ColumnDefinitions>
<Label Content="Assembly Path : " Grid.Row="0" Grid.Column="0" HorizontalContentAlignment="Right"
VerticalContentAlignment="Center" />
<TextBox Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2" Margin="5" VerticalContentAlignment="Center"
Text="{Binding Path, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
local:FileDragDrop.Command="{x:Static local:FileDragDrop.FileCmd}" />
<Label Content="SN Key Path : " Grid.Row="1" Grid.Column="0" HorizontalContentAlignment="Right"
VerticalContentAlignment="Center" />
<TextBox x:Name="PathBox" Grid.Row="1" Grid.Column="1" Margin="5" VerticalContentAlignment="Center"
TextChanged="PathBox_TextChanged"
Text="{Binding SNKeyPath, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
local:FileDragDrop.Command="{x:Static local:FileDragDrop.FileCmd}" />
<Button Grid.Row="1" Grid.Column="2" Margin="5" VerticalAlignment="Center" Height="26" Click="ChooseSNKey">
<TextBlock FontSize="14px" FontFamily="{DynamicResource FontAwesome}" Text="&#xf141;" Height="10px"
TextOptions.TextRenderingMode="GrayScale" />
</Button>
<Label Content="SN Key Password : " Grid.Row="2" Grid.Column="0" HorizontalContentAlignment="Right"
VerticalContentAlignment="Center" />
<TextBox x:Name="PwdBox" Grid.Row="2" Grid.Column="1" Margin="5" Grid.ColumnSpan="2"
VerticalContentAlignment="Center"
Text="{Binding SNKeyPassword, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<Button Grid.Row="3" Grid.ColumnSpan="3" HorizontalAlignment="Right" Content="Done"
Width="70" Margin="5" Click="Done" />
</Grid>
</Window>

Просмотреть файл

@ -0,0 +1,34 @@
using System;
using System.Windows;
using System.Windows.Controls;
using ConfuserEx.ViewModel;
using Ookii.Dialogs.Wpf;
namespace ConfuserEx.Views {
public partial class ProjectModuleView : Window {
private readonly ProjectModuleVM module;
public ProjectModuleView(ProjectModuleVM module) {
InitializeComponent();
this.module = module;
DataContext = module;
PwdBox.IsEnabled = !string.IsNullOrEmpty(PathBox.Text);
}
private void Done(object sender, RoutedEventArgs e) {
DialogResult = true;
}
private void PathBox_TextChanged(object sender, TextChangedEventArgs e) {
PwdBox.IsEnabled = !string.IsNullOrEmpty(PathBox.Text);
}
private void ChooseSNKey(object sender, RoutedEventArgs e) {
var ofd = new VistaOpenFileDialog();
ofd.Filter = "Supported Key Files (*.snk, *.pfx)|*.snk;*.pfx|All Files (*.*)|*.*";
if (ofd.ShowDialog() ?? false) {
module.SNKeyPath = ofd.FileName;
}
}
}
}

Просмотреть файл

@ -0,0 +1,85 @@
<Window x:Class="ConfuserEx.Views.ProjectRuleView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ConfuserEx"
xmlns:core="clr-namespace:Confuser.Core;assembly=Confuser.Core"
xmlns:proj="clr-namespace:Confuser.Core.Project;assembly=Confuser.Core"
Title="Edit rule..." Height="600" Width="400" x:Name="View"
Style="{StaticResource DarkWindow}" ShowInTaskbar="False" ResizeMode="NoResize">
<Grid Margin="5">
<Grid.Resources>
<local:ComponentConverter x:Key="ProtConverter"
xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
PresentationOptions:Freeze="True"
Components="{Binding Project.Protections}" />
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="36px" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="25px" />
<RowDefinition Height="36px" />
<RowDefinition Height="36px" />
<RowDefinition Height="25px" />
<RowDefinition Height="*" />
<RowDefinition Height="40px" />
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.ColumnSpan="2" Content="Pattern:" VerticalAlignment="Center"
HorizontalAlignment="Left" />
<TextBox x:Name="pattern" Grid.Row="1" Grid.ColumnSpan="2"
Text="{Binding Pattern, UpdateSourceTrigger=PropertyChanged}" FontFamily="Consolas" Margin="5"
VerticalContentAlignment="Center" />
<Image x:Name="errorImg" Grid.Row="1" Grid.ColumnSpan="2" Source="{StaticResource Error}"
Width="16px" Height="16px" ToolTip="{Binding ExpressionError}" Margin="0,0,10,0"
Visibility="Hidden" HorizontalAlignment="Right" />
<DockPanel Grid.Row="2" Grid.ColumnSpan="2" LastChildFill="False">
<Label DockPanel.Dock="Left" Content="Preset : " VerticalAlignment="Center" />
<ComboBox DockPanel.Dock="Left" SelectedItem="{Binding Preset, UpdateSourceTrigger=PropertyChanged}"
Margin="5" Width="100" VerticalAlignment="Center"
ItemsSource="{local:EnumValues {x:Type core:ProtectionPreset}}" />
<CheckBox DockPanel.Dock="Right" Content="Inherit protections"
IsChecked="{Binding Inherit}" Margin="5" VerticalAlignment="Center" />
</DockPanel>
<Label Grid.Row="3" Content="Protections:" VerticalAlignment="Center"
HorizontalAlignment="Left" />
<ListBox x:Name="prots" Grid.Row="4" Margin="5"
ItemsSource="{Binding Protections}" Grid.IsSharedSizeScope="True">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="Action" />
<ColumnDefinition Width="10px" />
<ColumnDefinition SharedSizeGroup="Protection" />
</Grid.ColumnDefinitions>
<ComboBox Grid.Column="0" Width="80" SelectedItem="{Binding Action}" IsEnabled="True"
ItemsSource="{local:EnumValues {x:Type proj:SettingItemAction}}" />
<local:CompComboBox Grid.Column="2" Width="150"
Components="{Binding Project.Protections, ElementName=View}"
SelectedComponent="{Binding Id, Converter={StaticResource ProtConverter}, Mode=TwoWay}" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<DockPanel Grid.Row="4" Grid.Column="1" LastChildFill="False">
<Button Height="26" Margin="5" DockPanel.Dock="Top" x:Name="AddBtn">
<TextBlock FontSize="14px" FontFamily="{DynamicResource FontAwesome}" Text="&#xf067;" Height="12px"
TextOptions.TextRenderingMode="GrayScale" />
</Button>
<Button Height="26" Margin="5" DockPanel.Dock="Top" x:Name="RemoveBtn">
<TextBlock FontSize="14px" FontFamily="{DynamicResource FontAwesome}" Text="&#xf068;" Height="12px"
TextOptions.TextRenderingMode="GrayScale" />
</Button>
</DockPanel>
<Button Grid.Row="5" Grid.ColumnSpan="2" HorizontalAlignment="Right"
Margin="5" Width="70" Content="Done" Click="Done" />
</Grid>
</Window>

Просмотреть файл

@ -0,0 +1,70 @@
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows;
using System.Windows.Media;
using Confuser.Core;
using Confuser.Core.Project;
using ConfuserEx.ViewModel;
using GalaSoft.MvvmLight.Command;
namespace ConfuserEx.Views {
public partial class ProjectRuleView : Window {
private readonly ProjectVM proj;
private readonly ProjectRuleVM rule;
public ProjectRuleView(ProjectVM proj, ProjectRuleVM rule) {
InitializeComponent();
this.rule = rule;
this.proj = proj;
DataContext = rule;
rule.PropertyChanged += OnPropertyChanged;
CheckValidity();
}
public ProjectVM Project {
get { return proj; }
}
public override void OnApplyTemplate() {
base.OnApplyTemplate();
AddBtn.Command = new RelayCommand(() => {
var prot = new ProjectSettingVM<Protection>(proj, new SettingItem<Protection>());
prot.Id = proj.Protections[0].Id;
rule.Protections.Add(prot);
});
RemoveBtn.Command = new RelayCommand(() => {
int selIndex = prots.SelectedIndex;
Debug.Assert(selIndex != -1);
rule.Protections.RemoveAt(prots.SelectedIndex);
prots.SelectedIndex = selIndex >= rule.Protections.Count ? rule.Protections.Count - 1 : selIndex;
}, () => prots.SelectedIndex != -1);
}
public void Cleanup() {
rule.PropertyChanged -= OnPropertyChanged;
}
private void OnPropertyChanged(object sender, PropertyChangedEventArgs e) {
if (e.PropertyName == "Expression")
CheckValidity();
}
private void CheckValidity() {
if (rule.Expression == null) {
pattern.BorderBrush = Brushes.Red;
errorImg.Visibility = Visibility.Visible;
} else {
pattern.ClearValue(BorderBrushProperty);
errorImg.Visibility = Visibility.Hidden;
}
}
private void Done(object sender, RoutedEventArgs e) {
DialogResult = true;
}
}
}

Просмотреть файл

@ -0,0 +1,49 @@
<Window x:Class="ConfuserEx.Views.ProjectTabAdvancedView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ConfuserEx"
Title="Advanced Settings..." Height="400" Width="600"
Style="{StaticResource DarkWindow}" ShowInTaskbar="False" ResizeMode="NoResize">
<Grid Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="36px" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="36px" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="36px" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="Probe Paths :" Margin="5" VerticalAlignment="Center" />
<ListBox Grid.Row="1" Grid.Column="0" Margin="5" x:Name="ProbePaths" ItemsSource="{Binding ProbePaths}"
local:FileDragDrop.Command="{x:Static local:FileDragDrop.DirectoryCmd}"
ScrollViewer.CanContentScroll="False" />
<StackPanel Grid.Row="1" Grid.Column="1">
<Button Height="26" Margin="5" DockPanel.Dock="Top" x:Name="AddProbe">
<TextBlock FontSize="14px" FontFamily="{DynamicResource FontAwesome}" Text="&#xf067;" Height="12px"
TextOptions.TextRenderingMode="GrayScale" />
</Button>
<Button Height="26" Margin="5" DockPanel.Dock="Top" x:Name="RemoveProbe">
<TextBlock FontSize="14px" FontFamily="{DynamicResource FontAwesome}" Text="&#xf068;" Height="12px"
TextOptions.TextRenderingMode="GrayScale" />
</Button>
</StackPanel>
<Label Grid.Row="0" Grid.Column="2" Content="Plugins :" Margin="5" VerticalAlignment="Center" />
<ListBox Grid.Row="1" Grid.Column="2" Margin="5" x:Name="PluginPaths" ItemsSource="{Binding Plugins}"
local:FileDragDrop.Command="{x:Static local:FileDragDrop.FileCmd}"
ScrollViewer.CanContentScroll="False" />
<StackPanel Grid.Row="1" Grid.Column="3">
<Button Height="26" Margin="5" DockPanel.Dock="Top" x:Name="AddPlugin">
<TextBlock FontSize="14px" FontFamily="{DynamicResource FontAwesome}" Text="&#xf067;" Height="12px"
TextOptions.TextRenderingMode="GrayScale" />
</Button>
<Button Height="26" Margin="5" DockPanel.Dock="Top" x:Name="RemovePlugin">
<TextBlock FontSize="14px" FontFamily="{DynamicResource FontAwesome}" Text="&#xf068;" Height="12px"
TextOptions.TextRenderingMode="GrayScale" />
</Button>
</StackPanel>
</Grid>
</Window>

Просмотреть файл

@ -0,0 +1,63 @@
using System;
using System.Diagnostics;
using System.Windows;
using ConfuserEx.ViewModel;
using GalaSoft.MvvmLight.Command;
using Ookii.Dialogs.Wpf;
namespace ConfuserEx.Views {
public partial class ProjectTabAdvancedView : Window {
private readonly ProjectVM project;
public ProjectTabAdvancedView(ProjectVM project) {
InitializeComponent();
this.project = project;
DataContext = project;
}
public override void OnApplyTemplate() {
base.OnApplyTemplate();
AddPlugin.Command = new RelayCommand(() => {
var ofd = new VistaOpenFileDialog();
ofd.Filter = ".NET assemblies (*.exe, *.dll)|*.exe;*.dll|All Files (*.*)|*.*";
ofd.Multiselect = true;
if (ofd.ShowDialog() ?? false) {
foreach (string plugin in ofd.FileNames) {
try {
ComponentDiscovery.LoadComponents(project.Protections, project.Packers, plugin);
project.Plugins.Add(new StringItem(plugin));
} catch {
MessageBox.Show("Failed to load plugin '" + plugin + "'.");
}
}
}
});
RemovePlugin.Command = new RelayCommand(() => {
int selIndex = PluginPaths.SelectedIndex;
Debug.Assert(selIndex != -1);
string plugin = project.Plugins[selIndex].Item;
ComponentDiscovery.RemoveComponents(project.Protections, project.Packers, plugin);
project.Plugins.RemoveAt(selIndex);
PluginPaths.SelectedIndex = selIndex >= project.Plugins.Count ? project.Plugins.Count - 1 : selIndex;
}, () => PluginPaths.SelectedIndex != -1);
AddProbe.Command = new RelayCommand(() => {
var fbd = new VistaFolderBrowserDialog();
if (fbd.ShowDialog() ?? false)
project.ProbePaths.Add(new StringItem(fbd.SelectedPath));
});
RemoveProbe.Command = new RelayCommand(() => {
int selIndex = ProbePaths.SelectedIndex;
Debug.Assert(selIndex != -1);
project.ProbePaths.RemoveAt(selIndex);
ProbePaths.SelectedIndex = selIndex >= project.ProbePaths.Count ? project.ProbePaths.Count - 1 : selIndex;
}, () => ProbePaths.SelectedIndex != -1);
}
}
}

Просмотреть файл

@ -0,0 +1,95 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ConfuserEx"
xmlns:vm="clr-namespace:ConfuserEx.ViewModel">
<DataTemplate DataType="{x:Type vm:ProjectTabVM}">
<Grid Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="36px" />
<RowDefinition Height="36px" />
<RowDefinition Height="36px" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150px" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="36px" />
</Grid.ColumnDefinitions>
<Label Content="Base Directory : " Grid.Row="0" Grid.Column="0" HorizontalContentAlignment="Right"
VerticalContentAlignment="Center" />
<TextBox Grid.Row="0" Grid.Column="1" Margin="5" VerticalContentAlignment="Center"
Text="{Binding App.Project.BaseDirectory, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
local:FileDragDrop.Command="{x:Static local:FileDragDrop.DirectoryCmd}" />
<Button Grid.Row="0" Grid.Column="2" Margin="5" VerticalAlignment="Center" Height="26"
Command="{Binding ChooseBaseDir}">
<TextBlock FontSize="14px" FontFamily="{DynamicResource FontAwesome}" Text="&#xf141;" Height="10px"
TextOptions.TextRenderingMode="GrayScale" />
</Button>
<Label Content="Output Directory : " Grid.Row="1" Grid.Column="0" HorizontalContentAlignment="Right"
VerticalContentAlignment="Center" />
<TextBox Grid.Row="1" Grid.Column="1" Margin="5" VerticalContentAlignment="Center"
Text="{Binding App.Project.OutputDirectory, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
local:FileDragDrop.Command="{x:Static local:FileDragDrop.DirectoryCmd}" />
<Button Grid.Row="1" Grid.Column="2" Margin="5" VerticalAlignment="Center" Height="26"
Command="{Binding ChooseOutputDir}">
<TextBlock FontSize="14px" FontFamily="{DynamicResource FontAwesome}" Text="&#xf141;" Height="10px"
TextOptions.TextRenderingMode="GrayScale" />
</Button>
<Grid Grid.Row="2" Grid.ColumnSpan="3">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150px" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label Content="Seed : " Grid.Column="0" HorizontalContentAlignment="Right"
VerticalContentAlignment="Center" />
<TextBox Grid.Column="1" Margin="5" VerticalContentAlignment="Center"
Text="{Binding App.Project.Seed, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
local:Skin.EmptyPrompt="Leave blank for random seed" />
<CheckBox Grid.Column="2" Content="Generate Debug Symbols" VerticalAlignment="Center" Margin="5"
IsChecked="{Binding App.Project.Debug, Mode=TwoWay}" />
</Grid>
<ListBox Grid.Row="3" Grid.ColumnSpan="2" Margin="5" local:Skin.EmptyPrompt="Drag input modules here"
ItemsSource="{Binding App.Project.Modules}" HorizontalContentAlignment="Stretch"
SelectedIndex="{Binding SelectedIndex}" ScrollViewer.HorizontalScrollBarVisibility="Disabled"
Grid.IsSharedSizeScope="True" local:FileDragDrop.Command="{Binding DragDrop}"
ScrollViewer.CanContentScroll="False">
<ListBox.ItemTemplate>
<DataTemplate DataType="{x:Type vm:ProjectModuleVM}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding AssemblyName}"
TextAlignment="Left" Margin="0,0,5,0" TextTrimming="CharacterEllipsis" />
<TextBlock Grid.Column="1" Text="{Binding Path}"
TextAlignment="Right" Margin="5,0,0,0" TextTrimming="CharacterEllipsis" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<DockPanel Grid.Row="3" Grid.Column="2" LastChildFill="False">
<Button Height="26" Margin="5" DockPanel.Dock="Top" Command="{Binding Add}">
<TextBlock FontSize="14px" FontFamily="{DynamicResource FontAwesome}" Text="&#xf067;" Height="12px"
TextOptions.TextRenderingMode="GrayScale" />
</Button>
<Button Height="26" Margin="5" DockPanel.Dock="Top" Command="{Binding Remove}">
<TextBlock FontSize="14px" FontFamily="{DynamicResource FontAwesome}" Text="&#xf068;" Height="12px"
TextOptions.TextRenderingMode="GrayScale" />
</Button>
<Button Height="26" Margin="5" DockPanel.Dock="Top" Command="{Binding Edit}">
<TextBlock FontSize="14px" FontFamily="{DynamicResource FontAwesome}" Text="&#xf044;" Height="12px"
TextOptions.TextRenderingMode="GrayScale" />
</Button>
<Button Height="26" Margin="5" DockPanel.Dock="Bottom" Command="{Binding Advanced}">
<TextBlock FontSize="14px" FontFamily="{DynamicResource FontAwesome}" Text="&#xf013;" Height="12px"
TextOptions.TextRenderingMode="GrayScale" />
</Button>
</DockPanel>
</Grid>
</DataTemplate>
</ResourceDictionary>

Просмотреть файл

@ -0,0 +1,37 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ConfuserEx"
xmlns:vm="clr-namespace:ConfuserEx.ViewModel">
<DataTemplate DataType="{x:Type vm:ProtectTabVM}">
<Grid Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="40px" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="100px" />
<ColumnDefinition Width="100px" />
</Grid.ColumnDefinitions>
<ProgressBar x:Name="progress" Grid.Row="0" Grid.Column="0" Margin="5"
Value="{Binding Progress}" Minimum="0" Maximum="1" />
<Button Grid.Row="0" Grid.Column="1" Margin="5" Content="Protect!" Command="{Binding ProtectCmd}" />
<Button Grid.Row="0" Grid.Column="2" Margin="5" Content="Cancel" Command="{Binding CancelCmd}" />
<RichTextBox x:Name="log" Grid.Row="1" Grid.ColumnSpan="3" Margin="5" FontFamily="Consolas"
IsReadOnly="True" IsReadOnlyCaretVisible="True" local:Skin.RTBDocument="{Binding LogDocument}"
VerticalScrollBarVisibility="Visible" />
</Grid>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Progress}" Value="{x:Null}">
<Setter TargetName="progress" Property="IsIndeterminate" Value="True" />
</DataTrigger>
<DataTrigger Binding="{Binding Result}" Value="True">
<Setter TargetName="log" Property="BorderBrush" Value="#40ff40" />
</DataTrigger>
<DataTrigger Binding="{Binding Result}" Value="False">
<Setter TargetName="log" Property="BorderBrush" Value="#ff4040" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ResourceDictionary>

Просмотреть файл

@ -0,0 +1,83 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ConfuserEx"
xmlns:vm="clr-namespace:ConfuserEx.ViewModel">
<DataTemplate DataType="{x:Type vm:SettingsTabVM}">
<Grid Background="Transparent">
<Grid.Resources>
<local:ComponentConverter x:Key="PackerConverter" x:Shared="False"
Components="{Binding App.Project.Packers}" />
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="40px" />
<RowDefinition Height="40px" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200px" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="36px" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Row="0" Grid.ColumnSpan="3" Orientation="Horizontal" Margin="5">
<CheckBox Content="Packer : " VerticalAlignment="Center" HorizontalAlignment="Right"
Margin="5,0,0,0" IsChecked="{Binding HasPacker}" />
<local:CompComboBox Width="300" Components="{Binding App.Project.Packers}" Margin="5,0,0,0"
IsEnabled="{Binding HasPacker}" HorizontalAlignment="Left"
VerticalAlignment="Center"
SelectedComponent="{Binding App.Project.Packer.Id, Converter={StaticResource PackerConverter}, Mode=TwoWay}" />
</StackPanel>
<Label Grid.Row="1" Grid.Column="0" Content="Modules : " VerticalAlignment="Bottom"
HorizontalAlignment="Left" Margin="5,0,0,0" />
<Label Grid.Row="1" Grid.Column="1" Content="Rules : " VerticalAlignment="Bottom"
HorizontalAlignment="Left" Margin="5,0,0,0" />
<ListBox Grid.Row="2" Grid.Column="0" Margin="5" ItemsSource="{Binding ModulesView}"
SelectedItem="{Binding SelectedList, Mode=OneWayToSource}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock>
<TextBlock.Text>
<PriorityBinding>
<Binding Path="SimpleName" />
<Binding Source="&lt;Global settings&gt;" />
</PriorityBinding>
</TextBlock.Text>
</TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<ListBox Grid.Row="2" Grid.Column="1" Margin="5" FontFamily="Consolas"
ItemsSource="{Binding SelectedList.Rules}"
SelectedIndex="{Binding SelectedRuleIndex, Mode=TwoWay}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock x:Name="txt" Text="{Binding Pattern}" />
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Expression}" Value="{x:Null}">
<Setter TargetName="txt" Property="Foreground" Value="Red" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<DockPanel Grid.Row="2" Grid.Column="2" LastChildFill="False">
<Button Height="26" Margin="5" DockPanel.Dock="Top" Command="{Binding Add}">
<TextBlock FontSize="14px" FontFamily="{DynamicResource FontAwesome}" Text="&#xf067;" Height="12px"
TextOptions.TextRenderingMode="GrayScale" />
</Button>
<Button Height="26" Margin="5" DockPanel.Dock="Top" Command="{Binding Remove}">
<TextBlock FontSize="14px" FontFamily="{DynamicResource FontAwesome}" Text="&#xf068;" Height="12px"
TextOptions.TextRenderingMode="GrayScale" />
</Button>
<Button Height="26" Margin="5" DockPanel.Dock="Top" Command="{Binding Edit}">
<TextBlock FontSize="14px" FontFamily="{DynamicResource FontAwesome}" Text="&#xf044;" Height="12px"
TextOptions.TextRenderingMode="GrayScale" />
</Button>
</DockPanel>
</Grid>
</DataTemplate>
</ResourceDictionary>

13
ConfuserEx/app.config Normal file
Просмотреть файл

@ -0,0 +1,13 @@
<?xml version="1.0"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.Practices.ServiceLocation" publicKeyToken="31BF3856AD364E35"
culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.2.0.0" newVersion="1.2.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

Просмотреть файл

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="CommonServiceLocator" version="1.2" targetFramework="net40" />
<package id="MvvmLightLibs" version="4.3.31.1" targetFramework="net40" />
<package id="TaskParallelLibrary" version="1.0.2856.0" targetFramework="net40" />
</packages>

Просмотреть файл

@ -24,7 +24,7 @@ Usage
`Confuser.CLI <path to project file>`
The project file is a ConfuserEx Project (*.crproj).
The format of project file can be found in ProjectFormat.md
The format of project file can be found in docs\ProjectFormat.md
Bug Report
----------

Двоичные данные
additional/Icon.pdn Normal file

Двоичный файл не отображается.

Двоичные данные
additional/Icon16.pdn Normal file

Двоичный файл не отображается.

Двоичные данные
additional/Icon256.pdn Normal file

Двоичный файл не отображается.

Двоичные данные
additional/Icon32.pdn Normal file

Двоичный файл не отображается.

Двоичные данные
additional/Icon48.pdn Normal file

Двоичный файл не отображается.

Двоичные данные
additional/Icon64.pdn Normal file

Двоичный файл не отображается.

Двоичные данные
deps/Ookii.Dialogs.Wpf.dll поставляемый Normal file

Двоичный файл не отображается.

Просмотреть файл

Просмотреть файл