示例#1
0
        private unsafe void DoBackSpew()
        {
            var returnSizeStep = 65536;

            // reset it back to zero
            *(long *)(OriginalBundleDownload + 0x40) = 0;

            var rawPointer      = myWriterStream.GetPointer() + 8;
            var currentPosition = 0;
            var totalLength     = (int)myWriterStream.Length;

            while (currentPosition < totalLength)
            {
                var currentRead   = Math.Min(returnSizeStep, totalLength - currentPosition);
                var bytesConsumed = BundleDownloadMethods.OriginalReceiveBytes(OriginalBundleDownload,
                                                                               (IntPtr)(rawPointer + currentPosition), currentRead);
                currentPosition += currentRead;

                if (bytesConsumed != currentRead)
                {
                    // The thing refused to eat our data?
                    break;
                }
            }

            myWriterStream.ReleasePointer();
        }
示例#2
0
        internal void CompleteDownload()
        {
            if (myMemoryMap == null)
            {
                MelonDebug.Msg($"Did not succ any bytes for ptr {OriginalBundleDownload}, just completing");
                BundleDownloadMethods.OriginalCompleteDownload(OriginalBundleDownload);
                return;
            }

            MelonDebug.Msg($"Succed {myWriterStream.Position} bytes out of declared {BundleDlInterceptor.GetTotalSize(OriginalBundleDownload)}; waiting for victim process");

            var stopwatch = Stopwatch.StartNew();
            var exitCode  = myVerifierProcess.WaitForExit(TimeSpan.FromSeconds(BundleVerifierMod.TimeLimit.Value));

            MelonDebug.Msg($"Process wait done after {stopwatch.ElapsedMilliseconds}ms extra wait");
            if (exitCode != 0)
            {
                var cleanedUrl = BundleVerifierMod.SanitizeUrl(Url);
                MelonLogger.Msg($"Verifier process failed with exit code {exitCode} ({VerifierExitCodes.GetExitCodeDescription(exitCode)}) for bundle uid={cleanedUrl.Item1}+{cleanedUrl.Item2}");
                BundleVerifierMod.BadBundleCache.Add(Url);
                MelonDebug.Msg("Reporting completion without data");
                // feed some garbage into it, otherwise it dies
                unsafe
                {
                    *(long *)(OriginalBundleDownload + 0x40) = 0;
                    var stub  = "UnityFS\0";
                    var bytes = Encoding.UTF8.GetBytes(stub);

                    fixed(byte *bytesPtr = bytes)
                    BundleDownloadMethods.OriginalReceiveBytes(OriginalBundleDownload, (IntPtr)bytesPtr, bytes.Length);
                }

                BundleDownloadMethods.OriginalCompleteDownload(OriginalBundleDownload);
                return;
            }

            MelonDebug.Msg("Bundle looks clean, spewing back...");
            DoBackSpew();
            MelonDebug.Msg("Back-spew done, completing");
            BundleDownloadMethods.OriginalCompleteDownload(OriginalBundleDownload);
            MelonDebug.Msg("Completed!");
        }
示例#3
0
        internal int ProcessBytes(byte[] bytes, int offset, int length)
        {
            try
            {
                myWriterStream.Write(bytes, offset, length);
            }
            catch (IOException ex)
            {
                MelonLogger.Error($"Received more bytes than declared for bundle URL {Url} (declared: {BundleDlInterceptor.GetTotalSize(OriginalBundleDownload)})");
                MelonLogger.Error(ex.ToString());
                DoBackSpew();
                unsafe
                {
                    fixed(byte *bytesPtr = bytes)
                    BundleDownloadMethods.OriginalReceiveBytes(OriginalBundleDownload, (IntPtr)bytesPtr, length);
                }

                BundleDlInterceptor.CancelIntercept(this);
            }

            return(length);
        }
示例#4
0
        public static void OnApplicationStart(HarmonyLib.Harmony harmonyInstance)
        {
            var category = MelonPreferences.CreateCategory(SettingsCategory, "Advanced Safety - Bundles");

            TimeLimit      = category.CreateEntry("TimeLimit", 15, "Time limit (seconds)");
            MemoryLimit    = category.CreateEntry("MemLimit", 2048, "Memory limit (megabytes)");
            ComponentLimit = category.CreateEntry("ComponentLimit", 10_000, "Component limit (0=unlimited)");

            EnabledSetting = category.CreateEntry("Enabled", true, "Check for corrupted bundles");
            OnlyPublics    = category.CreateEntry("OnlyPublics", true, "Only check bundles in public worlds");

            BadBundleCache    = new BundleHashCache(Path.Combine(MelonUtils.UserDataDirectory, "BadBundleHashes.bin"));
            ForceAllowedCache = new BundleHashCache(null);

            var initSuccess = BundleDownloadMethods.Init();

            if (!initSuccess)
            {
                return;
            }

            try
            {
                PrepareVerifierDir();
            }
            catch (IOException ex)
            {
                MelonLogger.Error("Unable to extract bundle verifier app, the mod will not work");
                MelonLogger.Error(ex.ToString());
                return;
            }

            harmonyInstance.Patch(typeof(NetworkManager).GetMethod("OnLeftRoom"), new HarmonyMethod(typeof(BundleVerifierMod), nameof(OnLeftRoom)));
            harmonyInstance.Patch(typeof(NetworkManager).GetMethod("OnJoinedRoom"), new HarmonyMethod(typeof(BundleVerifierMod), nameof(OnJoinedRoom)));

            EnabledSetting.OnValueChangedUntyped += () => MelonCoroutines.Start(CheckInstanceType());
            OnlyPublics.OnValueChangedUntyped    += () => MelonCoroutines.Start(CheckInstanceType());
        }