public void Load(DarksVMContext ctx, out ExecutionState state) { var sp = ctx.Registers[DarksVMConstants.REG_SP].U4; var typeSlot = ctx.Stack[sp--]; var valSlot = ctx.Stack[sp]; var unboxPtr = (typeSlot.U4 & 0x80000000) != 0; var valType = (Type)ctx.Instance.Data.LookupReference(typeSlot.U4 & ~0x80000000); if (unboxPtr) { unsafe { TypedReference typedRef; TypedReferenceHelpers.UnboxTypedRef(valSlot.O, &typedRef); var reference = new TypedRef(typedRef); valSlot = DarksVMSlot.FromObject(valSlot.O, valType); ctx.Stack[sp] = valSlot; } } else { if (valType == typeof(object) && valSlot.O != null) { valType = valSlot.O.GetType(); } valSlot = DarksVMSlot.FromObject(valSlot.O, valType); ctx.Stack[sp] = valSlot; } ctx.Stack.SetTopPosition(sp); ctx.Registers[DarksVMConstants.REG_SP].U4 = sp; state = ExecutionState.Next; }
public void Load(DarksVMContext ctx, out ExecutionState state) { uint sp = ctx.Registers[DarksVMConstants.REG_SP].U4; DarksVMSlot fieldSlot = ctx.Stack[sp--]; DarksVMSlot objSlot = ctx.Stack[sp]; var field = (FieldInfo)ctx.Instance.Data.LookupReference(fieldSlot.U4 & 0x7fffffff); if (!field.IsStatic && objSlot.O == null) { throw new NullReferenceException(); } if (!((fieldSlot.U4 & 0x80000000) != 0)) { object instance = field.DeclaringType.IsValueType && objSlot.O is IReference ? ((IReference)objSlot.O).GetValue(ctx, PointerType.OBJECT).ToObject(field.DeclaringType) : objSlot.ToObject(field.DeclaringType); ctx.Stack[sp] = DarksVMSlot.FromObject(field.GetValue(instance), field.FieldType); } else { ctx.Stack[sp] = new DarksVMSlot { O = new FieldRef(objSlot.O, field) }; } ctx.Stack.SetTopPosition(sp); ctx.Registers[DarksVMConstants.REG_SP].U4 = sp; state = ExecutionState.Next; }
private void InvokeNormal(DarksVMContext ctx, MethodBase targetMethod, byte opCode, ref uint sp, out ExecutionState state) { uint _sp = sp; ParameterInfo[] parameters = targetMethod.GetParameters(); object self = null; object[] args = new object[parameters.Length]; if (opCode != DarksVMConstants.ECALL_CALL || !targetMethod.IsVirtual) { args = new object[parameters.Length]; for (int i = parameters.Length - 1; i >= 0; i--) { args[i] = PopObject(ctx, parameters[i].ParameterType, ref sp); } if (!targetMethod.IsStatic && opCode != DarksVMConstants.ECALL_NEWOBJ) { self = PopObject(ctx, targetMethod.DeclaringType, ref sp); if (self != null && !targetMethod.DeclaringType.IsInstanceOfType(self)) { // ConfuserEx sometimes produce this to circumvent peverify (see ref proxy) // Reflection won't allow it, so use typed invoke this.InvokeTyped(ctx, targetMethod, opCode, ref _sp, out state); return; } } } else { int indexOffset = targetMethod.IsStatic ? 0 : 1; args = new object[parameters.Length + indexOffset]; for (int i = parameters.Length - 1; i >= 0; i--) { args[i + indexOffset] = PopObject(ctx, parameters[i].ParameterType, ref sp); } if (!targetMethod.IsStatic) { args[0] = PopObject(ctx, targetMethod.DeclaringType, ref sp); } targetMethod = DirectCall.GetDirectInvocationProxy(targetMethod); } object result; if (opCode != DarksVMConstants.ECALL_NEWOBJ) { if (!targetMethod.IsStatic && self == null) { throw new NullReferenceException(); } Type selfType; if (self == null || !(selfType = self.GetType()).IsArray || targetMethod.Name != "SetValue") { try { result = targetMethod.Invoke(self, args); } catch (TargetInvocationException ex) { DarksVMDispatcher.DoThrow(ctx, ex.InnerException); throw; } } else { Type valueType = args[0] == null?selfType.GetElementType() : args[0].GetType(); ArrayStoreHelpers.SetValue((Array)self, (int)args[1], args[0], valueType, selfType.GetElementType()); result = null; } } else { try { result = ((ConstructorInfo)targetMethod).Invoke(args); } catch (TargetInvocationException ex) { EHHelper.Rethrow(ex.InnerException, null); throw; } } if (targetMethod is MethodInfo && ((MethodInfo)targetMethod).ReturnType != typeof(void)) { ctx.Stack[++sp] = DarksVMSlot.FromObject(result, ((MethodInfo)targetMethod).ReturnType); } else if (opCode == DarksVMConstants.ECALL_NEWOBJ) { ctx.Stack[++sp] = DarksVMSlot.FromObject(result, targetMethod.DeclaringType); } ctx.Stack.SetTopPosition(sp); ctx.Registers[DarksVMConstants.REG_SP].U4 = sp; state = ExecutionState.Next; }
private void InvokeTyped(DarksVMContext ctx, MethodBase targetMethod, byte opCode, ref uint sp, out ExecutionState state) { ParameterInfo[] parameters = targetMethod.GetParameters(); int paramCount = parameters.Length; if (!targetMethod.IsStatic && opCode != DarksVMConstants.ECALL_NEWOBJ) { paramCount++; } Type constrainType = null; if (opCode == DarksVMConstants.ECALL_CALLVIRT_CONSTRAINED) { constrainType = (Type)ctx.Instance.Data.LookupReference(ctx.Stack[sp--].U4); } int indexOffset = targetMethod.IsStatic || opCode == DarksVMConstants.ECALL_NEWOBJ ? 0 : 1; var references = new IReference[paramCount]; var types = new Type[paramCount]; for (int i = paramCount - 1; i >= 0; i--) { Type paramType; if (!targetMethod.IsStatic && opCode != DarksVMConstants.ECALL_NEWOBJ) { if (i == 0) { if (!targetMethod.IsStatic) { DarksVMSlot thisSlot = ctx.Stack[sp]; if (thisSlot.O is ValueType && !targetMethod.DeclaringType.IsValueType) { Debug.Assert(targetMethod.DeclaringType.IsInterface); Debug.Assert(opCode == DarksVMConstants.ECALL_CALLVIRT); // Interface dispatch on valuetypes => use constrained. invocation constrainType = thisSlot.O.GetType(); } } paramType = constrainType != null?constrainType.MakeByRefType() : targetMethod.DeclaringType.IsValueType ? targetMethod.DeclaringType.MakeByRefType() : targetMethod.DeclaringType; } else { paramType = parameters[i - 1].ParameterType; } } else { paramType = parameters[i].ParameterType; } references[i] = PopRef(ctx, paramType, ref sp); if (paramType.IsByRef) { paramType = paramType.GetElementType(); } types[i] = paramType; } OpCode callOp; Type retType; if (opCode != DarksVMConstants.ECALL_CALL) { if (opCode != DarksVMConstants.ECALL_CALLVIRT && opCode != DarksVMConstants.ECALL_CALLVIRT_CONSTRAINED) { if (opCode != DarksVMConstants.ECALL_NEWOBJ) { throw new InvalidProgramException(); } else { callOp = System.Reflection.Emit.OpCodes.Newobj; retType = targetMethod.DeclaringType; } } else { callOp = System.Reflection.Emit.OpCodes.Callvirt; retType = targetMethod is MethodInfo ? ((MethodInfo)targetMethod).ReturnType : typeof(void); } } else { callOp = System.Reflection.Emit.OpCodes.Call; retType = targetMethod is MethodInfo ? ((MethodInfo)targetMethod).ReturnType : typeof(void); } DirectCall.TypedInvocation proxy = DirectCall.GetTypedInvocationProxy(targetMethod, callOp, constrainType); object result = proxy(ctx, references, types); if (retType != typeof(void)) { ctx.Stack[++sp] = DarksVMSlot.FromObject(result, retType); } else { if (opCode == DarksVMConstants.ECALL_NEWOBJ) { ctx.Stack[++sp] = DarksVMSlot.FromObject(result, retType); } } ctx.Stack.SetTopPosition(sp); ctx.Registers[DarksVMConstants.REG_SP].U4 = sp; state = ExecutionState.Next; }
private void Load(ulong codeAddr, uint key, DarksVMFuncSig sig, void *[] arguments, void *retTypedRef) { if (currentCtx != null) { ctxStack.Push(currentCtx); } currentCtx = new DarksVMContext(this); try { Debug.Assert(sig.ParamTypes.Length == arguments.Length); currentCtx.Stack.SetTopPosition((uint)arguments.Length + 1); for (uint i = 0; i < arguments.Length; i++) { var paramType = sig.ParamTypes[i]; if (paramType.IsByRef) { currentCtx.Stack[i + 1] = new DarksVMSlot { O = new TypedRef(arguments[i]) }; } else { var typedRef = *(TypedReference *)arguments[i]; currentCtx.Stack[i + 1] = DarksVMSlot.FromObject(TypedReference.ToObject(typedRef), __reftype(typedRef)); } } currentCtx.Stack[(uint)arguments.Length + 1] = new DarksVMSlot { U8 = 1 }; currentCtx.Registers[DarksVMConstants.REG_K1] = new DarksVMSlot { U4 = key }; currentCtx.Registers[DarksVMConstants.REG_BP] = new DarksVMSlot { U4 = 0 }; currentCtx.Registers[DarksVMConstants.REG_SP] = new DarksVMSlot { U4 = (uint)arguments.Length + 1 }; currentCtx.Registers[DarksVMConstants.REG_IP] = new DarksVMSlot { U8 = codeAddr }; DarksVMDispatcher.Load(currentCtx); Debug.Assert(currentCtx.EHStack.Count == 0); if (sig.RetType != typeof(void)) { if (sig.RetType.IsByRef) { var retRef = currentCtx.Registers[DarksVMConstants.REG_R0].O; if (!(retRef is IReference)) { throw new ExecutionEngineException(); } ((IReference)retRef).ToTypedReference(currentCtx, retTypedRef, sig.RetType.GetElementType()); } else { var retSlot = currentCtx.Registers[DarksVMConstants.REG_R0]; object retVal; if (Type.GetTypeCode(sig.RetType) == TypeCode.String && retSlot.O == null) { retVal = Data.LookupString(retSlot.U4); } else { retVal = retSlot.ToObject(sig.RetType); } TypedReferenceHelpers.SetTypedRef(retVal, retTypedRef); } } } finally { currentCtx.Stack.FreeAllLocalloc(); if (ctxStack.Count > 0) { currentCtx = ctxStack.Pop(); } } }
private object Load(ulong codeAddr, uint key, DarksVMFuncSig sig, object[] arguments) { if (currentCtx != null) { ctxStack.Push(currentCtx); } currentCtx = new DarksVMContext(this); try { Debug.Assert(sig.ParamTypes.Length == arguments.Length); currentCtx.Stack.SetTopPosition((uint)arguments.Length + 1); for (uint i = 0; i < arguments.Length; i++) { currentCtx.Stack[i + 1] = DarksVMSlot.FromObject(arguments[i], sig.ParamTypes[i]); } currentCtx.Stack[(uint)arguments.Length + 1] = new DarksVMSlot { U8 = 1 }; currentCtx.Registers[DarksVMConstants.REG_K1] = new DarksVMSlot { U4 = key }; currentCtx.Registers[DarksVMConstants.REG_BP] = new DarksVMSlot { U4 = 0 }; currentCtx.Registers[DarksVMConstants.REG_SP] = new DarksVMSlot { U4 = (uint)arguments.Length + 1 }; currentCtx.Registers[DarksVMConstants.REG_IP] = new DarksVMSlot { U8 = codeAddr }; DarksVMDispatcher.Load(currentCtx); Debug.Assert(currentCtx.EHStack.Count == 0); object retVal = null; if (sig.RetType != typeof(void)) { var retSlot = currentCtx.Registers[DarksVMConstants.REG_R0]; if (Type.GetTypeCode(sig.RetType) == TypeCode.String && retSlot.O == null) { retVal = Data.LookupString(retSlot.U4); } else { retVal = retSlot.ToObject(sig.RetType); } } return(retVal); } finally { currentCtx.Stack.FreeAllLocalloc(); if (ctxStack.Count > 0) { currentCtx = ctxStack.Pop(); } } }