From 52283917010c599d2468dc4facb04b6e14e14f3d Mon Sep 17 00:00:00 2001 From: issuimo <1992724048@qq.com> Date: Sun, 4 Feb 2024 12:07:57 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BA=86=20-=20=E6=97=A0?= =?UTF-8?q?=E6=B3=95=E6=B3=A8=E5=85=A5=E9=97=AE=E9=A2=98=20-=20=E6=A0=88?= =?UTF-8?q?=E6=BA=A2=E5=87=BA=E6=BC=8F=E6=B4=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Inject & launcher/Form1.Designer.cs | 14 + Inject & launcher/Form1.cs | 96 +-- .../Inject & launcher.csproj.user | 2 +- .../PublishProfiles/FolderProfile.pubxml.user | 2 +- Phasmophobia/dllmain.cpp | 541 +++++++------- Phasmophobia/library/UnityResolve.hpp | 697 ++++++++++-------- Phasmophobia/library/d3d11hook.h | 4 +- 7 files changed, 710 insertions(+), 646 deletions(-) diff --git a/Inject & launcher/Form1.Designer.cs b/Inject & launcher/Form1.Designer.cs index 550a0bd..8d492f4 100644 --- a/Inject & launcher/Form1.Designer.cs +++ b/Inject & launcher/Form1.Designer.cs @@ -32,6 +32,7 @@ partial class Form1 { this.linkLabel1 = new LinkLabel(); this.listBox1 = new ListBox(); this.button3 = new Button(); + this.label2 = new Label(); SuspendLayout(); // // button1 @@ -127,11 +128,23 @@ partial class Form1 { this.button3.UseVisualStyleBackColor = false; this.button3.Click += button3_Click; // + // label2 + // + this.label2.AutoSize = true; + this.label2.Font = new Font("Microsoft YaHei UI", 14.25F, FontStyle.Regular, GraphicsUnit.Point, 134); + this.label2.Location = new Point(135, 338); + this.label2.Name = "label2"; + this.label2.Size = new Size(26, 25); + this.label2.TabIndex = 9; + this.label2.Text = ">"; + this.label2.Click += label2_Click; + // // Form1 // AutoScaleDimensions = new SizeF(7F, 17F); AutoScaleMode = AutoScaleMode.Font; ClientSize = new Size(289, 381); + Controls.Add(this.label2); Controls.Add(this.button3); Controls.Add(this.listBox1); Controls.Add(this.linkLabel1); @@ -163,5 +176,6 @@ partial class Form1 { private LinkLabel linkLabel1; private ListBox listBox1; private Button button3; + private Label label2; } } diff --git a/Inject & launcher/Form1.cs b/Inject & launcher/Form1.cs index c5a9230..1658fa6 100644 --- a/Inject & launcher/Form1.cs +++ b/Inject & launcher/Form1.cs @@ -13,30 +13,8 @@ public partial class Form1 : Form { } } - [DllImport("kernel32.dll")] //声明API函数 - public static extern IntPtr VirtualAllocEx(IntPtr hwnd, IntPtr lpaddress, int size, int type, int tect); - - [DllImport("kernel32.dll")] - public static extern int WriteProcessMemory(IntPtr hwnd, IntPtr baseaddress, string buffer, int nsize, int filewriten); - - [DllImport("kernel32.dll")] - public static extern IntPtr GetProcAddress(IntPtr hwnd, string lpname); - - [DllImport("kernel32.dll")] - public static extern IntPtr GetModuleHandleA(string name); - - [DllImport("kernel32.dll")] - public static extern IntPtr CreateRemoteThread(IntPtr hwnd, IntPtr attrib, int size, IntPtr address, IntPtr par, int flags, IntPtr threadid); - - - [DllImport("KERNEL32.DLL ")] - public static extern int CloseHandle(IntPtr handle); - - [DllImport("kernel32.dll")] - public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId); - - [DllImport("kernel32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] - public static extern long GetLastError(); + [DllImport("Phasmophobia.dll")] //声明API函数 + public static extern void Inject(); /// /// @@ -87,7 +65,7 @@ public partial class Form1 : Form { p.StandardInput.AutoFlush = true; p.WaitForExit(); //等待程序执行完退出进程 p.Close(); - + this.button1.Enabled = true; }).Start(); } catch (ThreadStateException ex) { @@ -154,68 +132,16 @@ public partial class Form1 : Form { } private void button3_Click(object sender, EventArgs e) { -new Thread( - () => { - this.button3.Enabled = false; - findProcess: - var process = Process.GetProcessesByName("Phasmophobia"); - if (process == null || process.Length == 0) { - Thread.Sleep(5000); - goto findProcess; - } - - Int32 SYNCHRONIZE = 0x00100000; - - Int32 STANDARD_RIGHTS_REQUIRED = 0x000F0000; - - Int32 PROCESS_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFF); - - - string dllname = System.AppDomain.CurrentDomain.BaseDirectory + "Phasmophobia.dll"; - this.listBox1.Items.Add(Log.FormatLog("游戏ID: " + process[0].Id)); - nint handle = OpenProcess(PROCESS_ALL_ACCESS, false, process[0].Id); - this.listBox1.Items.Add(Log.FormatLog("游戏句柄: " + handle)); - this.listBox1.Items.Add(Log.FormatLog("正在注入...")); - IntPtr allocBaseAddress = VirtualAllocEx(handle, 0, dllname.Length, 4096, 4); - if (allocBaseAddress == 0) { - MessageBox.Show("内存分配失败", "错误"); - this.listBox1.Items.Add(Log.FormatLog("内存分配失败!")); - this.button3.Enabled = true; - return; - } - - this.listBox1.Items.Add(Log.FormatLog("已分配内存地址: " + allocBaseAddress)); - - if (WriteProcessMemory(handle, allocBaseAddress, dllname, dllname.Length, 0) == 0) { - MessageBox.Show("DLL写入失败 error:" + GetLastError(), "错误", 0); - this.listBox1.Items.Add(Log.FormatLog("DLL写入失败!")); - this.button3.Enabled = true; - return; - } - - IntPtr loadaddr = GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryA"); - if (loadaddr == 0) { - MessageBox.Show("取得LoadLibraryA的地址失败"); - this.listBox1.Items.Add(Log.FormatLog("取得LoadLibraryA的地址失败!")); - this.button3.Enabled = true; - return; - } - - this.listBox1.Items.Add(Log.FormatLog("LoadLibraryA内存地址: " + loadaddr)); - - IntPtr ThreadHwnd = CreateRemoteThread(handle, 0, 0, loadaddr, allocBaseAddress, 0, 0); - if (ThreadHwnd == IntPtr.Zero) { - MessageBox.Show("创建远程线程失败"); - this.listBox1.Items.Add(Log.FormatLog("创建远程线程失败!")); - this.button3.Enabled = true; - return; - } + new Thread( + () => { + this.button3.Enabled = false; + Form1.Inject(); + this.button3.Enabled = true; + }).Start(); + } - this.listBox1.Items.Add(Log.FormatLog("远程线程句柄: " + ThreadHwnd)); + private void label2_Click(object sender, EventArgs e) { - this.listBox1.Items.Add(Log.FormatLog("注入成功!")); - this.button3.Enabled = true; - }).Start(); } } } \ No newline at end of file diff --git a/Inject & launcher/Inject & launcher.csproj.user b/Inject & launcher/Inject & launcher.csproj.user index 4295dc0..07050c0 100644 --- a/Inject & launcher/Inject & launcher.csproj.user +++ b/Inject & launcher/Inject & launcher.csproj.user @@ -1,7 +1,7 @@  - <_LastSelectedProfileId>D:\代码\Phasmophobia\Inject & launcher\Properties\PublishProfiles\FolderProfile.pubxml + <_LastSelectedProfileId>E:\APP\PhasmophobiaCheat\Inject & launcher\Properties\PublishProfiles\FolderProfile.pubxml diff --git a/Inject & launcher/Properties/PublishProfiles/FolderProfile.pubxml.user b/Inject & launcher/Properties/PublishProfiles/FolderProfile.pubxml.user index e3d1e72..c1b3282 100644 --- a/Inject & launcher/Properties/PublishProfiles/FolderProfile.pubxml.user +++ b/Inject & launcher/Properties/PublishProfiles/FolderProfile.pubxml.user @@ -4,7 +4,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121. --> - True|2023-08-22T03:36:16.4713851Z;True|2023-08-22T11:34:34.7411867+08:00;True|2023-08-22T11:01:24.4057170+08:00;True|2023-08-22T10:48:04.0176246+08:00;True|2023-08-20T22:24:16.8807147+08:00;True|2023-08-20T22:17:07.7122993+08:00;True|2023-08-20T21:37:08.2505839+08:00;True|2023-08-20T21:30:39.9997950+08:00;True|2023-08-20T20:56:32.9642789+08:00;True|2023-08-20T20:54:22.2111866+08:00;True|2023-08-20T20:25:42.7514045+08:00;True|2023-08-20T20:22:31.1387630+08:00;True|2023-08-20T20:20:37.8825783+08:00;True|2023-08-20T20:18:02.5090329+08:00;True|2023-08-20T20:16:31.2357270+08:00;True|2023-08-20T17:56:11.7437646+08:00;False|2023-08-20T17:55:32.8103986+08:00;False|2023-08-20T17:55:08.6606799+08:00;False|2023-08-20T17:48:14.0384117+08:00;False|2023-08-20T17:47:00.1949649+08:00;False|2023-08-20T17:43:41.3829674+08:00;False|2023-08-20T17:42:45.4533940+08:00;False|2023-08-20T17:30:26.8329100+08:00;False|2023-08-20T17:25:37.0721141+08:00;False|2023-08-20T17:23:10.4866537+08:00;False|2023-08-20T17:22:06.2446466+08:00;False|2023-08-20T17:21:51.9085101+08:00;False|2023-08-20T17:13:49.4061589+08:00;False|2023-08-20T17:03:40.7429387+08:00;False|2023-08-20T17:01:08.0146089+08:00;True|2023-08-20T17:00:19.4299224+08:00;False|2023-08-20T16:59:59.4328076+08:00;False|2023-08-20T16:56:48.1290848+08:00;False|2023-08-20T16:55:52.5232280+08:00;False|2023-08-20T16:55:35.9491754+08:00;True|2023-08-20T16:54:20.3238788+08:00; + True|2024-02-04T04:06:59.4471403Z;True|2023-08-22T11:36:16.4713851+08:00;True|2023-08-22T11:34:34.7411867+08:00;True|2023-08-22T11:01:24.4057170+08:00;True|2023-08-22T10:48:04.0176246+08:00;True|2023-08-20T22:24:16.8807147+08:00;True|2023-08-20T22:17:07.7122993+08:00;True|2023-08-20T21:37:08.2505839+08:00;True|2023-08-20T21:30:39.9997950+08:00;True|2023-08-20T20:56:32.9642789+08:00;True|2023-08-20T20:54:22.2111866+08:00;True|2023-08-20T20:25:42.7514045+08:00;True|2023-08-20T20:22:31.1387630+08:00;True|2023-08-20T20:20:37.8825783+08:00;True|2023-08-20T20:18:02.5090329+08:00;True|2023-08-20T20:16:31.2357270+08:00;True|2023-08-20T17:56:11.7437646+08:00;False|2023-08-20T17:55:32.8103986+08:00;False|2023-08-20T17:55:08.6606799+08:00;False|2023-08-20T17:48:14.0384117+08:00;False|2023-08-20T17:47:00.1949649+08:00;False|2023-08-20T17:43:41.3829674+08:00;False|2023-08-20T17:42:45.4533940+08:00;False|2023-08-20T17:30:26.8329100+08:00;False|2023-08-20T17:25:37.0721141+08:00;False|2023-08-20T17:23:10.4866537+08:00;False|2023-08-20T17:22:06.2446466+08:00;False|2023-08-20T17:21:51.9085101+08:00;False|2023-08-20T17:13:49.4061589+08:00;False|2023-08-20T17:03:40.7429387+08:00;False|2023-08-20T17:01:08.0146089+08:00;True|2023-08-20T17:00:19.4299224+08:00;False|2023-08-20T16:59:59.4328076+08:00;False|2023-08-20T16:56:48.1290848+08:00;False|2023-08-20T16:55:52.5232280+08:00;False|2023-08-20T16:55:35.9491754+08:00;True|2023-08-20T16:54:20.3238788+08:00; \ No newline at end of file diff --git a/Phasmophobia/dllmain.cpp b/Phasmophobia/dllmain.cpp index fda3f34..427d027 100644 --- a/Phasmophobia/dllmain.cpp +++ b/Phasmophobia/dllmain.cpp @@ -6,6 +6,7 @@ #include "library/imgui/imgui_impl_dx11.h" #include "library/imgui/imgui_impl_win32.h" #include "library/imgui/imgui_internal.h" +#include extern auto ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) -> LRESULT; @@ -13,269 +14,271 @@ auto APIENTRY DllMain(HMODULE hModule, const DWORD ul_reason_for_call, LPVOID lp switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: init_space::Info::hModule = hModule; - std::thread([hModule] { - - // 打开控制台 - console::StartConsole(L"Console", false); - - // 初始化Mono - UnityResolve::Init(GetModuleHandleA("GameAssembly.dll"), UnityResolve::Mode::Il2Cpp); - - // 初始化功能列表 - init_space::Feature::Init(); - - // 安装D3D11HOOK - dx_hook::Hk11::Build([hModule] { - if (!init_space::Info::imGuiInit) { - UnityResolve::ThreadAttach(); - - IMGUI_CHECKVERSION(); - - // 创建ImGui上下文 - ImGui::CreateContext(); - ImPlot::CreateContext(); - - // 获取ImGui IO 并设置 键盘和手柄控制 - auto& io = ImGui::GetIO(); - io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; - io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; - - // 设置中文字体 - io.Fonts->AddFontFromMemoryTTF(Font::getallfont(), 2362740, 15, nullptr, io.Fonts->GetGlyphRangesChineseFull()); - - // 初始化ImGui D3D11设备和窗口 - ImGui_ImplWin32_Init(dx_hook::Hk11::GetHwnd()); - ImGui_ImplDX11_Init(dx_hook::Hk11::GetDevice(), dx_hook::Hk11::GetContext()); - - // 接管窗口消息 - dx_hook::Hk11::SetWndProc([](const HWND hWnd, const UINT msg, const WPARAM wParam, const LPARAM lParam) -> char { - POINT mPos; - GetCursorPos(&mPos); - ScreenToClient(dx_hook::Hk11::GetHwnd(), &mPos); - ImGui::GetIO().MousePos.x = static_cast(mPos.x); - ImGui::GetIO().MousePos.y = static_cast(mPos.y); - ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam); - - HotKey::PotMsg(msg); - - // 按键处理 - switch (msg) { - case WM_KEYDOWN: - // 处理界面显示/隐藏 - if (wParam == VK_DELETE) { - if (init_space::Info::mainShow) init_space::Info::mainShow = false; - else init_space::Info::mainShow = true; - } - break; - case WM_KEYUP: break; - case WM_CLOSE: const auto result = MessageBox(nullptr, L"你确定要退出游戏吗?", L"Confirmation",MB_YESNO | MB_ICONQUESTION); + if (GetModuleHandle(L"Phasmophobia.exe")) { + std::thread([hModule] { - if (result == IDYES) exit(0); - if (result == IDNO) return 2; - break; - } + // 打开控制台 + console::StartConsole(L"Console", false); - if (init_space::Info::mainShow == true) return false; - - return true; - }); - - auto HexToRGBA = [](const std::string& Hex) { - int r, g, b, a; - sscanf_s(Hex.c_str(), "%02x%02x%02x%02x", &r, &g, &b, &a); - const ImVec4 color{(static_cast(r) / 255), (static_cast(g) / 255), (static_cast(b) / 255), (static_cast(a) / 255)}; - return color; - }; - - auto& styles = ImGui::GetStyle(); - - // Colors - auto colors = styles.Colors; - colors[ImGuiCol_Border] = HexToRGBA("0C846ED5"); - colors[ImGuiCol_BorderShadow] = HexToRGBA("00000000"); - colors[ImGuiCol_Button] = HexToRGBA("0D9F9D9F"); - colors[ImGuiCol_ButtonActive] = HexToRGBA("076B3A94"); - colors[ImGuiCol_ButtonHovered] = HexToRGBA("0CAD4FCA"); - colors[ImGuiCol_CheckMark] = HexToRGBA("E6E6E680"); - colors[ImGuiCol_ChildBg] = HexToRGBA("00000045"); - colors[ImGuiCol_DragDropTarget] = HexToRGBA("333333FF"); - colors[ImGuiCol_FrameBg] = HexToRGBA("00000066"); - colors[ImGuiCol_FrameBgActive] = HexToRGBA("0D7F33B0"); - colors[ImGuiCol_FrameBgHovered] = HexToRGBA("09818B66"); - colors[ImGuiCol_Header] = HexToRGBA("0297959F"); - colors[ImGuiCol_HeaderActive] = HexToRGBA("07834ACC"); - colors[ImGuiCol_HeaderHovered] = HexToRGBA("00B8588A"); - colors[ImGuiCol_MenuBarBg] = HexToRGBA("069981CC"); - colors[ImGuiCol_ModalWindowDimBg] = HexToRGBA("3333335A"); - colors[ImGuiCol_NavHighlight] = HexToRGBA("7373E6CC"); - colors[ImGuiCol_NavWindowingDimBg] = HexToRGBA("CCCCCC33"); - colors[ImGuiCol_NavWindowingHighlight] = HexToRGBA("FFFFFFB3"); - colors[ImGuiCol_PlotHistogram] = HexToRGBA("E6B300FF"); - colors[ImGuiCol_PlotHistogramHovered] = HexToRGBA("FF9900FF"); - colors[ImGuiCol_PlotLines] = HexToRGBA("FFFFFFFF"); - colors[ImGuiCol_PlotLinesHovered] = HexToRGBA("E6B300FF"); - colors[ImGuiCol_PopupBg] = HexToRGBA("1D1D24EB"); - colors[ImGuiCol_ResizeGrip] = HexToRGBA("FFFFFF1A"); - colors[ImGuiCol_ResizeGripActive] = HexToRGBA("C7D2FFE6"); - colors[ImGuiCol_ResizeGripHovered] = HexToRGBA("C7D2FF99"); - colors[ImGuiCol_ScrollbarBg] = HexToRGBA("33404D99"); - colors[ImGuiCol_ScrollbarGrab] = HexToRGBA("0C864E65"); - colors[ImGuiCol_ScrollbarGrabActive] = HexToRGBA("02B3916F"); - colors[ImGuiCol_ScrollbarGrabHovered] = HexToRGBA("05925966"); - colors[ImGuiCol_Separator] = HexToRGBA("1CA09A7E"); - colors[ImGuiCol_SeparatorActive] = HexToRGBA("0099B1FF"); - colors[ImGuiCol_SeparatorHovered] = HexToRGBA("048897FF"); - colors[ImGuiCol_SliderGrab] = HexToRGBA("FFFFFF4D"); - colors[ImGuiCol_SliderGrabActive] = HexToRGBA("04882F99"); - colors[ImGuiCol_Tab] = HexToRGBA("18999F60"); - colors[ImGuiCol_TabActive] = HexToRGBA("038B4CD7"); - colors[ImGuiCol_TabHovered] = HexToRGBA("1E784BCC"); - colors[ImGuiCol_TabUnfocused] = HexToRGBA("FFFFFF00"); - colors[ImGuiCol_TabUnfocusedActive] = HexToRGBA("5A5AA700"); - colors[ImGuiCol_TableBorderLight] = HexToRGBA("FFFFFF00"); - colors[ImGuiCol_TableBorderStrong] = HexToRGBA("00014000"); - colors[ImGuiCol_TableHeaderBg] = HexToRGBA("2E8D89FF"); - colors[ImGuiCol_TableRowBg] = HexToRGBA("3E72769A"); - colors[ImGuiCol_TableRowBgAlt] = HexToRGBA("154D3E9B"); - colors[ImGuiCol_Text] = HexToRGBA("E6E6E6FF"); - colors[ImGuiCol_TextDisabled] = HexToRGBA("999999FF"); - colors[ImGuiCol_TextSelectedBg] = HexToRGBA("00A87E5A"); - colors[ImGuiCol_TitleBg] = HexToRGBA("00998D8A"); - colors[ImGuiCol_TitleBgActive] = HexToRGBA("008D556B"); - colors[ImGuiCol_TitleBgCollapsed] = HexToRGBA("27B6C14A"); - colors[ImGuiCol_WindowBg] = HexToRGBA("00000096"); - - //Styles - styles.Alpha = 1.0; - styles.AntiAliasedFill = true; - styles.AntiAliasedLines = true; - styles.AntiAliasedLinesUseTex = true; - styles.ButtonTextAlign = ImVec2(0.5, 0.5); - styles.CellPadding = ImVec2(4.0, 2.0); - styles.ChildBorderSize = 1.0; - styles.ChildRounding = 0.0; - styles.CircleTessellationMaxError = 0.30000001192092896; - styles.ColorButtonPosition = 1; - styles.ColumnsMinSpacing = 6.0; - styles.CurveTessellationTol = 1.25; - styles.DisabledAlpha = 0.6000000238418579; - styles.DisplaySafeAreaPadding = ImVec2(3.0, 3.0); - styles.DisplayWindowPadding = ImVec2(19.0, 19.0); - styles.FrameBorderSize = 0.0; - styles.FramePadding = ImVec2(4.0, 3.0); - styles.FrameRounding = 0.0; - styles.GrabMinSize = 10.0; - styles.GrabRounding = 0.0; - styles.IndentSpacing = 21.0; - styles.ItemInnerSpacing = ImVec2(4.0, 4.0); - styles.ItemSpacing = ImVec2(8.0, 4.0); - styles.LogSliderDeadzone = 4.0; - styles.MouseCursorScale = 1.0; - styles.PopupBorderSize = 0.0; - styles.PopupRounding = 0.0; - styles.ScrollbarRounding = 0.0; - styles.ScrollbarSize = 14.0; - styles.SelectableTextAlign = ImVec2(0.0, 0.0); - styles.TabBorderSize = 0.0; - styles.TabMinWidthForCloseButton = 0.0; - styles.TabRounding = 0.0; - styles.TouchExtraPadding = ImVec2(0.0, 0.0); - styles.WindowBorderSize = 0.0; - styles.WindowMenuButtonPosition = 0; - styles.WindowMinSize = ImVec2(32.0, 32.0); - styles.WindowPadding = ImVec2(8.0, 8.0); - styles.WindowRounding = 0.0; - styles.WindowTitleAlign = ImVec2(0.0, 0.5); - - init_space::Info::imGuiInit = true; - init_space::Info::mainShow = false; - init_space::Info::tipsShow = true; - } + // 初始化Mono + UnityResolve::Init(GetModuleHandleA("GameAssembly.dll"), UnityResolve::Mode::Il2Cpp); + + // 初始化功能列表 + init_space::Feature::Init(); + + // 安装D3D11HOOK + dx_hook::Hk11::Build([hModule] { + if (!init_space::Info::imGuiInit) { + UnityResolve::ThreadAttach(); + + IMGUI_CHECKVERSION(); + + // 创建ImGui上下文 + ImGui::CreateContext(); + ImPlot::CreateContext(); - // 创建新的画面帧 - ImGui_ImplDX11_NewFrame(); - ImGui_ImplWin32_NewFrame(); - ImGui::NewFrame(); - - // 主界面 - if (!init_space::Info::tipsShow) { - if (ImGui::Begin(reinterpret_cast(u8"Phasmophobia Cheat By 遂沫"), &init_space::Info::show, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings)) { - if (ImGui::Button(U8(u8"保存 (Save)"))) { - if (std::ofstream o(".\\cfg.json"); o) { - nlohmann::json js; - for (const auto& _features : init_space::Feature::features | std::views::values) - for (const auto func : _features) func->Save(js); - o << js; - o.close(); + // 获取ImGui IO 并设置 键盘和手柄控制 + auto& io = ImGui::GetIO(); + io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; + io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; + + // 设置中文字体 + io.Fonts->AddFontFromMemoryTTF(Font::getallfont(), 2362740, 15, nullptr, io.Fonts->GetGlyphRangesChineseFull()); + + // 初始化ImGui D3D11设备和窗口 + ImGui_ImplWin32_Init(dx_hook::Hk11::GetHwnd()); + ImGui_ImplDX11_Init(dx_hook::Hk11::GetDevice(), dx_hook::Hk11::GetContext()); + + // 接管窗口消息 + dx_hook::Hk11::SetWndProc([](const HWND hWnd, const UINT msg, const WPARAM wParam, const LPARAM lParam) -> char { + POINT mPos; + GetCursorPos(&mPos); + ScreenToClient(dx_hook::Hk11::GetHwnd(), &mPos); + ImGui::GetIO().MousePos.x = static_cast(mPos.x); + ImGui::GetIO().MousePos.y = static_cast(mPos.y); + ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam); + + HotKey::PotMsg(msg); + + // 按键处理 + switch (msg) { + case WM_KEYDOWN: + // 处理界面显示/隐藏 + if (wParam == VK_DELETE) { + if (init_space::Info::mainShow) init_space::Info::mainShow = false; + else init_space::Info::mainShow = true; + } + break; + case WM_KEYUP: break; + case WM_CLOSE: const auto result = MessageBox(nullptr, L"你确定要退出游戏吗?", L"Confirmation",MB_YESNO | MB_ICONQUESTION); + + if (result == IDYES) exit(0); + if (result == IDNO) return 2; + break; } - } - ImGui::SameLine(); - if (ImGui::Button(reinterpret_cast(u8"读取 (Load)"))) { - if (std::ifstream i(".\\cfg.json"); i) { - auto js = nlohmann::json::parse(i); - for (const auto& _features : init_space::Feature::features | std::views::values) { - for (const auto func : _features) - try { func->Load(js); } catch (...) {} + + if (init_space::Info::mainShow == true) return false; + + return true; + }); + + auto HexToRGBA = [](const std::string& Hex) { + int r, g, b, a; + sscanf_s(Hex.c_str(), "%02x%02x%02x%02x", &r, &g, &b, &a); + const ImVec4 color{(static_cast(r) / 255), (static_cast(g) / 255), (static_cast(b) / 255), (static_cast(a) / 255)}; + return color; + }; + + auto& styles = ImGui::GetStyle(); + + // Colors + auto colors = styles.Colors; + colors[ImGuiCol_Border] = HexToRGBA("0C846ED5"); + colors[ImGuiCol_BorderShadow] = HexToRGBA("00000000"); + colors[ImGuiCol_Button] = HexToRGBA("0D9F9D9F"); + colors[ImGuiCol_ButtonActive] = HexToRGBA("076B3A94"); + colors[ImGuiCol_ButtonHovered] = HexToRGBA("0CAD4FCA"); + colors[ImGuiCol_CheckMark] = HexToRGBA("E6E6E680"); + colors[ImGuiCol_ChildBg] = HexToRGBA("00000045"); + colors[ImGuiCol_DragDropTarget] = HexToRGBA("333333FF"); + colors[ImGuiCol_FrameBg] = HexToRGBA("00000066"); + colors[ImGuiCol_FrameBgActive] = HexToRGBA("0D7F33B0"); + colors[ImGuiCol_FrameBgHovered] = HexToRGBA("09818B66"); + colors[ImGuiCol_Header] = HexToRGBA("0297959F"); + colors[ImGuiCol_HeaderActive] = HexToRGBA("07834ACC"); + colors[ImGuiCol_HeaderHovered] = HexToRGBA("00B8588A"); + colors[ImGuiCol_MenuBarBg] = HexToRGBA("069981CC"); + colors[ImGuiCol_ModalWindowDimBg] = HexToRGBA("3333335A"); + colors[ImGuiCol_NavHighlight] = HexToRGBA("7373E6CC"); + colors[ImGuiCol_NavWindowingDimBg] = HexToRGBA("CCCCCC33"); + colors[ImGuiCol_NavWindowingHighlight] = HexToRGBA("FFFFFFB3"); + colors[ImGuiCol_PlotHistogram] = HexToRGBA("E6B300FF"); + colors[ImGuiCol_PlotHistogramHovered] = HexToRGBA("FF9900FF"); + colors[ImGuiCol_PlotLines] = HexToRGBA("FFFFFFFF"); + colors[ImGuiCol_PlotLinesHovered] = HexToRGBA("E6B300FF"); + colors[ImGuiCol_PopupBg] = HexToRGBA("1D1D24EB"); + colors[ImGuiCol_ResizeGrip] = HexToRGBA("FFFFFF1A"); + colors[ImGuiCol_ResizeGripActive] = HexToRGBA("C7D2FFE6"); + colors[ImGuiCol_ResizeGripHovered] = HexToRGBA("C7D2FF99"); + colors[ImGuiCol_ScrollbarBg] = HexToRGBA("33404D99"); + colors[ImGuiCol_ScrollbarGrab] = HexToRGBA("0C864E65"); + colors[ImGuiCol_ScrollbarGrabActive] = HexToRGBA("02B3916F"); + colors[ImGuiCol_ScrollbarGrabHovered] = HexToRGBA("05925966"); + colors[ImGuiCol_Separator] = HexToRGBA("1CA09A7E"); + colors[ImGuiCol_SeparatorActive] = HexToRGBA("0099B1FF"); + colors[ImGuiCol_SeparatorHovered] = HexToRGBA("048897FF"); + colors[ImGuiCol_SliderGrab] = HexToRGBA("FFFFFF4D"); + colors[ImGuiCol_SliderGrabActive] = HexToRGBA("04882F99"); + colors[ImGuiCol_Tab] = HexToRGBA("18999F60"); + colors[ImGuiCol_TabActive] = HexToRGBA("038B4CD7"); + colors[ImGuiCol_TabHovered] = HexToRGBA("1E784BCC"); + colors[ImGuiCol_TabUnfocused] = HexToRGBA("FFFFFF00"); + colors[ImGuiCol_TabUnfocusedActive] = HexToRGBA("5A5AA700"); + colors[ImGuiCol_TableBorderLight] = HexToRGBA("FFFFFF00"); + colors[ImGuiCol_TableBorderStrong] = HexToRGBA("00014000"); + colors[ImGuiCol_TableHeaderBg] = HexToRGBA("2E8D89FF"); + colors[ImGuiCol_TableRowBg] = HexToRGBA("3E72769A"); + colors[ImGuiCol_TableRowBgAlt] = HexToRGBA("154D3E9B"); + colors[ImGuiCol_Text] = HexToRGBA("E6E6E6FF"); + colors[ImGuiCol_TextDisabled] = HexToRGBA("999999FF"); + colors[ImGuiCol_TextSelectedBg] = HexToRGBA("00A87E5A"); + colors[ImGuiCol_TitleBg] = HexToRGBA("00998D8A"); + colors[ImGuiCol_TitleBgActive] = HexToRGBA("008D556B"); + colors[ImGuiCol_TitleBgCollapsed] = HexToRGBA("27B6C14A"); + colors[ImGuiCol_WindowBg] = HexToRGBA("00000096"); + + //Styles + styles.Alpha = 1.0; + styles.AntiAliasedFill = true; + styles.AntiAliasedLines = true; + styles.AntiAliasedLinesUseTex = true; + styles.ButtonTextAlign = ImVec2(0.5, 0.5); + styles.CellPadding = ImVec2(4.0, 2.0); + styles.ChildBorderSize = 1.0; + styles.ChildRounding = 0.0; + styles.CircleTessellationMaxError = 0.30000001192092896; + styles.ColorButtonPosition = 1; + styles.ColumnsMinSpacing = 6.0; + styles.CurveTessellationTol = 1.25; + styles.DisabledAlpha = 0.6000000238418579; + styles.DisplaySafeAreaPadding = ImVec2(3.0, 3.0); + styles.DisplayWindowPadding = ImVec2(19.0, 19.0); + styles.FrameBorderSize = 0.0; + styles.FramePadding = ImVec2(4.0, 3.0); + styles.FrameRounding = 0.0; + styles.GrabMinSize = 10.0; + styles.GrabRounding = 0.0; + styles.IndentSpacing = 21.0; + styles.ItemInnerSpacing = ImVec2(4.0, 4.0); + styles.ItemSpacing = ImVec2(8.0, 4.0); + styles.LogSliderDeadzone = 4.0; + styles.MouseCursorScale = 1.0; + styles.PopupBorderSize = 0.0; + styles.PopupRounding = 0.0; + styles.ScrollbarRounding = 0.0; + styles.ScrollbarSize = 14.0; + styles.SelectableTextAlign = ImVec2(0.0, 0.0); + styles.TabBorderSize = 0.0; + styles.TabMinWidthForCloseButton = 0.0; + styles.TabRounding = 0.0; + styles.TouchExtraPadding = ImVec2(0.0, 0.0); + styles.WindowBorderSize = 0.0; + styles.WindowMenuButtonPosition = 0; + styles.WindowMinSize = ImVec2(32.0, 32.0); + styles.WindowPadding = ImVec2(8.0, 8.0); + styles.WindowRounding = 0.0; + styles.WindowTitleAlign = ImVec2(0.0, 0.5); + + init_space::Info::imGuiInit = true; + init_space::Info::mainShow = false; + init_space::Info::tipsShow = true; + } + + // 创建新的画面帧 + ImGui_ImplDX11_NewFrame(); + ImGui_ImplWin32_NewFrame(); + ImGui::NewFrame(); + + // 主界面 + if (!init_space::Info::tipsShow) { + if (ImGui::Begin(reinterpret_cast(u8"Phasmophobia Cheat By 遂沫(github@issuimo)"), &init_space::Info::show, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings)) { + if (ImGui::Button(U8(u8"保存 (Save)"))) { + if (std::ofstream o(".\\cfg.json"); o) { + nlohmann::json js; + for (const auto& _features : init_space::Feature::features | std::views::values) + for (const auto func : _features) func->Save(js); + o << js; + o.close(); } - i.close(); } - } - ImGui::SameLine(); - ImGui::Checkbox(U8(u8"阻止 WndProc | Break WndProc"), &init_space::Info::mainShow); - - if (ImGui::BeginTabBar("memList")) { - for (const auto& [name, _features] : init_space::Feature::features) { - if (ImGui::BeginTabItem(name.c_str())) { - for (const auto func : _features) - if (func->GetInfo().needGroup) { if (ImGui::CollapsingHeader(func->GetInfo().groupName.c_str())) func->Render(); } else func->Render(); - ImGui::EndTabItem(); + ImGui::SameLine(); + if (ImGui::Button(reinterpret_cast(u8"读取 (Load)"))) { + if (std::ifstream i(".\\cfg.json"); i) { + auto js = nlohmann::json::parse(i); + for (const auto& _features : init_space::Feature::features | std::views::values) { + for (const auto func : _features) + try { func->Load(js); } catch (...) {} + } + i.close(); + } + } + ImGui::SameLine(); + ImGui::Checkbox(U8(u8"阻止 WndProc | Break WndProc"), &init_space::Info::mainShow); + + if (ImGui::BeginTabBar("memList")) { + for (const auto& [name, _features] : init_space::Feature::features) { + if (ImGui::BeginTabItem(name.c_str())) { + for (const auto func : _features) + if (func->GetInfo().needGroup) { if (ImGui::CollapsingHeader(func->GetInfo().groupName.c_str())) func->Render(); } else func->Render(); + ImGui::EndTabItem(); + } } + ImGui::EndTabBar(); } - ImGui::EndTabBar(); + + ImGui::End(); } + } + ImGui::SetNextWindowSize(ImVec2(1, 1)); + ImGui::SetNextWindowPos(ImVec2(-1000, -1000)); + if (ImGui::Begin("Draw (don`t selected)")) { + ImGui::GetBackgroundDrawList()->AddCircle(ImVec2(static_cast(init_space::Info::w) / 2.0f, static_cast(init_space::Info::h) / 2.0f), 3, 0xFF0000FF, 4, 2); + for (const auto& feature : init_space::Feature::features | std::views::values) for (const auto func : feature) if (func->GetInfo().needDraw) func->Draw(); ImGui::End(); } - } - ImGui::SetNextWindowSize(ImVec2(1, 1)); - ImGui::SetNextWindowPos(ImVec2(-1000, -1000)); - if (ImGui::Begin("Draw (don`t selected)")) { - ImGui::GetBackgroundDrawList()->AddCircle(ImVec2(static_cast(init_space::Info::w) / 2.0f, static_cast(init_space::Info::h) / 2.0f), 3, 0xFF0000FF, 4, 2); - for (const auto& feature : init_space::Feature::features | std::views::values) for (const auto func : feature) if (func->GetInfo().needDraw) func->Draw(); - ImGui::End(); - } - - if (init_space::Info::tipsShow) { - if (ImGui::Begin("Tips")) { - ImGui::Text(reinterpret_cast(u8"请勿用于破坏他人游戏体验 | Please do not use the assistance to disrupt others' gaming experience")); - ImGui::Text(reinterpret_cast(u8"请勿用于商业用途 | refrain from using it for commercial purposes.")); - if (ImGui::Button("OK")) init_space::Info::tipsShow = false; - ImGui::End(); + if (init_space::Info::tipsShow) { + if (ImGui::Begin("Tips")) { + ImGui::Text(reinterpret_cast(u8"请勿用于破坏他人游戏体验 | Please do not use the assistance to disrupt others' gaming experience")); + ImGui::Text(reinterpret_cast(u8"请勿用于商业用途 | refrain from using it for commercial purposes.")); + if (ImGui::Button("OK")) init_space::Info::tipsShow = false; + ImGui::End(); + } } - } - // 结束并渲染 - ImGui::EndFrame(); - ImGui::Render(); - dx_hook::Hk11::GetContext()->OMSetRenderTargets(1, dx_hook::Hk11::GetTargetView(), nullptr); - ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); - }); - - while (true) { - tagRECT Rect; - GetClientRect(dx_hook::Hk11::GetHwnd(), &Rect); - init_space::Info::w = Rect.right - Rect.left; - init_space::Info::h = Rect.bottom - Rect.top; - drawMath::UpdateResolutionScale(); - Sleep(100); - - for (const auto& feature : init_space::Feature::features | std::views::values) { - for (const auto func : feature) - if (func->GetInfo().needUpdate) func->Update(); + // 结束并渲染 + ImGui::EndFrame(); + ImGui::Render(); + dx_hook::Hk11::GetContext()->OMSetRenderTargets(1, dx_hook::Hk11::GetTargetView(), nullptr); + ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); + }); + + while (true) { + tagRECT Rect; + GetClientRect(dx_hook::Hk11::GetHwnd(), &Rect); + init_space::Info::w = Rect.right - Rect.left; + init_space::Info::h = Rect.bottom - Rect.top; + drawMath::UpdateResolutionScale(); + Sleep(100); + + for (const auto& feature : init_space::Feature::features | std::views::values) { + for (const auto func : feature) + if (func->GetInfo().needUpdate) func->Update(); + } } - } - }).detach(); + }).detach(); + } break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; @@ -283,3 +286,47 @@ auto APIENTRY DllMain(HMODULE hModule, const DWORD ul_reason_for_call, LPVOID lp } return TRUE; } + +auto CALLBACK HookCallBack(const int Code, const WPARAM wParam, const LPARAM lParam) -> LRESULT { + std::wstring file; + file.resize(255, '\0'); + GetModuleFileNameW(init_space::Info::hModule, file.data(), 255); + LoadLibraryW(file.c_str()); + return CallNextHookEx(nullptr, Code, wParam, lParam); +} + +auto GetIdByName(const std::wstring& name) -> DWORD { + const HANDLE hsnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (hsnapshot == INVALID_HANDLE_VALUE) return -1; + + PROCESSENTRY32 processer; + processer.dwSize = sizeof(PROCESSENTRY32); + + int flag = Process32First(hsnapshot, &processer); + while (flag != 0) { + if (processer.szExeFile == name) return processer.th32ProcessID; + flag = Process32Next(hsnapshot, &processer); + } + + CloseHandle(hsnapshot); + return -2; +} + +static DWORD idThread; + +auto CALLBACK EnumFunc(const HWND hWnd, const LPARAM pid) -> BOOL { + DWORD dwProcessId; + + dwProcessId = 0; + const DWORD windowThreadProcessId = GetWindowThreadProcessId(hWnd, &dwProcessId); + if (dwProcessId != pid || !IsWindowVisible(hWnd)) return 1; + idThread = windowThreadProcessId; + return 0; +} + +extern "C" _declspec(dllexport) auto Inject() -> void { + if (const auto pid = GetIdByName(L"Phasmophobia.exe")) { + EnumWindows(EnumFunc, pid); + if (auto lParam = SetWindowsHookExW(WH_GETMESSAGE, HookCallBack, init_space::Info::hModule, idThread)) PostThreadMessageW(idThread, WM_NULL, 0, 0); + } +} diff --git a/Phasmophobia/library/UnityResolve.hpp b/Phasmophobia/library/UnityResolve.hpp index edd78c5..8646463 100644 --- a/Phasmophobia/library/UnityResolve.hpp +++ b/Phasmophobia/library/UnityResolve.hpp @@ -1,20 +1,44 @@ -#ifndef UNITYRESOLVE_HPP +/* + * Update: 2024-1-25 13:00 + * Source: https://github.com/issuimo/UnityResolve.hpp + * Author: github@issuimo + */ + +#ifndef UNITYRESOLVE_HPP #define UNITYRESOLVE_HPP -#undef GetObject +#define WINDOWS_MODE 1 // 如果需要请改为 1 | 1 if you need +#define ANDROID_MODE 0 +#define LINUX_MODE 0 +/* Never + * #define MAC_MODE 0 + * #define IOS_MODE 0 + */ +#if WINDOWS_MODE || LINUX_MODE #include +#endif +#include #include #include +#include #include #include +#include #include +#if WINDOWS_MODE #include -#include +#undef GetObject +#endif +#if WINDOWS_MODE #ifdef _WIN64 #define UNITY_CALLING_CONVENTION __fastcall #elif _WIN32 #define UNITY_CALLING_CONVENTION __cdecl #endif +#elif ANDROID_MODE || LINUX_MODE +#include +#define UNITY_CALLING_CONVENTION +#endif class UnityResolve final { public: @@ -27,11 +51,10 @@ class UnityResolve final { enum class Mode : char { Il2Cpp, Mono, - Auto }; struct Assembly final { - void* address; + void* address; std::string name; std::string file; std::vector classes; @@ -43,7 +66,7 @@ class UnityResolve final { }; struct Type final { - void* address; + void* address; std::string name; int size; @@ -54,14 +77,14 @@ class UnityResolve final { }; struct Class final { - void* classinfo; + void* classinfo; std::string name; std::string parent; std::string namespaze; std::vector fields; std::vector methods; - template + template auto Get(const std::string& name, const std::vector& args = {}) -> RType* { if constexpr (std::is_same_v) for (auto pField : fields) if (pField->name == name) return static_cast(pField); if constexpr (std::is_same_v) for (const auto pField : fields) if (pField->name == name) return static_cast(pField->offset); @@ -69,7 +92,7 @@ class UnityResolve final { for (auto pMethod : methods) { if (pMethod->name == name) { if (pMethod->args.size() == args.size()) { - for (size_t index{ 0 }; const auto & typeName : args) if (typeName == "*" || typeName.empty() ? false : pMethod->args[index++]->pType->name != typeName) goto next; + for (size_t index{0}; const auto& typeName : args) if (typeName == "*" || typeName.empty() ? false : pMethod->args[index++]->pType->name != typeName) goto next; return static_cast(pMethod); } } @@ -81,23 +104,19 @@ class UnityResolve final { return nullptr; } - template - auto GetValue(void* obj, const std::string& name) -> RType { - return *reinterpret_cast(reinterpret_cast(obj) + Get(name)->offset); - } + template + auto GetValue(void* obj, const std::string& name) -> RType { return *reinterpret_cast(reinterpret_cast(obj) + Get(name)->offset); } - template - auto SetValue(void* obj, const std::string& name, RType value) -> void { - return *reinterpret_cast(reinterpret_cast(obj) + Get(name)->offset) = value; - } + template + auto SetValue(void* obj, const std::string& name, RType value) -> void { return *reinterpret_cast(reinterpret_cast(obj) + Get(name)->offset) = value; } [[nodiscard]] auto GetType() const -> Type { if (mode_ == Mode::Il2Cpp) { const auto pUType = Invoke("il2cpp_class_get_type", classinfo); - return { pUType, name, -1 }; + return {pUType, name, -1}; } const auto pUType = Invoke("mono_class_get_type", classinfo); - return { pUType, name, -1 }; + return {pUType, name, -1}; } /** @@ -106,11 +125,11 @@ class UnityResolve final { * \param type 类 * \return 返回实例指针数组 */ - template + template auto FindObjectsByType() -> std::vector { static Method* pMethod; - if (!pMethod) pMethod = UnityResolve::Get("UnityEngine.CoreModule.dll")->Get("Object")->Get(mode_ == Mode::Il2Cpp ? "FindObjectsOfType" : "FindObjectsOfTypeAll", { "System.Type" }); + if (!pMethod) pMethod = UnityResolve::Get("UnityEngine.CoreModule.dll")->Get("Object")->Get(mode_ == Mode::Il2Cpp ? "FindObjectsOfType" : "FindObjectsOfTypeAll", {"System.Type"}); if (pMethod) { std::vector rs{}; @@ -123,7 +142,7 @@ class UnityResolve final { throw std::logic_error("FindObjectsOfType nullptr"); } - template + template auto New() -> T* { if (mode_ == Mode::Il2Cpp) return Invoke("il2cpp_object_new", classinfo); return Invoke("mono_object_new", pDomain, classinfo); @@ -131,62 +150,58 @@ class UnityResolve final { }; struct Field final { - void* fieldinfo; + void* fieldinfo; std::string name; - Type* type; - Class* klass; + Type* type; + Class* klass; std::int32_t offset; // If offset is -1, then it's thread static bool static_field; - void* vTable; + void* vTable; - template + template auto SetValue(T* value) const -> void { if (!static_field) return; - if (mode_ == Mode::Il2Cpp) return Invoke("il2cpp_field_static_set_value", fieldinfo, value); - if (vTable) return Invoke("mono_field_static_set_value", vTable, fieldinfo, value); } - template + template auto GetValue(T* value) const -> void { if (!static_field) return; - if (mode_ == Mode::Il2Cpp) return Invoke("il2cpp_field_static_get_value", fieldinfo, value); - if (vTable) return Invoke("mono_field_static_get_value", vTable, fieldinfo, value); } }; struct Method final { - void* address; + void* address; std::string name; - Class* klass; - Type* return_type; + Class* klass; + Type* return_type; std::int32_t flags; bool static_function; - void* function; + void* function; struct Arg { std::string name; - Type* pType; + Type* pType; }; std::vector args; - template + template auto Invoke(Args... args) -> Return { Compile(); - if (function) return static_cast(function)(args...); + if (function) return reinterpret_cast(function)(args...); throw std::logic_error("nullptr"); } auto Compile() -> void { if (address && !function && mode_ == Mode::Mono) function = UnityResolve::Invoke("mono_compile_method", address); } - template + template auto RuntimeInvoke(Obj* obj, Args... args) -> Return { void* exc{}; void* argArray[sizeof...(Args) + 1]; if (sizeof...(Args) > 0) { - size_t index = 0; + size_t index = 0; ((argArray[index++] = static_cast(&args)), ...); } @@ -194,21 +209,19 @@ class UnityResolve final { if constexpr (std::is_same_v) { UnityResolve::Invoke("il2cpp_runtime_invoke", address, obj, argArray, exc); return; - } - else return *static_cast(UnityResolve::Invoke("il2cpp_runtime_invoke", address, obj, argArray, exc)); + } else return *static_cast(UnityResolve::Invoke("il2cpp_runtime_invoke", address, obj, argArray, exc)); } if constexpr (std::is_same_v) { UnityResolve::Invoke("mono_runtime_invoke", address, obj, argArray, exc); return; - } - else return *static_cast(UnityResolve::Invoke("mono_runtime_invoke", address, obj, argArray, exc)); + } else return *static_cast(UnityResolve::Invoke("mono_runtime_invoke", address, obj, argArray, exc)); } - template + template using MethodPointer = Return(UNITY_CALLING_CONVENTION*)(Args...); - template + template auto Cast() -> MethodPointer { Compile(); if (function) return static_cast>(function); @@ -232,229 +245,33 @@ class UnityResolve final { } } - static auto Init(const HMODULE hmodule, const Mode mode = Mode::Auto) -> void { - mode_ = mode; + static auto Init(void* hmodule, const Mode mode = Mode::Mono) -> void { + mode_ = mode; hmodule_ = hmodule; - if (mode == Mode::Auto) { - char path[0xFF]; - GetModuleFileNameA(hmodule, path, 0xFF); - const std::string file{ path }; - auto ret = file.substr(0, file.find_first_of('\\') + 1); - if (file.find("mono") != std::string::npos) mode_ = Mode::Mono; - else mode_ = Mode::Il2Cpp; - } - if (mode_ == Mode::Il2Cpp) { pDomain = Invoke("il2cpp_domain_get"); Invoke("il2cpp_thread_attach", pDomain); - size_t nrofassemblies = 0; - const auto assemblies = Invoke("il2cpp_domain_get_assemblies", pDomain, &nrofassemblies); - for (auto i = 0; i < nrofassemblies; i++) { - const auto ptr = assemblies[i]; - if (ptr == nullptr) continue; - const auto assembly = new Assembly{ .address = ptr }; - const void* image = Invoke("il2cpp_assembly_get_image", ptr); - assembly->file = Invoke("il2cpp_image_get_filename", image); - assembly->name = Invoke("il2cpp_image_get_name", image); - const auto count = Invoke("il2cpp_image_get_class_count", image); - UnityResolve::assembly.push_back(assembly); - for (auto i = 0; i < count; i++) { - const auto pClass = Invoke("il2cpp_image_get_class", image, i); - if (pClass == nullptr) continue; - const auto pAClass = new Class(); - pAClass->classinfo = pClass; - pAClass->name = Invoke("il2cpp_class_get_name", pClass); - if (const auto pPClass = Invoke("il2cpp_class_get_parent", pClass)) pAClass->parent = Invoke("il2cpp_class_get_name", pPClass); - pAClass->namespaze = Invoke("il2cpp_class_get_namespace", pClass); - assembly->classes.push_back(pAClass); - void* iter = nullptr; - void* field; - do - if ((field = Invoke("il2cpp_class_get_fields", pClass, &iter))) { - const auto pField = new Field{ .fieldinfo = field, .name = Invoke("il2cpp_field_get_name", field), .type = new Type{.address = Invoke("il2cpp_field_get_type", field)}, .klass = pAClass, .offset = Invoke("il2cpp_field_get_offset", field), .static_field = false, .vTable = nullptr }; - int tSize{}; - pField->static_field = pField->offset <= 0; - pField->type->name = Invoke("il2cpp_type_get_name", pField->type->address); - pField->type->size = -1; - pAClass->fields.push_back(pField); - } while (field); - iter = nullptr; - do - if ((field = Invoke("il2cpp_class_get_methods", pClass, &iter))) { - int fFlags{}; - const auto pMethod = new Method{ .address = field, .name = Invoke("il2cpp_method_get_name", field), .klass = pAClass, .return_type = new Type{.address = Invoke("il2cpp_method_get_return_type", field),}, .flags = Invoke("il2cpp_method_get_flags", field, &fFlags) }; - int tSize{}; - pMethod->static_function = pMethod->flags & 0x10; - pMethod->return_type->name = Invoke("il2cpp_type_get_name", pMethod->return_type->address); - pMethod->return_type->size = -1; - pMethod->function = *static_cast(field); - pAClass->methods.push_back(pMethod); - const auto argCount = Invoke("il2cpp_method_get_param_count", field); - for (auto index = 0; index < argCount; index++) pMethod->args.push_back(new Method::Arg{ Invoke("il2cpp_method_get_param_name", field, index), new Type{.address = Invoke("il2cpp_method_get_param", field, index), .name = Invoke("il2cpp_type_get_name", Invoke("il2cpp_method_get_param", field, index)), .size = -1} }); - } while (field); - iter = nullptr; - const void* i_class{}; - const void* iiter{}; - do - if ((i_class = Invoke("il2cpp_class_get_interfaces", pClass, &iiter))) { - do - if ((field = Invoke("il2cpp_class_get_fields", i_class, &iter))) { - const auto pField = new Field{ .fieldinfo = field, .name = Invoke("il2cpp_field_get_name", field), .type = new Type{.address = Invoke("il2cpp_field_get_type", field)}, .klass = pAClass, .offset = Invoke("il2cpp_field_get_offset", field), .static_field = false, .vTable = nullptr }; - int tSize{}; - pField->static_field = pField->offset <= 0; - pField->type->name = Invoke("il2cpp_type_get_name", pField->type->address); - pField->type->size = -1; - pAClass->fields.push_back(pField); - } while (field); - iter = nullptr; - do - if ((field = Invoke("il2cpp_class_get_methods", i_class, &iter))) { - int fFlags{}; - const auto pMethod = new Method{ .address = field, .name = Invoke("il2cpp_method_get_name", field), .klass = pAClass, .return_type = new Type{.address = Invoke("il2cpp_method_get_return_type", field),}, .flags = Invoke("il2cpp_method_get_flags", field, &fFlags) }; - int tSize{}; - pMethod->static_function = pMethod->flags & 0x10; - pMethod->return_type->name = Invoke("il2cpp_type_get_name", pMethod->return_type->address); - pMethod->return_type->size = -1; - pMethod->function = *static_cast(field); - pAClass->methods.push_back(pMethod); - const auto argCount = Invoke("il2cpp_method_get_param_count", field); - for (auto index = 0; index < argCount; index++) pMethod->args.push_back(new Method::Arg{ Invoke("il2cpp_method_get_param_name", field, index), new Type{.address = Invoke("il2cpp_method_get_param", field, index), .name = Invoke("il2cpp_type_get_name", Invoke("il2cpp_method_get_param", field, index)), .size = -1} }); - } while (field); - iter = nullptr; - } while (i_class); - } - } - } - else { + ForeachAssembly(); + } else { pDomain = Invoke("mono_get_root_domain"); Invoke("mono_thread_attach", pDomain); Invoke("mono_jit_thread_attach", pDomain); - Invoke&), std::vector&>("mono_assembly_foreach", [](void* ptr, std::vector& v) { - if (ptr == nullptr) return; - - const auto assembly = new Assembly{ .address = ptr, }; - - const void* image = Invoke("mono_assembly_get_image", ptr); - assembly->file = Invoke("mono_image_get_filename", image); - assembly->name = Invoke("mono_image_get_name", image); - assembly->name += ".dll"; - - const void* table = Invoke("mono_image_get_table_info", image, 2); - const auto count = Invoke("mono_table_info_get_rows", table); - v.push_back(assembly); - - int iClass{}; - for (auto i = 0; i < count; i++) { - const auto pClass = Invoke("mono_class_get", image, 0x02000000 | (i + 1)); - if (pClass == nullptr) continue; - - const auto pAClass = new Class(); - pAClass->classinfo = pClass; - pAClass->name = Invoke("mono_class_get_name", pClass); - if (const auto pPClass = Invoke("mono_class_get_parent", pClass)) pAClass->parent = Invoke("mono_class_get_name", pPClass); - pAClass->namespaze = Invoke("mono_class_get_namespace", pClass); - assembly->classes.push_back(pAClass); - - void* iter = nullptr; - void* field; - do - if ((field = Invoke("mono_class_get_fields", pClass, &iter))) { - const auto pField = new Field{ .fieldinfo = field, .name = Invoke("mono_field_get_name", field), .type = new Type{.address = Invoke("mono_field_get_type", field)}, .klass = pAClass, .offset = Invoke("mono_field_get_offset", field), .static_field = false, .vTable = nullptr }; - int tSize{}; - pField->static_field = pField->offset <= 0; - pField->type->name = Invoke("mono_type_get_name", pField->type->address); - pField->type->size = Invoke("mono_type_size", pField->type->address, &tSize); - pAClass->fields.push_back(pField); - if (pField->static_field) pField->vTable = Invoke("mono_class_vtable", pDomain, pClass); - } while (field); - iter = nullptr; - - auto iMethod{ 0 }; - do - if ((field = Invoke("mono_class_get_methods", pClass, &iter))) { - const auto signature = Invoke("mono_method_signature", field); - int fFlags{}; - const auto pMethod = new Method{ .address = field, .name = Invoke("mono_method_get_name", field), .klass = pAClass, .return_type = new Type{.address = Invoke("mono_signature_get_return_type", signature),}, .flags = Invoke("mono_method_get_flags", field, &fFlags) }; - int tSize{}; - pMethod->static_function = pMethod->flags & 0x10; - pMethod->return_type->name = Invoke("mono_type_get_name", pMethod->return_type->address); - pMethod->return_type->size = Invoke("mono_type_size", pMethod->return_type->address, &tSize); - pAClass->methods.push_back(pMethod); - - const auto names = new char* [Invoke("mono_signature_get_param_count", signature)]; - Invoke("mono_method_get_param_names", field, names); - - void* mIter = nullptr; - void* mType; - auto iname = 0; - do - if ((mType = Invoke("mono_signature_get_params", signature, &mIter))) { - int t_size{}; - pMethod->args.push_back(new Method::Arg{ names[iname], new Type{.address = mType, .name = Invoke("mono_type_get_name", mType), .size = Invoke("mono_type_size", mType, &t_size)} }); - iname++; - } while (mType); - } while (field); - iter = nullptr; - const void* iClass{}; - const void* iiter{}; - - do - if ((iClass = Invoke("mono_class_get_interfaces", pClass, &iiter))) { - do - if ((field = Invoke("mono_class_get_fields", iClass, &iter))) { - const auto pField = new Field{ .fieldinfo = field, .name = Invoke("mono_field_get_name", field), .type = new Type{.address = Invoke("mono_field_get_type", field)}, .klass = pAClass, .offset = Invoke("mono_field_get_offset", field), .static_field = false, .vTable = nullptr }; - int tSize{}; - pField->static_field = pField->offset <= 0; - pField->type->name = Invoke("mono_type_get_name", pField->type->address); - pField->type->size = Invoke("mono_type_size", pField->type->address, &tSize); - pAClass->fields.push_back(pField); - if (pField->static_field) pField->vTable = Invoke("mono_class_vtable", pDomain, pClass); - } while (field); - iter = nullptr; - - do - if ((field = Invoke("mono_class_get_methods", iClass, &iter))) { - const auto signature = Invoke("mono_method_signature", field); - int fFlags{}; - const auto pMethod = new Method{ .address = field, .name = Invoke("mono_method_get_name", field), .klass = pAClass, .return_type = new Type{.address = Invoke("mono_signature_get_return_type", signature),}, .flags = Invoke("mono_method_get_flags", field, &fFlags) }; - int tSize{}; - pMethod->static_function = pMethod->flags & 0x10; - pMethod->return_type->name = Invoke("mono_type_get_name", pMethod->return_type->address); - pMethod->return_type->size = Invoke("mono_type_size", pMethod->return_type->address, &tSize); - pAClass->methods.push_back(pMethod); - - const auto names = new char* [Invoke("mono_signature_get_param_count", signature)]; - Invoke("mono_method_get_param_names", field, names); - - void* mIter = nullptr; - void* mType; - auto iname = 0; - do - if ((mType = Invoke("mono_signature_get_params", signature, &mIter))) { - int t_size{}; - pMethod->args.push_back(new Method::Arg{ names[iname], new Type{.address = mType, .name = Invoke("mono_type_get_name", mType), .size = Invoke("mono_type_size", mType, &t_size)} }); - iname++; - } while (mType); - } while (field); - iter = nullptr; - iMethod = 0; - } while (iClass); - } - }, assembly); + ForeachAssembly(); if (Get("UnityEngine.dll") && (!Get("UnityEngine.CoreModule.dll") || !Get("UnityEngine.PhysicsModule.dll"))) { // 兼容某些游戏 (如生死狙击2) - for (const std::vector names = { "UnityEngine.CoreModule.dll", "UnityEngine.PhysicsModule.dll" }; const auto name : names) { - const auto ass = Get("UnityEngine.dll"); - const auto assembly = new Assembly{ .address = ass->address, .name = name, .file = ass->file, .classes = ass->classes }; + for (const std::vector names = {"UnityEngine.CoreModule.dll", "UnityEngine.PhysicsModule.dll"}; const auto name : names) { + const auto ass = Get("UnityEngine.dll"); + const auto assembly = new Assembly{.address = ass->address, .name = name, .file = ass->file, .classes = ass->classes}; UnityResolve::assembly.push_back(assembly); } } } } +#if WINDOWS_MODE || LINUX_MODE /*__cplusplus >= 202002L*/ static auto DumpToFile(const std::string& file) -> void { std::ofstream io(file, std::fstream::out); @@ -489,9 +306,8 @@ class UnityResolve final { io << '\n'; io.close(); - SetFileAttributesA((file).c_str(), FILE_ATTRIBUTE_READONLY); - SetFileAttributesA((file).c_str(), FILE_ATTRIBUTE_SYSTEM); } +#endif /** * \brief 调用dll函数 @@ -501,13 +317,19 @@ class UnityResolve final { * \param args 参数 * \return 模板类型 */ - template + template static auto Invoke(const std::string& funcName, Args... args) -> Return { static std::mutex mutex{}; std::lock_guard lock(mutex); // 检查函数是否已经获取地址, 没有则自动获取 - if (!address_.contains(funcName) || address_[funcName] == nullptr) address_[funcName] = static_cast(GetProcAddress(hmodule_, funcName.c_str())); + if (!address_.contains(funcName) || address_[funcName] == nullptr) { +#if WINDOWS_MODE + address_[funcName] = static_cast(GetProcAddress(static_cast(hmodule_), funcName.c_str())); +#elif ANDROID_MODE || LINUX_MODE + address_[funcName] = dlsym(hmodule_, funcName.c_str()); +#endif + } if (address_[funcName] != nullptr) return reinterpret_cast(address_[funcName])(args...); throw std::logic_error("Not find function"); @@ -520,6 +342,179 @@ class UnityResolve final { return nullptr; } +private: + static auto ForeachAssembly() -> void { + // 遍历程序集 + if (mode_ == Mode::Il2Cpp) { + size_t nrofassemblies = 0; + const auto assemblies = Invoke("il2cpp_domain_get_assemblies", pDomain, &nrofassemblies); + for (auto i = 0; i < nrofassemblies; i++) { + const auto ptr = assemblies[i]; + if (ptr == nullptr) continue; + auto assembly = new Assembly{.address = ptr}; + const auto image = Invoke("il2cpp_assembly_get_image", ptr); + assembly->file = Invoke("il2cpp_image_get_filename", image); + assembly->name = Invoke("il2cpp_image_get_name", image); + UnityResolve::assembly.push_back(assembly); + ForeachClass(assembly, image); + } + } else { + Invoke&), std::vector&>("mono_assembly_foreach", + [](void* ptr, std::vector& v) { + if (ptr == nullptr) return; + + const auto assembly = new Assembly{.address = ptr,}; + const auto image = Invoke("mono_assembly_get_image", ptr); + assembly->file = Invoke("mono_image_get_filename", image); + assembly->name = Invoke("mono_image_get_name", image); + assembly->name += ".dll"; + v.push_back(assembly); + + ForeachClass(assembly, image); + }, + assembly); + } + } + + static auto ForeachClass(Assembly* assembly, void* image) -> void { + // 遍历类 + if (mode_ == Mode::Il2Cpp) { + const auto count = Invoke("il2cpp_image_get_class_count", image); + for (auto i = 0; i < count; i++) { + const auto pClass = Invoke("il2cpp_image_get_class", image, i); + if (pClass == nullptr) continue; + const auto pAClass = new Class(); + pAClass->classinfo = pClass; + pAClass->name = Invoke("il2cpp_class_get_name", pClass); + if (const auto pPClass = Invoke("il2cpp_class_get_parent", pClass)) pAClass->parent = Invoke("il2cpp_class_get_name", pPClass); + pAClass->namespaze = Invoke("il2cpp_class_get_namespace", pClass); + assembly->classes.push_back(pAClass); + + ForeachFields(pAClass, pClass); + ForeachMethod(pAClass, pClass); + + void* i_class{}; + void* iter{}; + do { + if ((i_class = Invoke("il2cpp_class_get_interfaces", pClass, &iter))) { + ForeachFields(pAClass, i_class); + ForeachMethod(pAClass, i_class); + } + } while (i_class); + } + } else { + const void* table = Invoke("mono_image_get_table_info", image, 2); + const auto count = Invoke("mono_table_info_get_rows", table); + for (auto i = 0; i < count; i++) { + const auto pClass = Invoke("mono_class_get", image, 0x02000000 | (i + 1)); + if (pClass == nullptr) continue; + + const auto pAClass = new Class(); + pAClass->classinfo = pClass; + pAClass->name = Invoke("mono_class_get_name", pClass); + if (const auto pPClass = Invoke("mono_class_get_parent", pClass)) pAClass->parent = Invoke("mono_class_get_name", pPClass); + pAClass->namespaze = Invoke("mono_class_get_namespace", pClass); + assembly->classes.push_back(pAClass); + + ForeachFields(pAClass, pClass); + ForeachMethod(pAClass, pClass); + + void* iClass{}; + void* iiter{}; + + do { + if ((iClass = Invoke("mono_class_get_interfaces", pClass, &iiter))) { + ForeachFields(pAClass, iClass); + ForeachMethod(pAClass, iClass); + } + } while (iClass); + } + } + } + + static auto ForeachFields(Class* klass, void* pKlass) -> void { + // 遍历成员 + if (mode_ == Mode::Il2Cpp) { + void* iter = nullptr; + void* field; + do { + if ((field = Invoke("il2cpp_class_get_fields", pKlass, &iter))) { + const auto pField = new Field{.fieldinfo = field, .name = Invoke("il2cpp_field_get_name", field), .type = new Type{.address = Invoke("il2cpp_field_get_type", field)}, .klass = klass, .offset = Invoke("il2cpp_field_get_offset", field), .static_field = false, .vTable = nullptr}; + int tSize{}; + pField->static_field = pField->offset <= 0; + pField->type->name = Invoke("il2cpp_type_get_name", pField->type->address); + pField->type->size = -1; + klass->fields.push_back(pField); + } + } while (field); + } else { + void* iter = nullptr; + void* field; + do { + if ((field = Invoke("mono_class_get_fields", pKlass, &iter))) { + const auto pField = new Field{.fieldinfo = field, .name = Invoke("mono_field_get_name", field), .type = new Type{.address = Invoke("mono_field_get_type", field)}, .klass = klass, .offset = Invoke("mono_field_get_offset", field), .static_field = false, .vTable = nullptr}; + int tSize{}; + pField->static_field = pField->offset <= 0; + pField->type->name = Invoke("mono_type_get_name", pField->type->address); + pField->type->size = Invoke("mono_type_size", pField->type->address, &tSize); + klass->fields.push_back(pField); + } + } while (field); + } + } + + static auto ForeachMethod(Class* klass, void* pKlass) -> void { + // 遍历方法 + if (mode_ == Mode::Il2Cpp) { + void* iter = nullptr; + void* method; + do { + if ((method = Invoke("il2cpp_class_get_methods", pKlass, &iter))) { + int fFlags{}; + const auto pMethod = new Method{.address = method, .name = Invoke("il2cpp_method_get_name", method), .klass = klass, .return_type = new Type{.address = Invoke("il2cpp_method_get_return_type", method),}, .flags = Invoke("il2cpp_method_get_flags", method, &fFlags)}; + int tSize{}; + pMethod->static_function = pMethod->flags & 0x10; + pMethod->return_type->name = Invoke("il2cpp_type_get_name", pMethod->return_type->address); + pMethod->return_type->size = -1; + pMethod->function = *static_cast(method); + klass->methods.push_back(pMethod); + const auto argCount = Invoke("il2cpp_method_get_param_count", method); + for (auto index = 0; index < argCount; index++) pMethod->args.push_back(new Method::Arg{Invoke("il2cpp_method_get_param_name", method, index), new Type{.address = Invoke("il2cpp_method_get_param", method, index), .name = Invoke("il2cpp_type_get_name", Invoke("il2cpp_method_get_param", method, index)), .size = -1}}); + } + } while (method); + } else { + void* iter = nullptr; + void* method; + do { + if ((method = Invoke("mono_class_get_methods", pKlass, &iter))) { + const auto signature = Invoke("mono_method_signature", method); + int fFlags{}; + const auto pMethod = new Method{.address = method, .name = Invoke("mono_method_get_name", method), .klass = klass, .return_type = new Type{.address = Invoke("mono_signature_get_return_type", signature),}, .flags = Invoke("mono_method_get_flags", method, &fFlags)}; + int tSize{}; + pMethod->static_function = pMethod->flags & 0x10; + pMethod->return_type->name = Invoke("mono_type_get_name", pMethod->return_type->address); + pMethod->return_type->size = Invoke("mono_type_size", pMethod->return_type->address, &tSize); + klass->methods.push_back(pMethod); + + const auto names = new char*[Invoke("mono_signature_get_param_count", signature)]; + Invoke("mono_method_get_param_names", method, names); + + void* mIter = nullptr; + void* mType; + auto iname = 0; + do { + if ((mType = Invoke("mono_signature_get_params", signature, &mIter))) { + int t_size{}; + pMethod->args.push_back(new Method::Arg{names[iname], new Type{.address = mType, .name = Invoke("mono_type_get_name", mType), .size = Invoke("mono_type_size", mType, &t_size)}}); + iname++; + } + } while (mType); + } + } while (method); + } + } + +public: class UnityType final { public: struct Vector3; @@ -541,13 +536,13 @@ class UnityResolve final { struct Rect; struct Color; struct Matrix4x4; - template + template struct Array; struct String; struct Object; - template + template struct List; - template + template struct Dictionary; struct Behaviour; struct MonoBehaviour; @@ -859,13 +854,11 @@ class UnityResolve final { m_vEuler.x = static_cast(3.1415926) * 0.5F; m_vEuler.y = 2.F * atan2f(y, x); m_vEuler.z = 0.F; - } - else if (m_fTest < -0.4995F * m_fDist) { + } else if (m_fTest < -0.4995F * m_fDist) { m_vEuler.x = static_cast(3.1415926) * -0.5F; m_vEuler.y = -2.F * atan2f(y, x); m_vEuler.z = 0.F; - } - else { + } else { m_vEuler.x = asinf(2.F * (w * x - y * z)); m_vEuler.y = atan2f(2.F * w * y + 2.F * z * x, 1.F - 2.F * (x * x + y * y)); m_vEuler.z = atan2f(2.F * w * z + 2.F * x * y, 1.F - 2.F * (z * z + x * x)); @@ -960,15 +953,15 @@ class UnityResolve final { }; struct Rect { - float fX, fY; + float fX, fY; float fWidth, fHeight; Rect() { fX = fY = fWidth = fHeight = 0.f; } Rect(const float f1, const float f2, const float f3, const float f4) { - fX = f1; - fY = f2; - fWidth = f3; + fX = f1; + fY = f2; + fWidth = f3; fHeight = f4; } }; @@ -987,7 +980,7 @@ class UnityResolve final { }; struct Matrix4x4 { - float m[4][4] = { {0} }; + float m[4][4] = {{0}}; Matrix4x4() = default; @@ -996,11 +989,11 @@ class UnityResolve final { struct Object { union { - void* klass{ nullptr }; + void* klass{nullptr}; void* vtable; - } Il2CppClass; + } Il2CppClass; - struct MonitorData* monitor{ nullptr }; + struct MonitorData* monitor{nullptr}; auto GetType() -> CsType* { static Method* method; @@ -1020,13 +1013,24 @@ class UnityResolve final { }; struct String : Object { - int32_t m_stringLength{ 0 }; + int32_t m_stringLength{0}; wchar_t m_firstChar[32]{}; [[nodiscard]] auto ToString() const -> std::string { +#if WINDOWS_MODE std::string sRet(static_cast(m_stringLength) * 3 + 1, '\0'); WideCharToMultiByte(CP_UTF8, 0, m_firstChar, m_stringLength, sRet.data(), static_cast(sRet.size()), nullptr, nullptr); return sRet; +#elif LINUX_MODE + using convert_typeX = std::codecvt_utf8; + std::wstring_convert converterX; + return converterX.to_bytes(m_firstChar); +#elif ANDROID_MODE + // 可能存在bug 目前已有报告 "比如对象标签 有的时候会直接跳到游戏控制器里面去" + using convert_typeX = std::codecvt_utf8; + std::wstring_convert converterX; + return converterX.to_bytes(m_firstChar); +#endif } auto operator[](const int i) const -> wchar_t { return m_firstChar[i]; } @@ -1042,14 +1046,14 @@ class UnityResolve final { } }; - template + template struct Array : Object { struct { std::uintptr_t length; std::int32_t lower_bound; - }*bounds{ nullptr }; + }* bounds{nullptr}; - std::uintptr_t max_length{ 0 }; + std::uintptr_t max_length{0}; __declspec(align(8)) T* vector[32]{}; auto GetData() -> uintptr_t { return reinterpret_cast(&vector); } @@ -1109,16 +1113,74 @@ class UnityResolve final { } }; - template + template struct List : Object { Array* pList; + int size{}; + int version{}; + void* syncRoot{}; auto ToArray() -> Array* { return pList; } - static auto New(const Class* kalss, const std::uintptr_t size) -> List* { pList = Array::New(kalss, size); } + static auto New(const Class* kalss, const std::uintptr_t size) -> List* { + auto pList = new List(); + pList->pList = Array::New(kalss, size); + pList->size = size; + } + + auto operator[](const unsigned int m_uIndex) -> Type& { return pList->At(m_uIndex); } + + auto Add(Type* pDate) -> float { + static Method* method; + if (!method) method = Get("mscorlib.dll")->Get("List")->Get("Add"); + if (method) return method->Invoke(this, pDate); + throw std::logic_error("nullptr"); + } + + auto Remove(Type* pDate) -> float { + static Method* method; + if (!method) method = Get("mscorlib.dll")->Get("List")->Get("Remove"); + if (method) return method->Invoke(this, pDate); + throw std::logic_error("nullptr"); + } + + auto RemoveAt(int index) -> float { + static Method* method; + if (!method) method = Get("mscorlib.dll")->Get("List")->Get("RemoveAt"); + if (method) return method->Invoke(this, index); + throw std::logic_error("nullptr"); + } + + auto ForEach(void(*action)(Type* pDate)) -> float { + static Method* method; + if (!method) method = Get("mscorlib.dll")->Get("List")->Get("ForEach"); + if (method) return method->Invoke(this, action); + throw std::logic_error("nullptr"); + } + + auto GetRange(int index, int count) -> float { + static Method* method; + if (!method) method = Get("mscorlib.dll")->Get("List")->Get("GetRange"); + if (method) return method->Invoke(this, index, count); + throw std::logic_error("nullptr"); + } + + auto Clear() -> float { + static Method* method; + if (!method) method = Get("mscorlib.dll")->Get("List")->Get("Clear"); + if (method) return method->Invoke(this); + throw std::logic_error("nullptr"); + } + + auto Sort(int(*comparison)(Type* pX, Type* pY)) -> float { + static Method* method; + if (!method) method = Get("mscorlib.dll")->Get("List")->Get("Sort"); + if (method) return method->Invoke(this, comparison); + throw std::logic_error("nullptr"); + } }; - template + template struct Dictionary : Object { struct Entry { int iHashCode; @@ -1127,20 +1189,20 @@ class UnityResolve final { TValue tValue; }; - Array* pBuckets; + Array* pBuckets; Array* pEntries; int iCount; int iVersion; int iFreeList; int iFreeCount; - void* pComparer; - void* pKeys; - void* pValues; + void* pComparer; + void* pKeys; + void* pValues; auto GetEntry() -> Entry* { return static_cast(pEntries->GetData()); } auto GetKeyByIndex(const int iIndex) -> TKey { - TKey tKey = { 0 }; + TKey tKey = {0}; Entry* pEntry = GetEntry(); if (pEntry) tKey = pEntry[iIndex].m_tKey; @@ -1149,7 +1211,7 @@ class UnityResolve final { } auto GetValueByIndex(const int iIndex) -> TValue { - TValue tValue = { 0 }; + TValue tValue = {0}; Entry* pEntry = GetEntry(); if (pEntry) tValue = pEntry[iIndex].m_tValue; @@ -1158,7 +1220,7 @@ class UnityResolve final { } auto GetValueByKey(const TKey tKey) -> TValue { - TValue tValue = { 0 }; + TValue tValue = {0}; for (auto i = 0; i < iCount; i++) if (GetEntry()[i].m_tKey == tKey) tValue = GetEntry()[i].m_tValue; return tValue; } @@ -1178,14 +1240,14 @@ class UnityResolve final { static auto Instantiate(UnityObject* original) -> UnityObject* { static Method* method; - if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Object")->Get("Instantiate", { "*" }); + if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Object")->Get("Instantiate", {"*"}); if (method) return method->Invoke(original); throw std::logic_error("nullptr"); } static auto Destroy(UnityObject* original) -> void { static Method* method; - if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Object")->Get("Destroy", { "*" }); + if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Object")->Get("Destroy", {"*"}); if (method) return method->Invoke(original); throw std::logic_error("nullptr"); } @@ -1213,7 +1275,7 @@ class UnityResolve final { throw std::logic_error("nullptr"); } - template + template auto GetComponentsInChildren() -> Array { static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Component")->Get("GetComponentsInChildren"); @@ -1252,11 +1314,11 @@ class UnityResolve final { static auto GetAllCamera() -> std::vector { static Method* method; - static Class* klass; + static Class* klass; if (!method || !klass) { - method = Get("UnityEngine.CoreModule.dll")->Get("Camera")->Get("GetAllCameras", { "*" }); - klass = Get("UnityEngine.CoreModule.dll")->Get("Camera"); + method = Get("UnityEngine.CoreModule.dll")->Get("Camera")->Get("GetAllCameras", {"*"}); + klass = Get("UnityEngine.CoreModule.dll")->Get("Camera"); } if (method && klass) { @@ -1277,7 +1339,7 @@ class UnityResolve final { auto SetDepth(const float depth) -> void { static Method* method; - if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Camera")->Get("set_depth", { "*" }); + if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Camera")->Get("set_depth", {"*"}); if (method) return method->Invoke(this, depth); } @@ -1304,6 +1366,18 @@ class UnityResolve final { if (method) return method->Invoke(this, position, eye); throw std::logic_error("nullptr"); } + + auto CameraToWorldMatrix() -> Matrix4x4 { + static Method* method; + if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("Camera")->Get(mode_ == Mode::Mono ? "get_cameraToWorldMatrix_Injected" : "get_cameraToWorldMatrix"); + if (mode_ == Mode::Mono && method) { + Matrix4x4 matrix4{}; + method->Invoke(this, &matrix4); + return matrix4; + } + if (method) return method->Invoke(this); + throw std::logic_error("nullptr"); + } }; struct Transform : Component { @@ -1461,7 +1535,7 @@ class UnityResolve final { if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("GameObject")->Get("FindGameObjectsWithTag"); if (method) { std::vector rs{}; - const auto array = method->Invoke*, String*>(String::New(name)); + const auto array = method->Invoke*>(String::New(name)); rs.reserve(array->max_length); for (auto i = 0; i < array->max_length; i++) rs.push_back(array->At(i)); return rs; @@ -1476,14 +1550,21 @@ class UnityResolve final { throw std::logic_error("nullptr"); } + auto GetTag() -> String* { + static Method* method; + if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("GameObject")->Get("get_tag"); + if (method) return method->Invoke(this); + throw std::logic_error("nullptr"); + } + auto GetComponent() -> Component* { static Method* method; - if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("GameObject")->Get("GetComponent", { "System.Type" }); + if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("GameObject")->Get("GetComponent", {"System.Type"}); if (method) return method->Invoke(this); throw std::logic_error("nullptr"); } - template + template auto GetComponents(Class* type, bool useSearchTypeAsArrayReturnType = false, bool recursive = false, bool includeInactive = true, bool reverse = false, List* resultList = nullptr) -> std::vector { static Method* method; if (!method) method = Get("UnityEngine.CoreModule.dll")->Get("GameObject")->Get("GetComponentsInternal"); @@ -1491,16 +1572,12 @@ class UnityResolve final { throw std::logic_error("nullptr"); } - template - auto GetComponentsInChildren(Class* type, const bool includeInactive = false) -> std::vector { - return GetComponents(type, false, true, includeInactive, false, nullptr); - } + template + auto GetComponentsInChildren(Class* type, const bool includeInactive = false) -> std::vector { return GetComponents(type, false, true, includeInactive, false, nullptr); } - template - auto GetComponentsInParent(Class* type, const bool includeInactive = false) -> std::vector { - return GetComponents(type, false, true, includeInactive, true, nullptr); - } + template + auto GetComponentsInParent(Class* type, const bool includeInactive = false) -> std::vector { return GetComponents(type, false, true, includeInactive, true, nullptr); } }; struct LayerMask : Object { @@ -1619,28 +1696,28 @@ class UnityResolve final { struct Physics { static auto Linecast(const Vector3 start, const Vector3 end) -> bool { static Method* method; - if (!method) method = Get("UnityEngine.PhysicsModule.dll")->Get("Physics")->Get("Linecast", { "*", "*" }); + if (!method) method = Get("UnityEngine.PhysicsModule.dll")->Get("Physics")->Get("Linecast", {"*", "*"}); if (method) return method->Invoke(start, end); throw std::logic_error("nullptr"); } static auto Raycast(const Vector3 origin, const Vector3 direction, const float maxDistance) -> bool { static Method* method; - if (!method) method = Get("UnityEngine.PhysicsModule.dll")->Get("Physics")->Get("Raycast", { "*", "*", "*" }); + if (!method) method = Get("UnityEngine.PhysicsModule.dll")->Get("Physics")->Get("Raycast", {"*", "*", "*"}); if (method) return method->Invoke(origin, direction, maxDistance); throw std::logic_error("nullptr"); } static auto IgnoreCollision(Collider* collider1, Collider* collider2) -> void { static Method* method; - if (!method) method = Get("UnityEngine.PhysicsModule.dll")->Get("Physics")->Get("IgnoreCollision1", { "*", "*" }); + if (!method) method = Get("UnityEngine.PhysicsModule.dll")->Get("Physics")->Get("IgnoreCollision1", {"*", "*"}); if (method) return method->Invoke(collider1, collider2); throw std::logic_error("nullptr"); } }; private: - template + template static auto Invoke(const void* address, Args... args) -> Return { if (address != nullptr) return reinterpret_cast(address)(args...); throw std::logic_error("nullptr"); @@ -1649,8 +1726,8 @@ class UnityResolve final { private: inline static Mode mode_{}; - inline static HMODULE hmodule_; + inline static void* hmodule_; inline static std::unordered_map address_{}; - inline static void* pDomain{}; + inline static void* pDomain{}; }; -#endif // UNITYRESOLVE_HPP \ No newline at end of file +#endif // UNITYRESOLVE_HPP diff --git a/Phasmophobia/library/d3d11hook.h b/Phasmophobia/library/d3d11hook.h index 3f01b53..c656e0e 100644 --- a/Phasmophobia/library/d3d11hook.h +++ b/Phasmophobia/library/d3d11hook.h @@ -54,7 +54,7 @@ namespace dx_hook { inline static ID3D11DeviceContext* gContext{}; inline static ID3D11RenderTargetView* gTargetView{}; - static auto MyPresent(IDXGISwapChain* a, const UINT b, const UINT c) -> HRESULT { + static auto WINAPI MyPresent(IDXGISwapChain* a, const UINT b, const UINT c) -> HRESULT { if (!init) { gSwapChain = a; if (const auto result = a->GetDevice(__uuidof(gDevice), reinterpret_cast(&gDevice)); SUCCEEDED(result)) { @@ -72,7 +72,7 @@ namespace dx_hook { present(); - return HookManager::Call(MyPresent, a, b, c); + return HookManager::Scall(MyPresent, a, b, c); } static auto NewWndProc(const HWND hWnd, const UINT uMsg, const WPARAM wParam, const LPARAM lParam) -> LRESULT {