예제 #1
0
파일: HGame.cs 프로젝트: makinit/Tanji
        /// <summary>
        /// Dissassembles the Habbo Hotel flash client.
        /// </summary>
        public override void Disassemble()
        {
            WriteLog("Disassembling...");
            base.Disassemble();

            ABCFile abc = ABCFiles[2];
            ASClass habboMessagesClass = abc.FindFirstClassByName("HabboMessages");

            if (habboMessagesClass != null)
            {
                FindHabboMessageClasses(habboMessagesClass);

                WriteLog(string.Format("Outgoing({0})/Incoming({1}) messages extracted.",
                                       OutgoingMessages.Count, IncomingMessages.Count));
            }
        }
예제 #2
0
파일: HGame.cs 프로젝트: Simonvdh/Tanji
        /// <summary>
        /// Dissassembles the Habbo Hotel flash client.
        /// </summary>
        public override void Disassemble()
        {
            WriteLog("Disassembling...");
            base.Disassemble();

            for (int i = 0; i < ABCFiles.Count; i++)
            {
                ABCFile abc = ABCFiles[i];
                //WriteLog($"Fixing local registers in {abc.Methods.Count:n0} methods.");
                //FixLocalRegisters(abc);

                if (i == 2)
                {
                    ASClass habboMessagesClass = abc.FindFirstClassByName("HabboMessages");
                    if (habboMessagesClass != null)
                    {
                        FindHabboMessageClasses(habboMessagesClass);

                        WriteLog(string.Format("Outgoing({0})/Incoming({1}) messages extracted.",
                                               OutgoingMessages.Count, IncomingMessages.Count));
                    }
                }
            }
        }
예제 #3
0
파일: HGame.cs 프로젝트: makinit/Tanji
        protected int FindMessageReferences(ASClass fromClass, TraitContainer container, ASMethod fromMethod, int rank, int msgReferencesFound)
        {
            ABCFile abc = fromClass.ABC;

            using (var inCode = new FlashReader(fromMethod.Body.Bytecode))
            {
                var multinameStack = new Stack <ASMultiname>();
                while (inCode.IsDataAvailable)
                {
                    OPCode   op     = inCode.ReadOP();
                    object[] values = inCode.ReadValues(op);

                    switch (op)
                    {
                        #region Case: GetProperty
                    case OPCode.GetProperty:
                    {
                        multinameStack.Push(abc.Constants.Multinames[(int)values[0]]);
                        break;
                    }

                        #endregion
                        #region Case: NewFunction
                    case OPCode.NewFunction:
                    {
                        ASMethod newFuncMethod = abc.Methods[(int)values[0]];
                        msgReferencesFound = FindMessageReferences(fromClass, container, newFuncMethod, rank, msgReferencesFound);
                        break;
                    }

                        #endregion
                        #region Case: ConstructProp
                    case OPCode.ConstructProp:
                    {
                        ASMultiname constructPropType =
                            abc.Constants.Multinames[(int)values[0]];

                        ASClass messageClass =
                            abc.FindFirstClassByName(constructPropType.Name);

                        if (messageClass == null || !IsMessageClass(messageClass))
                        {
                            continue;
                        }

                        if (!_messageReferences.ContainsKey(messageClass))
                        {
                            _messageReferences[messageClass] = new List <ASReference>();
                        }

                        var msgReference = new ASReference(messageClass, fromClass, fromMethod);
                        if (!IsMessageOutgoing(messageClass))
                        {
                            ASMultiname topName = multinameStack.Pop();
                            msgReference.FromMethod = null;

                            IEnumerable <MethodGetterSetterTrait> mgsTraits =
                                container.FindMethodGetterSetterTraits();

                            rank = 0;     // TODO: Move this into a method or something, I'm re-writing it below as well.
                            foreach (MethodGetterSetterTrait mgsTrait in mgsTraits)
                            {
                                rank++;
                                if (mgsTrait.Method.TraitName == topName.Name)
                                {
                                    msgReference.FromMethod = mgsTrait.Method;
                                    break;
                                }
                            }
                            if (msgReference.FromMethod == null && multinameStack.Count > 0)
                            {
                                ASMultiname bottomName = multinameStack.Pop();
                                foreach (ASTrait trait in container.Traits)
                                {
                                    switch (trait.TraitType)
                                    {
                                        #region Case: Slot, Constant
                                    case TraitType.Slot:
                                    case TraitType.Constant:
                                    {
                                        if (trait.Name.Name != bottomName.Name)
                                        {
                                            continue;
                                        }

                                        var scTrait = (SlotConstantTrait)trait.Data;
                                        if (scTrait.TypeName.MultinameType != ConstantType.QName)
                                        {
                                            continue;
                                        }
                                        ASClass slotValueClass = abc.FindFirstClassByName(scTrait.TypeName.Name);

                                        rank      = 0;
                                        mgsTraits = slotValueClass.Instance.FindMethodGetterSetterTraits();
                                        foreach (MethodGetterSetterTrait mgsTrait in mgsTraits)
                                        {
                                            rank++;
                                            if (mgsTrait.Method.TraitName == topName.Name)
                                            {
                                                msgReference.FromMethod = mgsTrait.Method;
                                                break;
                                            }
                                        }

                                        if (msgReference.FromMethod != null)
                                        {
                                            msgReference.FromClass = slotValueClass;
                                        }

                                        break;
                                    }
                                        #endregion
                                    }
                                    if (msgReference.FromMethod != null)
                                    {
                                        break;
                                    }
                                }
                            }
                        }

                        msgReference.Id = ((++msgReferencesFound) + rank);
                        // We can't rely on the amount of references found, since the hooking of incoming messages are randomized each revision.
                        if (!IsMessageOutgoing(messageClass))
                        {
                            msgReference.Id = rank;
                        }

                        _messageReferences[messageClass].Add(msgReference);
                        break;
                    }
                        #endregion
                    }
                }
            }
            return(msgReferencesFound);
        }
예제 #4
0
파일: HGame.cs 프로젝트: makinit/Tanji
        protected void FindHabboMessageClasses(ASClass habboMessageClass)
        {
            if (habboMessageClass == null)
            {
                throw new NullReferenceException(nameof(habboMessageClass));
            }

            if (OutgoingMessages != null && IncomingMessages != null)
            {
                return;
            }

            ABCFile abc = habboMessageClass.ABC;

            if (habboMessageClass.Traits.Count < 2)
            {
                return;
            }

            int incomingMapTypeIndex = habboMessageClass.Traits[0].NameIndex;
            int outgoingMapTypeIndex = habboMessageClass.Traits[1].NameIndex;

            var outgoingClasses = new Dictionary <ushort, ASClass>();
            var incomingClasses = new Dictionary <ushort, ASClass>();

            ASMethod constructor = habboMessageClass.Constructor;

            using (var inCode = new FlashReader(constructor.Body.Bytecode))
            {
                while (inCode.IsDataAvailable)
                {
                    object[] values = inCode.ReadValuesUntil(OPCode.GetLex);
                    if (values == null)
                    {
                        break;
                    }

                    // Check if the instruction is referencing one of the in/out map types.
                    int  getLexTypeIndex = (int)values[0];
                    bool isOutgoing      = (getLexTypeIndex == outgoingMapTypeIndex);
                    if (!isOutgoing && getLexTypeIndex != incomingMapTypeIndex)
                    {
                        continue;
                    }

                    OPCode op = 0;
                    values = inCode.ReadValuesUntilEither(out op, OPCode.PushByte, OPCode.PushShort);

                    if (values == null)
                    {
                        return;
                    }
                    var header = Convert.ToUInt16(values[0]);

                    values = inCode.ReadValuesUntil(OPCode.GetLex);
                    if (values == null)
                    {
                        return;
                    }

                    getLexTypeIndex = (int)values[0];
                    ASMultiname messageType  = abc.Constants.Multinames[getLexTypeIndex];
                    ASClass     messageClass = abc.FindFirstClassByName(messageType.Name);

                    Dictionary <ushort, ASClass> messageClasses =
                        (isOutgoing ? outgoingClasses : incomingClasses);

                    messageClasses[header]           = messageClass;
                    _isMessageOutgoing[messageClass] = isOutgoing;
                }
            }

            #region Organize Outgoing Message Dictionaries
            IOrderedEnumerable <KeyValuePair <ushort, ASClass> > orderedOutgoing =
                outgoingClasses.OrderBy(kvp => kvp.Key);

            _outgoingHeaders = orderedOutgoing
                               .ToDictionary(kvp => kvp.Value, kvp => kvp.Key);

            OutgoingMessages = new ReadOnlyDictionary <ushort, ASClass>(
                orderedOutgoing.ToDictionary(kvp => kvp.Key, kvp => kvp.Value));
            #endregion
            #region Organize Incoming Message Dictionaries
            IOrderedEnumerable <KeyValuePair <ushort, ASClass> > orderedIncoming =
                incomingClasses.OrderBy(kvp => kvp.Key);

            _incomingHeaders = orderedIncoming
                               .ToDictionary(kvp => kvp.Value, kvp => kvp.Key);

            IncomingMessages = new ReadOnlyDictionary <ushort, ASClass>(
                orderedIncoming.ToDictionary(kvp => kvp.Key, kvp => kvp.Value));
            #endregion
        }