Merge branch 'master' into newcode
This commit is contained in:
commit
0f9184e9be
|
@ -265,9 +265,10 @@ namespace de4dot.blocks {
|
|||
updateSources();
|
||||
}
|
||||
|
||||
void addInstructions(IList<Instr> dest, IEnumerable<Instr> instrs) {
|
||||
foreach (var instr in instrs) {
|
||||
if (!instr.isNop())
|
||||
void addInstructions(IList<Instr> dest, IList<Instr> instrs) {
|
||||
for (int i = 0; i < instrs.Count; i++) {
|
||||
var instr = instrs[i];
|
||||
if (instr.OpCode != OpCodes.Nop)
|
||||
dest.Add(instr);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using Mono.Cecil;
|
||||
using Mono.Cecil.Cil;
|
||||
using Mono.Cecil.Metadata;
|
||||
|
||||
namespace de4dot.blocks {
|
||||
class TypeCache {
|
||||
|
@ -653,7 +654,7 @@ namespace de4dot.blocks {
|
|||
}
|
||||
|
||||
public static bool hasReturnValue(IMethodSignature method) {
|
||||
return !MemberReferenceHelper.verifyType(method.MethodReturnType.ReturnType, "mscorlib", "System.Void");
|
||||
return method.MethodReturnType.ReturnType.EType != ElementType.Void;
|
||||
}
|
||||
|
||||
public static void updateStack(Instruction instr, ref int stack, bool methodHasReturnValue) {
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Mono.Cecil;
|
||||
using Mono.Cecil.Metadata;
|
||||
|
||||
namespace de4dot.blocks {
|
||||
public enum CecilType {
|
||||
|
@ -821,7 +822,7 @@ namespace de4dot.blocks {
|
|||
}
|
||||
|
||||
public static bool isSystemObject(TypeReference typeReference) {
|
||||
return verifyType(typeReference, "mscorlib", "System.Object");
|
||||
return typeReference != null && typeReference.EType == ElementType.Object;
|
||||
}
|
||||
|
||||
public static string getCanonicalizedTypeRefName(TypeReference typeRef) {
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace de4dot.blocks.cflow {
|
|||
public void init(Blocks blocks, Block block) {
|
||||
this.blocks = blocks;
|
||||
this.block = block;
|
||||
instructionEmulator.init(blocks.Method.HasImplicitThis, false, blocks.Method.Parameters, blocks.Locals);
|
||||
instructionEmulator.init(blocks);
|
||||
}
|
||||
|
||||
// Returns true if code was updated, false otherwise
|
||||
|
|
|
@ -39,7 +39,7 @@ namespace de4dot.blocks.cflow {
|
|||
public bool deobfuscate() {
|
||||
bool changed = false;
|
||||
foreach (var block in allBlocks) {
|
||||
instructionEmulator.init(blocks.Method.HasImplicitThis, false, blocks.Method.Parameters, blocks.Locals);
|
||||
instructionEmulator.init(blocks);
|
||||
var instrs = block.Instructions;
|
||||
for (int i = 0; i < instrs.Count; i++) {
|
||||
var instr = instrs[i];
|
||||
|
|
|
@ -21,6 +21,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using Mono.Cecil;
|
||||
using Mono.Cecil.Cil;
|
||||
using Mono.Cecil.Metadata;
|
||||
|
||||
namespace de4dot.blocks.cflow {
|
||||
public class InstructionEmulator {
|
||||
|
@ -31,80 +32,64 @@ namespace de4dot.blocks.cflow {
|
|||
List<Value> locals = new List<Value>();
|
||||
int argBase;
|
||||
|
||||
MethodDefinition prev_method;
|
||||
List<Value> cached_args = new List<Value>();
|
||||
List<Value> cached_locals = new List<Value>();
|
||||
int cached_argBase;
|
||||
|
||||
public InstructionEmulator() {
|
||||
}
|
||||
|
||||
public InstructionEmulator(bool implicitThis, bool initLocals, IList<ParameterDefinition> parameterDefinitions, IList<VariableDefinition> variableDefinitions) {
|
||||
init(implicitThis, initLocals, parameterDefinitions, variableDefinitions);
|
||||
public InstructionEmulator(MethodDefinition method) {
|
||||
init(method);
|
||||
}
|
||||
|
||||
public void init(bool implicitThis, bool initLocals, IList<ParameterDefinition> parameterDefinitions, IList<VariableDefinition> variableDefinitions) {
|
||||
this.parameterDefinitions = parameterDefinitions;
|
||||
this.variableDefinitions = variableDefinitions;
|
||||
public void init(Blocks blocks) {
|
||||
init(blocks.Method);
|
||||
}
|
||||
|
||||
public void init(MethodDefinition method) {
|
||||
this.parameterDefinitions = method.Parameters;
|
||||
this.variableDefinitions = method.Body.Variables;
|
||||
valueStack.init();
|
||||
|
||||
args.Clear();
|
||||
argBase = 0;
|
||||
if (implicitThis) {
|
||||
argBase = 1;
|
||||
args.Add(new UnknownValue());
|
||||
}
|
||||
foreach (var arg in parameterDefinitions)
|
||||
args.Add(getUnknownValue(arg.ParameterType));
|
||||
if (method != prev_method) {
|
||||
prev_method = method;
|
||||
|
||||
if (initLocals) {
|
||||
locals.Clear();
|
||||
foreach (var local in variableDefinitions)
|
||||
locals.Add(getDefaultValue(local.VariableType));
|
||||
}
|
||||
else {
|
||||
locals.Clear();
|
||||
foreach (var local in variableDefinitions)
|
||||
locals.Add(getUnknownValue(local.VariableType));
|
||||
}
|
||||
}
|
||||
|
||||
static Value getDefaultValue(TypeReference typeReference) {
|
||||
if (typeReference == null)
|
||||
return new UnknownValue();
|
||||
if (!typeReference.IsValueType)
|
||||
return NullValue.Instance;
|
||||
else if (DotNetUtils.isAssembly(typeReference.Scope, "mscorlib")) {
|
||||
switch (typeReference.FullName) {
|
||||
case "System.Boolean":
|
||||
case "System.SByte":
|
||||
case "System.Byte":
|
||||
case "System.Int16":
|
||||
case "System.UInt16":
|
||||
case "System.Int32":
|
||||
case "System.UInt32":
|
||||
return new Int32Value(0);
|
||||
case "System.Int64":
|
||||
case "System.UInt64":
|
||||
return new Int64Value(0);
|
||||
case "System.Single":
|
||||
case "System.Double":
|
||||
return new Real8Value(0);
|
||||
cached_args.Clear();
|
||||
cached_argBase = 0;
|
||||
if (method.HasImplicitThis) {
|
||||
cached_argBase = 1;
|
||||
cached_args.Add(new UnknownValue());
|
||||
}
|
||||
for (int i = 0; i < parameterDefinitions.Count; i++)
|
||||
cached_args.Add(getUnknownValue(parameterDefinitions[i].ParameterType));
|
||||
|
||||
cached_locals.Clear();
|
||||
for (int i = 0; i < variableDefinitions.Count; i++)
|
||||
cached_locals.Add(getUnknownValue(variableDefinitions[i].VariableType));
|
||||
}
|
||||
return new UnknownValue();
|
||||
|
||||
argBase = cached_argBase;
|
||||
args.Clear();
|
||||
args.AddRange(cached_args);
|
||||
locals.Clear();
|
||||
locals.AddRange(cached_locals);
|
||||
}
|
||||
|
||||
static Value getUnknownValue(TypeReference typeReference) {
|
||||
if (typeReference == null)
|
||||
return new UnknownValue();
|
||||
if (DotNetUtils.isAssembly(typeReference.Scope, "mscorlib")) {
|
||||
switch (typeReference.FullName) {
|
||||
case "System.Boolean": return Int32Value.createUnknownBool();
|
||||
case "System.SByte": return Int32Value.createUnknown();
|
||||
case "System.Byte": return Int32Value.createUnknownUInt8();
|
||||
case "System.Int16": return Int32Value.createUnknown();
|
||||
case "System.UInt16": return Int32Value.createUnknownUInt16();
|
||||
case "System.Int32": return Int32Value.createUnknown();
|
||||
case "System.UInt32": return Int32Value.createUnknown();
|
||||
case "System.Int64": return Int64Value.createUnknown();
|
||||
case "System.UInt64": return Int64Value.createUnknown();
|
||||
}
|
||||
switch (typeReference.EType) {
|
||||
case ElementType.Boolean: return Int32Value.createUnknownBool();
|
||||
case ElementType.I1: return Int32Value.createUnknown();
|
||||
case ElementType.U1: return Int32Value.createUnknownUInt8();
|
||||
case ElementType.I2: return Int32Value.createUnknown();
|
||||
case ElementType.U2: return Int32Value.createUnknownUInt16();
|
||||
case ElementType.I4: return Int32Value.createUnknown();
|
||||
case ElementType.U4: return Int32Value.createUnknown();
|
||||
case ElementType.I8: return Int64Value.createUnknown();
|
||||
case ElementType.U8: return Int64Value.createUnknown();
|
||||
}
|
||||
return new UnknownValue();
|
||||
}
|
||||
|
@ -112,45 +97,44 @@ namespace de4dot.blocks.cflow {
|
|||
static Value truncateValue(Value value, TypeReference typeReference) {
|
||||
if (typeReference == null)
|
||||
return value;
|
||||
if (DotNetUtils.isAssembly(typeReference.Scope, "mscorlib")) {
|
||||
switch (typeReference.FullName) {
|
||||
case "System.Boolean":
|
||||
if (value.isInt32())
|
||||
return ((Int32Value)value).toBoolean();
|
||||
return Int32Value.createUnknownBool();
|
||||
|
||||
case "System.SByte":
|
||||
if (value.isInt32())
|
||||
return ((Int32Value)value).toInt8();
|
||||
return Int32Value.createUnknown();
|
||||
switch (typeReference.EType) {
|
||||
case ElementType.Boolean:
|
||||
if (value.isInt32())
|
||||
return ((Int32Value)value).toBoolean();
|
||||
return Int32Value.createUnknownBool();
|
||||
|
||||
case "System.Byte":
|
||||
if (value.isInt32())
|
||||
return ((Int32Value)value).toUInt8();
|
||||
return Int32Value.createUnknownUInt8();
|
||||
case ElementType.I1:
|
||||
if (value.isInt32())
|
||||
return ((Int32Value)value).toInt8();
|
||||
return Int32Value.createUnknown();
|
||||
|
||||
case "System.Int16":
|
||||
if (value.isInt32())
|
||||
return ((Int32Value)value).toInt16();
|
||||
return Int32Value.createUnknown();
|
||||
case ElementType.U1:
|
||||
if (value.isInt32())
|
||||
return ((Int32Value)value).toUInt8();
|
||||
return Int32Value.createUnknownUInt8();
|
||||
|
||||
case "System.UInt16":
|
||||
if (value.isInt32())
|
||||
return ((Int32Value)value).toUInt16();
|
||||
return Int32Value.createUnknownUInt16();
|
||||
case ElementType.I2:
|
||||
if (value.isInt32())
|
||||
return ((Int32Value)value).toInt16();
|
||||
return Int32Value.createUnknown();
|
||||
|
||||
case "System.Int32":
|
||||
case "System.UInt32":
|
||||
if (value.isInt32())
|
||||
return value;
|
||||
return Int32Value.createUnknown();
|
||||
case ElementType.U2:
|
||||
if (value.isInt32())
|
||||
return ((Int32Value)value).toUInt16();
|
||||
return Int32Value.createUnknownUInt16();
|
||||
|
||||
case "System.Int64":
|
||||
case "System.UInt64":
|
||||
if (value.isInt64())
|
||||
return value;
|
||||
return Int64Value.createUnknown();
|
||||
}
|
||||
case ElementType.I4:
|
||||
case ElementType.U4:
|
||||
if (value.isInt32())
|
||||
return value;
|
||||
return Int32Value.createUnknown();
|
||||
|
||||
case ElementType.I8:
|
||||
case ElementType.U8:
|
||||
if (value.isInt64())
|
||||
return value;
|
||||
return Int64Value.createUnknown();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
@ -282,8 +266,8 @@ namespace de4dot.blocks.cflow {
|
|||
case Code.Ldc_I8: valueStack.push(new Int64Value((long)instr.Operand)); break;
|
||||
case Code.Ldc_R4: valueStack.push(new Real8Value((float)instr.Operand)); break;
|
||||
case Code.Ldc_R8: valueStack.push(new Real8Value((double)instr.Operand)); break;
|
||||
case Code.Ldc_I4_0: valueStack.push(new Int32Value(0)); break;
|
||||
case Code.Ldc_I4_1: valueStack.push(new Int32Value(1)); break;
|
||||
case Code.Ldc_I4_0: valueStack.push(Int32Value.zero); break;
|
||||
case Code.Ldc_I4_1: valueStack.push(Int32Value.one); break;
|
||||
case Code.Ldc_I4_2: valueStack.push(new Int32Value(2)); break;
|
||||
case Code.Ldc_I4_3: valueStack.push(new Int32Value(3)); break;
|
||||
case Code.Ldc_I4_4: valueStack.push(new Int32Value(4)); break;
|
||||
|
@ -779,7 +763,7 @@ namespace de4dot.blocks.cflow {
|
|||
else if (val1.isInt64() && val2.isInt64())
|
||||
valueStack.push(Int64Value.Ceq((Int64Value)val1, (Int64Value)val2));
|
||||
else if (val1.isNull() && val2.isNull())
|
||||
valueStack.push(new Int32Value(1));
|
||||
valueStack.push(Int32Value.one);
|
||||
else
|
||||
valueStack.push(Int32Value.createUnknownBool());
|
||||
}
|
||||
|
|
|
@ -21,6 +21,9 @@ using System;
|
|||
|
||||
namespace de4dot.blocks.cflow {
|
||||
public class Int32Value : Value {
|
||||
public static readonly Int32Value zero = new Int32Value(0);
|
||||
public static readonly Int32Value one = new Int32Value(1);
|
||||
|
||||
const uint NO_UNKNOWN_BITS = uint.MaxValue;
|
||||
public readonly int value;
|
||||
public readonly uint validMask;
|
||||
|
@ -223,7 +226,7 @@ namespace de4dot.blocks.cflow {
|
|||
if (a.allBitsValid() && b.allBitsValid())
|
||||
return new Int32Value(a.value - b.value);
|
||||
if (ReferenceEquals(a, b))
|
||||
return new Int32Value(0);
|
||||
return zero;
|
||||
return createUnknown();
|
||||
}
|
||||
|
||||
|
@ -231,7 +234,7 @@ namespace de4dot.blocks.cflow {
|
|||
if (a.allBitsValid() && b.allBitsValid())
|
||||
return new Int32Value(a.value * b.value);
|
||||
if (a.isZero() || b.isZero())
|
||||
return new Int32Value(0);
|
||||
return zero;
|
||||
if (a.hasValue(1))
|
||||
return b;
|
||||
if (b.hasValue(1))
|
||||
|
@ -249,7 +252,7 @@ namespace de4dot.blocks.cflow {
|
|||
}
|
||||
}
|
||||
if (ReferenceEquals(a, b) && a.isNonZero())
|
||||
return new Int32Value(1);
|
||||
return one;
|
||||
if (b.hasValue(1))
|
||||
return a;
|
||||
return createUnknown();
|
||||
|
@ -265,7 +268,7 @@ namespace de4dot.blocks.cflow {
|
|||
}
|
||||
}
|
||||
if (ReferenceEquals(a, b) && a.isNonZero())
|
||||
return new Int32Value(1);
|
||||
return one;
|
||||
if (b.hasValue(1))
|
||||
return a;
|
||||
return createUnknown();
|
||||
|
@ -281,7 +284,7 @@ namespace de4dot.blocks.cflow {
|
|||
}
|
||||
}
|
||||
if ((ReferenceEquals(a, b) && a.isNonZero()) || b.hasValue(1))
|
||||
return new Int32Value(0);
|
||||
return zero;
|
||||
return createUnknown();
|
||||
}
|
||||
|
||||
|
@ -295,7 +298,7 @@ namespace de4dot.blocks.cflow {
|
|||
}
|
||||
}
|
||||
if ((ReferenceEquals(a, b) && a.isNonZero()) || b.hasValue(1))
|
||||
return new Int32Value(0);
|
||||
return zero;
|
||||
return createUnknown();
|
||||
}
|
||||
|
||||
|
@ -319,7 +322,7 @@ namespace de4dot.blocks.cflow {
|
|||
|
||||
public static Int32Value Xor(Int32Value a, Int32Value b) {
|
||||
if (ReferenceEquals(a, b))
|
||||
return new Int32Value(0);
|
||||
return zero;
|
||||
int av = a.value, bv = b.value;
|
||||
uint am = a.validMask, bm = b.validMask;
|
||||
return new Int32Value(av ^ bv, (uint)(am & bm));
|
||||
|
@ -369,8 +372,8 @@ namespace de4dot.blocks.cflow {
|
|||
|
||||
static Int32Value create(Bool3 b) {
|
||||
switch (b) {
|
||||
case Bool3.False: return new Int32Value(0);
|
||||
case Bool3.True: return new Int32Value(1);
|
||||
case Bool3.False: return zero;
|
||||
case Bool3.True: return one;
|
||||
default: return createUnknownBool();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,9 @@ using System;
|
|||
|
||||
namespace de4dot.blocks.cflow {
|
||||
public class Int64Value : Value {
|
||||
public static readonly Int64Value zero = new Int64Value(0);
|
||||
public static readonly Int64Value one = new Int64Value(1);
|
||||
|
||||
const ulong NO_UNKNOWN_BITS = ulong.MaxValue;
|
||||
public readonly long value;
|
||||
public readonly ulong validMask;
|
||||
|
@ -117,7 +120,7 @@ namespace de4dot.blocks.cflow {
|
|||
if (a.allBitsValid() && b.allBitsValid())
|
||||
return new Int64Value(a.value - b.value);
|
||||
if (ReferenceEquals(a, b))
|
||||
return new Int64Value(0);
|
||||
return zero;
|
||||
return createUnknown();
|
||||
}
|
||||
|
||||
|
@ -125,7 +128,7 @@ namespace de4dot.blocks.cflow {
|
|||
if (a.allBitsValid() && b.allBitsValid())
|
||||
return new Int64Value(a.value * b.value);
|
||||
if (a.isZero() || b.isZero())
|
||||
return new Int64Value(0);
|
||||
return zero;
|
||||
if (a.hasValue(1))
|
||||
return b;
|
||||
if (b.hasValue(1))
|
||||
|
@ -143,7 +146,7 @@ namespace de4dot.blocks.cflow {
|
|||
}
|
||||
}
|
||||
if (ReferenceEquals(a, b) && a.isNonZero())
|
||||
return new Int64Value(1);
|
||||
return one;
|
||||
if (b.hasValue(1))
|
||||
return a;
|
||||
return createUnknown();
|
||||
|
@ -159,7 +162,7 @@ namespace de4dot.blocks.cflow {
|
|||
}
|
||||
}
|
||||
if (ReferenceEquals(a, b) && a.isNonZero())
|
||||
return new Int64Value(1);
|
||||
return one;
|
||||
if (b.hasValue(1))
|
||||
return a;
|
||||
return createUnknown();
|
||||
|
@ -175,7 +178,7 @@ namespace de4dot.blocks.cflow {
|
|||
}
|
||||
}
|
||||
if ((ReferenceEquals(a, b) && a.isNonZero()) || b.hasValue(1))
|
||||
return new Int64Value(0);
|
||||
return zero;
|
||||
return createUnknown();
|
||||
}
|
||||
|
||||
|
@ -189,7 +192,7 @@ namespace de4dot.blocks.cflow {
|
|||
}
|
||||
}
|
||||
if ((ReferenceEquals(a, b) && a.isNonZero()) || b.hasValue(1))
|
||||
return new Int64Value(0);
|
||||
return zero;
|
||||
return createUnknown();
|
||||
}
|
||||
|
||||
|
@ -213,7 +216,7 @@ namespace de4dot.blocks.cflow {
|
|||
|
||||
public static Int64Value Xor(Int64Value a, Int64Value b) {
|
||||
if (ReferenceEquals(a, b))
|
||||
return new Int64Value(0);
|
||||
return zero;
|
||||
long av = a.value, bv = b.value;
|
||||
ulong am = a.validMask, bm = b.validMask;
|
||||
return new Int64Value(av ^ bv, am & bm);
|
||||
|
@ -263,8 +266,8 @@ namespace de4dot.blocks.cflow {
|
|||
|
||||
static Int32Value create(Bool3 b) {
|
||||
switch (b) {
|
||||
case Bool3.False: return new Int32Value(0);
|
||||
case Bool3.True: return new Int32Value(1);
|
||||
case Bool3.False: return Int32Value.zero;
|
||||
case Bool3.True: return Int32Value.one;
|
||||
default: return Int32Value.createUnknownBool();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -144,7 +144,7 @@ namespace de4dot.blocks.cflow {
|
|||
foreach (var source in new List<Block>(block.Sources)) {
|
||||
if (!isBranchBlock(source))
|
||||
continue;
|
||||
instructionEmulator.init(blocks.Method.HasImplicitThis, false, blocks.Method.Parameters, blocks.Locals);
|
||||
instructionEmulator.init(blocks);
|
||||
instructionEmulator.emulate(source.Instructions);
|
||||
|
||||
var target = getSwitchTarget(switchTargets, switchFallThrough, source, instructionEmulator.pop());
|
||||
|
@ -170,7 +170,7 @@ namespace de4dot.blocks.cflow {
|
|||
foreach (var source in new List<Block>(block.Sources)) {
|
||||
if (!isBranchBlock(source))
|
||||
continue;
|
||||
instructionEmulator.init(blocks.Method.HasImplicitThis, false, blocks.Method.Parameters, blocks.Locals);
|
||||
instructionEmulator.init(blocks);
|
||||
instructionEmulator.emulate(source.Instructions);
|
||||
|
||||
var target = getSwitchTarget(switchTargets, switchFallThrough, source, instructionEmulator.getLocal(switchVariable));
|
||||
|
@ -193,7 +193,7 @@ namespace de4dot.blocks.cflow {
|
|||
foreach (var source in new List<Block>(block.Sources)) {
|
||||
if (!isBranchBlock(source))
|
||||
continue;
|
||||
instructionEmulator.init(blocks.Method.HasImplicitThis, false, blocks.Method.Parameters, blocks.Locals);
|
||||
instructionEmulator.init(blocks);
|
||||
instructionEmulator.emulate(source.Instructions);
|
||||
|
||||
var target = getSwitchTarget(switchTargets, switchFallThrough, source, instructionEmulator.pop());
|
||||
|
@ -264,7 +264,7 @@ namespace de4dot.blocks.cflow {
|
|||
}
|
||||
|
||||
bool emulateGetTarget(Block switchBlock, out Block target) {
|
||||
instructionEmulator.init(blocks.Method.HasImplicitThis, false, blocks.Method.Parameters, blocks.Locals);
|
||||
instructionEmulator.init(blocks);
|
||||
try {
|
||||
instructionEmulator.emulate(switchBlock.Instructions, 0, switchBlock.Instructions.Count - 1);
|
||||
}
|
||||
|
@ -278,7 +278,7 @@ namespace de4dot.blocks.cflow {
|
|||
}
|
||||
|
||||
bool willHaveKnownTarget(Block switchBlock, Block source) {
|
||||
instructionEmulator.init(blocks.Method.HasImplicitThis, false, blocks.Method.Parameters, blocks.Locals);
|
||||
instructionEmulator.init(blocks);
|
||||
try {
|
||||
instructionEmulator.emulate(source.Instructions);
|
||||
instructionEmulator.emulate(switchBlock.Instructions, 0, switchBlock.Instructions.Count - 1);
|
||||
|
|
2
cecil
2
cecil
|
@ -1 +1 @@
|
|||
Subproject commit 766ef4e529f0c8a4584a708711a33a1752e658c6
|
||||
Subproject commit b12e75770c5ab14fbdfe141fd6dc1668adc71436
|
|
@ -64,6 +64,12 @@ namespace de4dot.code {
|
|||
addIfExists(path, @"Microsoft Visual Studio 9.0\Common7\IDE\PrivateAssemblies");
|
||||
addIfExists(path, @"Microsoft Visual Studio 10.0\Common7\IDE\PublicAssemblies");
|
||||
addIfExists(path, @"Microsoft Visual Studio 10.0\Common7\IDE\PrivateAssemblies");
|
||||
addIfExists(path, @"Microsoft XNA\XNA Game Studio\v2.0\References\Windows\x86");
|
||||
addIfExists(path, @"Microsoft XNA\XNA Game Studio\v2.0\References\Xbox360");
|
||||
addIfExists(path, @"Microsoft XNA\XNA Game Studio\v3.0\References\Windows\x86");
|
||||
addIfExists(path, @"Microsoft XNA\XNA Game Studio\v3.0\References\Xbox360");
|
||||
addIfExists(path, @"Microsoft XNA\XNA Game Studio\v4.0\References\Windows\x86");
|
||||
addIfExists(path, @"Microsoft XNA\XNA Game Studio\v4.0\References\Xbox360");
|
||||
}
|
||||
|
||||
// basePath is eg. "C:\Program Files (x86)\Microsoft Silverlight"
|
||||
|
|
|
@ -217,6 +217,7 @@
|
|||
<Compile Include="renamer\MemberInfos.cs" />
|
||||
<Compile Include="renamer\NameCreators.cs" />
|
||||
<Compile Include="renamer\Renamer.cs" />
|
||||
<Compile Include="renamer\ResourceRenamer.cs" />
|
||||
<Compile Include="renamer\TypeInfo.cs" />
|
||||
<Compile Include="renamer\TypeNames.cs" />
|
||||
<Compile Include="renamer\TypeRenamerState.cs" />
|
||||
|
|
|
@ -126,7 +126,7 @@ namespace de4dot.code.deobfuscators {
|
|||
public static Value[] getInitializedArray(int arraySize, MethodDefinition method, ref int newarrIndex, Code stelemOpCode) {
|
||||
var resultValueArray = new Value[arraySize];
|
||||
|
||||
var emulator = new InstructionEmulator(method.HasImplicitThis, false, method.Parameters, method.Body.Variables);
|
||||
var emulator = new InstructionEmulator(method);
|
||||
var theArray = new UnknownValue();
|
||||
emulator.push(theArray);
|
||||
|
||||
|
|
|
@ -24,12 +24,12 @@ using de4dot.blocks;
|
|||
|
||||
namespace de4dot.code.deobfuscators {
|
||||
class ExceptionLoggerRemover {
|
||||
Dictionary<MethodReference, bool> exceptionLoggerMethods = new Dictionary<MethodReference, bool>();
|
||||
MethodDefinitionAndDeclaringTypeDict<bool> exceptionLoggerMethods = new MethodDefinitionAndDeclaringTypeDict<bool>();
|
||||
|
||||
public int NumRemovedExceptionLoggers { get; set; }
|
||||
|
||||
public void add(MethodDefinition exceptionLogger) {
|
||||
exceptionLoggerMethods[exceptionLogger] = true;
|
||||
exceptionLoggerMethods.add(exceptionLogger, true);
|
||||
}
|
||||
|
||||
bool find(Blocks blocks, out TryBlock tryBlock) {
|
||||
|
@ -87,7 +87,7 @@ namespace de4dot.code.deobfuscators {
|
|||
}
|
||||
|
||||
protected virtual bool isExceptionLogger(MethodReference method) {
|
||||
return exceptionLoggerMethods.ContainsKey(method);
|
||||
return exceptionLoggerMethods.find(method);
|
||||
}
|
||||
|
||||
protected virtual bool HasExceptionLoggers {
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
using System.Collections.Generic;
|
||||
using Mono.Cecil;
|
||||
using Mono.Cecil.Cil;
|
||||
using Mono.Cecil.Metadata;
|
||||
using de4dot.blocks;
|
||||
|
||||
namespace de4dot.code.deobfuscators {
|
||||
|
@ -705,7 +706,7 @@ namespace de4dot.code.deobfuscators {
|
|||
return false;
|
||||
if (MemberReferenceHelper.isSystemObject(type))
|
||||
return false;
|
||||
if (MemberReferenceHelper.verifyType(type, "mscorlib", "System.Void"))
|
||||
if (type.EType == ElementType.Void)
|
||||
return false;
|
||||
|
||||
while (type != null) {
|
||||
|
|
|
@ -331,107 +331,7 @@ namespace de4dot.code.renamer {
|
|||
if (renamedTypes.Count == 0)
|
||||
return;
|
||||
|
||||
// Rename the longest names first. Otherwise eg. b.g.resources could be renamed
|
||||
// Class0.g.resources instead of Class1.resources when b.g was renamed Class1.
|
||||
renamedTypes.Sort((a, b) => Utils.compareInt32(b.oldFullName.Length, a.oldFullName.Length));
|
||||
|
||||
renameResourceNamesInCode(module, renamedTypes);
|
||||
renameResources(module, renamedTypes);
|
||||
}
|
||||
|
||||
void renameResourceNamesInCode(Module module, IEnumerable<TypeInfo> renamedTypes) {
|
||||
// This is needed to speed up this method
|
||||
var oldToNewTypeName = new Dictionary<string, string>(StringComparer.Ordinal);
|
||||
foreach (var info in renamedTypes)
|
||||
oldToNewTypeName[info.oldFullName] = info.type.TypeDefinition.FullName;
|
||||
|
||||
List<string> validResourceNames = new List<string>();
|
||||
if (module.ModuleDefinition.Resources != null) {
|
||||
foreach (var resource in module.ModuleDefinition.Resources) {
|
||||
var name = resource.Name;
|
||||
if (name.EndsWith(".resources", StringComparison.Ordinal))
|
||||
validResourceNames.Add(name);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var method in module.getAllMethods()) {
|
||||
if (!method.HasBody)
|
||||
continue;
|
||||
foreach (var instr in method.Body.Instructions) {
|
||||
if (instr.OpCode != OpCodes.Ldstr)
|
||||
continue;
|
||||
var s = (string)instr.Operand;
|
||||
if (string.IsNullOrEmpty(s))
|
||||
continue; // Ignore emtpy strings since we'll get lots of false warnings
|
||||
|
||||
string newName = null;
|
||||
string oldName = null;
|
||||
if (oldToNewTypeName.ContainsKey(s)) {
|
||||
oldName = s;
|
||||
newName = oldToNewTypeName[s];
|
||||
}
|
||||
else if (s.EndsWith(".resources", StringComparison.Ordinal)) {
|
||||
// This should rarely, if ever, execute...
|
||||
foreach (var info in renamedTypes) { // Slow loop
|
||||
var newName2 = renameResourceString(s, info.oldFullName, info.type.TypeDefinition.FullName);
|
||||
if (newName2 != s) {
|
||||
newName = newName2;
|
||||
oldName = info.oldFullName;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (newName == null || string.IsNullOrEmpty(oldName))
|
||||
continue;
|
||||
|
||||
bool isValid = false;
|
||||
foreach (var validName in validResourceNames) {
|
||||
if (Utils.StartsWith(validName, oldName, StringComparison.Ordinal)) {
|
||||
isValid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!isValid)
|
||||
continue;
|
||||
|
||||
if (s == "" || !module.ObfuscatedFile.RenameResourcesInCode)
|
||||
Log.v("Possible resource name in code: '{0}' => '{1}' in method {2}", Utils.removeNewlines(s), newName, Utils.removeNewlines(method));
|
||||
else {
|
||||
instr.Operand = newName;
|
||||
Log.v("Renamed resource string in code: '{0}' => '{1}' ({2})", Utils.removeNewlines(s), newName, Utils.removeNewlines(method));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void renameResources(Module module, IEnumerable<TypeInfo> renamedTypes) {
|
||||
if (module.ModuleDefinition.Resources == null)
|
||||
return;
|
||||
foreach (var resource in module.ModuleDefinition.Resources) {
|
||||
var s = resource.Name;
|
||||
foreach (var info in renamedTypes) {
|
||||
var newName = renameResourceString(s, info.oldFullName, info.type.TypeDefinition.FullName);
|
||||
if (newName != s) {
|
||||
resource.Name = newName;
|
||||
Log.v("Renamed resource in resources: {0} => {1}", Utils.removeNewlines(s), newName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static string renameResourceString(string s, string oldTypeName, string newTypeName) {
|
||||
if (!Utils.StartsWith(s, oldTypeName, StringComparison.Ordinal))
|
||||
return s;
|
||||
if (s.Length == oldTypeName.Length)
|
||||
return newTypeName;
|
||||
// s.Length > oldTypeName.Length
|
||||
if (s[oldTypeName.Length] != '.')
|
||||
return s;
|
||||
if (!s.EndsWith(".resources", StringComparison.Ordinal))
|
||||
return s;
|
||||
return newTypeName + s.Substring(oldTypeName.Length);
|
||||
new ResourceRenamer(module).rename(renamedTypes);
|
||||
}
|
||||
|
||||
// Make sure the renamed types are using valid CLS names. That means renaming all
|
||||
|
|
163
de4dot.code/renamer/ResourceRenamer.cs
Normal file
163
de4dot.code/renamer/ResourceRenamer.cs
Normal file
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
Copyright (C) 2011-2012 de4dot@gmail.com
|
||||
|
||||
This file is part of de4dot.
|
||||
|
||||
de4dot is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
de4dot is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Mono.Cecil;
|
||||
using Mono.Cecil.Cil;
|
||||
using de4dot.blocks;
|
||||
using de4dot.code.renamer.asmmodules;
|
||||
|
||||
namespace de4dot.code.renamer {
|
||||
class ResourceRenamer {
|
||||
Module module;
|
||||
Dictionary<string, Resource> nameToResource;
|
||||
|
||||
public ResourceRenamer(Module module) {
|
||||
this.module = module;
|
||||
}
|
||||
|
||||
public void rename(List<TypeInfo> renamedTypes) {
|
||||
// Rename the longest names first. Otherwise eg. b.g.resources could be renamed
|
||||
// Class0.g.resources instead of Class1.resources when b.g was renamed Class1.
|
||||
renamedTypes.Sort((a, b) => Utils.compareInt32(b.oldFullName.Length, a.oldFullName.Length));
|
||||
|
||||
nameToResource = new Dictionary<string, Resource>(module.ModuleDefinition.Resources.Count * 3, StringComparer.Ordinal);
|
||||
foreach (var resource in module.ModuleDefinition.Resources) {
|
||||
var name = resource.Name;
|
||||
nameToResource[name] = resource;
|
||||
if (name.EndsWith(".g.resources"))
|
||||
nameToResource[name.Substring(0, name.Length - 12)] = resource;
|
||||
int index = name.LastIndexOf('.');
|
||||
if (index > 0)
|
||||
nameToResource[name.Substring(0, index)] = resource;
|
||||
}
|
||||
|
||||
renameResourceNamesInCode(renamedTypes);
|
||||
renameResources(renamedTypes);
|
||||
}
|
||||
|
||||
void renameResourceNamesInCode(List<TypeInfo> renamedTypes) {
|
||||
var oldNameToTypeInfo = new Dictionary<string, TypeInfo>(StringComparer.Ordinal);
|
||||
foreach (var info in renamedTypes)
|
||||
oldNameToTypeInfo[info.oldFullName] = info;
|
||||
|
||||
foreach (var method in module.getAllMethods()) {
|
||||
if (!method.HasBody)
|
||||
continue;
|
||||
var instrs = method.Body.Instructions;
|
||||
for (int i = 0; i < instrs.Count; i++) {
|
||||
var instr = instrs[i];
|
||||
if (instr.OpCode != OpCodes.Ldstr)
|
||||
continue;
|
||||
var codeString = (string)instr.Operand;
|
||||
if (string.IsNullOrEmpty(codeString))
|
||||
continue;
|
||||
|
||||
Resource resource;
|
||||
if (!nameToResource.TryGetValue(codeString, out resource))
|
||||
continue;
|
||||
|
||||
TypeInfo typeInfo;
|
||||
if (!oldNameToTypeInfo.TryGetValue(codeString, out typeInfo))
|
||||
continue;
|
||||
var newName = typeInfo.type.TypeDefinition.FullName;
|
||||
|
||||
bool renameCodeString = module.ObfuscatedFile.RenameResourcesInCode ||
|
||||
isCallingResourceManagerCtor(instrs, i, typeInfo);
|
||||
if (!renameCodeString)
|
||||
Log.v("Possible resource name in code: '{0}' => '{1}' in method {2}", Utils.removeNewlines(codeString), newName, Utils.removeNewlines(method));
|
||||
else {
|
||||
instr.Operand = newName;
|
||||
Log.v("Renamed resource string in code: '{0}' => '{1}' ({2})", Utils.removeNewlines(codeString), newName, Utils.removeNewlines(method));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool isCallingResourceManagerCtor(IList<Instruction> instrs, int ldstrIndex, TypeInfo typeInfo) {
|
||||
try {
|
||||
int index = ldstrIndex + 1;
|
||||
|
||||
var ldtoken = instrs[index++];
|
||||
if (ldtoken.OpCode.Code != Code.Ldtoken)
|
||||
return false;
|
||||
if (!MemberReferenceHelper.compareTypes(typeInfo.type.TypeDefinition, ldtoken.Operand as TypeReference))
|
||||
return false;
|
||||
|
||||
if (!checkCalledMethod(instrs[index++], "System.Type", "(System.RuntimeTypeHandle)"))
|
||||
return false;
|
||||
if (!checkCalledMethod(instrs[index++], "System.Reflection.Assembly", "()"))
|
||||
return false;
|
||||
|
||||
var newobj = instrs[index++];
|
||||
if (newobj.OpCode.Code != Code.Newobj)
|
||||
return false;
|
||||
if (newobj.Operand.ToString() != "System.Void System.Resources.ResourceManager::.ctor(System.String,System.Reflection.Assembly)")
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (ArgumentOutOfRangeException) {
|
||||
return false;
|
||||
}
|
||||
catch (IndexOutOfRangeException) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool checkCalledMethod(Instruction instr, string returnType, string parameters) {
|
||||
if (instr.OpCode.Code != Code.Call && instr.OpCode.Code != Code.Callvirt)
|
||||
return false;
|
||||
return DotNetUtils.isMethod(instr.Operand as MethodReference, returnType, parameters);
|
||||
}
|
||||
|
||||
class RenameInfo {
|
||||
public Resource resource;
|
||||
public TypeInfo typeInfo;
|
||||
public string newResourceName;
|
||||
public RenameInfo(Resource resource, TypeInfo typeInfo, string newResourceName) {
|
||||
this.resource = resource;
|
||||
this.typeInfo = typeInfo;
|
||||
this.newResourceName = newResourceName;
|
||||
}
|
||||
public override string ToString() {
|
||||
return string.Format("{0} => {1}", resource.Name, newResourceName);
|
||||
}
|
||||
}
|
||||
|
||||
void renameResources(List<TypeInfo> renamedTypes) {
|
||||
var newNames = new Dictionary<Resource, RenameInfo>();
|
||||
foreach (var info in renamedTypes) {
|
||||
var oldFullName = info.oldFullName;
|
||||
Resource resource;
|
||||
if (!nameToResource.TryGetValue(oldFullName, out resource))
|
||||
continue;
|
||||
if (newNames.ContainsKey(resource))
|
||||
continue;
|
||||
var newTypeName = info.type.TypeDefinition.FullName;
|
||||
var newName = newTypeName + resource.Name.Substring(oldFullName.Length);
|
||||
newNames[resource] = new RenameInfo(resource, info, newName);
|
||||
|
||||
Log.v("Renamed resource in resources: {0} => {1}", Utils.removeNewlines(resource.Name), newName);
|
||||
resource.Name = newName;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -29,7 +29,7 @@ namespace de4dot.code.renamer {
|
|||
class TypeInfo : MemberInfo {
|
||||
public string oldNamespace;
|
||||
public string newNamespace;
|
||||
public VariableNameState variableNameState = new VariableNameState();
|
||||
public VariableNameState variableNameState = VariableNameState.create();
|
||||
public TypeDef type;
|
||||
MemberInfos memberInfos;
|
||||
|
||||
|
@ -306,7 +306,7 @@ namespace de4dot.code.renamer {
|
|||
info.newName = "e";
|
||||
}
|
||||
else {
|
||||
var newVariableNameState = variableNameState.clone();
|
||||
var newVariableNameState = variableNameState.cloneParamsOnly();
|
||||
var checker = NameChecker;
|
||||
foreach (var paramDef in methodDef.ParamDefs) {
|
||||
var info = param(paramDef);
|
||||
|
|
|
@ -25,6 +25,8 @@ namespace de4dot.code.renamer {
|
|||
abstract class TypeNames {
|
||||
protected Dictionary<string, NameCreator> typeNames = new Dictionary<string, NameCreator>(StringComparer.Ordinal);
|
||||
protected NameCreator genericParamNameCreator = new NameCreator("gparam_");
|
||||
protected Dictionary<string, string> fullNameToShortName;
|
||||
protected Dictionary<string, string> fullNameToShortNamePrefix;
|
||||
|
||||
public string create(TypeReference typeRef) {
|
||||
if (typeRef.IsGenericInstance) {
|
||||
|
@ -46,21 +48,28 @@ namespace de4dot.code.renamer {
|
|||
if (typeNames.TryGetValue(typeFullName, out nc))
|
||||
return nc.create();
|
||||
|
||||
var name = elementType.FullName;
|
||||
var parts = name.Replace('/', '.').Split(new char[] { '.' });
|
||||
var newName = parts[parts.Length - 1];
|
||||
int tickIndex = newName.LastIndexOf('`');
|
||||
if (tickIndex > 0)
|
||||
newName = newName.Substring(0, tickIndex);
|
||||
var fullName = elementType.FullName;
|
||||
string shortName;
|
||||
var dict = prefix == "" ? fullNameToShortName : fullNameToShortNamePrefix;
|
||||
if (!dict.TryGetValue(fullName, out shortName)) {
|
||||
fullName = fullName.Replace('/', '.');
|
||||
int index = fullName.LastIndexOf('.');
|
||||
shortName = index > 0 ? fullName.Substring(index + 1) : fullName;
|
||||
|
||||
return addTypeName(typeFullName, newName, prefix).create();
|
||||
index = shortName.LastIndexOf('`');
|
||||
if (index > 0)
|
||||
shortName = shortName.Substring(0, index);
|
||||
}
|
||||
|
||||
return addTypeName(typeFullName, shortName, prefix).create();
|
||||
}
|
||||
|
||||
static string getPrefix(TypeReference typeRef) {
|
||||
string prefix = "";
|
||||
while (typeRef is PointerType) {
|
||||
typeRef = ((PointerType)typeRef).ElementType;
|
||||
prefix += "p";
|
||||
while (typeRef is TypeSpecification) {
|
||||
if (typeRef.IsPointer)
|
||||
prefix += "p";
|
||||
typeRef = ((TypeSpecification)typeRef).ElementType;
|
||||
}
|
||||
return prefix;
|
||||
}
|
||||
|
@ -81,8 +90,9 @@ namespace de4dot.code.renamer {
|
|||
|
||||
public virtual TypeNames merge(TypeNames other) {
|
||||
foreach (var pair in other.typeNames) {
|
||||
if (typeNames.ContainsKey(pair.Key))
|
||||
typeNames[pair.Key].merge(pair.Value);
|
||||
NameCreator nc;
|
||||
if (typeNames.TryGetValue(pair.Key, out nc))
|
||||
nc.merge(pair.Value);
|
||||
else
|
||||
typeNames[pair.Key] = pair.Value.clone();
|
||||
}
|
||||
|
@ -96,40 +106,50 @@ namespace de4dot.code.renamer {
|
|||
}
|
||||
|
||||
class VariableNameCreator : TypeNames {
|
||||
static Dictionary<string, string> ourFullNameToShortName;
|
||||
static Dictionary<string, string> ourFullNameToShortNamePrefix;
|
||||
static VariableNameCreator() {
|
||||
ourFullNameToShortName = new Dictionary<string, string>(StringComparer.Ordinal) {
|
||||
{ "System.Boolean", "bool" },
|
||||
{ "System.Byte", "byte" },
|
||||
{ "System.Char", "char" },
|
||||
{ "System.Double", "double" },
|
||||
{ "System.Int16", "short" },
|
||||
{ "System.Int32", "int" },
|
||||
{ "System.Int64", "long" },
|
||||
{ "System.IntPtr", "intptr" },
|
||||
{ "System.SByte", "sbyte" },
|
||||
{ "System.Single", "float" },
|
||||
{ "System.String", "string" },
|
||||
{ "System.UInt16", "ushort" },
|
||||
{ "System.UInt32", "uint" },
|
||||
{ "System.UInt64", "ulong" },
|
||||
{ "System.UIntPtr", "uintptr" },
|
||||
{ "System.Decimal", "decimal" },
|
||||
};
|
||||
ourFullNameToShortNamePrefix = new Dictionary<string, string>(StringComparer.Ordinal) {
|
||||
{ "System.Boolean", "Bool" },
|
||||
{ "System.Byte", "Byte" },
|
||||
{ "System.Char", "Char" },
|
||||
{ "System.Double", "Double" },
|
||||
{ "System.Int16", "Short" },
|
||||
{ "System.Int32", "Int" },
|
||||
{ "System.Int64", "Long" },
|
||||
{ "System.IntPtr", "IntPtr" },
|
||||
{ "System.SByte", "SByte" },
|
||||
{ "System.Single", "Float" },
|
||||
{ "System.String", "String" },
|
||||
{ "System.UInt16", "UShort" },
|
||||
{ "System.UInt32", "UInt" },
|
||||
{ "System.UInt64", "ULong" },
|
||||
{ "System.UIntPtr", "UIntPtr" },
|
||||
{ "System.Decimal", "Decimal" },
|
||||
};
|
||||
}
|
||||
|
||||
public VariableNameCreator() {
|
||||
initTypeName("System.Boolean", "bool");
|
||||
initTypeName("System.Byte", "byte");
|
||||
initTypeName("System.Char", "char");
|
||||
initTypeName("System.Double", "double");
|
||||
initTypeName("System.Int16", "short");
|
||||
initTypeName("System.Int32", "int");
|
||||
initTypeName("System.Int64", "long");
|
||||
initTypeName("System.IntPtr", "intptr", "IntPtr");
|
||||
initTypeName("System.SByte", "sbyte", "SByte");
|
||||
initTypeName("System.Single", "float");
|
||||
initTypeName("System.String", "string");
|
||||
initTypeName("System.UInt16", "ushort", "UShort");
|
||||
initTypeName("System.UInt32", "uint", "UInt");
|
||||
initTypeName("System.UInt64", "ulong", "ULong");
|
||||
initTypeName("System.UIntPtr", "uintptr", "UIntPtr");
|
||||
initTypeName("System.Decimal", "decimal");
|
||||
}
|
||||
|
||||
void initTypeName(string fullName, string newName, string ptrName = null) {
|
||||
if (ptrName == null)
|
||||
ptrName = upperFirst(newName);
|
||||
initTypeName2(fullName, "", newName);
|
||||
initTypeName2(fullName + "[]", "", newName);
|
||||
initTypeName2(fullName + "[][]", "", newName);
|
||||
initTypeName2(fullName + "[][][]", "", newName);
|
||||
initTypeName2(fullName + "[0...,0...]", "", newName);
|
||||
initTypeName2(fullName + "*", "p", ptrName);
|
||||
initTypeName2(fullName + "**", "pp", ptrName);
|
||||
}
|
||||
|
||||
void initTypeName2(string fullName, string prefix, string newName) {
|
||||
addTypeName(fullName, newName, prefix);
|
||||
addTypeName(fullName + "&", newName, prefix);
|
||||
fullNameToShortName = ourFullNameToShortName;
|
||||
fullNameToShortNamePrefix = ourFullNameToShortNamePrefix;
|
||||
}
|
||||
|
||||
static string lowerLeadingChars(string name) {
|
||||
|
@ -152,6 +172,14 @@ namespace de4dot.code.renamer {
|
|||
}
|
||||
|
||||
class PropertyNameCreator : TypeNames {
|
||||
static Dictionary<string, string> ourFullNameToShortName = new Dictionary<string, string>(StringComparer.Ordinal);
|
||||
static Dictionary<string, string> ourFullNameToShortNamePrefix = new Dictionary<string, string>(StringComparer.Ordinal);
|
||||
|
||||
public PropertyNameCreator() {
|
||||
fullNameToShortName = ourFullNameToShortName;
|
||||
fullNameToShortNamePrefix = ourFullNameToShortNamePrefix;
|
||||
}
|
||||
|
||||
protected override string fixName(string prefix, string name) {
|
||||
return prefix.ToUpperInvariant() + upperFirst(name);
|
||||
}
|
||||
|
|
|
@ -21,19 +21,43 @@ using Mono.Cecil;
|
|||
|
||||
namespace de4dot.code.renamer {
|
||||
class VariableNameState {
|
||||
ExistingNames existingVariableNames = new ExistingNames();
|
||||
ExistingNames existingMethodNames = new ExistingNames();
|
||||
ExistingNames existingPropertyNames = new ExistingNames();
|
||||
ExistingNames existingEventNames = new ExistingNames();
|
||||
TypeNames variableNameCreator = new VariableNameCreator(); // For fields and method args
|
||||
TypeNames propertyNameCreator = new PropertyNameCreator();
|
||||
NameCreator eventNameCreator = new NameCreator("Event_");
|
||||
NameCreator genericPropertyNameCreator = new NameCreator("Prop_");
|
||||
public NameCreator staticMethodNameCreator = new NameCreator("smethod_");
|
||||
public NameCreator instanceMethodNameCreator = new NameCreator("method_");
|
||||
ExistingNames existingVariableNames;
|
||||
ExistingNames existingMethodNames;
|
||||
ExistingNames existingPropertyNames;
|
||||
ExistingNames existingEventNames;
|
||||
TypeNames variableNameCreator; // For fields and method args
|
||||
TypeNames propertyNameCreator;
|
||||
NameCreator eventNameCreator;
|
||||
NameCreator genericPropertyNameCreator;
|
||||
public NameCreator staticMethodNameCreator;
|
||||
public NameCreator instanceMethodNameCreator;
|
||||
|
||||
public VariableNameState clone() {
|
||||
return new VariableNameState().merge(this);
|
||||
public static VariableNameState create() {
|
||||
var vns = new VariableNameState();
|
||||
vns.existingVariableNames = new ExistingNames();
|
||||
vns.existingMethodNames = new ExistingNames();
|
||||
vns.existingPropertyNames = new ExistingNames();
|
||||
vns.existingEventNames = new ExistingNames();
|
||||
vns.variableNameCreator = new VariableNameCreator();
|
||||
vns.propertyNameCreator = new PropertyNameCreator();
|
||||
vns.eventNameCreator = new NameCreator("Event_");
|
||||
vns.genericPropertyNameCreator = new NameCreator("Prop_");
|
||||
vns.staticMethodNameCreator = new NameCreator("smethod_");
|
||||
vns.instanceMethodNameCreator = new NameCreator("method_");
|
||||
return vns;
|
||||
}
|
||||
|
||||
VariableNameState() {
|
||||
}
|
||||
|
||||
// Cloning only params will speed up the method param renaming code
|
||||
public VariableNameState cloneParamsOnly() {
|
||||
var vns = new VariableNameState();
|
||||
vns.existingVariableNames = new ExistingNames();
|
||||
vns.variableNameCreator = new VariableNameCreator();
|
||||
vns.existingVariableNames.merge(existingVariableNames);
|
||||
vns.variableNameCreator.merge(variableNameCreator);
|
||||
return vns;
|
||||
}
|
||||
|
||||
public VariableNameState merge(VariableNameState other) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user