From 8523c4912b759a34d1886b93716b8c9417d17f51 Mon Sep 17 00:00:00 2001 From: Anairkoen Schno Date: Fri, 13 Dec 2019 16:01:01 -0600 Subject: [PATCH] Added another check to the anti-piracy --- IPA.Injector/AntiPiracy.cs | 71 ++++++++++++++++++++++++++++++ IPA.Loader/Utilities/Extensions.cs | 63 ++++++++++++++++++++++++++ 2 files changed, 134 insertions(+) diff --git a/IPA.Injector/AntiPiracy.cs b/IPA.Injector/AntiPiracy.cs index ed610f86..bfa1116e 100644 --- a/IPA.Injector/AntiPiracy.cs +++ b/IPA.Injector/AntiPiracy.cs @@ -1,5 +1,7 @@ using System; using System.IO; +using System.Runtime.InteropServices; +using System.Security.Principal; using IPA.Utilities; #if NET3 using Net3_Proxy; @@ -16,6 +18,20 @@ namespace IPA.Injector { var dataPlugins = Path.Combine(GameVersionEarly.ResolveDataPath(path), "Plugins"); + try + { + var userDir = GetPath(new Guid("374DE290-123F-4565-9164-39C4925E467B"), + KnownFolderFlags.AliasOnly | KnownFolderFlags.DontVerify); + var userDir2 = GetPath(new Guid("7d83ee9b-2244-4e70-b1f5-5393042af1e4"), + KnownFolderFlags.AliasOnly | KnownFolderFlags.DontVerify); + + var curdir = Environment.CurrentDirectory; + + if (curdir.IsSubPathOf(userDir) || + curdir.IsSubPathOf(userDir2)) return false; + } + catch { } + return File.Exists(Path.Combine(path, "IGG-GAMES.COM.url")) || File.Exists(Path.Combine(path, "SmartSteamEmu.ini")) || @@ -24,5 +40,60 @@ namespace IPA.Injector File.Exists(Path.Combine(dataPlugins, "HUHUVR_steam_api64.dll")) || Directory.GetFiles(dataPlugins, "*.ini", SearchOption.TopDirectoryOnly).Length > 0; } + + private static string GetPath(Guid guid, KnownFolderFlags flags) + { + int result = SHGetKnownFolderPath(guid, (uint)flags, WindowsIdentity.GetCurrent().Token, out IntPtr outPath); + if (result >= 0) + { + string path = Marshal.PtrToStringUni(outPath); + Marshal.FreeCoTaskMem(outPath); + return path; + } + else + { + throw new ExternalException("Cannot get the known folder path. It may not be available on this system.", + result); + } + } + + /// + /// Retrieves the full path of a known folder identified by the folder's known folder ID. + /// + /// A known folder ID that identifies the folder. + /// Flags that specify special retrieval options. This value can be 0; otherwise, one or + /// more of the values. + /// An access token that represents a particular user. If this parameter is NULL, which is + /// the most common usage, the function requests the known folder for the current user. Assigning a value of -1 + /// indicates the Default User. The default user profile is duplicated when any new user account is created. + /// Note that access to the Default User folders requires administrator privileges. + /// When this method returns, contains the address of a string that specifies the path of + /// the known folder. The returned path does not include a trailing backslash. + /// Returns S_OK if successful, or an error value otherwise. + /// bb762188 + [DllImport("Shell32.dll")] + private static extern int SHGetKnownFolderPath([MarshalAs(UnmanagedType.LPStruct)]Guid rfid, uint dwFlags, + IntPtr hToken, out IntPtr ppszPath); + + /// + /// Represents the retrieval options for known folders. + /// + /// dd378447 + [Flags] + private enum KnownFolderFlags : uint + { + None = 0x00000000, + SimpleIDList = 0x00000100, + NotParentRelative = 0x00000200, + DefaultPath = 0x00000400, + Init = 0x00000800, + NoAlias = 0x00001000, + DontUnexpand = 0x00002000, + DontVerify = 0x00004000, + Create = 0x00008000, + NoAppcontainerRedirection = 0x00010000, + AliasOnly = 0x80000000 + } + } } diff --git a/IPA.Loader/Utilities/Extensions.cs b/IPA.Loader/Utilities/Extensions.cs index cfcfcb29..6161705f 100644 --- a/IPA.Loader/Utilities/Extensions.cs +++ b/IPA.Loader/Utilities/Extensions.cs @@ -1,4 +1,8 @@ using System; +using System.IO; +#if NET3 +using Path = Net3_Proxy.Path; +#endif namespace IPA.Utilities { @@ -23,5 +27,64 @@ namespace IPA.Utilities /// the bool? to unwrap /// the unwrapped value, or if it was public static bool Unwrap(this bool? self) => self != null && self.Value; + + /// + /// Returns true if starts with the path . + /// The comparison is case-insensitive, handles / and \ slashes as folder separators and + /// only matches if the base dir folder name is matched exactly ("c:\foobar\file.txt" is not a sub path of "c:\foo"). + /// + public static bool IsSubPathOf(this string path, string baseDirPath) + { + string normalizedPath = Path.GetFullPath(path.Replace('/', '\\') + .WithEnding("\\")); + + string normalizedBaseDirPath = Path.GetFullPath(baseDirPath.Replace('/', '\\') + .WithEnding("\\")); + + return normalizedPath.StartsWith(normalizedBaseDirPath, StringComparison.OrdinalIgnoreCase); + } + + /// + /// Returns with the minimal concatenation of (starting from end) that + /// results in satisfying .EndsWith(ending). + /// + /// "hel".WithEnding("llo") returns "hello", which is the result of "hel" + "lo". + public static string WithEnding(this string str, string ending) + { + if (str == null) + return ending; + + string result = str; + + // Right() is 1-indexed, so include these cases + // * Append no characters + // * Append up to N characters, where N is ending length + for (int i = 0; i <= ending.Length; i++) + { + string tmp = result + ending.Right(i); + if (tmp.EndsWith(ending)) + return tmp; + } + + return result; + } + + /// Gets the rightmost characters from a string. + /// The string to retrieve the substring from. + /// The number of characters to retrieve. + /// The substring. + public static string Right(this string value, int length) + { + if (value == null) + { + throw new ArgumentNullException("value"); + } + if (length < 0) + { + throw new ArgumentOutOfRangeException("length", length, "Length is less than zero"); + } + + return (length < value.Length) ? value.Substring(value.Length - length) : value; + } } }