Пример #1
0
        private ASCode(ABCFile abc, ASMethodBody body, bool deobfuscate)
        {
            _abc  = abc;
            _body = body;

            _instructions = new List <ASInstruction>();
            _indices      = new Dictionary <ASInstruction, int>();
            _opGroups     = new Dictionary <OPCode, List <ASInstruction> >();

            JumpExits   = new Dictionary <Jumper, ASInstruction>();
            SwitchExits = new Dictionary <LookUpSwitchIns, ASInstruction[]>();

            // TODO Implement deobfuscation while reading.
            LoadInstructions();
        }
Пример #2
0
 protected void RemoveDeadFalseConditions(ASMethodBody body)
 {
     using (var inCode = new FlashReader(body.Bytecode))
         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();
                 }
             }
             body.Bytecode = outCode.ToArray();
         }
 }
Пример #3
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());
                }
        }
Пример #4
0
 protected void RemoveDeadFalseConditions(ASMethodBody body)
 {
     using (var inCode = new FlashReader(body.Bytecode))
     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();
         }
         body.Bytecode = outCode.ToArray();
     }
 }
Пример #5
0
 public ASCode(ABCFile abc, ASMethodBody body)
     : this(abc, body, false)
 {
 }