Exemple #1
0
        public void Write(ASTrait trait)
        {
            Write(trait.Id);
            Write(trait.QName);
            Write(trait.IsStatic);
            Write((byte)trait.Kind);
            Write((byte)trait.Attributes);
            switch (trait.Kind)
            {
            case TraitKind.Slot:
            case TraitKind.Constant:
            {
                Write(trait.Type);
                if (trait.Value != null)
                {
                    Write(trait.ValueKind, trait.Value);
                }
                break;
            }

            case TraitKind.Method:
            case TraitKind.Getter:
            case TraitKind.Setter:
            {
                Write(trait.Method);
                break;
            }
            }
        }
Exemple #2
0
        protected void ScanForMessageReferences(ABCFile abc)
        {
            if (!FindMessageInstances())
            {
                return;
            }
            if (_messageReferencesCache.Count > 0)
            {
                return;
            }

            var messageClasses = new Dictionary <string, ASClass>(
                OutgoingTypes.Count + IncomingTypes.Count);

            foreach (ASClass outClass in OutgoingTypes.Values)
            {
                messageClasses.Add(
                    outClass.Instance.Type.ObjName, outClass);
            }
            foreach (ASClass inClass in IncomingTypes.Values)
            {
                messageClasses.Add(
                    inClass.Instance.Type.ObjName, inClass);
            }
            foreach (ASClass asClass in abc.Classes)
            {
                ASInstance asInstance = asClass.Instance;
                if (asInstance.ClassInfo.HasFlag(ClassFlags.Interface))
                {
                    continue;
                }
                ScanForMessageReference(messageClasses, asClass, asClass.Constructor, 0);
                ScanForMessageReference(messageClasses, asClass, asClass.Instance.Constructor, 0);

                if (asInstance.Traits.Count < 1)
                {
                    continue;
                }
                for (int i = 0; i < asInstance.Traits.Count; i++)
                {
                    ASTrait trait = asInstance.Traits[i];
                    if (trait.TraitType != TraitType.Method)
                    {
                        continue;
                    }

                    var mgsTrait = (MethodGetterSetterTrait)trait.Data;
                    ScanForMessageReference(messageClasses, asClass, mgsTrait.Method, i);
                }
            }
        }
Exemple #3
0
        /// <summary>
        ///     Modifies the "ClientHelloMessageComposer" (Packet 4000) class
        ///     to send the current environment instead of the protocol revision.
        /// </summary>
        public void PatchClientHelloMessageComposer()
        {
            var abc = _flash.AbcGame;

            // Grab ClientHelloMessageComposer.
            var composerClass = MessagesOutgoing[4000].Clazz;

            // Find CommunicationUtils.
            var communicationUtilsClass  = _lookup.Get(HabboClass.CommunicationUtils);
            var communicationUtilsMethod = communicationUtilsClass.Traits
                                           .AsParallel()
                                           .FirstOrDefault(x => x.IsStatic &&
                                                           x.Kind == TraitKind.Method &&
                                                           x.Method.Parameters.Count == 2 &&
                                                           x.Method.Parameters[1].IsOptional &&
                                                           x.Method.ReturnType.Name.Equals("String"));

            if (communicationUtilsMethod == null)
            {
                throw new ApplicationException("Unable to find communicationUtilsMethod.");
            }

            // Find com.sulake.habbo.communication.demo:IncomingMessages.
            var incomingMessagesClass  = _lookup.Get(HabboClass.IncomingMessages);
            var incomingMessagesMethod = incomingMessagesClass.Instance.Traits
                                         .AsParallel()
                                         .Where(x => x.Kind == TraitKind.Method &&
                                                x.Method.Parameters.Count == 1 &&
                                                x.Method.Parameters[0].Type.Name.Equals("Event") &&
                                                x.Method.Parameters[0].IsOptional &&
                                                x.Method.ReturnType.Name.Equals("void"))
                                         .Select(x => x.Method)
                                         .FirstOrDefault();

            if (incomingMessagesMethod == null)
            {
                throw new ApplicationException("Unable to find incomingMessagesMethod.");
            }

            var incomingMessagesCode = incomingMessagesMethod.Body.ParseCode();

            // Modify the method of IncomingMessages.
            var constructComposer = incomingMessagesCode
                                    .Where(x => x.OP == OPCode.ConstructProp && ((ConstructPropIns)x).PropertyName.NameIndex == composerClass.QName.NameIndex)
                                    .Cast <ConstructPropIns>()
                                    .First();

            // IncomingMessages: Add an argument when constructing the message.
            constructComposer.ArgCount = 1;

            // IncomingMessages: Add the argument value.
            incomingMessagesCode.InsertRange(incomingMessagesCode.IndexOf(constructComposer), new ASInstruction[]
            {
                new GetLexIns(abc, abc.Pool.Multinames.IndexOf(communicationUtilsClass.QName)),
                new PushStringIns(abc, "environment"),
                new CallPropertyIns(abc, communicationUtilsMethod.QNameIndex, 1),
                new CoerceSIns()
            });

            // IncomingMessages: Increase stack.
            incomingMessagesMethod.Body.MaxStack += 4;
            incomingMessagesMethod.Body.Code      = incomingMessagesCode.ToArray();

            // Modify the constructor of ClientHelloMessageComposer.
            var composerConstructor = composerClass.Instance.Constructor;
            var composerCode        = composerConstructor.Body.ParseCode();

            // ClientHelloMessageComposer: Add "String" parameter.
            composerConstructor.Parameters.Add(new ASParameter(abc.Pool, composerConstructor)
            {
                TypeIndex = abc.Pool.GetMultinameIndex("String")
            });

            // ClientHelloMessageComposer: Add "environmentId" variable.
            var composerSlotQName = new ASMultiname(abc.Pool)
            {
                NameIndex      = abc.Pool.AddConstant("environmentId"),
                Kind           = MultinameKind.QName,
                NamespaceIndex = 1
            };

            var composerSlot = new ASTrait(abc)
            {
                Kind       = TraitKind.Slot,
                QNameIndex = abc.Pool.AddConstant(composerSlotQName),
                TypeIndex  = abc.Pool.GetMultinameIndex("String")
            };

            composerClass.Instance.Traits.Add(composerSlot);

            // ClientHelloMessageComposer: Set parameter of constructor to "environmentId".
            composerCode.InsertRange(composerCode.Count - 1, new ASInstruction[]
            {
                new GetLocal1Ins(),
                new FindPropertyIns(abc, composerSlot.QNameIndex),
                new SwapIns(),
                new SetPropertyIns(abc, composerSlot.QNameIndex),
            });

            composerConstructor.Body.LocalCount = 2;
            composerConstructor.Body.MaxStack   = 2;
            composerConstructor.Body.Code       = composerCode.ToArray();

            // Modify the method that returns packet as array.
            var getArrayMethod = composerClass.Instance.Traits
                                 .AsParallel()
                                 .First(x => x.Kind == TraitKind.Method &&
                                        x.Method.Parameters.Count == 0 &&
                                        x.Method.ReturnType.Name.Equals("Array"));

            var getArrayCode = getArrayMethod.Method.Body.ParseCode();

            // getArray: Remove everything until constructing array.
            getArrayCode.Clear();
            getArrayCode.AddRange(new ASInstruction[]
            {
                new GetLocal0Ins(),
                new PushScopeIns(),

                new PushStringIns(abc, Revision),
                new PushStringIns(abc, RevisionProtocol),
                new PushIntIns(abc, 3), // Android.
                new PushIntIns(abc, 1),
                new GetLexIns(abc, composerSlot.QNameIndex),

                new NewArrayIns(5),
                new ReturnValueIns(),
            });

            // getArray: Apply patch.
            getArrayMethod.Method.Body.MaxStack   = 5;
            getArrayMethod.Method.Body.LocalCount = 1;
            getArrayMethod.Method.Body.Code       = getArrayCode.ToArray();

            // ClientHelloMessageComposer: Clean class.
            composerClass.Instance.Traits.Remove(composerClass.Instance.Traits.First(x => x.Kind == TraitKind.Slot && x.QNameIndex != composerSlot.QNameIndex));
        }
Exemple #4
0
        public bool FindMessageInstances()
        {
            if (OutgoingTypes.Count > 0 &&
                IncomingTypes.Count > 0)
            {
                return(true);
            }

            ABCFile abc           = ABCFiles[2];
            ASClass habboMessages = abc.FindClassByName("HabboMessages");

            if (habboMessages == null || habboMessages.Traits.Count < 2)
            {
                return(false);
            }

            ASTrait incomingMap = habboMessages.Traits[0];
            ASTrait outgoingMap = habboMessages.Traits[1];

            using (var mapReader = new FlashReader(
                       habboMessages.Constructor.Body.Bytecode.ToArray()))
            {
                while (mapReader.Position != mapReader.Length)
                {
                    OPCode op = mapReader.ReadOP();
                    if (op != OPCode.GetLex)
                    {
                        continue;
                    }

                    int  mapTypeIndex = mapReader.Read7BitEncodedInt();
                    bool isOutgoing   = (mapTypeIndex == outgoingMap.TypeIndex);
                    bool isIncoming   = (mapTypeIndex == incomingMap.TypeIndex);
                    if (!isOutgoing && !isIncoming)
                    {
                        continue;
                    }

                    op = mapReader.ReadOP();
                    if (op != OPCode.PushShort && op != OPCode.PushByte)
                    {
                        continue;
                    }

                    ushort header = 0;
                    if (op == OPCode.PushByte)
                    {
                        header = mapReader.ReadByte();
                    }
                    else
                    {
                        header = (ushort)mapReader.Read7BitEncodedInt();
                    }

                    op = mapReader.ReadOP();
                    if (op != OPCode.GetLex)
                    {
                        continue;
                    }

                    int         messageTypeIndex = mapReader.Read7BitEncodedInt();
                    ASMultiname messageType      = abc.Constants.Multinames[messageTypeIndex];
                    ASClass     messageInstance  = abc.FindClassByName(messageType.ObjName);

                    if (isOutgoing)
                    {
                        OutgoingTypes[header] = messageInstance;
                    }
                    else if (isIncoming)
                    {
                        IncomingTypes[header] = messageInstance;
                    }
                }
            }

            return(OutgoingTypes.Count > 0 &&
                   IncomingTypes.Count > 0);
        }
Exemple #5
0
        private List <HReference> FindMessageReferences(ASClass fromClass, ASContainer fromContainer, ASMethod fromMethod)
        {
            int     instructionRank = 0;
            ABCFile abc             = fromMethod.GetABC();

            Stack <ASMultiname> nameStack  = new Stack <ASMultiname>();
            List <HReference>   references = new List <HReference>();

            ASContainer container = null;
            ASCode      code      = fromMethod.Body.ParseCode();

            for (int i = 0; i < code.Count; i++)
            {
                ASInstruction instruction = code[i];
                switch (instruction.OP)
                {
                default: continue;

                case OPCode.NewFunction:
                {
                    NewFunctionIns newFunction = (NewFunctionIns)instruction;
                    references.AddRange(FindMessageReferences(fromClass, fromContainer, newFunction.Method));
                    continue;
                }

                case OPCode.GetProperty:
                {
                    GetPropertyIns getProperty = (GetPropertyIns)instruction;
                    nameStack.Push(getProperty.PropertyName);
                    continue;
                }

                case OPCode.GetLex:
                {
                    GetLexIns getLex = (GetLexIns)instruction;
                    container = abc.GetClass(getLex.TypeName.Name);
                    continue;
                }

                case OPCode.GetLocal_0:
                {
                    container = fromContainer;
                    continue;
                }

                case OPCode.ConstructProp:
                {
                    ConstructPropIns constructProp = (ConstructPropIns)instruction;
                    nameStack.Push(constructProp.PropertyName);
                    break;
                }
                }

                ASMultiname messageQName = nameStack.Pop();
                if (string.IsNullOrWhiteSpace(messageQName.Name))
                {
                    continue;
                }

                ASClass messageClass = abc.GetClass(messageQName.Name);
                if (messageClass == null)
                {
                    continue;
                }

                if (!_messages.TryGetValue(messageClass, out HMessage message))
                {
                    continue;
                }
                if (message.References.Any(r => r.FromMethod == fromMethod))
                {
                    continue;
                }

                HReference reference = new HReference();
                message.References.Add(reference);

                if (message.IsOutgoing)
                {
                    reference.FromClass       = fromClass;
                    reference.FromMethod      = fromMethod;
                    reference.InstructionRank = ++instructionRank;
                    reference.IsAnonymous     = (!fromMethod.IsConstructor && fromMethod.Trait == null);

                    references.Add(reference);
                }
                else
                {
                    ASMultiname methodName     = nameStack.Pop();
                    ASMethod    callbackMethod = fromContainer.GetMethod(methodName.Name);
                    if (callbackMethod == null)
                    {
                        callbackMethod = container.GetMethod(methodName.Name);
                        if (callbackMethod == null)
                        {
                            ASMultiname slotName = nameStack.Pop();

                            ASTrait hostTrait = container.GetTraits(TraitKind.Slot)
                                                .FirstOrDefault(st => st.QName == slotName);

                            container      = abc.GetInstance(hostTrait.Type.Name);
                            callbackMethod = container.GetMethod(methodName.Name);
                        }
                    }
                    reference.FromMethod = callbackMethod;
                }
            }
            return(references);
        }