Add support for reading r8 values. Also rename some methods

This commit is contained in:
de4dot 2012-07-30 19:07:25 +02:00
parent 94b21490da
commit 06b7374276
4 changed files with 188 additions and 37 deletions

View File

@ -27,8 +27,9 @@ namespace de4dot.code.deobfuscators {
class ConstantsReader { class ConstantsReader {
protected IInstructions instructions; protected IInstructions instructions;
protected IList<VariableDefinition> locals; protected IList<VariableDefinition> locals;
protected Dictionary<VariableDefinition, int> localsValues32 = new Dictionary<VariableDefinition, int>(); protected Dictionary<VariableDefinition, int> localsValuesInt32 = new Dictionary<VariableDefinition, int>();
protected Dictionary<VariableDefinition, long> localsValues64 = new Dictionary<VariableDefinition, long>(); protected Dictionary<VariableDefinition, long> localsValuesInt64 = new Dictionary<VariableDefinition, long>();
protected Dictionary<VariableDefinition, double> localsValuesDouble = new Dictionary<VariableDefinition, double>();
bool emulateConvInstrs; bool emulateConvInstrs;
public interface IInstructions { public interface IInstructions {
@ -108,26 +109,30 @@ namespace de4dot.code.deobfuscators {
this.locals = locals; this.locals = locals;
} }
public void setConstant32(VariableDefinition local, int value) { public void setConstantInt32(VariableDefinition local, int value) {
localsValues32[local] = value; localsValuesInt32[local] = value;
} }
public void setConstant32(VariableDefinition local, uint value) { public void setConstantInt32(VariableDefinition local, uint value) {
setConstant32(local, (int)value); setConstantInt32(local, (int)value);
} }
public void setConstant64(VariableDefinition local, long value) { public void setConstantInt64(VariableDefinition local, long value) {
localsValues64[local] = value; localsValuesInt64[local] = value;
} }
public void setConstant64(VariableDefinition local, ulong value) { public void setConstantInt64(VariableDefinition local, ulong value) {
setConstant64(local, (long)value); setConstantInt64(local, (long)value);
}
public void setConstantDouble(VariableDefinition local, double value) {
localsValuesDouble[local] = value;
} }
public bool getNextInt32(ref int index, out int val) { public bool getNextInt32(ref int index, out int val) {
for (; index < instructions.Count; index++) { for (; index < instructions.Count; index++) {
var instr = instructions[index]; var instr = instructions[index];
if (!isLoadConstant32(instr)) if (!isLoadConstantInt32(instr))
continue; continue;
return getInt32(ref index, out val); return getInt32(ref index, out val);
@ -137,30 +142,44 @@ namespace de4dot.code.deobfuscators {
return false; return false;
} }
public bool isLoadConstant32(Instruction instr) { public bool isLoadConstantInt32(Instruction instr) {
if (DotNetUtils.isLdcI4(instr)) if (DotNetUtils.isLdcI4(instr))
return true; return true;
if (DotNetUtils.isLdloc(instr)) { if (DotNetUtils.isLdloc(instr)) {
int tmp; int tmp;
return getLocalConstant32(instr, out tmp); return getLocalConstantInt32(instr, out tmp);
} }
if (DotNetUtils.isLdarg(instr)) { if (DotNetUtils.isLdarg(instr)) {
int tmp; int tmp;
return getArgConstant32(instr, out tmp); return getArgConstantInt32(instr, out tmp);
} }
return false; return false;
} }
public bool isLoadConstant64(Instruction instr) { public bool isLoadConstantInt64(Instruction instr) {
if (instr.OpCode.Code == Code.Ldc_I8) if (instr.OpCode.Code == Code.Ldc_I8)
return true; return true;
if (DotNetUtils.isLdloc(instr)) { if (DotNetUtils.isLdloc(instr)) {
long tmp; long tmp;
return getLocalConstant64(instr, out tmp); return getLocalConstantInt64(instr, out tmp);
} }
if (DotNetUtils.isLdarg(instr)) { if (DotNetUtils.isLdarg(instr)) {
long tmp; long tmp;
return getArgConstant64(instr, out tmp); return getArgConstantInt64(instr, out tmp);
}
return false;
}
public bool isLoadConstantDouble(Instruction instr) {
if (instr.OpCode.Code == Code.Ldc_R8)
return true;
if (DotNetUtils.isLdloc(instr)) {
double tmp;
return getLocalConstantDouble(instr, out tmp);
}
if (DotNetUtils.isLdarg(instr)) {
double tmp;
return getArgConstantDouble(instr, out tmp);
} }
return false; return false;
} }
@ -246,7 +265,7 @@ namespace de4dot.code.deobfuscators {
case Code.Ldloc_1: case Code.Ldloc_1:
case Code.Ldloc_2: case Code.Ldloc_2:
case Code.Ldloc_3: case Code.Ldloc_3:
if (!getLocalConstant32(instr, out op1)) if (!getLocalConstantInt32(instr, out op1))
goto done; goto done;
stack.Push(new ConstantInfo<int>(index, op1)); stack.Push(new ConstantInfo<int>(index, op1));
break; break;
@ -257,7 +276,7 @@ namespace de4dot.code.deobfuscators {
case Code.Ldarg_1: case Code.Ldarg_1:
case Code.Ldarg_2: case Code.Ldarg_2:
case Code.Ldarg_3: case Code.Ldarg_3:
if (!getArgConstant32(instr, out op1)) if (!getArgConstantInt32(instr, out op1))
goto done; goto done;
stack.Push(new ConstantInfo<int>(index, op1)); stack.Push(new ConstantInfo<int>(index, op1));
break; break;
@ -429,7 +448,7 @@ done:
case Code.Ldloc_1: case Code.Ldloc_1:
case Code.Ldloc_2: case Code.Ldloc_2:
case Code.Ldloc_3: case Code.Ldloc_3:
if (!getLocalConstant64(instr, out op1)) if (!getLocalConstantInt64(instr, out op1))
goto done; goto done;
stack.Push(new ConstantInfo<long>(index, op1)); stack.Push(new ConstantInfo<long>(index, op1));
break; break;
@ -440,7 +459,7 @@ done:
case Code.Ldarg_1: case Code.Ldarg_1:
case Code.Ldarg_2: case Code.Ldarg_2:
case Code.Ldarg_3: case Code.Ldarg_3:
if (!getArgConstant64(instr, out op1)) if (!getArgConstantInt64(instr, out op1))
goto done; goto done;
stack.Push(new ConstantInfo<long>(index, op1)); stack.Push(new ConstantInfo<long>(index, op1));
break; break;
@ -528,7 +547,122 @@ done:
return true; return true;
} }
protected virtual bool getLocalConstant32(Instruction instr, out int value) { public bool getDouble(ref int index, out double val) {
val = 0;
if (index >= instructions.Count)
return false;
var stack = new Stack<ConstantInfo<double>>();
double op1;
ConstantInfo<double> info1, info2;
for (; index < instructions.Count; index++) {
var instr = instructions[index];
switch (instr.OpCode.Code) {
case Code.Conv_R4:
if (!emulateConvInstrs || stack.Count < 1)
goto done;
stack.Push(new ConstantInfo<double>(index, (float)stack.Pop().constant));
break;
case Code.Conv_R8:
if (!emulateConvInstrs || stack.Count < 1)
goto done;
stack.Push(new ConstantInfo<double>(index, stack.Pop().constant));
break;
case Code.Neg:
if (stack.Count < 1)
goto done;
stack.Push(new ConstantInfo<double>(index, -stack.Pop().constant));
break;
case Code.Ldloc:
case Code.Ldloc_S:
case Code.Ldloc_0:
case Code.Ldloc_1:
case Code.Ldloc_2:
case Code.Ldloc_3:
if (!getLocalConstantDouble(instr, out op1))
goto done;
stack.Push(new ConstantInfo<double>(index, op1));
break;
case Code.Ldarg:
case Code.Ldarg_S:
case Code.Ldarg_0:
case Code.Ldarg_1:
case Code.Ldarg_2:
case Code.Ldarg_3:
if (!getArgConstantDouble(instr, out op1))
goto done;
stack.Push(new ConstantInfo<double>(index, op1));
break;
case Code.Ldc_R4:
stack.Push(new ConstantInfo<double>(index, (float)instr.Operand));
break;
case Code.Ldc_R8:
stack.Push(new ConstantInfo<double>(index, (double)instr.Operand));
break;
case Code.Add:
if (stack.Count < 2)
goto done;
info2 = stack.Pop();
info1 = stack.Pop();
stack.Push(new ConstantInfo<double>(index, info1.constant + info2.constant));
break;
case Code.Sub:
if (stack.Count < 2)
goto done;
info2 = stack.Pop();
info1 = stack.Pop();
stack.Push(new ConstantInfo<double>(index, info1.constant - info2.constant));
break;
case Code.Mul:
if (stack.Count < 2)
goto done;
info2 = stack.Pop();
info1 = stack.Pop();
stack.Push(new ConstantInfo<double>(index, info1.constant * info2.constant));
break;
case Code.Div:
if (stack.Count < 2)
goto done;
info2 = stack.Pop();
info1 = stack.Pop();
stack.Push(new ConstantInfo<double>(index, info1.constant / info2.constant));
break;
case Code.Div_Un:
if (stack.Count < 2)
goto done;
info2 = stack.Pop();
info1 = stack.Pop();
stack.Push(new ConstantInfo<double>(index, (int)((uint)info1.constant / (uint)info2.constant)));
break;
default:
goto done;
}
}
done:
if (stack.Count == 0)
return false;
while (stack.Count > 1)
stack.Pop();
info1 = stack.Pop();
index = info1.index + 1;
val = info1.constant;
return true;
}
protected virtual bool getLocalConstantInt32(Instruction instr, out int value) {
value = 0; value = 0;
if (locals == null) if (locals == null)
return false; return false;
@ -537,15 +671,15 @@ done:
return false; return false;
if (local.VariableType.EType != ElementType.I4 && local.VariableType.EType != ElementType.U4) if (local.VariableType.EType != ElementType.I4 && local.VariableType.EType != ElementType.U4)
return false; return false;
return localsValues32.TryGetValue(local, out value); return localsValuesInt32.TryGetValue(local, out value);
} }
protected virtual bool getArgConstant32(Instruction instr, out int value) { protected virtual bool getArgConstantInt32(Instruction instr, out int value) {
value = 0; value = 0;
return false; return false;
} }
protected virtual bool getLocalConstant64(Instruction instr, out long value) { protected virtual bool getLocalConstantInt64(Instruction instr, out long value) {
value = 0; value = 0;
if (locals == null) if (locals == null)
return false; return false;
@ -554,10 +688,27 @@ done:
return false; return false;
if (local.VariableType.EType != ElementType.I8 && local.VariableType.EType != ElementType.U8) if (local.VariableType.EType != ElementType.I8 && local.VariableType.EType != ElementType.U8)
return false; return false;
return localsValues64.TryGetValue(local, out value); return localsValuesInt64.TryGetValue(local, out value);
} }
protected virtual bool getArgConstant64(Instruction instr, out long value) { protected virtual bool getArgConstantInt64(Instruction instr, out long value) {
value = 0;
return false;
}
protected virtual bool getLocalConstantDouble(Instruction instr, out double value) {
value = 0;
if (locals == null)
return false;
var local = DotNetUtils.getLocalVar(locals, instr);
if (local == null)
return false;
if (local.VariableType.EType != ElementType.R8)
return false;
return localsValuesDouble.TryGetValue(local, out value);
}
protected virtual bool getArgConstantDouble(Instruction instr, out double value) {
value = 0; value = 0;
return false; return false;
} }

View File

@ -27,12 +27,12 @@ namespace de4dot.code.deobfuscators.DeepSea {
: base(instrs) { : base(instrs) {
} }
protected override bool getLocalConstant32(Instruction instr, out int value) { protected override bool getLocalConstantInt32(Instruction instr, out int value) {
value = 0; value = 0;
return true; return true;
} }
protected override bool getArgConstant32(Instruction instr, out int value) { protected override bool getArgConstantInt32(Instruction instr, out int value) {
value = 0; value = 0;
return true; return true;
} }

View File

@ -43,12 +43,12 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
var local = DotNetUtils.getLocalVar(locals, stloc); var local = DotNetUtils.getLocalVar(locals, stloc);
if (local == null || local.VariableType.EType != ElementType.I4) if (local == null || local.VariableType.EType != ElementType.I4)
break; break;
localsValues32[local] = value; localsValuesInt32[local] = value;
index++; index++;
} }
if (localsValues32.Count != 2) if (localsValuesInt32.Count != 2)
localsValues32.Clear(); localsValuesInt32.Clear();
} }
} }
} }

View File

@ -275,7 +275,7 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
var instrs = stringMethod.Body.Instructions; var instrs = stringMethod.Body.Instructions;
for (int i = 0; i < instrs.Count; i++) { for (int i = 0; i < instrs.Count; i++) {
var ldci4 = instrs[i]; var ldci4 = instrs[i];
if (!stringMethodConsts.isLoadConstant32(ldci4)) if (!stringMethodConsts.isLoadConstantInt32(ldci4))
continue; continue;
int index = i, tmp; int index = i, tmp;
if (!stringMethodConsts.getInt32(ref index, out tmp) || !isFlagsMask(tmp)) if (!stringMethodConsts.getInt32(ref index, out tmp) || !isFlagsMask(tmp))
@ -320,7 +320,7 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
var instr = stringMethod.Body.Instructions[i]; var instr = stringMethod.Body.Instructions[i];
if (instr.OpCode.FlowControl != FlowControl.Next) if (instr.OpCode.FlowControl != FlowControl.Next)
break; break;
if (!stringMethodConsts.isLoadConstant32(instr)) if (!stringMethodConsts.isLoadConstantInt32(instr))
continue; continue;
int index2 = i, value; int index2 = i, value;
if (!stringMethodConsts.getInt32(ref index2, out value)) if (!stringMethodConsts.getInt32(ref index2, out value))
@ -512,7 +512,7 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
sb.Append((char)(val >> shift)); sb.Append((char)(val >> shift));
shift = 0; shift = 0;
} }
if (stringMethodConsts.isLoadConstant32(instr)) { if (stringMethodConsts.isLoadConstantInt32(instr)) {
int tmp; int tmp;
if (!stringMethodConsts.getInt32(ref i, out tmp)) if (!stringMethodConsts.getInt32(ref i, out tmp))
break; break;
@ -599,7 +599,7 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
if (instr.OpCode.Code != Code.Call && instr.OpCode.FlowControl != FlowControl.Next) if (instr.OpCode.Code != Code.Call && instr.OpCode.FlowControl != FlowControl.Next)
break; break;
if (!stringMethodConsts.isLoadConstant32(instr)) if (!stringMethodConsts.isLoadConstantInt32(instr))
continue; continue;
int tmp; int tmp;
@ -795,7 +795,7 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET {
var instr = instrs[i]; var instr = instrs[i];
if (instr.OpCode.FlowControl != FlowControl.Next) if (instr.OpCode.FlowControl != FlowControl.Next)
return -1; return -1;
if (stringMethodConsts.isLoadConstant32(instr)) if (stringMethodConsts.isLoadConstantInt32(instr))
return i; return i;
} }