Пример #1
0
        private bool CheckParameters(Il2CppMethodDefinition method, MethodAnalysis context, bool isInstance)
        {
            var actualArgs = new List <IAnalysedOperand>();

            if (!isInstance)
            {
                actualArgs.Add(context.GetOperandInRegister("rcx") ?? context.GetOperandInRegister("xmm0"));
            }

            actualArgs.Add(context.GetOperandInRegister("rdx") ?? context.GetOperandInRegister("xmm1"));
            actualArgs.Add(context.GetOperandInRegister("r8") ?? context.GetOperandInRegister("xmm2"));
            actualArgs.Add(context.GetOperandInRegister("r9") ?? context.GetOperandInRegister("xmm3"));

            foreach (var parameterData in method.Parameters !)
            {
                if (actualArgs.Count(a => a != null) == 0)
                {
                    return(false);
                }

                var arg = actualArgs.RemoveAndReturn(0);
                switch (arg)
                {
                case ConstantDefinition cons when cons.Type.FullName != parameterData.Type.ToString():                    //Constant type mismatch
                case LocalDefinition local when !Utils.IsManagedTypeAnInstanceOfCppOne(parameterData.Type, local.Type !): //Local type mismatch
                    return(false);
                }
            }

            if (actualArgs.Any(a => a != null && !context.IsEmptyRegArg(a)))
            {
                return(false); //Left over args - it's probably not this one
            }
            return(true);
        }
        public GlobalMethodRefToConstantAction(MethodAnalysis context, Instruction instruction) : base(context, instruction)
        {
            var globalAddress = instruction.GetRipBasedInstructionMemoryAddress();

            MethodData = LibCpp2IlMain.GetMethodDefinitionByGlobalAddress(globalAddress);
            var(type, genericParams) = Utils.TryLookupTypeDefByName(MethodData !.DeclaringType.FullName);

            if (type == null)
            {
                Console.WriteLine("Failed to lookup managed type for declaring type of " + MethodData.GlobalKey + ", which is " + MethodData.DeclaringType.FullName);
                return;
            }

            ResolvedMethod = type.Methods.FirstOrDefault(m => m.Name == MethodData.Name);

            if (ResolvedMethod == null)
            {
                return;
            }

            var destReg = instruction.Op0Kind == OpKind.Register ? Utils.GetRegisterNameNew(instruction.Op0Register) : null;
            var name    = ResolvedMethod.Name;

            ConstantWritten = context.MakeConstant(typeof(MethodDefinition), ResolvedMethod, name, destReg);
        }
Пример #3
0
        public LoadVirtualFunctionPointerAction(MethodAnalysis context, Instruction instruction) : base(context, instruction)
        {
            regReadFrom = Utils.GetRegisterNameNew(instruction.MemoryBase);
            var inReg = context.GetOperandInRegister(regReadFrom);

            if (!(inReg is ConstantDefinition cons) || !(cons.Value is Il2CppClassIdentifier klass))
            {
                return;
            }

            classReadFrom = klass.backingType;

            var readOffset = instruction.MemoryDisplacement;

            methodPointerRead = Utils.GetMethodFromReadKlassOffset((int)readOffset);

            if (methodPointerRead == null)
            {
                return;
            }

            var regPutInto = Utils.GetRegisterNameNew(instruction.Op0Register);

            if (regPutInto == "rsp")
            {
                //todo how do we handle this kind of instruction - does it even exist?
                // var stackOffset = Utils.GetOperandMemoryOffset(instruction.Operands[0]);
                // context.PushToStack(context.MakeConstant(typeof(MethodDefinition), methodPointerRead), stackOffset);
            }
            else
            {
                destinationConstant = context.MakeConstant(typeof(MethodDefinition), methodPointerRead, reg: regPutInto);
            }
        }
Пример #4
0
        public ComparisonAction(MethodAnalysis context, Instruction instruction) : base(context, instruction)
        {
            var r0           = Utils.GetRegisterNameNew(instruction.Op0Register);
            var r1           = Utils.GetRegisterNameNew(instruction.Op1Register);
            var ripBasedAddr = instruction.GetRipBasedInstructionMemoryAddress();

            if (r0 != "rsp")
            {
                ArgumentOne = instruction.Op0Kind == OpKind.Register
                    ? context.GetOperandInRegister(r0)
                    : instruction.Op0Kind.IsImmediate()
                        ? context.MakeConstant(typeof(int), instruction.GetImmediate(0))
                        : LibCpp2IlMain.GetAnyGlobalByAddress(ripBasedAddr).Offset == ripBasedAddr
                            ? context.MakeConstant(typeof(GlobalIdentifier), LibCpp2IlMain.GetAnyGlobalByAddress(ripBasedAddr))
                            : context.MakeConstant(typeof(UnknownGlobalAddr), new UnknownGlobalAddr(ripBasedAddr));
            }
            if (r1 != "rsp")
            {
                ArgumentTwo = instruction.Op1Kind == OpKind.Register
                    ? context.GetOperandInRegister(r1)
                    : instruction.Op1Kind.IsImmediate()
                        ? context.MakeConstant(typeof(int), instruction.GetImmediate(1))
                        :  LibCpp2IlMain.GetAnyGlobalByAddress(ripBasedAddr).Offset == ripBasedAddr
                            ? context.MakeConstant(typeof(GlobalIdentifier), LibCpp2IlMain.GetAnyGlobalByAddress(ripBasedAddr))
                            : context.MakeConstant(typeof(UnknownGlobalAddr), new UnknownGlobalAddr(ripBasedAddr));
            }
        }
Пример #5
0
        public RegToRegMoveAction(MethodAnalysis context, Instruction instruction) : base(context, instruction)
        {
            originalReg = Utils.GetRegisterNameNew(instruction.Op1Register);
            newReg      = Utils.GetRegisterNameNew(instruction.Op0Register);
            beingMoved  = context.GetOperandInRegister(originalReg);

            context.SetRegContent(newReg, beingMoved);
        }
Пример #6
0
        public InterfaceOffsetsReadAction(MethodAnalysis context, Instruction instruction) : base(context, instruction)
        {
            var regName     = Utils.GetRegisterNameNew(instruction.MemoryBase);
            var regConstant = context.GetConstantInReg(regName);

            _loadedFor       = (Il2CppClassIdentifier)regConstant.Value;
            InterfaceOffsets = _loadedFor.backingType.InterfaceOffsets;

            _destReg          = Utils.GetRegisterNameNew(instruction.Op0Register);
            _destinationConst = context.MakeConstant(typeof(Il2CppInterfaceOffset[]), InterfaceOffsets, reg: _destReg);
        }
Пример #7
0
        public AllocateInstanceAction(MethodAnalysis context, Instruction instruction) : base(context, instruction)
        {
            var constant = context.GetConstantInReg("rcx");

            if (constant == null || constant.Type != typeof(TypeDefinition))
            {
                return;
            }

            TypeCreated = (TypeDefinition)constant.Value;

            LocalReturned = context.MakeLocal(TypeCreated, reg: "rax");
        }
Пример #8
0
        public LocateSpecificInterfaceOffsetAction(MethodAnalysis context, Instruction instruction) : base(context, instruction)
        {
            var secondOpName = Utils.GetRegisterNameNew(instruction.Op1Register);
            var secondOp     = context.GetConstantInReg(secondOpName);

            _interfaceType = (TypeDefinition)secondOp.Value;

            offsetReads = (InterfaceOffsetsReadAction)context.Actions.Last(a => a is InterfaceOffsetsReadAction);

            var cppType = SharedState.MonoToCppTypeDefs[_interfaceType];

            _matchingInterfaceOffset = offsetReads.InterfaceOffsets.First(i => i.type == cppType);
        }
        public GlobalStringRefToConstantAction(MethodAnalysis context, Instruction instruction) : base(context, instruction)
        {
            var globalAddress = instruction.GetRipBasedInstructionMemoryAddress();

            ResolvedString = LibCpp2IlMain.GetLiteralByAddress(globalAddress);

            if (ResolvedString == null)
            {
                return;
            }

            var destReg = instruction.Op0Kind == OpKind.Register ? Utils.GetRegisterNameNew(instruction.Op0Register) : null;

            ConstantWritten = context.MakeConstant(typeof(string), ResolvedString, null, destReg);
        }
        public GlobalTypeRefToConstantAction(MethodAnalysis context, Instruction instruction) : base(context, instruction)
        {
            var globalAddress = instruction.GetRipBasedInstructionMemoryAddress();
            var typeData      = LibCpp2IlMain.GetTypeGlobalByAddress(globalAddress);

            var(type, genericParams) = Utils.TryLookupTypeDefByName(typeData !.ToString());
            ResolvedType             = type;

            if (ResolvedType == null)
            {
                return;
            }

            _destReg = instruction.Op0Kind == OpKind.Register ? Utils.GetRegisterNameNew(instruction.Op0Register) : null;
            var name = ResolvedType.Name;

            ConstantWritten = context.MakeConstant(typeof(TypeDefinition), ResolvedType, name, _destReg);
        }
Пример #11
0
        public ClassPointerLoadAction(MethodAnalysis context, Instruction instruction) : base(context, instruction)
        {
            destReg = Utils.GetRegisterNameNew(instruction.Op0Register);
            if (instruction.Op0Register == Register.RSP)
            {
                Console.WriteLine("WARNING: CLASS POINTER LOAD DEST IS STACK.");
            }

            var sourceReg = Utils.GetRegisterNameNew(instruction.MemoryBase);
            var inReg     = context.GetOperandInRegister(sourceReg);

            localCopiedFrom = inReg is LocalDefinition local ? local : inReg is ConstantDefinition cons && cons.Value is NewSafeCastResult result ? result.original : null;
            if (localCopiedFrom == null)
            {
                return;
            }

            var cppTypeDef = SharedState.MonoToCppTypeDefs[localCopiedFrom.Type !];
Пример #12
0
        public CallManagedFunctionAction(MethodAnalysis context, Instruction instruction) : base(context, instruction)
        {
            var jumpTarget = instruction.NearBranchTarget;
            var objectMethodBeingCalledOn = context.GetLocalInReg("rcx");
            var listOfCallableMethods     = LibCpp2IlMain.GetManagedMethodImplementationsAtAddress(jumpTarget);

            if (listOfCallableMethods == null)
            {
                return;
            }

            Il2CppMethodDefinition possibleTarget = null;

            if (objectMethodBeingCalledOn?.Type != null)
            {
                //Direct instance methods take priority
                possibleTarget = listOfCallableMethods.FirstOrDefault(m => !m.IsStatic && Utils.AreManagedAndCppTypesEqual(LibCpp2ILUtils.WrapType(m.DeclaringType !), objectMethodBeingCalledOn.Type) && CheckParameters(m, context, true));

                //todo check args and null out

                if (possibleTarget == null)
                {
                    //Base class instance methods
                    possibleTarget = listOfCallableMethods.FirstOrDefault(m => !m.IsStatic && Utils.IsManagedTypeAnInstanceOfCppOne(LibCpp2ILUtils.WrapType(m.DeclaringType !), objectMethodBeingCalledOn.Type) && CheckParameters(m, context, true));
                }

                //check args again.
            }

            //Check static methods
            if (possibleTarget == null)
            {
                possibleTarget = listOfCallableMethods.FirstOrDefault(m => m.IsStatic && CheckParameters(m, context, false));
            }


            if (possibleTarget != null)
            {
                target = SharedState.UnmanagedToManagedMethods[possibleTarget];
                return;
            }

            // SharedState.MethodsByAddress.TryGetValue(jumpTarget, out target);
        }
        public JumpIfNonZeroOrNonNullAction(MethodAnalysis context, Instruction instruction) : base(context, instruction)
        {
            jumpTarget = instruction.NearBranchTarget;

            if (jumpTarget > instruction.NextIP && jumpTarget < context.AbsoluteMethodEnd)
            {
                isIfStatement = true;
                if (!context.IdentifiedIfStatementStarts.Contains(jumpTarget))
                {
                    context.IdentifiedIfStatementStarts.Add(jumpTarget);
                }
            }

            associatedCompare = (ComparisonAction)context.Actions.LastOrDefault(a => a is ComparisonAction);
            if (associatedCompare != null)
            {
                nullMode = associatedCompare.ArgumentOne == associatedCompare.ArgumentTwo;
            }
        }
        public LoadInterfaceMethodDataAction(MethodAnalysis context, Instruction instruction) : base(context, instruction)
        {
            if (context.GetConstantInReg("rcx") is {} castConstant &&
                castConstant.Value is NewSafeCastResult castResult &&
                context.GetConstantInReg("rdx") is {} interfaceConstant &&
                interfaceConstant.Value is TypeDefinition interfaceType &&
                context.GetConstantInReg("r8") is {} slotConstant &&
                slotConstant.Value is int slot &&
                context.Actions.FirstOrDefault(a => a is LocateSpecificInterfaceOffsetAction) is LocateSpecificInterfaceOffsetAction locator
                )
            {
                _invokedOn     = castResult.original;
                _interfaceType = interfaceType;
                _slotNumber    = slot;
                resolvedMethod = SharedState.VirtualMethodsBySlot[(ushort)(locator._matchingInterfaceOffset.offset + _slotNumber)];

                _resultConstant = context.MakeConstant(typeof(MethodDefinition), resolvedMethod, reg: "rax");
            }
        }
Пример #15
0
        public CallManagedFunctionInRegAction(MethodAnalysis context, Instruction instruction) : base(context, instruction)
        {
            var regName = Utils.GetRegisterNameNew(instruction.MemoryBase);
            var operand = context.GetConstantInReg(regName);

            _targetMethod = (MethodDefinition)operand.Value;

            if (!_targetMethod.IsStatic)
            {
                _instanceCalledOn = context.GetLocalInReg("rcx");
                if (_instanceCalledOn == null)
                {
                    var cons = context.GetConstantInReg("rcx");
                    if (cons?.Value is NewSafeCastResult castResult)
                    {
                        _instanceCalledOn = castResult.original;
                    }
                }
            }
        }
Пример #16
0
        public CallVirtualMethodAction(MethodAnalysis context, Instruction instruction) : base(context, instruction)
        {
            var inReg = context.GetOperandInRegister(Utils.GetRegisterNameNew(instruction.MemoryBase));

            if (!(inReg is ConstantDefinition cons) || !(cons.Value is Il2CppClassIdentifier klass))
            {
                return;
            }

            var classReadFrom = klass.backingType;

            var readOffset = instruction.MemoryDisplacement;

            Called = Utils.GetMethodFromReadKlassOffset((int)readOffset);

            if (Called == null)
            {
                return;
            }

            CalledOn = context.GetLocalInReg("rcx");
        }
Пример #17
0
        public SafeCastAction(MethodAnalysis context, Instruction instruction) : base(context, instruction)
        {
            var inReg = context.GetOperandInRegister("rcx");

            castSource = inReg is LocalDefinition local ? local : inReg is ConstantDefinition cons && cons.Value is NewSafeCastResult result ? result.original : null;
            var destOp = context.GetOperandInRegister("rdx");

            if (destOp is ConstantDefinition cons2 && cons2.Type == typeof(TypeDefinition))
            {
                destinationType = (TypeDefinition)cons2.Value;
            }

            if (destinationType == null || castSource == null)
            {
                return;
            }

            _castResult = context.MakeConstant(typeof(NewSafeCastResult), new NewSafeCastResult
            {
                castTo   = destinationType,
                original = castSource
            }, reg: "rax");
        }
Пример #18
0
 public ActionAllocateInstance(MethodAnalysis context, Instruction instruction) : base(context, instruction)
 {
 }
Пример #19
0
 public ReturnFromFunctionAction(MethodAnalysis context, Instruction instruction) : base(context, instruction)
 {
 }
Пример #20
0
 public StackToRegCopyAction(MethodAnalysis context, Instruction instruction) : base(context, instruction)
 {
 }
Пример #21
0
 public ConstantToFieldAction(MethodAnalysis context, Instruction instruction) : base(context, instruction)
 {
     constantValue = instruction.GetImmediate(1);
 }
Пример #22
0
 public CallInitMethodAction(MethodAnalysis context, Instruction instruction) : base(context, instruction)
 {
 }
Пример #23
0
 public LookupNativeFunctionAction(MethodAnalysis context, Instruction instruction) : base(context, instruction)
 {
 }
Пример #24
0
 public BaseAction(MethodAnalysis context, Instruction instruction)
 {
 }
Пример #25
0
 public ArrayOffsetToLocalAction(MethodAnalysis context, Instruction instruction) : base(context, instruction)
 {
 }
Пример #26
0
 public FieldToLocalAction(MethodAnalysis context, Instruction instruction) : base(context, instruction)
 {
 }
Пример #27
0
 public ClearRegAction(MethodAnalysis context, Instruction instruction) : base(context, instruction)
 {
     regCleared = Utils.GetRegisterNameNew(instruction.Op0Register);
     context.ZeroRegister(regCleared);
 }
Пример #28
0
 public CallNativeMethodFailureAction(MethodAnalysis context, Instruction instruction) : base(context, instruction)
 {
 }
Пример #29
0
 public InstanceVirtualMethodCallAction(MethodAnalysis context, Instruction instruction) : base(context, instruction)
 {
 }
Пример #30
0
 public ConstantToStackAction(MethodAnalysis context, Instruction instruction) : base(context, instruction)
 {
 }