Update array cflow deobfuscator

This commit is contained in:
de4dot 2012-12-14 09:18:14 +01:00
parent 574eb0ee3d
commit bbbdf0b0ff
2 changed files with 102 additions and 12 deletions

View File

@ -91,6 +91,48 @@ namespace de4dot.code.deobfuscators.DeepSea {
return changed;
}
static bool IsLdelem(ArrayBlockState.FieldInfo info, Code code) {
switch (info.elementType) {
case ElementType.Boolean:
case ElementType.I1:
case ElementType.U1:
return code == Code.Ldelem_I1 || code == Code.Ldelem_U1;
case ElementType.Char:
case ElementType.I2:
case ElementType.U2:
return code == Code.Ldelem_I2 || code == Code.Ldelem_U2;
case ElementType.I4:
case ElementType.U4:
return code == Code.Ldelem_I4 || code == Code.Ldelem_U4;
default:
return false;
}
}
static bool IsStelem(ArrayBlockState.FieldInfo info, Code code) {
switch (info.elementType) {
case ElementType.Boolean:
case ElementType.I1:
case ElementType.U1:
return code == Code.Stelem_I1;
case ElementType.Char:
case ElementType.I2:
case ElementType.U2:
return code == Code.Stelem_I2;
case ElementType.I4:
case ElementType.U4:
return code == Code.Stelem_I4;
default:
return false;
}
}
bool deobfuscate1(Block block, int i) {
var instrs = block.Instructions;
if (i >= instrs.Count - 2)
@ -111,11 +153,11 @@ namespace de4dot.code.deobfuscators.DeepSea {
return false;
var ldelem = instrs[i + 2];
if (ldelem.OpCode.Code != Code.Ldelem_U1)
if (!IsLdelem(info, ldelem.OpCode.Code))
return false;
block.remove(i, 3 - 1);
instrs[i] = new Instr(Instruction.CreateLdcI4(info.array[ldci4.getLdcI4Value()]));
instrs[i] = new Instr(Instruction.CreateLdcI4((int)info.readArrayElement(ldci4.getLdcI4Value())));
return true;
}
@ -136,11 +178,11 @@ namespace de4dot.code.deobfuscators.DeepSea {
return false;
var ldelem = instrs[i + 2];
if (ldelem.OpCode.Code != Code.Ldelem_U1)
if (!IsLdelem(info, ldelem.OpCode.Code))
return false;
block.remove(i, 3 - 1);
instrs[i] = new Instr(Instruction.CreateLdcI4(info.array[ldci4.getLdcI4Value()]));
instrs[i] = new Instr(Instruction.CreateLdcI4((int)info.readArrayElement(ldci4.getLdcI4Value())));
return true;
}
@ -169,7 +211,7 @@ namespace de4dot.code.deobfuscators.DeepSea {
if (i >= instrs.Count)
return false;
var stelem = instrs[i];
if (stelem.OpCode.Code != Code.Stelem_I1)
if (!IsStelem(info, stelem.OpCode.Code))
return false;
block.remove(start, i - start + 1);

View File

@ -17,6 +17,7 @@
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using dot10.DotNet;
using dot10.DotNet.Emit;
@ -28,14 +29,62 @@ namespace de4dot.code.deobfuscators.DeepSea {
FieldDefAndDeclaringTypeDict<FieldInfo> fieldToInfo = new FieldDefAndDeclaringTypeDict<FieldInfo>();
public class FieldInfo {
public readonly ElementType elementType;
public readonly FieldDef field;
public readonly FieldDef arrayInitField;
public readonly byte[] array;
public readonly Array array;
public FieldInfo(FieldDef field, FieldDef arrayInitField) {
this.field = field;
this.elementType = ((SZArraySig)field.FieldType).Next.GetElementType();
this.arrayInitField = arrayInitField;
this.array = (byte[])arrayInitField.InitialValue.Clone();
this.array = createArray(elementType, arrayInitField.InitialValue);
}
static Array createArray(ElementType etype, byte[] data) {
switch (etype) {
case ElementType.Boolean:
case ElementType.I1:
case ElementType.U1:
return (byte[])data.Clone();
case ElementType.Char:
case ElementType.I2:
case ElementType.U2:
var ary2 = new ushort[data.Length / 2];
Buffer.BlockCopy(data, 0, ary2, 0, ary2.Length * 2);
return ary2;
case ElementType.I4:
case ElementType.U4:
var ary4 = new uint[data.Length / 4];
Buffer.BlockCopy(data, 0, ary4, 0, ary4.Length * 4);
return ary4;
default:
throw new ApplicationException("Invalid etype");
}
}
public uint readArrayElement(int index) {
switch (elementType) {
case ElementType.Boolean:
case ElementType.I1:
case ElementType.U1:
return ((byte[])array)[index];
case ElementType.Char:
case ElementType.I2:
case ElementType.U2:
return ((ushort[])array)[index];
case ElementType.I4:
case ElementType.U4:
return ((uint[])array)[index];
default:
throw new ApplicationException("Invalid etype");
}
}
}
@ -71,10 +120,6 @@ namespace de4dot.code.deobfuscators.DeepSea {
if (instrs == null)
continue;
var arrayType = instrs[0].Operand as ITypeDefOrRef;
if (arrayType == null || (arrayType.FullName != "System.Byte" && !arrayType.DefinitionAssembly.IsCorLib()))
continue;
var arrayInitField = instrs[2].Operand as FieldDef;
if (arrayInitField == null || arrayInitField.InitialValue == null || arrayInitField.InitialValue.Length == 0)
continue;
@ -84,7 +129,10 @@ namespace de4dot.code.deobfuscators.DeepSea {
continue;
var targetField = instrs[4].Operand as FieldDef;
if (targetField == null)
if (targetField == null || targetField.FieldType.GetElementType() != ElementType.SZArray)
continue;
var etype = ((SZArraySig)targetField.FieldType).Next.GetElementType();
if (etype < ElementType.Boolean || etype > ElementType.U4)
continue;
if (fieldToInfo.find(targetField) == null) {