Beispiel #1
0
        /// <summary>
        /// Returns the hardcoded client revision string from the Outgoing[4000] message class.
        /// </summary>
        /// <returns></returns>
        public string GetClientRevision()
        {
            if (!string.IsNullOrWhiteSpace(_clientRevision))
            {
                return(_clientRevision);
            }

            if (!(OutgoingMessages?.ContainsKey(4000) ?? false))
            {
                return(string.Empty);
            }

            ASInstance outgoingInstance = OutgoingMessages[4000].Instance;
            ASMethod   method           = outgoingInstance.FindFirstMethod(null, "Array");

            if (method == null)
            {
                return(string.Empty);
            }

            using (var inCode = new FlashReader(method.Body.Bytecode))
            {
                object[] values          = inCode.ReadValuesUntil(OPCode.PushString);
                var      pushStringIndex = (int)values[0];

                _clientRevision = method.ABC.Constants.Strings[pushStringIndex];
            }
            return(_clientRevision);
        }
Beispiel #2
0
        protected void FindMessageReferences()
        {
            ABCFile abc = ABCFiles[2];

            WriteLog($"Searching {abc.Methods.Count:n0} methods for references to Outgoing({OutgoingMessages.Count})/Incoming({IncomingMessages.Count}) messages...");
            foreach (ASClass asClass in abc.Classes)
            {
                ASInstance asInstance = asClass.Instance;
                if (asInstance.Flags.HasFlag(ClassFlags.Interface))
                {
                    continue;
                }

                int referencesFound = 0;
                referencesFound += FindMessageReferences(asClass, asClass, asClass.Constructor, -1, 0);
                referencesFound += FindMessageReferences(asClass, asClass.Instance, asClass.Instance.Constructor, -2, 0);

                referencesFound += FindMessageReferences(asClass, asClass);
                referencesFound += FindMessageReferences(asClass, asClass.Instance);
            }   // What to do with the total message reference count in a class?

            int usedOutMsgs   = _messageReferences.Count(msgClass => _isMessageOutgoing[msgClass.Key]);
            int unusedOutMsgs = (OutgoingMessages.Count - usedOutMsgs);
            int usedInMsgs    = (_messageReferences.Count - usedOutMsgs);
            int unusedInMsgs  = (IncomingMessages.Count - usedInMsgs);

            WriteLog($@"Outgoing/Incoming message reference search complete.
Unused Outgoing messages: {unusedOutMsgs}/{OutgoingMessages.Count}
Unused Incoming messages: {unusedInMsgs}/{IncomingMessages.Count}");
        }
Beispiel #3
0
        static string DumpMessages(string type, IDictionary <ushort, ASClass> messages)
        {
            string headerDump = string.Empty;
            bool   isOutgoing = (type == "Outgoing");
            IList <Tuple <ushort, string, ASInstance> > organizedMessages = OrganizeByHash(messages, Client, isOutgoing);

            foreach (Tuple <ushort, string, ASInstance> organizedMessage in organizedMessages)
            {
                ushort     header   = organizedMessage.Item1;
                string     hash     = organizedMessage.Item2;
                ASInstance instance = organizedMessage.Item3;

                string ctorSignature = instance.Constructor.ToString();
                if (!isOutgoing)
                {
                    ASClass parserClass =
                        Client.GetIncomingParser(instance);

                    ctorSignature += (", Parser: " +
                                      parserClass.Instance.Type.ObjName);
                }

                headerDump += $"{type}[{header}]({hash}): {instance.Type.ObjName}{ctorSignature}\r\n";
                CountDuplicates(isOutgoing, hash);
            }
            return(headerDump.Trim());
        }
Beispiel #4
0
        /// <summary>
        /// Injects the specified public RSA keys into the bytecode that handles the verification of the received primes.
        /// </summary>
        /// <param name="exponent">The public exponent.</param>
        /// <param name="modulus">The public modulus.</param>
        public void ReplaceRSAKeys(int exponent, string modulus)
        {
            ABCFile    abc = ABCFiles[2];
            ASInstance habboCommDemoInstance = abc.FindFirstInstanceByName("HabboCommunicationDemo");

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

            ASMethod method          = null;
            int      rsaKeyTypeIndex = abc.Constants.IndexOfMultiname("RSAKey");

            foreach (MethodGetterSetterTrait mgsTrait in mgsTraits)
            {
                if (mgsTrait.Method.ReturnType.Name != "void")
                {
                    continue;
                }
                if (mgsTrait.Method.Parameters.Count != 1)
                {
                    continue;
                }

                if (ContainsOperation(mgsTrait.Method, OPCode.GetLex, rsaKeyTypeIndex))
                {
                    method = mgsTrait.Method;
                    WriteLog($"Found reference to 'RSAKey' in method '{method}'.");
                    break;
                }
            }

            using (var outCode = new FlashWriter())
                using (var inCode = new FlashReader(method.Body.Bytecode))
                {
                    int modulusStringIndex     = abc.Constants.AddString(modulus);
                    int exponentStringIndex    = abc.Constants.AddString(exponent.ToString("x")); // Turn the number to hex, remeber guys, (65537= 10001(hex))
                    int keyObfuscatorTypeIndex = abc.Constants.IndexOfMultiname("KeyObfuscator");

                    // Replace the first 'GetLex[KeyObfuscator]' operation with 'PushString[modulus]'.
                    ReplaceNextOperation(inCode, outCode, method,
                                         OPCode.GetLex, new object[] { keyObfuscatorTypeIndex },
                                         OPCode.PushString, new object[] { modulusStringIndex });

                    // Ignore these operations, do not write.
                    inCode.ReadValuesUntil(OPCode.CallProperty);

                    // Replace the second 'GetLex[KeyObfuscator]' operation with 'PushString[exponent]'.
                    ReplaceNextOperation(inCode, outCode, method,
                                         OPCode.GetLex, new object[] { keyObfuscatorTypeIndex },
                                         OPCode.PushString, new object[] { exponentStringIndex });

                    // Ignore these operations, do not write.
                    inCode.ReadValuesUntil(OPCode.CallProperty);

                    CopyBytecode(inCode, outCode);
                    method.Body.Bytecode = outCode.ToArray();
                }
        }
Beispiel #5
0
        public string ExtractPacketLog(HMessage packet, bool toServer)
        {
            ASInstance messageInstance = (toServer ?
                                          MainUI.ConnectionPg.Game.OutgoingTypes : MainUI.ConnectionPg.Game.IncomingTypes)[packet.Header].Instance;

            string arrow = (toServer ? "->" : "<-");
            string type  = (toServer ? "Outgoing" : "Incoming");

            return($"{type}({packet.Header}, {packet.Length}, {messageInstance.Type.ObjName}) {arrow} {packet}");
        }
Beispiel #6
0
        private ASClass GetMessageParser()
        {
            ABCFile    abc      = Class.GetABC();
            ASInstance instance = Class.Instance;

            ASInstance superInstance = abc.GetInstance(instance.Super);

            if (superInstance == null)
            {
                superInstance = instance;
            }

            ASMethod parserGetterMethod = superInstance.GetGetter("parser")?.Method;

            if (parserGetterMethod == null)
            {
                return(null);
            }

            IEnumerable <ASMethod> methods = instance.GetMethods();

            foreach (ASMethod method in methods.Concat(new[] { instance.Constructor }))
            {
                ASCode code = method.Body.ParseCode();
                foreach (ASInstruction instruction in code)
                {
                    ASMultiname multiname = null;
                    if (instruction.OP == OPCode.FindPropStrict)
                    {
                        var findPropStrictIns = (FindPropStrictIns)instruction;
                        multiname = findPropStrictIns.PropertyName;
                    }
                    else if (instruction.OP == OPCode.GetLex)
                    {
                        var getLexIns = (GetLexIns)instruction;
                        multiname = getLexIns.TypeName;
                    }
                    else
                    {
                        continue;
                    }

                    foreach (ASClass refClass in abc.GetClasses(multiname))
                    {
                        ASInstance refInstance = refClass.Instance;
                        if (refInstance.ContainsInterface(parserGetterMethod.ReturnType.Name))
                        {
                            return(refClass);
                        }
                    }
                }
            }
            return(null);
        }
Beispiel #7
0
        public string ExtractStructureLog(HMessage packet, bool toServer)
        {
            if (!toServer || _invalidStructures[packet.Destination]
                .Contains(packet.Header))
            {
                return(string.Empty);
            }

            ASInstance messageInstance = (toServer ?
                                          MainUI.ConnectionPg.Game.OutgoingTypes : MainUI.ConnectionPg.Game.IncomingTypes)[packet.Header].Instance;

            string   arguments   = $"{{l}}{{u:{packet.Header}}}";
            ASMethod messageCtor = messageInstance.Constructor;

            foreach (ASParameter param in messageCtor.Parameters)
            {
                try
                {
                    arguments += "{";
                    switch (param.Type.ObjName.ToLower())
                    {
                    default:
                        return(string.Empty);

                    case "string":
                        arguments += "s:" + packet.ReadString();
                        break;

                    case "int":
                        arguments += "i:" + packet.ReadInteger();
                        break;

                    case "boolean":
                        arguments += "b:" + packet.ReadBoolean();
                        break;
                    }
                    arguments += "}";
                }
                catch
                {
                    _invalidStructures[packet.Destination]
                    .Add(packet.Header);
                }
            }

            if (packet.Readable != 0)
            {
                arguments = string.Empty;
            }

            packet.Position = 0;
            return(arguments);
        }
Beispiel #8
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);
                }
            }
        }
Beispiel #9
0
        private void WriteMessage(StreamWriter output, MessageItem message)
        {
            ASInstance instance = message.Class.Instance;

            string name           = instance.QName.Name;
            string constructorSig = instance.Constructor.ToAS3(true);

            output.Write($"[{message.Id}, {message.Hash}] = {name}{constructorSig}");
            if (!message.IsOutgoing && message.Parser != null)
            {
                output.Write($"[Parser: {message.Parser.Instance.QName.Name}]");
            }
            output.WriteLine();
        }
Beispiel #10
0
        protected ASMethod FindVerifyMethod(ASInstance instance, ABCFile abc, out int rsaStart)
        {
            List <MethodGetterSetterTrait> methodTraits =
                instance.FindTraits <MethodGetterSetterTrait>(TraitType.Method);

            rsaStart = -1;
            foreach (MethodGetterSetterTrait mgsTrait in methodTraits)
            {
                ASMethod method = mgsTrait.Method;

                if (method.ReturnType.ObjName != "void")
                {
                    continue;
                }
                if (method.Parameters.Count != 1)
                {
                    continue;
                }

                using (var code = new FlashReader(method.Body.Bytecode))
                {
                    while (code.Position != code.Length)
                    {
                        OPCode op = code.ReadOP();
                        if (op != OPCode.GetLex)
                        {
                            continue;
                        }

                        int         typeIndex = code.Read7BitEncodedInt();
                        ASMultiname type      = abc.Constants.Multinames[typeIndex];

                        if (type?.ObjName == "RSAKey")
                        {
                            rsaStart = code.Position;
                            return(method);
                        }
                    }
                }
            }
            return(null);
        }
Beispiel #11
0
        public bool DisableClientEncryption()
        {
            ASInstance rc4 = ABCFiles[2].FindInstanceByName("ArcFour");

            if (rc4 == null)
            {
                ABCFiles[2].FindInstanceByName("RC4");
            }
            if (rc4 == null)
            {
                return(false);
            }

            int modifyCount = 0;

            foreach (ASTrait trait in rc4.Traits)
            {
                if (trait.TraitType != TraitType.Method)
                {
                    continue;
                }
                var rc4Method = ((MethodGetterSetterTrait)trait.Data).Method;

                if (rc4Method.ReturnType.ObjName != "ByteArray")
                {
                    continue;
                }
                if (rc4Method.Parameters.Count != 1)
                {
                    continue;
                }
                if (rc4Method.Parameters[0].Type.ObjName != "ByteArray")
                {
                    continue;
                }

                modifyCount++;
                InsertEarlyReturnLocal(rc4Method, 1);
            }
            return(modifyCount >= 2);
        }
Beispiel #12
0
        public bool DisableExpirationDateCheck()
        {
            ABCFile    abc           = ABCFiles[2];
            ASInstance windowContext = abc.FindInstanceByName("WindowContext");

            if (windowContext == null)
            {
                return(false);
            }

            using (var inCode = new FlashReader(windowContext.Constructor.Body.Bytecode))
                using (var outCode = new FlashWriter())
                {
                    int setLocal11Itterations = 0;
                    while (inCode.Position != inCode.Length)
                    {
                        OPCode op = inCode.ReadOP();
                        outCode.WriteOP(op);
                        if (op != OPCode.SetLocal)
                        {
                            continue;
                        }

                        int setLocalIndex = inCode.Read7BitEncodedInt();
                        outCode.Write7BitEncodedInt(setLocalIndex);
                        if (setLocalIndex != 11 || (++setLocal11Itterations != 2))
                        {
                            continue;
                        }

                        outCode.WriteOP(OPCode.ReturnVoid);
                        outCode.Write(inCode.ToArray(), inCode.Position,
                                      inCode.Length - inCode.Position);

                        windowContext.Constructor.Body.Bytecode = outCode.ToArray();
                        return(true);
                    }
                }
            return(false);
        }
Beispiel #13
0
        private string GetIncomingStructure(ASInstance instance, ASMethod method)
        {
            if (method.Body.Exceptions.Count > 0)
            {
                return(null);
            }

            ASCode code = method.Body.ParseCode();

            if (code.JumpExits.Count > 0 || code.SwitchExits.Count > 0)
            {
                return(null);
            }

            string  structure = null;
            ABCFile abc       = method.GetABC();

            for (int i = 0; i < code.Count; i++)
            {
                ASInstruction instruction = code[i];
                if (instruction.OP != OPCode.GetLocal_1)
                {
                    continue;
                }

                ASInstruction next = code[++i];
                switch (next.OP)
                {
                case OPCode.CallProperty:
                {
                    var callProperty = (CallPropertyIns)next;
                    if (callProperty.ArgCount > 0)
                    {
                        ASMultiname   propertyName = null;
                        ASInstruction previous     = code[i - 2];

                        switch (previous.OP)
                        {
                        case OPCode.GetLex:
                        {
                            var getLex = (GetLexIns)previous;
                            propertyName = getLex.TypeName;
                            break;
                        }

                        case OPCode.ConstructProp:
                        {
                            var constructProp = (ConstructPropIns)previous;
                            propertyName = constructProp.PropertyName;
                            break;
                        }

                        case OPCode.GetLocal_0:
                        {
                            propertyName = instance.QName;
                            break;
                        }
                        }

                        ASInstance innerInstance = abc.GetInstance(propertyName);
                        ASMethod   innerMethod   = innerInstance.GetMethod(callProperty.PropertyName.Name, null, callProperty.ArgCount);
                        if (innerMethod == null)
                        {
                            ASClass innerClass = abc.GetClass(propertyName);
                            innerMethod = innerClass.GetMethod(callProperty.PropertyName.Name, null, callProperty.ArgCount);
                        }

                        string innerStructure = GetIncomingStructure(innerInstance, innerMethod);
                        if (string.IsNullOrWhiteSpace(innerStructure))
                        {
                            return(null);
                        }
                        structure += innerStructure;
                    }
                    else
                    {
                        if (!TryGetStructurePiece(callProperty.PropertyName, null, out char piece))
                        {
                            return(null);
                        }
                        structure += piece;
                    }
                    break;
                }

                case OPCode.ConstructProp:
                {
                    var        constructProp = (ConstructPropIns)next;
                    ASInstance innerInstance = abc.GetInstance(constructProp.PropertyName);

                    string innerStructure = GetIncomingStructure(innerInstance, innerInstance.Constructor);
                    if (string.IsNullOrWhiteSpace(innerStructure))
                    {
                        return(null);
                    }
                    structure += innerStructure;
                    break;
                }

                case OPCode.ConstructSuper:
                {
                    ASInstance superInstance = abc.GetInstance(instance.Super);

                    string innerStructure = GetIncomingStructure(superInstance, superInstance.Constructor);
                    if (string.IsNullOrWhiteSpace(innerStructure))
                    {
                        return(null);
                    }
                    structure += innerStructure;
                    break;
                }

                case OPCode.CallSuper:
                {
                    var        callSuper     = (CallSuperIns)next;
                    ASInstance superInstance = abc.GetInstance(instance.Super);
                    ASMethod   superMethod   = superInstance.GetMethod(callSuper.MethodName.Name, null, callSuper.ArgCount);

                    string innerStructure = GetIncomingStructure(superInstance, superMethod);
                    if (string.IsNullOrWhiteSpace(innerStructure))
                    {
                        return(null);
                    }
                    structure += innerStructure;
                    break;
                }

                case OPCode.CallPropVoid:
                {
                    var callPropVoid = (CallPropVoidIns)next;
                    if (callPropVoid.ArgCount != 0)
                    {
                        return(null);
                    }

                    if (!TryGetStructurePiece(callPropVoid.PropertyName, null, out char piece))
                    {
                        return(null);
                    }
                    structure += piece;
                    break;
                }

                default: return(null);
                }
            }
            return(structure);
        }
Beispiel #14
0
        public void InjectMessageLogger()
        {
            ABCFile    abc             = ABCFiles.Last();
            ASInstance decoderInstance = null;

            foreach (ASInstance instance in abc.Instances)
            {
                if (instance.IsInterface)
                {
                    continue;
                }
                if (instance.Traits.Count != 12)
                {
                    continue;
                }
                if (instance.Constructor.Parameters.Count != 2)
                {
                    continue;
                }
                if (instance.Constructor.Parameters[0].Type.Name != "int")
                {
                    continue;
                }
                if (instance.Constructor.Parameters[1].Type.Name != "ByteArray")
                {
                    continue;
                }

                decoderInstance = instance;
                break;
            }

            var methods = decoderInstance.GetMethods();
            var i       = 0;

            foreach (var method in methods)
            {
                ASCode methodCode = method.Body.ParseCode();

                switch (i)
                {
                case 0:
                    // set header
                    methodCode.InsertRange(methodCode.Count - 1, new ASInstruction[]
                    {
                        new ConvertIIns(),
                        new SetLocal1Ins(),
                        new GetLexIns(abc, abc.Pool.GetMultinameIndex("ExternalInterface")),
                        new PushStringIns(abc, "FlashExternalInterface.logIncomingHeader"),
                        new GetLocal1Ins(),
                        new CallPropVoidIns(abc, abc.Pool.GetMultinameIndex("call"), 2),
                        new GetLocal1Ins()
                    });
                    break;

                case 1:
                    // readString
                    methodCode.InsertRange(methodCode.Count - 1, new ASInstruction[]
                    {
                        new ConvertSIns(),
                        new SetLocal1Ins(),
                        new GetLexIns(abc, abc.Pool.GetMultinameIndex("ExternalInterface")),
                        new PushStringIns(abc, "FlashExternalInterface.logIncoming"),
                        new PushStringIns(abc, "string"),
                        new GetLocal1Ins(),
                        new CallPropVoidIns(abc, abc.Pool.GetMultinameIndex("call"), 3),
                        new GetLocal1Ins()
                    });
                    break;

                case 2:
                    // readInteger
                    methodCode.InsertRange(methodCode.Count - 1, new ASInstruction[]
                    {
                        new ConvertIIns(),
                        new SetLocal1Ins(),
                        new GetLexIns(abc, abc.Pool.GetMultinameIndex("ExternalInterface")),
                        new PushStringIns(abc, "FlashExternalInterface.logIncoming"),
                        new PushStringIns(abc, "integer"),
                        new GetLocal1Ins(),
                        new CallPropVoidIns(abc, abc.Pool.GetMultinameIndex("call"), 3),
                        new GetLocal1Ins()
                    });
                    break;

                case 3:
                    // readBoolean
                    methodCode.InsertRange(methodCode.Count - 1, new ASInstruction[]
                    {
                        new ConvertBIns(),
                        new SetLocal1Ins(),
                        new GetLexIns(abc, abc.Pool.GetMultinameIndex("ExternalInterface")),
                        new PushStringIns(abc, "FlashExternalInterface.logIncoming"),
                        new PushStringIns(abc, "boolean"),
                        new GetLocal1Ins(),
                        new CallPropVoidIns(abc, abc.Pool.GetMultinameIndex("call"), 3),
                        new GetLocal1Ins()
                    });
                    break;

                case 4:
                    // readShort
                    methodCode.InsertRange(methodCode.Count - 1, new ASInstruction[]
                    {
                        new ConvertIIns(),
                        new SetLocal1Ins(),
                        new GetLexIns(abc, abc.Pool.GetMultinameIndex("ExternalInterface")),
                        new PushStringIns(abc, "FlashExternalInterface.logIncoming"),
                        new PushStringIns(abc, "short"),
                        new GetLocal1Ins(),
                        new CallPropVoidIns(abc, abc.Pool.GetMultinameIndex("call"), 3),
                        new GetLocal1Ins()
                    });
                    break;

                case 5:
                    // readByte
                    methodCode.InsertRange(methodCode.Count - 1, new ASInstruction[]
                    {
                        new ConvertIIns(),
                        new SetLocal1Ins(),
                        new GetLexIns(abc, abc.Pool.GetMultinameIndex("ExternalInterface")),
                        new PushStringIns(abc, "FlashExternalInterface.logIncoming"),
                        new PushStringIns(abc, "byte"),
                        new GetLocal1Ins(),
                        new CallPropVoidIns(abc, abc.Pool.GetMultinameIndex("call"), 3),
                        new GetLocal1Ins()
                    });
                    break;

                case 6:
                    // readFloat
                    methodCode.InsertRange(methodCode.Count - 1, new ASInstruction[]
                    {
                        new ConvertDIns(),
                        new SetLocal1Ins(),
                        new GetLexIns(abc, abc.Pool.GetMultinameIndex("ExternalInterface")),
                        new PushStringIns(abc, "FlashExternalInterface.logIncoming"),
                        new PushStringIns(abc, "float"),
                        new GetLocal1Ins(),
                        new CallPropVoidIns(abc, abc.Pool.GetMultinameIndex("call"), 3),
                        new GetLocal1Ins()
                    });
                    break;
                }
                i++;

                method.Body.Code        = methodCode.ToArray();
                method.Body.LocalCount += 2;
                method.Body.MaxStack   += 3;
                Console.WriteLine("Patched function " + i);
            }
        }
Beispiel #15
0
        private void FindMessagesReferences()
        {
            int     classRank = 1;
            ABCFile abc       = ABCFiles.Last();

            foreach (ASClass @class in abc.Classes)
            {
                ASInstance instance = @class.Instance;
                if (_messages.ContainsKey(@class))
                {
                    continue;
                }
                if (instance.Flags.HasFlag(ClassFlags.Interface))
                {
                    continue;
                }

                IEnumerable <ASMethod> methods = (new[] { @class.Constructor, instance.Constructor })
                                                 .Concat(instance.GetMethods())
                                                 .Concat(@class.GetMethods());

                int methodRank = 0;
                foreach (ASMethod fromMethod in methods)
                {
                    bool        isStatic      = (fromMethod.Trait?.IsStatic ?? @class.Constructor == fromMethod);
                    ASContainer fromContainer = (isStatic ? (ASContainer)@class : instance);

                    List <HReference> refernces = FindMessageReferences(@class, fromContainer, fromMethod);
                    if (refernces.Count > 0)
                    {
                        methodRank++;
                    }
                    foreach (HReference reference in refernces)
                    {
                        reference.IsStatic   = isStatic;
                        reference.ClassRank  = classRank;
                        reference.MethodRank = methodRank;
                        reference.GroupCount = refernces.Count;
                    }
                }
                if (methodRank > 0)
                {
                    classRank++;
                }
            }

            Dictionary <ASContainer, List <HReference> > froms = new Dictionary <ASContainer, List <HReference> >();

            foreach (HMessage incomingMsg in InMessages.Values)
            {
                foreach (HReference reference in incomingMsg.References)
                {
                    if (!froms.TryGetValue(reference.FromMethod.Container, out List <HReference> references))
                    {
                        references = new List <HReference>();
                        froms.Add(reference.FromMethod.Container, references);
                    }
                    if (!references.Contains(reference))
                    {
                        references.Add(reference);
                    }
                }
            }

            classRank = 1;
            foreach (ASClass @class in abc.Classes)
            {
                ASContainer container = null;
                if (froms.TryGetValue(@class, out List <HReference> references))
                {
                    container = @class;
                }
                else if (froms.TryGetValue(@class.Instance, out references))
                {
                    container = @class.Instance;
                }
                if (container != null)
                {
                    Dictionary <ASMethod, List <HReference> > methodReferenceGroups = new Dictionary <ASMethod, List <HReference> >();
                    foreach (HReference reference in references)
                    {
                        reference.FromClass       = @class;
                        reference.InstructionRank = -1;
                        reference.ClassRank       = classRank;
                        reference.IsStatic        = container.IsStatic;
                        reference.GroupCount      = references.Count;

                        if (!methodReferenceGroups.TryGetValue(reference.FromMethod, out List <HReference> methodReferences))
                        {
                            methodReferences = new List <HReference>();
                            methodReferenceGroups.Add(reference.FromMethod, methodReferences);
                        }
                        methodReferences.Add(reference);
                    }

                    int methodRank = 1;
                    foreach (ASMethod method in container.GetMethods())
                    {
                        if (methodReferenceGroups.TryGetValue(method, out List <HReference> methodReferences))
                        {
                            foreach (HReference reference in methodReferences)
                            {
                                reference.MethodRank = methodRank;
                            }
                            methodRank++;
                        }
                    }
                    classRank++;
                }
            }
        }
Beispiel #16
0
        /// <summary>
        /// Returns the Incoming message's parser class.
        /// </summary>
        /// <param name="messageClass">The Incoming message class to extract the parser class from.</param>
        /// <returns></returns>
        public ASClass GetIncomingMessageParser(ASClass messageClass)
        {
            if (_messageParsers.ContainsKey(messageClass))
            {
                return(_messageParsers[messageClass]);
            }

            ABCFile    abc = messageClass.ABC;
            ASClass    incomingMsgParserClass = null;
            ASInstance incomingMsgInstance    = messageClass.Instance;

            try
            {
                ASInstance incomingMsgSuperInstance = abc.FindFirstInstanceByName(
                    incomingMsgInstance.SuperType.Name);

                ASMultiname parserReturnType = incomingMsgSuperInstance
                                               .FindFirstGetter("parser", null).ReturnType;

                List <ASMethod> methods =
                    incomingMsgInstance.FindMethodGetterSetterTraits()
                    .Select(mgsTrait => mgsTrait.Method).ToList();

                methods.Add(incomingMsgInstance.Constructor);
                foreach (ASMethod method in methods)
                {
                    var referencedClasses = new List <ASClass>();
                    using (var inCode = new FlashReader(method.Body.Bytecode))
                    {
                        while (inCode.IsDataAvailable)
                        {
                            OPCode   op     = 0;
                            object[] values = inCode.ReadValuesUntilEither(out op, OPCode.FindPropStrict, OPCode.GetLex);
                            if (values == null)
                            {
                                break;
                            }

                            var         typeIndex = (int)values[0];
                            ASMultiname type      = abc.Constants.Multinames[typeIndex];

                            List <ASClass> instances = abc.FindClassesByName(type.Name);
                            referencedClasses.AddRange(instances);
                        }
                    }
                    foreach (ASClass referencedClass in referencedClasses)
                    {
                        ASInstance referencedInstance = referencedClass.Instance;
                        if (referencedInstance.ContainsInterface(parserReturnType.Name))
                        {
                            incomingMsgParserClass = referencedClass;
                            return(incomingMsgParserClass);
                        }
                    }
                }
            }
            finally
            {
                if (incomingMsgParserClass != null)
                {
                    _messageParsers[messageClass] =
                        incomingMsgParserClass;
                }
            }
            return(incomingMsgParserClass);
        }
Beispiel #17
0
        private PacketValue[] GetIncomingStructure(ASInstance instance, ASMethod method)
        {
            if (method.Body.Exceptions.Count > 0)
            {
                return(null);
            }

            ASCode code = method.Body.ParseCode();

            if (code.JumpExits.Count > 0 || code.SwitchExits.Count > 0)
            {
                return(null);
            }

            List <PacketValue> structure = new List <PacketValue>();
            ABCFile            abc       = method.GetABC();

            for (int i = 0; i < code.Count; i++)
            {
                ASInstruction instruction = code[i];
                if (instruction.OP != OPCode.GetLocal_1)
                {
                    continue;
                }

                ASInstruction next = code[++i];
                switch (next.OP)
                {
                case OPCode.CallProperty:
                {
                    CallPropertyIns callProperty = (CallPropertyIns)next;
                    if (callProperty.ArgCount > 0)
                    {
                        ASMultiname   propertyName = null;
                        ASInstruction previous     = code[i - 2];

                        switch (previous.OP)
                        {
                        case OPCode.GetLex:
                        {
                            GetLexIns getLex = (GetLexIns)previous;
                            propertyName = getLex.TypeName;
                            break;
                        }

                        case OPCode.ConstructProp:
                        {
                            ConstructPropIns constructProp = (ConstructPropIns)previous;
                            propertyName = constructProp.PropertyName;
                            break;
                        }

                        case OPCode.GetLocal_0:
                        {
                            propertyName = instance.QName;
                            break;
                        }
                        }

                        ASInstance innerInstance = abc.GetInstance(propertyName);
                        ASMethod   innerMethod   = innerInstance.GetMethod(callProperty.PropertyName.Name, null, callProperty.ArgCount);
                        if (innerMethod == null)
                        {
                            ASClass innerClass = abc.GetClass(propertyName);
                            innerMethod = innerClass.GetMethod(callProperty.PropertyName.Name, null, callProperty.ArgCount);
                        }

                        PacketValue[] innerStructure = GetIncomingStructure(innerInstance, innerMethod);
                        if (innerStructure == null)
                        {
                            return(null);
                        }
                        structure.AddRange(innerStructure);
                    }
                    else
                    {
                        if (!TryGetPacketValue(callProperty.PropertyName, null, out PacketValue piece))
                        {
                            return(null);
                        }
                        structure.Add(piece);
                    }
                    break;
                }

                case OPCode.ConstructProp:
                {
                    ConstructPropIns constructProp = (ConstructPropIns)next;
                    ASInstance       innerInstance = abc.GetInstance(constructProp.PropertyName);

                    PacketValue[] innerStructure = GetIncomingStructure(innerInstance, innerInstance.Constructor);
                    if (innerStructure == null)
                    {
                        return(null);
                    }
                    structure.AddRange(innerStructure);
                    break;
                }

                case OPCode.ConstructSuper:
                {
                    ASInstance superInstance = abc.GetInstance(instance.Super);

                    PacketValue[] innerStructure = GetIncomingStructure(superInstance, superInstance.Constructor);
                    if (innerStructure == null)
                    {
                        return(null);
                    }
                    structure.AddRange(innerStructure);
                    break;
                }

                case OPCode.CallSuper:
                {
                    CallSuperIns callSuper     = (CallSuperIns)next;
                    ASInstance   superInstance = abc.GetInstance(instance.Super);
                    ASMethod     superMethod   = superInstance.GetMethod(callSuper.MethodName.Name, null, callSuper.ArgCount);

                    PacketValue[] innerStructure = GetIncomingStructure(superInstance, superMethod);
                    if (innerStructure == null)
                    {
                        return(null);
                    }
                    structure.AddRange(innerStructure);
                    break;
                }

                case OPCode.CallPropVoid:
                {
                    CallPropVoidIns callPropVoid = (CallPropVoidIns)next;
                    if (callPropVoid.ArgCount != 0)
                    {
                        return(null);
                    }

                    if (!TryGetPacketValue(callPropVoid.PropertyName, null, out PacketValue piece))
                    {
                        return(null);
                    }
                    structure.Add(piece);
                    break;
                }

                default: return(null);
                }
            }
            return(structure.Count == 0 ? null : structure.ToArray());
        }
Beispiel #18
0
        /// <summary>
        /// Modifies the bytecode to allow the client to connect to anywhere.
        /// </summary>
        public void BypassRemoteHostCheck()
        {
            ABCFile    abc           = ABCFiles[2];
            ASInstance habboCommMngr = abc.FindFirstInstanceByName("HabboCommunicationManager");

            if (habboCommMngr == null)
            {
                return;
            }

            int    hostValueSlotObjTypeIndex = -1;
            string hostValueSlotObjName      = string.Empty;

            foreach (ASTrait trait in habboCommMngr.Traits)
            {
                if (trait.TraitType != TraitType.Slot)
                {
                    continue;
                }
                if (((SlotConstantTrait)trait.Data).TypeName.Name != "String")
                {
                    continue;
                }

                hostValueSlotObjName      = trait.Name.Name;
                hostValueSlotObjTypeIndex = trait.NameIndex;
                break;
            }

            ASMethod initCompMethod = habboCommMngr
                                      .FindFirstMethod("initComponent", "void");

            int getPropertyObjTypeIndex = abc.Constants
                                          .IndexOfMultiname("getProperty");

            ASMethod initConnectionMethod = null;

            using (var outCode = new FlashWriter())
                using (var inCode = new FlashReader(initCompMethod.Body.Bytecode))
                {
                    object[] values = inCode.ReadValuesUntil(OPCode.CallPropVoid, null, 0);

                    if (values == null)
                    {
                        return;
                    }
                    CopyBytecode(inCode, outCode, 0, inCode.Position);

                    outCode.WriteOP(OPCode.GetLocal_0);
                    outCode.WriteOP(OPCode.FindPropStrict, getPropertyObjTypeIndex);
                    outCode.WriteOP(OPCode.PushString, abc.Constants.AddString("connection.info.host"));
                    outCode.WriteOP(OPCode.CallProperty, getPropertyObjTypeIndex, 1);
                    outCode.WriteOP(OPCode.InitProperty, hostValueSlotObjTypeIndex);
                    WriteLog($"Method '{initCompMethod}' modified to include '{hostValueSlotObjName} = getProperty(\"connection.info.host\");'.");

                    CopyBytecode(inCode, outCode);
                    initCompMethod.Body.Bytecode = outCode.ToArray();

                    values = inCode.ReadValuesUntil(OPCode.CallPropVoid);
                    ASMultiname callPropVoidType = abc.Constants.Multinames[(int)values[0]];
                    initConnectionMethod = habboCommMngr.FindFirstMethod(callPropVoidType.Name, "void");
                }

            using (var outCode = new FlashWriter())
                using (var inCode = new FlashReader(initConnectionMethod.Body.Bytecode))
                {
                    int  ifNeCount          = 0;
                    int  byteJumpCountPos   = 0;
                    int  differenceOffset   = 0;
                    uint byteJumpCountValue = 0;
                    int  magicNumberIndex   = abc.Constants.AddInteger(65290);
                    while (inCode.IsDataAvailable)
                    {
                        OPCode   op     = inCode.ReadOP();
                        object[] values = null;

                        if (op != OPCode.PushInt)
                        {
                            values = inCode.ReadValues(op);
                            outCode.WriteOP(op, values);

                            if (op == OPCode.IfNe &&
                                (++ifNeCount == 2 || ifNeCount == 4))
                            {
                                byteJumpCountPos   = (outCode.Position - 3);
                                byteJumpCountValue = (uint)values[0];
                            }
                            continue;
                        }

                        bool isFinalPushInt = false;
                        int  pushIntIndex   = inCode.Read7BitEncodedInt();
                        int  pushIntValue   = abc.Constants.Integers[pushIntIndex];
                        #region Switch: pushIntValue
                        switch (pushIntValue)
                        {
                        case 65244: //97
                        case 65185: //32
                        case 65191: //175
                        case 65189: //123
                        case 65188: //164
                        case 65174: //45
                        case 65238: //297
                        case 65184: //127
                        case 65171: //20
                        case 65172: //58
                        {
                            pushIntIndex   = magicNumberIndex;
                            isFinalPushInt = (pushIntValue == 65172);
                            break;
                        }
                        }
                        #endregion
                        outCode.WriteOP(op, pushIntIndex);

                        int byteDifference = (((inCode.Position - outCode.Length) * -1) - differenceOffset);
                        if (isFinalPushInt)
                        {
                            int curPos = outCode.Position;
                            differenceOffset += byteDifference;

                            outCode.Position = byteJumpCountPos;
                            outCode.WriteS24(byteJumpCountValue + (uint)byteDifference);
                            outCode.Position = curPos;

                            if (ifNeCount == 4)
                            {
                                CopyBytecode(inCode, outCode);
                                initConnectionMethod.Body.Bytecode = outCode.ToArray();
                                WriteLog($"Method '{initConnectionMethod}' modified to not append suffix to the host value.");
                                return;
                            }
                        }
                    }
                }
        }
Beispiel #19
0
        public ASClass GetIncomingParser(ASInstance incomingInstance)
        {
            if (_incomingParsersCache.ContainsKey(incomingInstance))
            {
                return(_incomingParsersCache[incomingInstance]);
            }

            ASClass parserClass = null;
            ABCFile abc         = incomingInstance.ABC;

            try
            {
                using (var codeOut = new FlashReader(
                           incomingInstance.Constructor.Body.Bytecode))
                {
                    while (codeOut.IsDataAvailable)
                    {
                        OPCode   op     = codeOut.ReadOP();
                        object[] values = codeOut.ReadValues(op);
                        if (op != OPCode.GetLex)
                        {
                            continue;
                        }

                        var         getLexIndex = (int)values[0];
                        ASMultiname getLexName  = abc.Constants.Multinames[getLexIndex];
                        parserClass = abc.FindClassByName(getLexName.ObjName);
                        if (parserClass != null)
                        {
                            return(parserClass);
                        }
                        break;
                    }
                }

                ASInstance incomingSuperInstance = abc.FindInstanceByName(
                    incomingInstance.SuperType.ObjName);

                ASMultiname parserReturnType = incomingSuperInstance
                                               .FindGetter("parser").Method.ReturnType;

                SlotConstantTrait parserSlot = incomingSuperInstance
                                               .FindSlot("*", parserReturnType.ObjName);

                foreach (ASTrait trait in incomingInstance.Traits)
                {
                    if (trait.TraitType != TraitType.Method)
                    {
                        continue;
                    }

                    var mgsTrait = (MethodGetterSetterTrait)trait.Data;
                    if (mgsTrait.Method.Parameters.Count != 0)
                    {
                        continue;
                    }

                    using (var codeOut = new FlashReader(
                               mgsTrait.Method.Body.Bytecode))
                    {
                        while (codeOut.IsDataAvailable)
                        {
                            OPCode   op     = codeOut.ReadOP();
                            object[] values = codeOut.ReadValues(op);
                            if (op != OPCode.GetLex)
                            {
                                continue;
                            }

                            var         getLexIndex = (int)values[0];
                            ASMultiname getLexType  = abc.Constants.Multinames[getLexIndex];
                            if (getLexType.ObjName != parserSlot.ObjName)
                            {
                                continue;
                            }

                            parserClass = abc.FindClassByName(mgsTrait.Method.ReturnType.ObjName);
                            if (parserClass != null)
                            {
                                return(parserClass);
                            }
                            break;
                        }
                    }
                }
                return(parserClass);
            }
            finally
            {
                if (parserClass != null)
                {
                    _incomingParsersCache[incomingInstance] = parserClass;
                }
            }
        }
Beispiel #20
0
        public bool BypassRemoteHostCheck()
        {
            ABCFile    abc         = ABCFiles[2];
            ASInstance commManager = abc.FindInstanceByName("HabboCommunicationManager");

            if (commManager == null)
            {
                return(false);
            }

            // The "host" value is always the first slot, for now.
            string hostValueSlotName = commManager.FindTraits <SlotConstantTrait>(TraitType.Slot)
                                       .Where(t => t.Type.ObjName == "String").ToArray()[0].ObjName;

            ASMethod initComponent = commManager.FindMethod("initComponent", "void").Method;

            if (initComponent == null)
            {
                return(false);
            }

            using (var inCode = new FlashReader(initComponent.Body.Bytecode))
                using (var outCode = new FlashWriter(inCode.Length))
                {
                    int hostSlotIndex = abc.Constants.IndexOfMultiname(hostValueSlotName);
                    while (inCode.Position != inCode.Length)
                    {
                        OPCode op = inCode.ReadOP();
                        outCode.WriteOP(op);
                        if (op != OPCode.GetLocal_0)
                        {
                            continue;
                        }

                        op = inCode.ReadOP();
                        outCode.WriteOP(op);
                        if (op != OPCode.CallPropVoid)
                        {
                            continue;
                        }

                        int callPropVoidIndex = inCode.Read7BitEncodedInt();
                        outCode.Write7BitEncodedInt(callPropVoidIndex);

                        int callPropVoidArgCount = inCode.Read7BitEncodedInt();
                        outCode.Write7BitEncodedInt(callPropVoidArgCount);

                        if (callPropVoidArgCount != 0)
                        {
                            continue;
                        }

                        int getPropertyNameIndex = abc.Constants
                                                   .IndexOfMultiname("getProperty");

                        outCode.WriteOP(OPCode.GetLocal_0);
                        outCode.WriteOP(OPCode.FindPropStrict);
                        outCode.Write7BitEncodedInt(getPropertyNameIndex);

                        outCode.WriteOP(OPCode.PushString);
                        outCode.Write7BitEncodedInt(abc.Constants.AddString("connection.info.host"));

                        outCode.WriteOP(OPCode.CallProperty);
                        outCode.Write7BitEncodedInt(getPropertyNameIndex);
                        outCode.Write7BitEncodedInt(1);

                        outCode.WriteOP(OPCode.InitProperty);
                        outCode.Write7BitEncodedInt(hostSlotIndex);

                        outCode.Write(inCode.ToArray(),
                                      inCode.Position, inCode.Length - inCode.Position);

                        do
                        {
                            op = inCode.ReadOP();
                        }while (op != OPCode.CallPropVoid);

                        callPropVoidIndex = inCode.Read7BitEncodedInt();
                        ASMultiname callPropVoidName = abc.Constants.Multinames[callPropVoidIndex];
                        ASMethod    connectMethod    = commManager.FindMethod(callPropVoidName.ObjName, "void").Method;
                        RemoveHostSuffix(abc, connectMethod);

                        initComponent.Body.Bytecode = outCode.ToArray();
                        return(true);
                    }
                }
            return(false);
        }
Beispiel #21
0
        public bool ReplaceRSA(int exponent, string modulus)
        {
            ABCFile abc          = ABCFiles[2];
            int     modulusIndex = abc.Constants.AddString(modulus);

            int exponentIndex = abc.Constants
                                .AddString(exponent.ToString("x"));

            int        rsaStart  = 0;
            ASInstance commClass = abc.FindInstanceByName("HabboCommunicationDemo");
            ASMethod   verifier  = FindVerifyMethod(commClass, abc, out rsaStart);

            using (var inCode = new FlashReader(verifier.Body.Bytecode))
                using (var outCode = new FlashWriter(inCode.Length))
                {
                    bool searchingKeys = true;
                    inCode.Position = rsaStart;
                    outCode.Write(inCode.ToArray(), 0, rsaStart);

                    while (inCode.Position != inCode.Length)
                    {
                        byte codeByte = inCode.ReadByte();
                        outCode.Write(codeByte);

                        if (!searchingKeys)
                        {
                            outCode.Write(inCode.ToArray(),
                                          inCode.Position, inCode.Length - inCode.Position);

                            break;
                        }
                        switch ((OPCode)codeByte)
                        {
                        case OPCode.GetLex:
                        {
                            outCode.Position--;
                            outCode.WriteOP(OPCode.PushString);

                            int         typeIndex = inCode.Read7BitEncodedInt();
                            ASMultiname type      = abc.Constants.Multinames[typeIndex];

                            inCode.ReadOP();
                            inCode.Read7BitEncodedInt();
                            inCode.Read7BitEncodedInt();

                            if (modulusIndex > 0)
                            {
                                outCode.Write7BitEncodedInt(modulusIndex);
                                modulusIndex = -1;
                            }
                            else if (searchingKeys)
                            {
                                outCode.Write7BitEncodedInt(exponentIndex);
                                searchingKeys = false;
                            }
                            break;
                        }

                        case OPCode.PushString:
                        {
                            int    stringIndex = inCode.Read7BitEncodedInt();
                            string value       = abc.Constants.Strings[stringIndex];

                            if (string.IsNullOrWhiteSpace(Modulus))
                            {
                                Modulus = value;
                                outCode.Write7BitEncodedInt(modulusIndex);
                            }
                            else if (string.IsNullOrWhiteSpace(Exponent))
                            {
                                Exponent = value;
                                outCode.Write7BitEncodedInt(exponentIndex);

                                searchingKeys = false;
                            }
                            break;
                        }

                        default: continue;
                        }
                    }

                    verifier.Body.Bytecode = outCode.ToArray();
                    if (!searchingKeys)
                    {
                        return(true);
                    }
                }
            return(false);
        }