|
1 | 1 | using MelonLoader; |
2 | 2 | using System; |
3 | | -using System.Collections.Generic; |
4 | | -using System.IO; |
5 | | -using System.Linq; |
6 | 3 | using System.Reflection; |
7 | | -using System.Text; |
8 | | -using System.Threading.Tasks; |
9 | | -using System.Windows.Forms; |
10 | 4 |
|
11 | | -[assembly: MelonInfo(typeof(Astrum.AstralBypass), nameof(Astrum.AstralBypass), "0.1.0", downloadLink: "github.com/Astrum-Project/" + nameof(Astrum.AstralBypass))] |
| 5 | +[assembly: MelonInfo(typeof(Astrum.AstralBypass), nameof(Astrum.AstralBypass), "0.1.1", downloadLink: "github.com/Astrum-Project/" + nameof(Astrum.AstralBypass))] |
12 | 6 | [assembly: MelonColor(ConsoleColor.DarkMagenta)] |
13 | 7 |
|
14 | 8 | namespace Astrum |
15 | 9 | { |
16 | | - public class AstralBypass : MelonPlugin |
| 10 | + public partial class AstralBypass : MelonPlugin |
17 | 11 | { |
18 | | - private const string pluginsPath = "Plugins/AstralBypass.dll"; |
19 | | - private const string modsPath = "Mods/AstralBypass.dll"; |
20 | | - private const int renameExitStatus = 69_8153697; // random number, but the 69 should indicate that it's human written; |
| 12 | + private const BindingFlags PrivateStatic = BindingFlags.NonPublic | BindingFlags.Static; |
21 | 13 |
|
22 | | - private static IntPtr pIC = IntPtr.Zero; |
| 14 | + static AstralBypass() => PEBKACHelper.CheckForUserError(); |
23 | 15 |
|
24 | | - static AstralBypass() |
25 | | - { |
26 | | - CheckLocation(); |
27 | | - |
28 | | - FindIC(); |
29 | | - } |
30 | | - |
31 | | - private static void CheckLocation() |
32 | | - { |
33 | | - if (File.Exists(pluginsPath)) return; |
34 | | - |
35 | | - if (File.Exists(modsPath)) MoveToPlugins(modsPath); |
36 | | - |
37 | | - // since people love renaming their dlls for some reason |
38 | | - string plugin = Directory.EnumerateFiles("Plugins") |
39 | | - .Where(x => x.ToLower().EndsWith(".dll")) |
40 | | - .Where(x => new FileInfo(x).Length < 100_000) // 100kb |
41 | | - .FirstOrDefault(x => File.ReadAllText(x).Contains("AstralBypass.pdb")); |
42 | | - |
43 | | - if (plugin != null) MoveToPlugins(plugin); |
44 | | - |
45 | | - string mod = Directory.EnumerateFiles("Mods") |
46 | | - .Where(x => x.ToLower().EndsWith(".dll")) |
47 | | - .Where(x => new FileInfo(x).Length < 100_000) |
48 | | - .FirstOrDefault(x => File.ReadAllText(x).Contains("AstralBypass.pdb")); |
49 | | - |
50 | | - if (mod != null) MoveToPlugins(mod); |
51 | | - |
52 | | - MessageBox.Show("Failed to locate AstralBypass.\nPlease place \"AstralBypass.dll\" into your plugins folder.\nThe game has been halted for you to do this.", "Problems loading AstralBypass"); |
53 | | - Environment.Exit(renameExitStatus); |
54 | | - } |
55 | | - |
56 | | - private static void MoveToPlugins(string orig) |
57 | | - { |
58 | | - Console.Beep(); |
59 | | - Console.Beep(); |
60 | | - Console.Beep(); |
61 | | - MessageBox.Show("AstralBypass was in the wrong folder or incorrectly named.\nIt will now be relocated to your plugins folder", "Restarting game..."); |
62 | | - |
63 | | - if (File.Exists(pluginsPath)) |
64 | | - File.Delete(pluginsPath); |
65 | | - File.Move(orig, pluginsPath); |
66 | | - |
67 | | - Environment.Exit(renameExitStatus); |
68 | | - } |
69 | | - |
70 | | - private static void FindIC() |
71 | | - { |
72 | | - // TODO: add other ML versions to this |
73 | | - pIC = AstralCore.Utils.PatternScanner.Scan( |
74 | | - "bootstrap.dll", |
75 | | - "66 0F 2F C7" + // comisd xmm0, xmm7 |
76 | | - "77 1E" + // ja bootstrap.7FFF9D5688D6 |
77 | | - "66 0F 2F ?? ?? ?? ?? ??" + // comisd xmm7,qword ptr ds:[7FFF9D583EC8] |
78 | | - "77 14" + // ja bootstrap.7FFF9D5688D6 |
79 | | - "48 8D 4D B0" + // lea rcx,qword ptr ss:[rbp-50] |
80 | | - "E8 ?? ?? ?? ??" + // call bootstrap.7FFF9D567AF0 |
81 | | - "49 8B CF" + // mov rcx,r15 |
82 | | - "FF 15 ?? ?? ?? ??" + // call qword ptr ds:[< &mono_image_close >] |
83 | | - "EB 2E" + // jmp bootstrap.7FFF9D568904 |
84 | | - "48 8D 4D B0" + // lea rcx,qword ptr ss:[rbp-50] |
85 | | - "E8 ?? ?? ?? ??" + // call bootstrap.7FFF9D567AF0 |
86 | | - "49 8B CF" + // mov rcx,r15 |
87 | | - "FF 15 ?? ?? ?? ??" + // call qword ptr ds:[< &mono_image_close >] |
88 | | - "48 8B ?? ?? ?? ?? ??" + // mov rbx, qword ptr ds:[< &mono_raise_exception >] |
89 | | - "48 8B ?? ?? ?? ?? ??" + // mov rax, qword ptr ds:[< &mono_get_exception_bad_image_format >] |
90 | | - "48 8D ?? ?? ?? ?? ??" + // lea rcx, qword ptr ds:[7FFF9D5820B8] |
91 | | - "FF D0" + // call rax |
92 | | - "48 8B C8" + // mov rcx, rax |
93 | | - "FF D3", // call rbx ; <== PATCHING THIS |
94 | | - 80 |
| 16 | + public override void OnApplicationEarlyStart() => |
| 17 | + HarmonyInstance.Patch( |
| 18 | + typeof(Assembly).GetMethod(nameof(Assembly.Load), new Type[2] { typeof(byte[]), typeof(byte[]) }), |
| 19 | + typeof(AstralBypass).GetMethod(nameof(AssemblyLoadPre), PrivateStatic).ToNewHarmonyMethod(), |
| 20 | + typeof(AstralBypass).GetMethod(nameof(AssemblyLoadPost), PrivateStatic).ToNewHarmonyMethod() |
95 | 21 | ); |
96 | 22 |
|
97 | | - if (pIC == IntPtr.Zero) AstralCore.Logger.Error("Failed to find Integrity Check"); |
98 | | - else BypassIC(); |
99 | | - } |
100 | | - |
101 | | - public static void BypassIC() => AstralCore.Utils.MemoryUtils.WriteBytes(pIC, new byte[2] { 0x90, 0x90 }); |
102 | | - public static void RepairIC() => AstralCore.Utils.MemoryUtils.WriteBytes(pIC, new byte[2] { 0xFF, 0xD3 }); |
| 23 | + private static void AssemblyLoadPre() => IntegrityChecks.Bypass(); |
| 24 | + private static void AssemblyLoadPost() => IntegrityChecks.Repair(); |
| 25 | + |
| 26 | + // if this bypass breaks, open an issue on the github |
| 27 | + // i have a more aggressive fix than this non-intrusive one |
103 | 28 | } |
104 | 29 | } |
0 commit comments