Exemplo n.º 1
0
        private PacketValue[] GetOutgoingStructure(ASCode code, Local getLocal)
        {
            List <PacketValue> structure = new List <PacketValue>();

            for (int i = 0; i < code.Count; i++)
            {
                ASInstruction instruction = code[i];
                if (instruction == getLocal)
                {
                    break;
                }
                if (!Local.IsGetLocal(instruction.OP))
                {
                    continue;
                }

                Local local = (Local)instruction;
                if (local.Register != getLocal.Register)
                {
                    continue;
                }

                for (i += 1; i < code.Count; i++)
                {
                    ASInstruction next = code[i];
                    if (next.OP != OPCode.CallPropVoid)
                    {
                        continue;
                    }

                    CallPropVoidIns callPropVoid = (CallPropVoidIns)next;
                    if (callPropVoid.PropertyName.Name != "push")
                    {
                        continue;
                    }

                    ASInstruction previous = code[i - 1];
                    if (previous.OP == OPCode.GetProperty)
                    {
                        ASClass        classToCheck = Class;
                        GetPropertyIns getProperty  = (GetPropertyIns)previous;
                        ASMultiname    propertyName = getProperty.PropertyName;

                        ASInstruction beforeGetProp = code[i - 2];
                        if (beforeGetProp.OP == OPCode.GetLex)
                        {
                            GetLexIns getLex = (GetLexIns)beforeGetProp;
                            classToCheck = classToCheck.GetABC().GetClass(getLex.TypeName);
                        }

                        if (!TryGetPacketValue(propertyName, classToCheck, out PacketValue piece))
                        {
                            return(null);
                        }
                        structure.Add(piece);
                    }
                }
            }
            return(structure.Count == 0 ? null : structure.ToArray());
        }
Exemplo n.º 2
0
        private string GetOutgoingStructure(ASCode code, Local getLocal)
        {
            string structure = null;

            for (int i = 0; i < code.Count; i++)
            {
                ASInstruction instruction = code[i];
                if (instruction == getLocal)
                {
                    break;
                }
                if (!Local.IsGetLocal(instruction.OP))
                {
                    continue;
                }

                var local = (Local)instruction;
                if (local.Register != getLocal.Register)
                {
                    continue;
                }

                for (i += 1; i < code.Count; i++)
                {
                    ASInstruction next = code[i];
                    if (next.OP != OPCode.CallPropVoid)
                    {
                        continue;
                    }

                    var callPropVoid = (CallPropVoidIns)next;
                    if (callPropVoid.PropertyName.Name != "push")
                    {
                        continue;
                    }

                    ASInstruction previous = code[i - 1];
                    if (previous.OP == OPCode.GetProperty)
                    {
                        ASClass     classToCheck = Class;
                        var         getProperty  = (GetPropertyIns)previous;
                        ASMultiname propertyName = getProperty.PropertyName;

                        ASInstruction beforeGetProp = code[i - 2];
                        if (beforeGetProp.OP == OPCode.GetLex)
                        {
                            var getLex = (GetLexIns)beforeGetProp;
                            classToCheck = classToCheck.GetABC().GetClass(getLex.TypeName);
                        }

                        if (!TryGetStructurePiece(propertyName, classToCheck, out char piece))
                        {
                            return(null);
                        }
                        structure += piece;
                    }
                }
            }
            return(structure);
        }
Exemplo n.º 3
0
        public ASCode ParseCode(bool ignoreCache = false)
        {
            if (_cachedCode != null && !ignoreCache)
            {
                return(_cachedCode);
            }

            return(_cachedCode = new ASCode(ABC, this));
        }
Exemplo n.º 4
0
        private void LoadMessages()
        {
            ABCFile abc = ABCFiles.Last();
            ASClass habboMessagesClass = abc.GetClass("HabboMessages");

            if (habboMessagesClass == null)
            {
                IsPostShuffle = false;
                foreach (ASClass @class in abc.Classes)
                {
                    if (@class.Traits.Count != 2 || @class.Traits[0].Type?.Name != "Map" || @class.Traits[1].Type?.Name != "Map")
                    {
                        continue;
                    }
                    if (@class.Instance.Traits.Count != 2)
                    {
                        continue;
                    }

                    habboMessagesClass = @class;
                    break;
                }
                if (habboMessagesClass == null)
                {
                    return;
                }
            }

            ASCode code            = habboMessagesClass.Constructor.Body.ParseCode();
            int    outMapTypeIndex = habboMessagesClass.Traits[1].QNameIndex;

            ASInstruction[] instructions = code
                                           .Where(i => i.OP == OPCode.GetLex ||
                                                  i.OP == OPCode.PushShort ||
                                                  i.OP == OPCode.PushByte).ToArray();

            for (int i = 0; i < instructions.Length; i += 3)
            {
                GetLexIns getLexInst = instructions[i + 0] as GetLexIns;
                bool      isOutgoing = getLexInst?.TypeNameIndex == outMapTypeIndex;

                Primitive primitive = instructions[i + 1] as Primitive;
                ushort    id        = Convert.ToUInt16(primitive?.Value);

                getLexInst = instructions[i + 2] as GetLexIns;
                ASClass messageClass = abc.GetClass(getLexInst?.TypeName.Name);

                HMessage message = new HMessage(id, isOutgoing, messageClass);
                (isOutgoing ? OutMessages : InMessages).Add(id, message);

                if (!_messages.ContainsKey(messageClass))
                {
                    _messages.Add(messageClass, message);
                }
            }
        }
Exemplo n.º 5
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);
        }
Exemplo n.º 6
0
        public static int IndexOf(this ASCode code, int startIndex, OPCode op)
        {
            for (var i = startIndex; i < code.Count; i++)
            {
                if (code[i].OP == op)
                {
                    return(i);
                }
            }

            return(-1);
        }
Exemplo n.º 7
0
        public static int LastIndexOf(this ASCode code, int startIndex, OPCode op)
        {
            for (var i = startIndex; i >= 0; i--)
            {
                if (code[i].OP == op)
                {
                    return(i);
                }
            }

            return(-1);
        }
Exemplo n.º 8
0
        public static int LastIndexOf(this ASCode code, OPCode op)
        {
            for (var i = code.Count - 1; i >= 0; i--)
            {
                if (code[i].OP == op)
                {
                    return(i);
                }
            }

            return(-1);
        }
Exemplo n.º 9
0
        public void Write(ASMethod method)
        {
            Write(method.IsConstructor);
            if (!method.IsConstructor)
            {
                Write(method.ReturnType);
            }
            Write(method.Parameters.Count);
            foreach (ASParameter parameter in method.Parameters)
            {
                Write(parameter.Type);
                if (!string.IsNullOrWhiteSpace(parameter.Name) &&
                    HGame.IsValidIdentifier(parameter.Name, true))
                {
                    Write(parameter.Name);
                }
                Write(parameter.IsOptional);
                if (parameter.IsOptional)
                {
                    Write((byte)parameter.ValueKind);
                    Write(parameter.ValueKind, parameter.Value);
                }
            }
            ASCode code = method.Body.ParseCode();

            foreach (OPCode op in code.GetOPGroups().Keys)
            {
                if (op != OPCode.GetLex &&
                    op != OPCode.GetProperty &&
                    op != OPCode.CallProperty)
                {
                    continue;
                }

                Write((byte)op);
            }
        }
Exemplo n.º 10
0
        public ASMethodBody(ABCFile abc, FlashReader reader)
        {
            _abc = abc;

            MethodIndex = reader.Read7BitEncodedInt();

            MaxStack = reader.Read7BitEncodedInt();
            LocalCount = reader.Read7BitEncodedInt();
            InitialScopeDepth = reader.Read7BitEncodedInt();
            MaxScopeDepth = reader.Read7BitEncodedInt();

            Code = new ASCode(abc, this,
                reader.ReadBytes(reader.Read7BitEncodedInt()));

            Exceptions = new List<ASException>(reader.Read7BitEncodedInt());
            for (int i = 0; i < Exceptions.Capacity; i++)
                Exceptions.Add(new ASException(abc, reader));

            Traits = new List<ASTrait>(reader.Read7BitEncodedInt());
            for (int i = 0; i < Traits.Capacity; i++)
                Traits.Add(new ASTrait(abc, reader));

            Method.Body = this;
        }
Exemplo n.º 11
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);
        }
Exemplo n.º 12
0
        private PacketValue[] GetOutgoingStructure(ASCode code, ASInstruction beforeReturn, int length)
        {
            int getLocalEndIndex = -1;
            int pushingEndIndex  = code.IndexOf(beforeReturn);

            PacketValue[]         structure    = new PacketValue[length];
            Dictionary <int, int> pushedLocals = new Dictionary <int, int>();

            for (int i = pushingEndIndex - 1; i >= 0; i--)
            {
                ASInstruction instruction = code[i];
                if (instruction.OP == OPCode.GetProperty)
                {
                    ASClass        classToCheck = Class;
                    GetPropertyIns getProperty  = (GetPropertyIns)instruction;
                    ASMultiname    propertyName = getProperty.PropertyName;

                    ASInstruction previous = code[i - 1];
                    if (previous.OP == OPCode.GetLex)
                    {
                        GetLexIns getLex = (GetLexIns)previous;
                        classToCheck = classToCheck.GetABC().GetClass(getLex.TypeName);
                    }

                    if (!TryGetPacketValue(propertyName, classToCheck, out PacketValue piece))
                    {
                        return(null);
                    }
                    structure[--length] = piece;
                }
                else if (Local.IsGetLocal(instruction.OP) &&
                         instruction.OP != OPCode.GetLocal_0)
                {
                    Local local = (Local)instruction;
                    pushedLocals.Add(local.Register, --length);
                    if (getLocalEndIndex == -1)
                    {
                        getLocalEndIndex = i;
                    }
                }
                if (length == 0)
                {
                    break;
                }
            }
            for (int i = getLocalEndIndex - 1; i >= 0; i--)
            {
                ASInstruction instruction = code[i];
                if (!Local.IsSetLocal(instruction.OP))
                {
                    continue;
                }

                Local local = (Local)instruction;
                if (pushedLocals.TryGetValue(local.Register, out int structIndex))
                {
                    ASInstruction beforeSet = code[i - 1];
                    pushedLocals.Remove(local.Register);
                    switch (beforeSet.OP)
                    {
                    case OPCode.PushInt:
                    case OPCode.PushByte:
                    case OPCode.Convert_i:
                        structure[structIndex] = PacketValue.Integer;
                        break;

                    case OPCode.Coerce_s:
                    case OPCode.PushString:
                        structure[structIndex] = PacketValue.String;
                        break;

                    case OPCode.PushTrue:
                    case OPCode.PushFalse:
                        structure[structIndex] = PacketValue.Boolean;
                        break;

                    default:
                        throw new Exception($"Don't know what this value type is, tell someone about this please.\r\nOP: {beforeSet.OP}");
                    }
                }
                if (pushedLocals.Count == 0)
                {
                    break;
                }
            }
            return(structure);
        }
Exemplo n.º 13
0
        private PacketValue[] GetOutgoingStructure(ASClass @class, ASMultiname propertyName)
        {
            ASMethod constructor = @class.Instance.Constructor;

            if (constructor.Body.Exceptions.Count > 0)
            {
                return(null);
            }

            ASCode code = constructor.Body.ParseCode();

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

            List <PacketValue> structure = new List <PacketValue>();

            for (int i = 0; i < code.Count; i++)
            {
                ASInstruction instruction = code[i];
                if (instruction.OP == OPCode.NewArray)
                {
                    NewArrayIns newArray = (NewArrayIns)instruction;
                    if (newArray.ArgCount > 0)
                    {
                        PacketValue[] structurePieces = new PacketValue[newArray.ArgCount];
                        for (int j = i - 1, length = newArray.ArgCount; j >= 0; j--)
                        {
                            ASInstruction previous = code[j];
                            if (Local.IsGetLocal(previous.OP) && previous.OP != OPCode.GetLocal_0)
                            {
                                Local       local     = (Local)previous;
                                ASParameter parameter = constructor.Parameters[local.Register - 1];

                                if (!TryGetPacketValue(parameter.Type, null, out PacketValue piece))
                                {
                                    return(null);
                                }
                                structurePieces[--length] = piece;
                            }
                            if (length == 0)
                            {
                                structure.AddRange(structurePieces);
                                break;
                            }
                        }
                    }
                }
                else if (instruction.OP == OPCode.ConstructSuper)
                {
                    ConstructSuperIns constructSuper = (ConstructSuperIns)instruction;
                    if (constructSuper.ArgCount > 0)
                    {
                        ASClass superClass = @class.GetABC().GetClass(@class.Instance.Super);
                        structure.AddRange(GetOutgoingStructure(superClass, propertyName));
                    }
                }
                if (instruction.OP != OPCode.GetProperty)
                {
                    continue;
                }

                GetPropertyIns getProperty = (GetPropertyIns)instruction;
                if (getProperty.PropertyName != propertyName)
                {
                    continue;
                }

                ASInstruction next         = code[++i];
                ASClass       classToCheck = @class;
                if (Local.IsGetLocal(next.OP))
                {
                    if (next.OP == OPCode.GetLocal_0)
                    {
                        continue;
                    }

                    Local       local     = (Local)next;
                    ASParameter parameter = constructor.Parameters[local.Register - 1];

                    if (!TryGetPacketValue(parameter.Type, null, out PacketValue piece))
                    {
                        return(null);
                    }
                    structure.Add(piece);
                }
                else
                {
                    if (next.OP == OPCode.FindPropStrict)
                    {
                        classToCheck = null;
                    }
                    else if (next.OP == OPCode.GetLex)
                    {
                        GetLexIns getLex = (GetLexIns)next;
                        classToCheck = classToCheck.GetABC().GetClass(getLex.TypeName);
                    }
                    do
                    {
                        next         = code[++i];
                        propertyName = null;
                        if (next.OP == OPCode.GetProperty)
                        {
                            getProperty  = (GetPropertyIns)next;
                            propertyName = getProperty.PropertyName;
                        }
                        else if (next.OP == OPCode.CallProperty)
                        {
                            CallPropertyIns callProperty = (CallPropertyIns)next;
                            propertyName = callProperty.PropertyName;
                        }
                    }while (next.OP != OPCode.GetProperty && next.OP != OPCode.CallProperty);

                    if (!TryGetPacketValue(propertyName, classToCheck, out PacketValue piece))
                    {
                        return(null);
                    }
                    structure.Add(piece);
                }
            }
            return(structure.Count == 0 ? null : structure.ToArray());
        }
Exemplo n.º 14
0
 protected void RemoveDeadFalseConditions(ASCode code)
 {
     using (var inCode = new FlashReader(code.ToArray()))
     using (var outCode = new FlashWriter(inCode.Length))
     {
         while (inCode.Position != inCode.Length)
         {
             OPCode op = inCode.ReadOP();
             if (op != OPCode.PushFalse)
             {
                 outCode.WriteOP(op);
                 continue;
             }
             op = inCode.ReadOP();
             if (op != OPCode.PushFalse)
             {
                 outCode.WriteOP(OPCode.PushFalse);
                 outCode.WriteOP(op);
                 continue;
             }
             op = inCode.ReadOP();
             if (op != OPCode.IfNe)
             {
                 outCode.WriteOP(OPCode.PushFalse);
                 outCode.WriteOP(OPCode.PushFalse);
                 outCode.WriteOP(op);
                 continue;
             }
             else inCode.ReadS24();
         }
         code.Clear();
         code.AddRange(outCode.ToArray());
     }
 }
Exemplo n.º 15
0
        private PacketValue[] GetOutgoingStructure(ASClass @class)
        {
            ASMethod getArrayMethod = @class.Instance.GetMethod(null, "Array", 0);

            if (getArrayMethod == null)
            {
                ASClass superClass = @class.GetABC().GetClass(@class.Instance.Super);
                return(GetOutgoingStructure(superClass));
            }
            if (getArrayMethod.Body.Exceptions.Count > 0)
            {
                return(null);
            }
            ASCode getArrayCode = getArrayMethod.Body.ParseCode();

            if (getArrayCode.JumpExits.Count > 0 || getArrayCode.SwitchExits.Count > 0)
            {
                // Unable to parse data structure that relies on user input that is not present,
                // since the structure may change based on the provided input.
                return(null);
            }

            ASInstruction resultPusher = null;

            for (int i = getArrayCode.Count - 1; i >= 0; i--)
            {
                ASInstruction instruction = getArrayCode[i];
                if (instruction.OP == OPCode.ReturnValue)
                {
                    resultPusher = getArrayCode[i - 1];
                    break;
                }
            }

            int argCount = -1;

            if (resultPusher.OP == OPCode.ConstructProp)
            {
                argCount = ((ConstructPropIns)resultPusher).ArgCount;
            }
            else if (resultPusher.OP == OPCode.NewArray)
            {
                argCount = ((NewArrayIns)resultPusher).ArgCount;
            }

            if (argCount > 0)
            {
                return(GetOutgoingStructure(getArrayCode, resultPusher, argCount));
            }

            if (argCount == 0 || resultPusher.OP == OPCode.PushNull)
            {
                return(null);
            }

            if (resultPusher.OP == OPCode.GetProperty)
            {
                GetPropertyIns getProperty = (GetPropertyIns)resultPusher;
                return(GetOutgoingStructure(Class, getProperty.PropertyName));
            }

            return(Local.IsGetLocal(resultPusher.OP) ?
                   GetOutgoingStructure(getArrayCode, (Local)resultPusher) : null);
        }
Exemplo n.º 16
0
 public ASMethodBody(ABCFile abc)
 {
     _abc = abc;
     Code = new ASCode(abc, this);
 }
Exemplo n.º 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());
        }
Exemplo n.º 18
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);
        }
Exemplo n.º 19
0
        public void ReplaceLocalizationDefaults(RetroLocalizationConfig[] localizationConfigs)
        {
            var abc               = _flash.AbcGame;
            var symbols           = (SymbolClassTag)_flash.Tags.Last(x => x.Kind == TagKind.SymbolClass);
            var localizationClass = abc.GetClass("HabboLocalizationCom");

            // Save all old localizations.
            var localizations = localizationConfigs
                                .Select(x => x.HotelCodeBase).Distinct()
                                .ToDictionary(x => x, y =>
            {
                var binaryDataId = symbols.Entries.First(x => x.Item2.Contains(y));
                var binaryData   = (DefineBinaryDataTag)_flash.Tags.First(x => x.Kind == TagKind.DefineBinaryData && ((DefineBinaryDataTag)x).Id == binaryDataId.Item1);

                return(binaryData.Data);
            });

            // Find all old localizations.
            var localizationSymbols = symbols.Entries.Where(x => x.Item2.Contains("default_localizations_")).ToArray();
            var localizationTraits  = localizationClass.Traits.Where(x => x.IsStatic && x.QName.Name.StartsWith("default_localizations_")).ToArray();
            var localizationClasses = abc.Classes.Where(x => x.QName.Name.StartsWith("default_localizations_")).ToArray();

            if (localizationSymbols.Length != localizationTraits.Length ||
                localizationTraits.Length != localizationClasses.Length)
            {
                throw new ApplicationException("Localization result amount mismatch.");
            }

            // Remove all old localization references.

            // - Remove symbols
            foreach (var symbol in localizationSymbols)
            {
                _flash.Tags.RemoveAll(x => x.Kind == TagKind.DefineBinaryData && ((DefineBinaryDataTag)x).Id == symbol.Item1);
                symbols.Entries.RemoveAll(x => x.Item1 == symbol.Item1);
            }

            // - Remove "public static var default_localizations_*"
            localizationClass.Traits.RemoveAll(trait => trait.QName.Name.StartsWith("default_localizations_"));

            var body = localizationClass.Constructor.Body.ParseCode();

            var getLex      = body.First(x => x.OP == OPCode.GetLex && ((GetLexIns)x).TypeName.Name.StartsWith("default_localizations_"));
            var getLexIndex = body.IndexOf(getLex);
            var setProp     = body.LastIndexOf(body.Count - 1, OPCode.SetProperty);

            body.RemoveRange(getLexIndex, setProp - getLexIndex + 1);

            localizationClass.Constructor.Body.Code = body.ToArray();

            // - Remove "default_localizations_" classes / instances / scripts
            // TODO: Figure out how to fix all index based stuff, because this messes it up. DO NOT USE YET.
            // _flash.AbcGame.Classes.RemoveAll(x => x.QName.Name.StartsWith("default_localizations_"));
            // _flash.AbcGame.Instances.RemoveAll(x => x.QName.Name.StartsWith("default_localizations_"));
            // _flash.AbcGame.Scripts.RemoveAll(x => x.QName.Name.Contains("default_localizations_"));

            // Add localizations.
            foreach (var config in localizationConfigs)
            {
                var localizationName    = $"custom_localizations_{config.HotelCode}";
                var defLocalizationName = $"own_default_localizations_{config.HotelCode}";

                var localizationMultiNameIndex = abc.Pool.AddConstant(new ASMultiname(abc.Pool)
                {
                    NameIndex      = abc.Pool.AddConstant(localizationName),
                    Kind           = MultinameKind.QName,
                    NamespaceIndex = 1
                });

                #region Create localization class

                // Create instance.
                var instanceConstructor = new ASMethod(abc)
                {
                    ReturnTypeIndex = 0
                };

                var instanceConstructorIndex = abc.AddMethod(instanceConstructor);

                var instanceConstructorBody = new ASMethodBody(abc)
                {
                    MethodIndex       = instanceConstructorIndex,
                    MaxStack          = 1,
                    LocalCount        = 1,
                    InitialScopeDepth = 0,
                    MaxScopeDepth     = 1,
                    Code = new byte[] { 0xD0, 0x30, 0xD0, 0x49, 0x00, 0x47 }
                };

                abc.AddMethodBody(instanceConstructorBody);

                // Create class.
                var classConstructor = new ASMethod(abc)
                {
                    ReturnTypeIndex = 0
                };

                var classConstructorIndex = abc.AddMethod(classConstructor);

                var classConstructorBody = new ASMethodBody(abc)
                {
                    MethodIndex       = classConstructorIndex,
                    MaxStack          = 0,
                    LocalCount        = 1,
                    InitialScopeDepth = 0,
                    MaxScopeDepth     = 0,
                    Code = new byte[] { 0x47 }
                };

                abc.AddMethodBody(classConstructorBody);

                // Add class to SWF.
                var classIndex = abc.AddClass(
                    new ASClass(abc)
                {
                    ConstructorIndex = classConstructorIndex
                },
                    new ASInstance(abc)
                {
                    ConstructorIndex = instanceConstructorIndex,
                    QNameIndex       = localizationMultiNameIndex,
                    SuperIndex       = abc.Pool.GetMultinameIndex("ByteArray"),
                    Flags            = ClassFlags.Sealed
                }
                    );

                // Create script.
                var initializerMethod = new ASMethod(abc)
                {
                    ReturnTypeIndex = 0
                };

                var initializerMethodIndex = abc.AddMethod(initializerMethod);

                var initializerMethodBody = new ASMethodBody(abc)
                {
                    MethodIndex       = initializerMethodIndex,
                    MaxStack          = 3,
                    LocalCount        = 1,
                    InitialScopeDepth = 0,
                    MaxScopeDepth     = 3,
                    Code = new byte[0]
                };

                abc.AddMethodBody(initializerMethodBody);

                var initializerMethodBodyCode = new ASCode(abc, initializerMethodBody);

                initializerMethodBodyCode.AddRange(new ASInstruction[]
                {
                    new GetLocal0Ins(),
                    new PushScopeIns(),
                    new GetScopeObjectIns(0),
                    new GetLexIns(abc, abc.Pool.GetMultinameIndex("Object")),
                    new PushScopeIns(),
                    new GetLexIns(abc, abc.Pool.GetMultinameIndex("ByteArray")),
                    new DupIns(),
                    new PushScopeIns(),
                    new NewClassIns(abc, classIndex),
                    new PopScopeIns(),
                    new PopScopeIns(),
                    new InitPropertyIns(abc, localizationMultiNameIndex),
                    new ReturnVoidIns()
                });

                initializerMethodBody.Code = initializerMethodBodyCode.ToArray();

                var initScript = new ASScript(abc)
                {
                    InitializerIndex = initializerMethodIndex
                };

                initScript.Traits.Add(new ASTrait(abc)
                {
                    ClassIndex = classIndex,
                    QNameIndex = localizationMultiNameIndex,
                    Kind       = TraitKind.Class
                });

                _flash.AbcGame.AddScript(initScript);

                #endregion

                #region Create binary data symbol

                var symbolId = symbols.AddSymbol(localizationName);
                var data     = localizations[config.HotelCodeBase];

                _flash.Tags.Insert(_flash.Tags.IndexOf(symbols), new DefineBinaryDataTag(symbolId, data));

                #endregion

                #region Add to HabboLocalizationCom

                var defLocalizationMultiNameIndex = abc.Pool.AddConstant(new ASMultiname(abc.Pool)
                {
                    NameIndex      = abc.Pool.AddConstant(defLocalizationName),
                    Kind           = MultinameKind.QName,
                    NamespaceIndex = 1
                });

                localizationClass.Traits.Add(new ASTrait(abc)
                {
                    QNameIndex = defLocalizationMultiNameIndex,
                    TypeIndex  = abc.Pool.GetMultinameIndex("Class")
                });

                var constructorBody = localizationClass.Constructor.Body.ParseCode();

                constructorBody.InsertRange(constructorBody.Count - 1, new ASInstruction[]
                {
                    new GetLexIns(abc, localizationMultiNameIndex),
                    new FindPropertyIns(abc, defLocalizationMultiNameIndex),
                    new SwapIns(),
                    new SetPropertyIns(abc, defLocalizationMultiNameIndex)
                });

                localizationClass.Constructor.Body.Code = constructorBody.ToArray();

                #endregion
            }

            // Swap localization to load.
            var stringId = abc.Pool.Strings.IndexOf("default_localizations_");
            abc.Pool.Strings[stringId] = "own_default_localizations_";

            // Replace localization_configuration_txt.
            var locConfigBuilder = new StringBuilder();

            for (var i = 0; i < localizationConfigs.Length; i++)
            {
                var config    = localizationConfigs[i];
                var currentId = i + 1;

                locConfigBuilder.AppendLine($"localization.{currentId}={config.HotelCode}");
                locConfigBuilder.AppendLine($"localization.{currentId}.code={config.Code}");
                locConfigBuilder.AppendLine($"localization.{currentId}.name={config.Name}");
                locConfigBuilder.AppendLine($"localization.{currentId}.url={config.Url}");
            }

            var locConfigId = symbols.Entries.First(x => x.Item2.Contains("localization_configuration_txt"));
            var locConfig   = (DefineBinaryDataTag)_flash.Tags.First(x => x.Kind == TagKind.DefineBinaryData && ((DefineBinaryDataTag)x).Id == locConfigId.Item1);

            locConfig.Data = Encoding.UTF8.GetBytes(locConfigBuilder.ToString());

            // Replace localizations manifest.
            string localizationManifestStr           = null;
            DefineBinaryDataTag localizationManifest = null;

            foreach (var(entryId, _) in symbols.Entries)
            {
                var binaryData = (DefineBinaryDataTag)_flash.Tags.FirstOrDefault(x => x.Kind == TagKind.DefineBinaryData && ((DefineBinaryDataTag)x).Id == entryId);
                if (binaryData != null)
                {
                    var dataString = Encoding.UTF8.GetString(binaryData.Data);
                    if (dataString.Contains("<asset mimeType=\"text/plain\" name=\"default_localizations_en\" />"))
                    {
                        localizationManifestStr = dataString;
                        localizationManifest    = binaryData;
                        break;
                    }
                }
            }

            if (localizationManifest == null || localizationManifestStr == null)
            {
                throw new ApplicationException("Could not find localizationManifest or localizationManifestStr.");
            }

            var xmlDocument = new XmlDocument();
            xmlDocument.LoadXml(localizationManifestStr);

            var defaultLoc     = new string[] { "development_localizations" };
            var manifestAssets = xmlDocument.GetElementsByTagName("assets")[0];
            manifestAssets.RemoveAll();

            foreach (var name in defaultLoc.Union(localizationConfigs.Select(x => "own_default_localizations_" + x.HotelCode)))
            {
                var child = xmlDocument.CreateElement("asset");

                child.SetAttribute("mimeType", "text/plain");
                child.SetAttribute("name", name);

                manifestAssets.AppendChild(child);
            }

            using (var stringWriter = new StringWriter())
                using (var xmlTextWriter = XmlWriter.Create(stringWriter, new XmlWriterSettings
                {
                    Indent = true
                }))
                {
                    xmlDocument.WriteTo(xmlTextWriter);
                    xmlTextWriter.Flush();

                    localizationManifest.Data = Encoding.UTF8.GetBytes(stringWriter.GetStringBuilder().ToString());
                }
        }
Exemplo n.º 20
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);
            }
        }