From 0ce2525dca81cf73f84f2ebf982cbbb6f051ce0b Mon Sep 17 00:00:00 2001 From: js6pak Date: Tue, 9 Mar 2021 14:54:34 +0100 Subject: [PATCH] de:fortelove: --- Reactor.Greenhouse/Compiler.cs | 7 +- .../Generation/GenerationContext.cs | 16 +++ Reactor.Greenhouse/Generation/Generator.cs | 80 +++++++----- Reactor.Greenhouse/Generation/TypeContext.cs | 121 ++++++++++-------- Reactor.Greenhouse/Mappings | 2 +- Reactor.Greenhouse/Program.cs | 15 +-- .../Setup/Provider/AndroidProvider.cs | 3 +- .../Setup/Provider/ItchProvider.cs | 13 +- .../Setup/Provider/SteamProvider.cs | 3 +- Reactor.OxygenFilter/Mappings.cs | 7 + Reactor.OxygenFilter/ObfuscationMapper.cs | 5 - 11 files changed, 163 insertions(+), 109 deletions(-) diff --git a/Reactor.Greenhouse/Compiler.cs b/Reactor.Greenhouse/Compiler.cs index f8b2571..dc5bb46 100644 --- a/Reactor.Greenhouse/Compiler.cs +++ b/Reactor.Greenhouse/Compiler.cs @@ -10,8 +10,13 @@ namespace Reactor.Greenhouse { public static class Compiler { - public static void Apply(this Mappings current, Mappings mappings) + public static void Apply(this Mappings current, Mappings mappings, Func findMappingsFunc) { + foreach (var id in mappings.DependsOn) + { + current.Apply(findMappingsFunc(id), findMappingsFunc); + } + static void ApplyType(List types, MappedType newType) { var type = types.SingleOrDefault(x => newType.Equals(x)); diff --git a/Reactor.Greenhouse/Generation/GenerationContext.cs b/Reactor.Greenhouse/Generation/GenerationContext.cs index 0a807f1..b0fbd73 100644 --- a/Reactor.Greenhouse/Generation/GenerationContext.cs +++ b/Reactor.Greenhouse/Generation/GenerationContext.cs @@ -15,5 +15,21 @@ namespace Reactor.Greenhouse.Generation CleanModule = cleanModule; ObfuscatedModule = obfuscatedModule; } + + public TypeContext GetOrCreate(TypeDefinition obfuscated, TypeDefinition clean, TypeContext parent = null) + { + if (!Map.TryGetValue(obfuscated, out var typeContext)) + { + typeContext = new TypeContext(this, double.MaxValue, clean) + { + ObfuscatedType = obfuscated, + Declaring = parent + }; + + Map[obfuscated] = typeContext; + } + + return typeContext; + } } } diff --git a/Reactor.Greenhouse/Generation/Generator.cs b/Reactor.Greenhouse/Generation/Generator.cs index 67c880e..406dc4d 100644 --- a/Reactor.Greenhouse/Generation/Generator.cs +++ b/Reactor.Greenhouse/Generation/Generator.cs @@ -41,20 +41,37 @@ namespace Reactor.Greenhouse.Generation foreach (var (obfuscatedType, typeContext) in context.Map.ToDictionary(k => k.Key, v => v.Value)) { - var mappedType = typeContext.ToMappedType( - obfuscatedType, - (obfuscatedNested, cleanNested) => + if (obfuscatedType.DeclaringType != null) + { + var existingParent = context.Map.SingleOrDefault(x => x.Value.CleanType == typeContext.CleanType.DeclaringType).Key; + + if (existingParent != null && existingParent != obfuscatedType.DeclaringType) { - if (!context.Map.TryGetValue(obfuscatedNested, out var nested)) - { - nested = new TypeContext(context, double.MaxValue, cleanNested); - context.Map[obfuscatedNested] = nested; - } + context.Map.Remove(obfuscatedType); + continue; + } + } - return nested; - }); + typeContext.ObfuscatedType = obfuscatedType; + typeContext.UpdateNested(); - if (mappedType == null || obfuscatedType.DeclaringType != null) + if (obfuscatedType.DeclaringType != null) + { + var declaring = context.GetOrCreate(obfuscatedType.DeclaringType, typeContext.CleanType.DeclaringType); + declaring.Nested.Add(typeContext); + } + } + + foreach (var (obfuscatedType, typeContext) in context.Map) + { + if (obfuscatedType.DeclaringType != null) + { + continue; + } + + var mappedType = typeContext.ToMappedType(); + + if (mappedType == null) continue; result.Types.Add(mappedType); @@ -63,38 +80,40 @@ namespace Reactor.Greenhouse.Generation return result; } - private static bool TestEnum(TypeDefinition cleanType, TypeDefinition obfuscatedType) + private static double TestEnum(TypeDefinition cleanType, TypeDefinition obfuscatedType) { if (!obfuscatedType.IsEnum) - return false; + return 0; - if (cleanType.Fields.Count != obfuscatedType.Fields.Count) - return false; + var points = 0d; for (var i = 0; i < cleanType.Fields.Count; i++) { var cleanField = cleanType.Fields[i]; + if (i >= obfuscatedType.Fields.Count) + break; + var obfuscatedField = obfuscatedType.Fields[i]; - if (cleanField.Name != obfuscatedField.Name) + if (cleanField.Name == obfuscatedField.Name) { - return false; + points++; } - if (cleanField.HasConstant && !cleanField.Constant.Equals(obfuscatedField.Constant)) + if (cleanField.HasConstant && cleanField.Constant.Equals(obfuscatedField.Constant)) { - return false; + points++; } } - return true; + return points; } private static double TestField(FieldDefinition cleanField, FieldDefinition obfuscatedField) { var points = 0d; - if (cleanField.Attributes.IgnoreVisibility() != obfuscatedField.Attributes.IgnoreVisibility()) + if (cleanField.Attributes != obfuscatedField.Attributes) { points -= 1; } @@ -170,12 +189,18 @@ namespace Reactor.Greenhouse.Generation if (cleanType.Name.StartsWith("<")) return 0; - if (cleanType.Attributes.IgnoreVisibility() != obfuscatedType.Attributes.IgnoreVisibility()) + if (cleanType.Attributes != obfuscatedType.Attributes) return 0; + if (cleanType.DeclaringType != null && obfuscatedType.DeclaringType == null) + return 0; + + if (cleanType.FullName == obfuscatedType.FullName) + return double.MaxValue; + if (cleanType.IsEnum) { - return TestEnum(cleanType, obfuscatedType) ? double.MaxValue : 0; + return TestEnum(cleanType, obfuscatedType); } if (cleanType.BaseType != null && obfuscatedType.BaseType != null && cleanType.BaseType.FullName != obfuscatedType.BaseType.FullName) @@ -188,12 +213,6 @@ namespace Reactor.Greenhouse.Generation var points = 0d; - // this will only work with up to date mono dll (:fortelove:) - if (obfuscatedType.Fields.Count != cleanType.Fields.Count || obfuscatedType.Properties.Count != cleanType.Properties.Count || obfuscatedType.NestedTypes.Count != cleanType.NestedTypes.Count) - { - return 0; - } - for (var i = 0; i < cleanType.Fields.Count; i++) { var cleanField = cleanType.Fields[i]; @@ -252,6 +271,9 @@ namespace Reactor.Greenhouse.Generation if (obfuscatedType.Name.StartsWith("<") && obfuscatedType.Name.EndsWith(">")) continue; + if (obfuscatedType.FullName.StartsWith("Rewired")) + continue; + var points = TestType(cleanType, obfuscatedType); if (points > winnerPoints) diff --git a/Reactor.Greenhouse/Generation/TypeContext.cs b/Reactor.Greenhouse/Generation/TypeContext.cs index 8272a7a..babb8c7 100644 --- a/Reactor.Greenhouse/Generation/TypeContext.cs +++ b/Reactor.Greenhouse/Generation/TypeContext.cs @@ -14,13 +14,18 @@ namespace Reactor.Greenhouse.Generation public double Points { get; } public TypeDefinition CleanType { get; } + public TypeDefinition ObfuscatedType { get; set; } + + public TypeContext Declaring { get; set; } + public HashSet Nested { get; } = new HashSet(); + public string CleanFullName => CleanType.FullName; public TypeContext(GenerationContext context, double points, TypeDefinition cleanType) { Context = context; Points = points; - CleanType = cleanType; + CleanType = cleanType ?? throw new ArgumentNullException(nameof(cleanType)); } public override string ToString() @@ -30,65 +35,85 @@ namespace Reactor.Greenhouse.Generation private static readonly Regex CompilerGeneratedRegex = new Regex(@"^<([\w\d]+)>.__\d+$", RegexOptions.Compiled); - public MappedType ToMappedType(TypeDefinition obfuscatedType, Func nestedFunc) + public void UpdateNested() + { + if (ObfuscatedType.NestedTypes.Count == CleanType.NestedTypes.Count) + { + for (var i = 0; i < CleanType.NestedTypes.Count; i++) + { + var cleanNested = CleanType.NestedTypes[i]; + var obfuscatedNested = ObfuscatedType.NestedTypes[i]; + + Nested.Add(Context.GetOrCreate(obfuscatedNested, cleanNested, this)); + } + } + } + + public MappedType ToMappedType() { var match = CompilerGeneratedRegex.Match(CleanType.Name); - var mappedType = new MappedType(obfuscatedType.FullName, match.Success ? (match.Groups[1].Value + "__d") : CleanType.Name.Replace("<>", "")); + var mappedType = new MappedType(ObfuscatedType.FullName, match.Success ? (match.Groups[1].Value + "__d") : CleanType.Name.Replace("<>", "")); - for (var i = 0; i < CleanType.Fields.Count; i++) + if (ObfuscatedType.Fields.Count == CleanType.Fields.Count) { - var cleanField = CleanType.Fields[i]; - var obfuscatedField = obfuscatedType.Fields[i]; - - if (obfuscatedType.DeclaringType != null) + for (var i = 0; i < CleanType.Fields.Count; i++) { - switch (obfuscatedField.Name) + var cleanField = CleanType.Fields[i]; + var obfuscatedField = ObfuscatedType.Fields[i]; + + if (ObfuscatedType.DeclaringType != null) { - case "<>1__state": - mappedType.Fields.Add(new MappedMember(obfuscatedField.Name, "__state")); - continue; - case "<>2__current": - mappedType.Fields.Add(new MappedMember(obfuscatedField.Name, "__current")); - continue; - case "<>4__this": - mappedType.Fields.Add(new MappedMember(obfuscatedField.Name, "__this")); + switch (obfuscatedField.Name) + { + case "<>1__state": + mappedType.Fields.Add(new MappedMember(obfuscatedField.Name, "__state")); + continue; + case "<>2__current": + mappedType.Fields.Add(new MappedMember(obfuscatedField.Name, "__current")); + continue; + case "<>4__this": + mappedType.Fields.Add(new MappedMember(obfuscatedField.Name, "__this")); + continue; + } + + var fieldMatch = CompilerGeneratedRegex.Match(obfuscatedField.Name); + + if (fieldMatch.Success) + { + mappedType.Fields.Add(new MappedMember(obfuscatedField.Name, fieldMatch.Groups[1].Value)); continue; + } } - var fieldMatch = CompilerGeneratedRegex.Match(obfuscatedField.Name); - - if (fieldMatch.Success) - { - mappedType.Fields.Add(new MappedMember(obfuscatedField.Name, fieldMatch.Groups[1].Value)); + if (!obfuscatedField.Name.IsObfuscated()) continue; - } + + mappedType.Fields.Add(new MappedMember(obfuscatedField.Name, cleanField.Name)); } - - if (!obfuscatedField.Name.IsObfuscated()) - continue; - - mappedType.Fields.Add(new MappedMember(obfuscatedField.Name, cleanField.Name)); } - for (var i = 0; i < CleanType.Properties.Count; i++) + if (ObfuscatedType.Properties.Count == CleanType.Properties.Count) { - var cleanProperty = CleanType.Properties[i]; - var obfuscatedProperty = obfuscatedType.Properties[i]; + for (var i = 0; i < CleanType.Properties.Count; i++) + { + var cleanProperty = CleanType.Properties[i]; + var obfuscatedProperty = ObfuscatedType.Properties[i]; - if (!obfuscatedProperty.Name.IsObfuscated()) - continue; + if (!obfuscatedProperty.Name.IsObfuscated()) + continue; - mappedType.Properties.Add(new MappedMember(obfuscatedProperty.Name, cleanProperty.Name)); + mappedType.Properties.Add(new MappedMember(obfuscatedProperty.Name, cleanProperty.Name)); + } } foreach (var cleanMethod in CleanType.GetMethods()) { - if (obfuscatedType.GetMethods().Any(x => x.Name == cleanMethod.Name)) + if (ObfuscatedType.GetMethods().Any(x => x.Name == cleanMethod.Name)) continue; var matching = new List(); - foreach (var obfuscatedMethod in obfuscatedType.GetMethods().Where(x => x.Name.IsObfuscated())) + foreach (var obfuscatedMethod in ObfuscatedType.GetMethods().Where(x => x.Name.IsObfuscated())) { if (cleanMethod.ReturnType.FullName != obfuscatedMethod.ReturnType.FullName) continue; @@ -132,9 +157,9 @@ namespace Reactor.Greenhouse.Generation } } - if (obfuscatedType.DeclaringType != null) + if (ObfuscatedType.DeclaringType != null) { - foreach (var obfuscatedMethod in obfuscatedType.Methods) + foreach (var obfuscatedMethod in ObfuscatedType.Methods) { var methodMatch = CompilerGeneratedRegex.Match(obfuscatedMethod.Name); @@ -145,26 +170,16 @@ namespace Reactor.Greenhouse.Generation } } - for (var i = 0; i < CleanType.NestedTypes.Count; i++) + foreach (var nestedTypeContext in Nested) { - var cleanNested = CleanType.NestedTypes[i]; - var obfuscatedNested = obfuscatedType.NestedTypes[i]; - - if (cleanNested.Fields.Count != obfuscatedNested.Fields.Count) + var nestedType = nestedTypeContext.ToMappedType(); + if (nestedType != null) { - break; - } - - var nestedContext = nestedFunc(obfuscatedNested, cleanNested); - var mappedNested = nestedContext.ToMappedType(obfuscatedNested, nestedFunc); - - if (mappedNested != null) - { - mappedType.Nested.Add(mappedNested); + mappedType.Nested.Add(nestedType); } } - if (!obfuscatedType.Name.IsObfuscated() && !mappedType.Fields.Any() && !mappedType.Methods.Any() && !mappedType.Properties.Any() && !mappedType.Nested.Any()) + if (!ObfuscatedType.Name.IsObfuscated() && !mappedType.Fields.Any() && !mappedType.Methods.Any() && !mappedType.Properties.Any() && !mappedType.Nested.Any()) return null; return mappedType; diff --git a/Reactor.Greenhouse/Mappings b/Reactor.Greenhouse/Mappings index 1f5050d..30b991d 160000 --- a/Reactor.Greenhouse/Mappings +++ b/Reactor.Greenhouse/Mappings @@ -1 +1 @@ -Subproject commit 1f5050d89f6399968fac1f5b4e250c056900d0c5 +Subproject commit 30b991d6a8531077b0c004a77f39b14eb3477fa8 diff --git a/Reactor.Greenhouse/Program.cs b/Reactor.Greenhouse/Program.cs index d83c742..09eed7d 100644 --- a/Reactor.Greenhouse/Program.cs +++ b/Reactor.Greenhouse/Program.cs @@ -56,11 +56,14 @@ namespace Reactor.Greenhouse using var moduleDef = ModuleDefinition.ReadModule(File.OpenRead(game.Dll)); var generated = Generator.Generate(new GenerationContext(cleanModule, moduleDef)); + generated.GameVersion = version.ToString(); + generated.Version = Mappings.CurrentVersion; await File.WriteAllTextAsync(Path.Combine("work", version + ".generated.json"), JsonConvert.SerializeObject(generated, Formatting.Indented)); - Apply(generated, Path.Combine("universal.json")); - Apply(generated, Path.Combine(version + ".json")); + var mappings = Read(version.ToString()); + + generated.Apply(mappings, Read); generated.Compile(moduleDef); @@ -68,13 +71,9 @@ namespace Reactor.Greenhouse await File.WriteAllTextAsync(Path.Combine("bin", version + ".json"), JsonConvert.SerializeObject(generated)); } - private static void Apply(Mappings generated, string file) + private static Mappings Read(string file) { - if (File.Exists(file)) - { - var mappings = JsonConvert.DeserializeObject(File.ReadAllText(file)); - generated.Apply(mappings); - } + return JsonConvert.DeserializeObject(File.ReadAllText(file + ".json")); } public class ShouldSerializeContractResolver : CamelCasePropertyNamesContractResolver diff --git a/Reactor.Greenhouse/Setup/Provider/AndroidProvider.cs b/Reactor.Greenhouse/Setup/Provider/AndroidProvider.cs index e62a8d1..8299c60 100644 --- a/Reactor.Greenhouse/Setup/Provider/AndroidProvider.cs +++ b/Reactor.Greenhouse/Setup/Provider/AndroidProvider.cs @@ -10,7 +10,8 @@ namespace Reactor.Greenhouse.Setup.Provider { private Dictionary VersionMap { get; } = new Dictionary { - [new GameVersion("2020.11.17a")] = "https://www.apkmirror.com/wp-content/themes/APKMirror/download.php?id=1753109" + [new GameVersion("2020.11.17a")] = "https://www.apkmirror.com/wp-content/themes/APKMirror/download.php?id=1753109", + [new GameVersion("2021.3.5a")] = "https://www.apkmirror.com/wp-content/themes/APKMirror/download.php?id=2032358&forcebaseapk" }; public string DownloadUrl { get; } diff --git a/Reactor.Greenhouse/Setup/Provider/ItchProvider.cs b/Reactor.Greenhouse/Setup/Provider/ItchProvider.cs index 828ad6e..022d7a5 100644 --- a/Reactor.Greenhouse/Setup/Provider/ItchProvider.cs +++ b/Reactor.Greenhouse/Setup/Provider/ItchProvider.cs @@ -16,16 +16,8 @@ namespace Reactor.Greenhouse.Setup.Provider { public class ItchProvider : BaseProvider { - private Dictionary VersionMap { get; } = new Dictionary - { - [new GameVersion("2020.11.17i")] = 1047908, - }; - - public int UploadId { get; } - public ItchProvider(GameVersion version) : base(version) { - UploadId = VersionMap[version]; } private HttpClient HttpClient { get; } = new HttpClient(new HttpClientHandler @@ -57,6 +49,7 @@ namespace Reactor.Greenhouse.Setup.Provider } } + // TODO butlerd and multi version support? public override async Task DownloadAsync() { var htmlParser = new HtmlParser(); @@ -83,7 +76,7 @@ namespace Reactor.Greenhouse.Setup.Provider var downloadPageUrl = ((IHtmlAnchorElement) pageDocument.QuerySelector("a[class=button]")).Href; var downloadDocument = htmlParser.ParseDocument(await HttpClient.GetStringAsync(downloadPageUrl)); - // var uploadId = ((IHtmlAnchorElement) downloadDocument.QuerySelector("a[class='button download_btn']")).Dataset["upload_id"]; + var uploadId = ((IHtmlAnchorElement) downloadDocument.QuerySelector("a[class='button download_btn']")).Dataset["upload_id"]; var keyRegex = new Regex("key\":\"(.+)\","); var key = downloadDocument.QuerySelectorAll("script[type='text/javascript']") @@ -92,7 +85,7 @@ namespace Reactor.Greenhouse.Setup.Provider .Single(x => x.Success) .Groups[1].Value; - var json = await HttpClient.PostAsync($"https://innersloth.itch.io/among-us/file/{UploadId}?key={key}", null); + var json = await HttpClient.PostAsync($"https://innersloth.itch.io/among-us/file/{uploadId}?key={key}", null); var response = JsonConvert.DeserializeObject(await json.Content.ReadAsStringAsync()); Console.WriteLine($"Downloading {response.Url}"); diff --git a/Reactor.Greenhouse/Setup/Provider/SteamProvider.cs b/Reactor.Greenhouse/Setup/Provider/SteamProvider.cs index ea70508..77ea343 100644 --- a/Reactor.Greenhouse/Setup/Provider/SteamProvider.cs +++ b/Reactor.Greenhouse/Setup/Provider/SteamProvider.cs @@ -15,7 +15,8 @@ namespace Reactor.Greenhouse.Setup.Provider private Dictionary VersionMap { get; } = new Dictionary { [new GameVersion("2019.10.10s")] = 3162069540887216240, - [new GameVersion("2020.12.9s")] = 3306639722673334636 + [new GameVersion("2020.12.9s")] = 3306639722673334636, + [new GameVersion("2021.3.5s")] = 5200448423569257054 }; public ulong Manifest { get; } diff --git a/Reactor.OxygenFilter/Mappings.cs b/Reactor.OxygenFilter/Mappings.cs index ffc3ead..52b564a 100644 --- a/Reactor.OxygenFilter/Mappings.cs +++ b/Reactor.OxygenFilter/Mappings.cs @@ -9,6 +9,13 @@ namespace Reactor.OxygenFilter { public class Mappings { + public const int CurrentVersion = 1; + + public int Version { get; set; } + public string GameVersion { get; set; } + + public string[] DependsOn { get; set; } = new string[0]; + public List Types { get; set; } = new List(); public MappedType Find(string name, Func predicate) diff --git a/Reactor.OxygenFilter/ObfuscationMapper.cs b/Reactor.OxygenFilter/ObfuscationMapper.cs index e072d72..2b5763c 100644 --- a/Reactor.OxygenFilter/ObfuscationMapper.cs +++ b/Reactor.OxygenFilter/ObfuscationMapper.cs @@ -187,11 +187,6 @@ namespace Reactor.OxygenFilter foreach (var member in typeDef.Methods) { - if (member.Name.IsObfuscated() && member.CustomAttributes.All(x => x.AttributeType != mappedAttribute)) - { - MapMember(member, $"Method_{i}"); - } - var j = 0; foreach (var parameter in member.Parameters) {