This repository has been archived by the owner on Jan 27, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
27 changed files
with
307 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using Confuser.Core.Services; | ||
using dnlib.DotNet; | ||
|
||
namespace Confuser.Core.API { | ||
internal class APIStore : IAPIStore { | ||
readonly ConfuserContext context; | ||
readonly RandomGenerator random; | ||
readonly SortedList<int, List<IDataStore>> dataStores; | ||
readonly List<IOpaquePredicateDescriptor> predicates; | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="APIStore" /> class. | ||
/// </summary> | ||
/// <param name="context">The working context.</param> | ||
public APIStore(ConfuserContext context) { | ||
this.context = context; | ||
random = context.Registry.GetService<IRandomService>().GetRandomGenerator("APIStore"); | ||
|
||
dataStores = new SortedList<int, List<IDataStore>>(); | ||
predicates = new List<IOpaquePredicateDescriptor>(); | ||
} | ||
|
||
/// <inheritdoc /> | ||
public void AddStore(IDataStore dataStore) { | ||
dataStores.AddListEntry(dataStore.Priority, dataStore); | ||
} | ||
|
||
/// <inheritdoc /> | ||
public void AddPredicate(IOpaquePredicateDescriptor predicate) { | ||
predicates.Add(predicate); | ||
} | ||
|
||
/// <inheritdoc /> | ||
public IDataStore GetStore(MethodDef method) { | ||
for (int i = dataStores.Count - 1; i >= 0; i--) { | ||
var list = dataStores[i]; | ||
for (int j = list.Count - 1; j >= 0; i--) { | ||
if (list[j].IsUsable(method)) | ||
return list[j]; | ||
} | ||
} | ||
return null; | ||
} | ||
|
||
/// <inheritdoc /> | ||
public IOpaquePredicateDescriptor GetPredicate(MethodDef method, OpaquePredicateType? type, params int[] argCount) { | ||
var randomPredicates = predicates.ToArray(); | ||
random.Shuffle(randomPredicates); | ||
foreach (var predicate in randomPredicates) { | ||
if (predicate.IsUsable(method) && | ||
(type == null || predicate.Type == type.Value) && | ||
(argCount == null || Array.IndexOf(argCount, predicate.ArgumentCount) != -1)) | ||
return predicate; | ||
} | ||
return null; | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Provides storage for API interfaces | ||
/// </summary> | ||
public interface IAPIStore { | ||
/// <summary> | ||
/// Adds the specified data store into this store. | ||
/// </summary> | ||
/// <param name="dataStore">The data store.</param> | ||
void AddStore(IDataStore dataStore); | ||
|
||
/// <summary> | ||
/// Finds a suitable data store for the specified method, with the | ||
/// specified number of keys. | ||
/// </summary> | ||
/// <param name="method">The method.</param> | ||
/// <returns>The suitable data store if found, or <c>null</c> if not found.</returns> | ||
/// <remarks> | ||
/// It should never returns null --- ConfuserEx has internal data store. | ||
/// </remarks> | ||
IDataStore GetStore(MethodDef method); | ||
|
||
/// <summary> | ||
/// Adds the specified opaque predicate into this store. | ||
/// </summary> | ||
/// <param name="predicate">The opaque predicate.</param> | ||
void AddPredicate(IOpaquePredicateDescriptor predicate); | ||
|
||
/// <summary> | ||
/// Finds a suitable opaque predicate for the specified method, with the | ||
/// specified properties. | ||
/// </summary> | ||
/// <param name="method">The method.</param> | ||
/// <param name="type">The required type of predicate, or <c>null</c> if it does not matter.</param> | ||
/// <param name="argCount">The required numbers of arguments, or <c>null</c> if it does not matter.</param> | ||
/// <returns>The suitable opaque predicate if found, or <c>null</c> if not found.</returns> | ||
IOpaquePredicateDescriptor GetPredicate(MethodDef method, OpaquePredicateType? type, params int[] argCount); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
using System; | ||
using dnlib.DotNet; | ||
using dnlib.DotNet.Emit; | ||
|
||
namespace Confuser.Core.API { | ||
/// <summary> | ||
/// A data store. | ||
/// </summary> | ||
public interface IDataStore { | ||
/// <summary> | ||
/// Gets the priority of this data store; higher priority means it | ||
/// would be tried earlier. | ||
/// </summary> | ||
/// <value>The priority of this data store.</value> | ||
int Priority { get; } | ||
|
||
/// <summary> | ||
/// Gets the number of keys this predicate has. | ||
/// </summary> | ||
/// <remarks> | ||
/// Keys are used by the data store to encrypt data/whatever purpose. | ||
/// </remarks> | ||
/// <value>The number of keys this data store has.</value> | ||
int KeyCount { get; } | ||
|
||
/// <summary> | ||
/// Determines whether this data store can be used in the specified method. | ||
/// </summary> | ||
/// <param name="method">The method.</param> | ||
/// <value><c>true</c> if this data store can be used in the specified method; otherwise, <c>false</c>.</value> | ||
bool IsUsable(MethodDef method); | ||
|
||
/// <summary> | ||
/// Creates an accessor of this data store for the specified method. | ||
/// </summary> | ||
/// <param name="method">The method.</param> | ||
/// <param name="keys">The keys.</param> | ||
/// <param name="data">The data to store.</param> | ||
/// <returns>A newly accessor of this data store.</returns> | ||
IDataStoreAccessor CreateAccessor(MethodDef method, uint[] keys, byte[] data); | ||
} | ||
|
||
/// <summary> | ||
/// An accessor of data store. | ||
/// </summary> | ||
public interface IDataStoreAccessor { | ||
/// <summary> | ||
/// Emits the runtime instruction sequence for this accessor. | ||
/// </summary> | ||
/// <returns>An instruction sequence that returns the stored data.</returns> | ||
Instruction[] Emit(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
using System; | ||
using dnlib.DotNet; | ||
using dnlib.DotNet.Emit; | ||
|
||
namespace Confuser.Core.API { | ||
/// <summary> | ||
/// The descriptor of a type of opaque predicate. | ||
/// </summary> | ||
public interface IOpaquePredicateDescriptor { | ||
/// <summary> | ||
/// Gets the type of the opaque predicate. | ||
/// </summary> | ||
/// <value>The type of the opaque predicate.</value> | ||
OpaquePredicateType Type { get; } | ||
|
||
/// <summary> | ||
/// Gets the number of arguments this predicate has. | ||
/// </summary> | ||
/// <remarks> | ||
/// When <see cref="IOpaquePredicateDescriptor.Type" /> is <see cref="OpaquePredicateType.Invariant" />, | ||
/// there can be 0 or more arguments. | ||
/// When <see cref="IOpaquePredicateDescriptor.Type" /> is <see cref="OpaquePredicateType.Function" />, | ||
/// there must be more than 0 arguments. | ||
/// </remarks> | ||
/// <value>The number of arguments this predicate has.</value> | ||
int ArgumentCount { get; } | ||
|
||
/// <summary> | ||
/// Determines whether this predicate can be used with the specified method. | ||
/// </summary> | ||
/// <param name="method">The method.</param> | ||
/// <value><c>true</c> if this predicate can be used with the specified method; otherwise, <c>false</c>.</value> | ||
bool IsUsable(MethodDef method); | ||
|
||
/// <summary> | ||
/// Creates a new opaque predicate for the specified method. | ||
/// </summary> | ||
/// <param name="method">The method.</param> | ||
/// <returns>A newly create opaque predicate.</returns> | ||
IOpaquePredicate CreatePredicate(MethodDef method); | ||
} | ||
|
||
/// <summary> | ||
/// An instance of opaque predicate. | ||
/// </summary> | ||
public interface IOpaquePredicate { | ||
/// <summary> | ||
/// Emits the runtime instruction sequence for this predicate. | ||
/// </summary> | ||
/// <param name="loadArg"> | ||
/// A function that returns an instruction sequence that returns the input value, | ||
/// or <c>null</c> if <see cref="IOpaquePredicateDescriptor.ArgumentCount" /> is 0. | ||
/// </param> | ||
/// <returns>An instruction sequence that returns the value of this predicate.</returns> | ||
Instruction[] Emit(Func<Instruction[]> loadArg); | ||
|
||
/// <summary> | ||
/// Computes the value of this predicate with the specified argument. | ||
/// </summary> | ||
/// <param name="arg">The argument to this predicate.</param> | ||
/// <returns>The return value of this predicate.</returns> | ||
uint GetValue(uint[] arg); | ||
} | ||
|
||
/// <summary> | ||
/// The type of opaque predicate. | ||
/// </summary> | ||
public enum OpaquePredicateType { | ||
/// <summary> | ||
/// A function, in a mathematics sense, with one input and one output. | ||
/// </summary> | ||
Function, | ||
|
||
/// <summary> | ||
/// A constant function, always returning the same value. | ||
/// </summary> | ||
Invariant | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.