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(); }
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(); } }
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()); } }
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(); } }
public ASCode(ABCFile abc, ASMethodBody body) : this(abc, body, false) { }