Esempio n. 1
0
        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;
        }
Esempio n. 2
0
        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;
        }
Esempio n. 3
0
        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;
        }
Esempio n. 4
0
        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;
        }
Esempio n. 5
0
        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();
                }
            }
        }
Esempio n. 6
0
        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();
                }
            }
        }