mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
增加米奇妙妙工具
This commit is contained in:
@@ -8,6 +8,7 @@ WM_NULL
|
|||||||
// Type & Enum definition
|
// Type & Enum definition
|
||||||
CWMO_FLAGS
|
CWMO_FLAGS
|
||||||
MINMAXINFO
|
MINMAXINFO
|
||||||
|
LPTHREAD_START_ROUTINE
|
||||||
|
|
||||||
// COMCTL32
|
// COMCTL32
|
||||||
DefSubclassProc
|
DefSubclassProc
|
||||||
@@ -23,11 +24,17 @@ GetDeviceCaps
|
|||||||
|
|
||||||
// KERNEL32
|
// KERNEL32
|
||||||
CreateEvent
|
CreateEvent
|
||||||
|
CreateRemoteThread
|
||||||
CreateToolhelp32Snapshot
|
CreateToolhelp32Snapshot
|
||||||
|
GetModuleHandle
|
||||||
|
GetProcAddress
|
||||||
Module32First
|
Module32First
|
||||||
Module32Next
|
Module32Next
|
||||||
ReadProcessMemory
|
ReadProcessMemory
|
||||||
SetEvent
|
SetEvent
|
||||||
|
VirtualAllocEx
|
||||||
|
VirtualFreeEx
|
||||||
|
WaitForSingleObject
|
||||||
WriteProcessMemory
|
WriteProcessMemory
|
||||||
|
|
||||||
// OLE32
|
// OLE32
|
||||||
|
|||||||
@@ -5,6 +5,11 @@ using Snap.Hutao.Core;
|
|||||||
using Snap.Hutao.Service.Game.Unlocker;
|
using Snap.Hutao.Service.Game.Unlocker;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using Windows.Win32.Foundation;
|
||||||
|
using Windows.Win32.System.Memory;
|
||||||
|
using Windows.Win32.System.Threading;
|
||||||
|
using static Windows.Win32.PInvoke;
|
||||||
|
|
||||||
namespace Snap.Hutao.Service.Game;
|
namespace Snap.Hutao.Service.Game;
|
||||||
|
|
||||||
@@ -83,4 +88,68 @@ internal static class ProcessInterop
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 加载并注入指定路径的库
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="hProcess">进程句柄</param>
|
||||||
|
/// <param name="libraryPathu8">库的路径,不包含'\0'</param>
|
||||||
|
[SuppressMessage("", "SH002")]
|
||||||
|
public static unsafe void LoadLibraryAndInject(HANDLE hProcess, ReadOnlySpan<byte> libraryPathu8)
|
||||||
|
{
|
||||||
|
HINSTANCE hKernelDll = GetModuleHandle("kernel32.dll");
|
||||||
|
Marshal.ThrowExceptionForHR(Marshal.GetLastPInvokeError());
|
||||||
|
|
||||||
|
FARPROC pLoadLibraryA = GetProcAddress(hKernelDll, libraryPathu8);
|
||||||
|
Marshal.ThrowExceptionForHR(Marshal.GetLastPInvokeError());
|
||||||
|
|
||||||
|
void* pNativeLibraryPath = default;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
VIRTUAL_ALLOCATION_TYPE allocType = VIRTUAL_ALLOCATION_TYPE.MEM_RESERVE | VIRTUAL_ALLOCATION_TYPE.MEM_COMMIT;
|
||||||
|
pNativeLibraryPath = VirtualAllocEx(hProcess, default, unchecked((uint)libraryPathu8.Length + 1), allocType, PAGE_PROTECTION_FLAGS.PAGE_READWRITE);
|
||||||
|
Marshal.ThrowExceptionForHR(Marshal.GetLastPInvokeError());
|
||||||
|
|
||||||
|
WriteProcessMemory(hProcess, pNativeLibraryPath, libraryPathu8);
|
||||||
|
Marshal.ThrowExceptionForHR(Marshal.GetLastPInvokeError());
|
||||||
|
|
||||||
|
LPTHREAD_START_ROUTINE lpThreadLoadLibraryA = pLoadLibraryA.CreateDelegate<LPTHREAD_START_ROUTINE>();
|
||||||
|
HANDLE hLoadLibraryAThread = default;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
hLoadLibraryAThread = CreateRemoteThread(hProcess, default, 0, lpThreadLoadLibraryA, pNativeLibraryPath, 0);
|
||||||
|
Marshal.ThrowExceptionForHR(Marshal.GetLastPInvokeError());
|
||||||
|
|
||||||
|
// What are we waiting for?
|
||||||
|
WaitForSingleObject(hLoadLibraryAThread, 2000);
|
||||||
|
Marshal.ThrowExceptionForHR(Marshal.GetLastPInvokeError());
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
CloseHandle(hLoadLibraryAThread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
VirtualFreeEx(hProcess, pNativeLibraryPath, 0, VIRTUAL_FREE_TYPE.MEM_RELEASE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[SuppressMessage("", "SH002")]
|
||||||
|
private static unsafe FARPROC GetProcAddress(HINSTANCE hModule, ReadOnlySpan<byte> lpProcName)
|
||||||
|
{
|
||||||
|
fixed (byte* lpProcNameLocal = lpProcName)
|
||||||
|
{
|
||||||
|
return Windows.Win32.PInvoke.GetProcAddress(hModule, new PCSTR(lpProcNameLocal));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[SuppressMessage("", "SH002")]
|
||||||
|
private static unsafe BOOL WriteProcessMemory(HANDLE hProcess, void* lpBaseAddress, ReadOnlySpan<byte> buffer)
|
||||||
|
{
|
||||||
|
fixed (void* lpBuffer = buffer)
|
||||||
|
{
|
||||||
|
return Windows.Win32.PInvoke.WriteProcessMemory(hProcess, lpBaseAddress, lpBuffer, unchecked((uint)buffer.Length));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,10 @@
|
|||||||
PrimaryButtonText="{shcm:ResourceString Name=ContentDialogConfirmPrimaryButtonText}"
|
PrimaryButtonText="{shcm:ResourceString Name=ContentDialogConfirmPrimaryButtonText}"
|
||||||
Style="{StaticResource DefaultContentDialogStyle}"
|
Style="{StaticResource DefaultContentDialogStyle}"
|
||||||
mc:Ignorable="d">
|
mc:Ignorable="d">
|
||||||
|
<ContentDialog.Resources>
|
||||||
|
<x:Double x:Key="NumberBoxMinWidth">180</x:Double>
|
||||||
|
<x:Double x:Key="ContentDialogMaxWidth">1200</x:Double>
|
||||||
|
</ContentDialog.Resources>
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="auto"/>
|
<RowDefinition Height="auto"/>
|
||||||
@@ -48,11 +51,11 @@
|
|||||||
TextTrimming="CharacterEllipsis"/>
|
TextTrimming="CharacterEllipsis"/>
|
||||||
<NumberBox
|
<NumberBox
|
||||||
Grid.Column="2"
|
Grid.Column="2"
|
||||||
MinWidth="100"
|
MinWidth="{StaticResource NumberBoxMinWidth}"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Maximum="{Binding LevelMax}"
|
Maximum="{Binding LevelMax}"
|
||||||
Minimum="{Binding LevelMin}"
|
Minimum="{Binding LevelMin}"
|
||||||
SpinButtonPlacementMode="Compact"
|
SpinButtonPlacementMode="Inline"
|
||||||
Value="{Binding LevelCurrent, Mode=TwoWay}"/>
|
Value="{Binding LevelCurrent, Mode=TwoWay}"/>
|
||||||
<FontIcon
|
<FontIcon
|
||||||
Grid.Column="3"
|
Grid.Column="3"
|
||||||
@@ -61,11 +64,11 @@
|
|||||||
Glyph=""/>
|
Glyph=""/>
|
||||||
<NumberBox
|
<NumberBox
|
||||||
Grid.Column="4"
|
Grid.Column="4"
|
||||||
MinWidth="100"
|
MinWidth="{StaticResource NumberBoxMinWidth}"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Maximum="{Binding LevelMax}"
|
Maximum="{Binding LevelMax}"
|
||||||
Minimum="{Binding LevelMin}"
|
Minimum="{Binding LevelMin}"
|
||||||
SpinButtonPlacementMode="Compact"
|
SpinButtonPlacementMode="Inline"
|
||||||
Value="{Binding LevelTarget, Mode=TwoWay}"/>
|
Value="{Binding LevelTarget, Mode=TwoWay}"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
@@ -95,11 +98,11 @@
|
|||||||
TextTrimming="CharacterEllipsis"/>
|
TextTrimming="CharacterEllipsis"/>
|
||||||
<NumberBox
|
<NumberBox
|
||||||
Grid.Column="2"
|
Grid.Column="2"
|
||||||
MinWidth="100"
|
MinWidth="{StaticResource NumberBoxMinWidth}"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Maximum="{Binding LevelMax}"
|
Maximum="{Binding LevelMax}"
|
||||||
Minimum="{Binding LevelMin}"
|
Minimum="{Binding LevelMin}"
|
||||||
SpinButtonPlacementMode="Compact"
|
SpinButtonPlacementMode="Inline"
|
||||||
Value="{Binding LevelCurrent, Mode=TwoWay}"/>
|
Value="{Binding LevelCurrent, Mode=TwoWay}"/>
|
||||||
<FontIcon
|
<FontIcon
|
||||||
Grid.Column="3"
|
Grid.Column="3"
|
||||||
@@ -108,11 +111,11 @@
|
|||||||
Glyph=""/>
|
Glyph=""/>
|
||||||
<NumberBox
|
<NumberBox
|
||||||
Grid.Column="4"
|
Grid.Column="4"
|
||||||
MinWidth="100"
|
MinWidth="{StaticResource NumberBoxMinWidth}"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Maximum="{Binding LevelMax}"
|
Maximum="{Binding LevelMax}"
|
||||||
Minimum="{Binding LevelMin}"
|
Minimum="{Binding LevelMin}"
|
||||||
SpinButtonPlacementMode="Compact"
|
SpinButtonPlacementMode="Inline"
|
||||||
Value="{Binding LevelTarget, Mode=TwoWay}"/>
|
Value="{Binding LevelTarget, Mode=TwoWay}"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
|
|||||||
Reference in New Issue
Block a user