Beispiel #1
0
        public Dictionary <string, KeyInfo> GetKeys()
        {
            Dictionary <string, KeyInfo> @return = new Dictionary <string, KeyInfo>();

            foreach (ulong key in TrackedFiles[0x90])
            {
                STUEncryptionKey encryptionKey = GetInstance <STUEncryptionKey>(key);
                if (encryptionKey == null)
                {
                    continue;
                }
                @return[GetFileName(key)] = new KeyInfo(key, encryptionKey.KeyNameProper, encryptionKey.Key);
            }

            return(@return);
        }
Beispiel #2
0
        private static void Main()
        {
            Console.OutputEncoding = Encoding.UTF8;

            Files        = new Dictionary <ulong, PackageRecord>();
            TrackedFiles = new Dictionary <ushort, HashSet <ulong> >();

            #region Tool Detection
            HashSet <Type> tools = new HashSet <Type>();
            {
                Assembly    asm   = typeof(ITool).Assembly;
                Type        t     = typeof(ITool);
                List <Type> types = asm.GetTypes().Where(tt => tt != t && t.IsAssignableFrom(tt)).ToList();
                foreach (Type tt in types)
                {
                    ToolAttribute attrib = tt.GetCustomAttribute <ToolAttribute>();
                    if (tt.IsInterface || attrib == null)
                    {
                        continue;
                    }
                    tools.Add(tt);

                    if (attrib.TrackTypes == null)
                    {
                        continue;
                    }
                    foreach (ushort type in attrib.TrackTypes)
                    {
                        if (!TrackedFiles.ContainsKey(type))
                        {
                            TrackedFiles[type] = new HashSet <ulong>();
                        }
                    }
                }
            }
            #endregion

            Flags = FlagParser.Parse <ToolFlags>(() => PrintHelp(tools));
            if (Flags == null)
            {
                return;
            }

            Logger.EXIT = !Flags.GracefulExit;

            ITool     targetTool      = null;
            ICLIFlags targetToolFlags = null;

            #region Tool Activation

            foreach (Type type in tools)
            {
                ToolAttribute attrib = type.GetCustomAttribute <ToolAttribute>();

                if (!string.Equals(attrib.Keyword, Flags.Mode, StringComparison.InvariantCultureIgnoreCase))
                {
                    continue;
                }
                targetTool = Activator.CreateInstance(type) as ITool;

                if (attrib.CustomFlags != null)
                {
                    Type flags = attrib.CustomFlags;
                    if (typeof(ICLIFlags).IsAssignableFrom(flags))
                    {
                        targetToolFlags = typeof(FlagParser).GetMethod("Parse", new Type[] { }).MakeGenericMethod(flags).Invoke(null, null) as ICLIFlags;
                    }
                }
                break;
            }

            #endregion

            if (targetTool == null)
            {
                FlagParser.Help <ToolFlags>(false);
                PrintHelp(tools);
                if (Debugger.IsAttached)
                {
                    Debugger.Break();
                }
                return;
            }

            #region Initialize CASC
            Log("{0} v{1}", Assembly.GetExecutingAssembly().GetName().Name, Util.GetVersion());
            Log("Initializing CASC...");
            Log("Set language to {0}", Flags.Language);
            CDNIndexHandler.Cache.Enabled   = Flags.UseCache;
            CDNIndexHandler.Cache.CacheData = Flags.CacheData;
            CDNIndexHandler.Cache.Validate  = Flags.ValidateCache;
            // ngdp:us:pro
            // http:us:pro:us.patch.battle.net:1119
            if (Flags.OverwatchDirectory.ToLowerInvariant().Substring(0, 5) == "ngdp:")
            {
                string   cdn     = Flags.OverwatchDirectory.Substring(5, 4);
                string[] parts   = Flags.OverwatchDirectory.Substring(5).Split(':');
                string   region  = "us";
                string   product = "pro";
                if (parts.Length > 1)
                {
                    region = parts[1];
                }
                if (parts.Length > 2)
                {
                    product = parts[2];
                }
                if (cdn == "bnet")
                {
                    Config = CASCConfig.LoadOnlineStorageConfig(product, region);
                }
                else
                {
                    if (cdn == "http")
                    {
                        string host = string.Join(":", parts.Skip(3));
                        Config = CASCConfig.LoadOnlineStorageConfig(host, product, region, true, true, true);
                    }
                }
            }
            else
            {
                Config = CASCConfig.LoadLocalStorageConfig(Flags.OverwatchDirectory, !Flags.SkipKeys, false);
            }
            Config.Languages = new HashSet <string>(new[] { Flags.Language });
            #endregion

            foreach (Dictionary <string, string> build in Config.BuildInfo)
            {
                if (!build.ContainsKey("Tags"))
                {
                    continue;
                }
                if (build["Tags"].Contains("XX?"))
                {
                    IsPTR = true;
                }
                // us ptr region is known as XX, so just look for it in the tags.
                // this should work... untested for Asia
            }

            BuildVersion = uint.Parse(Config.BuildName.Split('.').Last());

            if (Flags.SkipKeys)
            {
                Log("Disabling Key auto-detection...");
            }

            Log("Using Overwatch Version {0}", Config.BuildName);
            CASC = CASCHandler.OpenStorage(Config);
            Root = CASC.Root as OwRootHandler;
            if (Root == null)
            {
                ErrorLog("Not a valid overwatch installation");
                return;
            }

            // Fail when trying to extract data from a specified language with 2 or less files found.
            if (!Root.APMFiles.Any())
            {
                ErrorLog("Could not find the files for language {0}. Please confirm that you have that language installed, and are using the names from the target language.", Flags.Language);
                if (!Flags.GracefulExit)
                {
                    return;
                }
            }

            Log("Mapping...");
            TrackedFiles[0x90] = new HashSet <ulong>();
            IO.MapCMF();
            IO.LoadGUIDTable();
            Sound.WwiseBank.GetReady();

            #region Key Detection
            if (!Flags.SkipKeys)
            {
                Log("Adding Encryption Keys...");

                foreach (ulong key in TrackedFiles[0x90])
                {
                    if (!ValidKey(key))
                    {
                        continue;
                    }
                    using (Stream stream = IO.OpenFile(Files[key])) {
                        if (stream == null)
                        {
                            continue;
                        }

                        STUEncryptionKey encryptionKey = GetInstance <STUEncryptionKey>(key);
                        if (encryptionKey != null && encryptionKey.LongKey != 0 && !KeyService.keys.ContainsKey(encryptionKey.LongRevKey))
                        {
                            KeyService.keys.Add(encryptionKey.LongRevKey, encryptionKey.KeyValue);
                            Log("Added Encryption Key {0}, Value: {1}", encryptionKey.KeyNameProper, encryptionKey.Key);
                        }
                    }
                }
            }
            #endregion

            Log("Tooling...");
            targetTool.Parse(targetToolFlags);
            if (Debugger.IsAttached)
            {
                Debugger.Break();
            }
        }
Beispiel #3
0
        static void Main(string[] args)
        {
            Console.OutputEncoding = Encoding.UTF8;
            List <IOvertool> tools = new List <IOvertool>();

            {
                Assembly    asm   = typeof(IOvertool).Assembly;
                Type        t     = typeof(IOvertool);
                List <Type> types = asm.GetTypes().Where(tt => tt != t && t.IsAssignableFrom(tt)).ToList();
                foreach (Type tt in types)
                {
                    if (tt.IsInterface)
                    {
                        continue;
                    }
                    IOvertool toolinst = (IOvertool)Activator.CreateInstance(tt);
                    if (toolinst.Display)
                    {
                        tools.Add(toolinst);
                    }
                }
            }

            OverToolFlags flags = FlagParser.Parse <OverToolFlags>(() => PrintHelp(tools));

            if (flags == null)
            {
                return;
            }

            Logger.EXIT = !flags.GracefulExit;

            bool quiet = flags.Quiet;

            string root = flags.OverwatchDirectory;
            string opt  = flags.Mode;

            IOvertool tool = null;
            Dictionary <ushort, List <ulong> > track = new Dictionary <ushort, List <ulong> > {
                [0x90] = new List <ulong>() // internal requirements
            };

            toolsMap = new Dictionary <string, IOvertool>();
            foreach (IOvertool t in tools)
            {
                if (t.FullOpt == opt || (opt.Length == 1 && t.Opt != (char)0 && t.Opt == opt[0]))
                {
                    tool = t;
                }

                if (t.Track != null)
                {
                    foreach (ushort tr in t.Track)
                    {
                        if (!track.ContainsKey(tr))
                        {
                            track[tr] = new List <ulong>();
                        }
                    }
                }

                if (toolsMap.ContainsKey(t.FullOpt))
                {
                    Console.Out.WriteLine("Duplicate opt! {0} conflicts with {1}", t.Title, toolsMap[t.FullOpt].Title);
                }
                if (t.FullOpt.Length == 1)
                {
                    Console.Out.WriteLine("FullOpt should not be length 1 for {0}", t.Title);
                }
                toolsMap[t.FullOpt] = t;
            }
            if (tool == null || flags.Positionals.Length - 2 < tool.MinimumArgs)
            {
                PrintHelp(tools);
                return;
            }

            Dictionary <ulong, Record> map = new Dictionary <ulong, Record>();

            Console.Out.WriteLine("{0} v{1}", Assembly.GetExecutingAssembly().GetName().Name, OWLib.Util.GetVersion());
            Console.Out.WriteLine("Initializing CASC...");
            Console.Out.WriteLine("Set language to {0}", flags.Language);
            CDNIndexHandler.Cache.Enabled   = flags.UseCache;
            CDNIndexHandler.Cache.CacheData = flags.CacheData;
            CDNIndexHandler.Cache.Validate  = flags.ValidateCache;
            CASCConfig config = null;

            // ngdp:us:pro
            // http:us:pro:us.patch.battle.net:1119
            if (root.ToLowerInvariant().Substring(0, 5) == "ngdp:")
            {
                string   cdn     = root.Substring(5, 4);
                string[] parts   = root.Substring(5).Split(':');
                string   region  = "us";
                string   product = "pro";
                if (parts.Length > 1)
                {
                    region = parts[1];
                }
                if (parts.Length > 2)
                {
                    product = parts[2];
                }
                if (cdn == "bnet")
                {
                    config = CASCConfig.LoadOnlineStorageConfig(product, region);
                }
                else
                {
                    if (cdn == "http")
                    {
                        string host = string.Join(":", parts.Skip(3));
                        config = CASCConfig.LoadOnlineStorageConfig(host, product, region, true, true, true);
                    }
                }
            }
            else
            {
                config = CASCConfig.LoadLocalStorageConfig(root, !flags.SkipKeys, false);
            }
            config.Languages = new HashSet <string>(new string[1] {
                flags.Language
            });

            if (flags.SkipKeys)
            {
                Console.Out.WriteLine("Disabling Key auto-detection...");
            }

            Regex versionRegex = new Regex(@"\d+\.\d+");
            Match versionMatch = versionRegex.Match(config.BuildName);

            if (versionMatch.Success)
            {
                float version = float.Parse(versionMatch.Value);

                if (version > 1.13)
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.Out.WriteLine("==========\nWARNING: Overtool only works with Overwatch version 1.13 and below! You are using {0}!", config.BuildName);
                    Console.Out.WriteLine("You must use DataTool for Overwatch 1.14 and above!\n==========");
                    Console.ResetColor();
                }
            }

            Console.Out.WriteLine("Using Overwatch Version {0}", config.BuildName);
            CASCHandler   handler = CASCHandler.OpenStorage(config);
            OwRootHandler ow      = handler.Root as OwRootHandler;

            if (ow == null)
            {
                Console.Error.WriteLine("Not a valid overwatch installation");
                return;
            }

            // Fail when trying to extract data from a specified language with 2 or less files found.
            if (ow.APMFiles.Count() == 0)
            {
                Console.Error.WriteLine("Could not find the files for language {0}. Please confirm that you have that language installed, and are using the names from the target language.", flags.Language);
                if (!flags.GracefulExit)
                {
                    return;
                }
            }

            Console.Out.WriteLine("Mapping...");
            Util.MapCMF(ow, handler, map, track, flags.Language);

            if (!flags.SkipKeys)
            {
                Console.Out.WriteLine("Adding Encryption Keys...");

                foreach (ulong key in track[0x90])
                {
                    if (!map.ContainsKey(key))
                    {
                        continue;
                    }
                    using (Stream stream = Util.OpenFile(map[key], handler)) {
                        if (stream == null)
                        {
                            continue;
                        }
                        ISTU stu = ISTU.NewInstance(stream, UInt32.Parse(config.BuildName.Split('.').Last()));
                        if (!(stu.Instances.FirstOrDefault() is STUEncryptionKey))
                        {
                            continue;
                        }
                        STUEncryptionKey ek = stu.Instances.FirstOrDefault() as STUEncryptionKey;
                        if (ek != null && !KeyService.keys.ContainsKey(ek.LongRevKey))
                        {
                            KeyService.keys.Add(ek.LongRevKey, ek.KeyValue);
                            Console.Out.WriteLine("Added Encryption Key {0}, Value: {1}", ek.KeyNameProper, ek.Key);
                        }
                    }
                }
            }

            Console.Out.WriteLine("Tooling...");

            tool.Parse(track, map, handler, quiet, flags);
            if (System.Diagnostics.Debugger.IsAttached)
            {
                System.Diagnostics.Debugger.Break();
            }
        }
Beispiel #4
0
            private string DumpGUID(IndentHelper indentHelper, ulong guid)
            {
                string baseString = $"\r\n{indentHelper + 1}[{GetGUIDTypeName(guid)}]";

                STUInstance[] instances;
                switch (GUID.Type(guid))
                {
                default:
                    return("");

                case 0x7C:
                case 0xA9:
                    return($"{baseString} \"{GetOWString(guid, _handler, _map)}\"");

                case 0x90:
                    instances = GetInstances(guid, _handler, _map);
                    if (instances[0] == null)
                    {
                        return(null);
                    }
                    STUEncryptionKey encryptionKey = instances[0] as STUEncryptionKey;
                    return($"{baseString} {encryptionKey?.KeyNameProper}:{encryptionKey?.Key}");

                case 0xA5:
                    instances = GetInstances(guid, _handler, _map);
                    STUUnlock unlock      = instances.OfType <STUUnlock>().First();
                    string    baseString2 = $"\r\n{indentHelper + 1}[{GetGUIDTypeName(guid)}";
                    if (unlock == null)
                    {
                        return(null);
                    }
                    if (unlock is STUUnlock_Currency)
                    {
                        return($"{baseString2}:Credits] {(unlock as STUUnlock_Currency).Amount} Credits");
                    }
                    else if (unlock is STULevelPortrait)
                    {
                        STULevelPortrait portrait = unlock as STULevelPortrait;
                        return
                            ($"{baseString2}:Credits] {portrait.Tier} Star:{portrait.Star} Level:{portrait.Level}");
                    }
                    else if (unlock is STUCompetitiveCurrencyReward)
                    {
                        STUCompetitiveCurrencyReward competitiveCurrencyReward = unlock as STUCompetitiveCurrencyReward;
                        return
                            ($"{baseString2}:CompetitivePoints] {competitiveCurrencyReward.Amount} points");
                    }
                    else
                    {
                        return($"{baseString2}:{unlock.GetType().Name}] \"{GetOWString(unlock.CosmeticName, _handler, _map)}\"");
                    }

                case 0x9E:
                    instances = GetInstances(guid, _handler, _map);
                    if (instances[0] == null)
                    {
                        return(null);
                    }
                    STULoadout ability = instances[0] as STULoadout;
                    return($"{baseString} \"{GetOWString(ability?.Name, _handler, _map)}\" ({ability?.Category})");

                case 0xC5:
                    instances = GetInstances(guid, _handler, _map);
                    if (instances[0] == null)
                    {
                        return(null);
                    }
                    STUGamemode gamemode = instances[0] as STUGamemode;
                    return($"{baseString} \"{GetOWString(gamemode?.DisplayName, _handler, _map)}\"");

                case 0xC6:
                    instances = GetInstances(guid, _handler, _map);
                    if (instances[0] == null)
                    {
                        return(null);
                    }
                    STUGameRulesetSchema gameRulsetSchema = instances[0] as STUGameRulesetSchema;
                    return($"{baseString} \"{GetOWString(gameRulsetSchema?.Name, _handler, _map)}\"");

                case 0x75:
                    instances = GetInstances(guid, _handler, _map);
                    if (instances[0] == null)
                    {
                        return(null);
                    }
                    STUHero hero = instances[0] as STUHero;
                    return($"{baseString} \"{GetOWString(hero?.Name, _handler, _map)}\"");
                }
            }