static int findLdStFieldIndex(IList <Instr> instrs, int index) { int stack = 0; for (int i = index; i < instrs.Count; i++) { var instr = instrs[i]; if (stack == 0 && (instr.OpCode.Code == Code.Ldfld || instr.OpCode.Code == Code.Ldflda)) { return(i); } if (stack == 1 && instr.OpCode.Code == Code.Stfld) { return(i); } int pushes, pops; DotNetUtils.calculateStackUsage(instr.Instruction, false, out pushes, out pops); stack -= pops; if (stack < 0) { break; } stack += pushes; } throw new ApplicationException("Could not find ldfld/stfld"); }
void updateStack(Instruction instr) { int pushes, pops; DotNetUtils.calculateStackUsage(instr, false, out pushes, out pops); if (pops == -1) { valueStack.clear(); } else { valueStack.pop(pops); valueStack.push(pushes); } }
void emulate_Call(Instruction instr, MethodReference method) { int pushes, pops; DotNetUtils.calculateStackUsage(instr, false, out pushes, out pops); valueStack.pop(pops); if (pushes == 1) { valueStack.push(getUnknownValue(method.MethodReturnType.ReturnType)); } else { valueStack.push(pushes); } }
// May not return all args. The args are returned in reverse order. public static PushedArgs getPushedArgInstructions(IList <Instruction> instructions, int index) { try { int pushes, pops; DotNetUtils.calculateStackUsage(instructions[index], false, out pushes, out pops); if (pops != -1) { return(getPushedArgInstructions(instructions, index, pops)); } } catch (System.NullReferenceException) { // Here if eg. invalid metadata token in a call instruction (operand is null) } return(new PushedArgs(0)); }
bool emulateToReturn(int index, Instruction lastInstr) { int pushes, pops; DotNetUtils.calculateStackUsage(lastInstr, false, out pushes, out pops); for (int i = 0; i < pops; i++) { instructionEmulator.pop(); } returnValue = null; if (pushes != 0) { returnValue = new UnknownValue(); instructionEmulator.setProtected(returnValue); instructionEmulator.push(returnValue); } if (!emulateInstructions(ref index, true)) { return(false); } if (index >= methodToInline.Body.Instructions.Count) { return(false); } if (methodToInline.Body.Instructions[index].OpCode.Code != Code.Ret) { return(false); } if (returnValue != null) { if (instructionEmulator.pop() != returnValue) { return(false); } } return(instructionEmulator.stackSize() == 0); }
// May not return all args. The args are returned in reverse order. static PushedArgs getPushedArgInstructions(IList <Instruction> instructions, int index, int numArgs) { var pushedArgs = new PushedArgs(numArgs); Instruction instr; int skipPushes = 0; while (index >= 0 && pushedArgs.CanAddMore) { instr = getPreviousInstruction(instructions, ref index); if (instr == null) { break; } int pushes, pops; DotNetUtils.calculateStackUsage(instr, false, out pushes, out pops); if (pops == -1) { break; } if (instr.OpCode.Code == Code.Dup) { pushes = 1; pops = 0; } if (pushes > 1) { break; } if (skipPushes > 0) { skipPushes -= pushes; if (skipPushes < 0) { break; } skipPushes += pops; } else { if (pushes == 1) { pushedArgs.add(instr); } skipPushes += pops; } } instr = pushedArgs.get(0); if (instr != null && instr.OpCode.Code == Code.Dup) { instr = getPreviousInstruction(instructions, ref index); if (instr != null) { int pushes, pops; DotNetUtils.calculateStackUsage(instr, false, out pushes, out pops); if (pushes == 1 && pops == 0) { pushedArgs.set(0, instr); } } } pushedArgs.fixDups(); return(pushedArgs); }
static void calculateStackUsage(Instruction instr, bool methodHasReturnValue, out int pushes, out int pops) { DotNetUtils.calculateStackUsage(instr, false, out pushes, out pops); }
bool getArg(MethodReference method, Block block, ref object arg, ref int instrIndex) { while (true) { if (instrIndex < 0) { // We're here if there were no cflow deobfuscation, or if there are two or // more blocks branching to the decrypter method, or the two blocks can't be // merged because one is outside the exception handler (eg. buggy obfuscator). Log.w("Could not find all arguments to method {0} ({1:X8})", Utils.removeNewlines(method), method.MetadataToken.ToInt32()); errors++; return(false); } var instr = block.Instructions[instrIndex--]; switch (instr.OpCode.Code) { case Code.Ldc_I4: case Code.Ldc_I8: case Code.Ldc_R4: case Code.Ldc_R8: case Code.Ldstr: arg = instr.Operand; break; case Code.Ldc_I4_S: arg = (int)(sbyte)instr.Operand; break; case Code.Ldc_I4_0: arg = 0; break; case Code.Ldc_I4_1: arg = 1; break; case Code.Ldc_I4_2: arg = 2; break; case Code.Ldc_I4_3: arg = 3; break; case Code.Ldc_I4_4: arg = 4; break; case Code.Ldc_I4_5: arg = 5; break; case Code.Ldc_I4_6: arg = 6; break; case Code.Ldc_I4_7: arg = 7; break; case Code.Ldc_I4_8: arg = 8; break; case Code.Ldc_I4_M1: arg = -1; break; case Code.Ldnull: arg = null; break; case Code.Nop: continue; case Code.Ldloc: case Code.Ldloc_S: case Code.Ldloc_0: case Code.Ldloc_1: case Code.Ldloc_2: case Code.Ldloc_3: getLocalVariableValue(Instr.getLocalVar(theMethod.Body.Variables, instr), out arg); break; case Code.Ldfld: case Code.Ldsfld: arg = instr.Operand; break; default: int pushes, pops; DotNetUtils.calculateStackUsage(instr.Instruction, false, out pushes, out pops); if (!useUnknownArgs || pushes != 1) { Log.w("Could not find all arguments to method {0} ({1:X8}), instr: {2}", Utils.removeNewlines(method), method.MetadataToken.ToInt32(), instr); errors++; return(false); } for (int i = 0; i < pops; i++) { if (!getArg(method, block, ref arg, ref instrIndex)) { return(false); } } arg = null; break; } break; } return(true); }