public static byte[] getInitializedArray(int arraySize, MethodDefinition method, ref int newarrIndex) { var resultValueArray = new Value[arraySize]; var emulator = new InstructionEmulator(method.HasThis, false, method.Parameters, method.Body.Variables); var theArray = new UnknownValue(); emulator.push(theArray); var instructions = method.Body.Instructions; int i; for (i = newarrIndex + 1; i < instructions.Count; i++) { var instr = instructions[i]; if (instr.OpCode.FlowControl != FlowControl.Next) break; if (instr.OpCode.Code == Code.Newarr) break; if (instr.OpCode.Code == Code.Stelem_I1) { var value = emulator.pop(); var index = emulator.pop() as Int32Value; var array = emulator.pop(); if (ReferenceEquals(array, theArray) && index != null && index.allBitsValid()) { if (0 <= index.value && index.value < resultValueArray.Length) resultValueArray[index.value] = value; } } else emulator.emulate(instr); } if (i != newarrIndex + 1) i--; newarrIndex = i; byte[] resultArray = new byte[resultValueArray.Length]; for (i = 0; i < resultArray.Length; i++) { var intValue = resultValueArray[i] as Int32Value; if (intValue == null || !intValue.allBitsValid()) return null; resultArray[i] = (byte)intValue.value; } return resultArray; }
// Switch deobfuscation when block uses stloc N, ldloc N to load switch constant // blk1: // ldc.i4 X // br swblk // swblk: // stloc N // ldloc N // switch (......) bool deobfuscateStLdloc(IList <Block> switchTargets, Block switchFallThrough, Block block) { bool changed = false; foreach (var source in new List <Block>(block.Sources)) { if (!isBranchBlock(source)) { continue; } instructionEmulator.init(blocks); instructionEmulator.emulate(source.Instructions); var target = getSwitchTarget(switchTargets, switchFallThrough, instructionEmulator.pop()); if (target == null) { continue; } source.replaceLastNonBranchWithBranch(0, target); source.add(new Instr(OpCodes.Pop.ToInstruction())); changed = true; } return(changed); }
bool emulate_Beq() { var val2 = instructionEmulator.pop(); var val1 = instructionEmulator.pop(); if (val1.isInt32() && val2.isInt32()) return emulateBranch(2, Int32Value.compareEq((Int32Value)val1, (Int32Value)val2)); else if (val1.isInt64() && val2.isInt64()) return emulateBranch(2, Int64Value.compareEq((Int64Value)val1, (Int64Value)val2)); else if (val1.isNull() && val2.isNull()) return emulateBranch(2, true); else return false; }
public static Value[] getInitializedArray(int arraySize, MethodDef method, ref int newarrIndex, Code stelemOpCode) { var resultValueArray = new Value[arraySize]; var emulator = new InstructionEmulator(method); var theArray = new UnknownValue(); emulator.push(theArray); var instructions = method.Body.Instructions; int i; for (i = newarrIndex + 1; i < instructions.Count; i++) { var instr = instructions[i]; if (instr.OpCode.FlowControl != FlowControl.Next) break; if (instr.OpCode.Code == Code.Newarr) break; switch (instr.OpCode.Code) { case Code.Newarr: case Code.Newobj: goto done; case Code.Stloc: case Code.Stloc_S: case Code.Stloc_0: case Code.Stloc_1: case Code.Stloc_2: case Code.Stloc_3: case Code.Starg: case Code.Starg_S: case Code.Stsfld: case Code.Stfld: if (emulator.peek() == theArray && i != newarrIndex + 1 && i != newarrIndex + 2) goto done; break; } if (instr.OpCode.Code == stelemOpCode) { var value = emulator.pop(); var index = emulator.pop() as Int32Value; var array = emulator.pop(); if (ReferenceEquals(array, theArray) && index != null && index.allBitsValid()) { if (0 <= index.value && index.value < resultValueArray.Length) resultValueArray[index.value] = value; } } else emulator.emulate(instr); } done: if (i != newarrIndex + 1) i--; newarrIndex = i; return resultValueArray; }