-
Автор темы
- #1
Привет. У dotnet есть технология NativeAOT которая позволяет компилировать нашу .NET сборку сразу в машинный код и вместе с этим у него появилось одно преимущество.
С ним можно линковать другие статические библиотеки. Этим я сегодня воспользуюсь и покажу тебе самый крутой хук. Будем хукать скорость в одной игре на IL2CPP виде функции и в ней же получим поле на высоту прыжка и изменим его значение тоже.
1. Создание статической библиотеки:
С этим не должно быть никаких проблем.
Просто компилируем статическую библиотеку вместе с MinHook.
2. Создание DLL на C#:
Для компиляции в нативный формат нашего .net, нам нужен sdk не ниже .NET 7. На более ранних версиях компиляция недоступна. И так:
Дальше выбираем версию .NET и создаем проект.
3. Настройка DLL:
В csproj сразу вставляем вот такие атрибуты:
4. Импортирование методов:
Теперь нам надо импортировать сами методы. Делается это вот так:
После, нам надо создать точку входа. Делается это путем вставки атрибута UnmanagedCallersOnly:
Будем мы ломать игрушку под названием Paint The Town Red. А именно скорость персонажа и высоту его прыжка.
Создаем делегат под нашу функцию:
public float GetCurrentMoveTypeSpeed() Функция под хук
{
return 0f;
}
Потом пишем функцию на который будем перенаправлять вызов:
И пишем метод для самого хука:
Последний штрих: вызов в точке входа:
Всё. Теперь осталось только открыть проект в терминале (правой кнопкой мыши на проект -> Открыть в терминале). И написать команду "dotnet publish -r win-x64 -c Release". Наша DLL появиться в папке bin\Release\net<version>\native.
Дальше осталось просто заинжектировать и вуаля:
Хук работает! На всякий случай оставлю весь код тут:
С ним можно линковать другие статические библиотеки. Этим я сегодня воспользуюсь и покажу тебе самый крутой хук. Будем хукать скорость в одной игре на IL2CPP виде функции и в ней же получим поле на высоту прыжка и изменим его значение тоже.
1. Создание статической библиотеки:
С этим не должно быть никаких проблем.
Просто компилируем статическую библиотеку вместе с MinHook.
2. Создание DLL на C#:
Для компиляции в нативный формат нашего .net, нам нужен sdk не ниже .NET 7. На более ранних версиях компиляция недоступна. И так:
Дальше выбираем версию .NET и создаем проект.
3. Настройка DLL:
В csproj сразу вставляем вот такие атрибуты:
XML:
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<PublishAot>true</PublishAot> <!-- Это включит компиляцию -->
</PropertyGroup>
<!-- Теперь нам надо подключить статическую библиотеку: -->
<ItemGroup>
<DirectPInvoke Include="Minhook" /> <!-- Любое название -->
<NativeLibrary Include="Release\hellow.lib" Condition="$(RuntimeIdentifier.StartsWith('win'))" /> <!-- Путь до либки -->
<LinkerArg Include="/DEPENDENTLOADFLAG:0x800" Condition="$(RuntimeIdentifier.StartsWith('win'))" /> <!-- Этот атрибут необязателен. Благодаря этому атрибуту, компоновщиком будет link.exe -->
</ItemGroup>
4. Импортирование методов:
Теперь нам надо импортировать сами методы. Делается это вот так:
C#:
using System.Runtime.InteropServices;
public unsafe class Main
{
[DllImport("Minhook")] // Тут пишем название которое указали в DirectPInvoke
public static extern void MH_Initialize();
[DllImport("Minhook")]
public static extern void MH_CreateHook(void* pTarget, void* myMethod, void** pOriginal);
[DllImport("Minhook")]
public static extern void MH_EnableHook(void* pTarget);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr GetModuleHandle(string lpModuleName); // Для легкого получения модуля
}
После, нам надо создать точку входа. Делается это путем вставки атрибута UnmanagedCallersOnly:
C#:
[UnmanagedCallersOnly(EntryPoint = "DllMain", CallConvs = [typeof(CallConvStdcall)])]
public static bool DllMain(IntPtr hModule, uint ul_reason_for_call, IntPtr lpReserved)
{
if (ul_reason_for_call == 1)
{
}
return true;
}
//Тут только DLL_ATTACH. При желании вы можете дописать сюда ещё DETACH и всё остальное
Создаем делегат под нашу функцию:
public float GetCurrentMoveTypeSpeed() Функция под хук
{
return 0f;
}
C#:
static delegate* unmanaged[Cdecl]<void*, void*, float> speedModif_o = null;
// void* = класс, void* = methodInfo, float = возвращаемое значение.
C#:
static float GetCurrentMoveTypeSpeed(void* __this, void* methodInfo)
{
*(float*)((ulong)(nint)__this + 0x38) = 15; // получение значения поля высоты прыжка
return 99; // скорость всегда будет возвращаться в виде 99
}
// [Token(Token = "0x4004588")]
// [FieldOffset(Offset = "0x38")]
// [SerializeField]
// private float m_JumpSpeed;
И пишем метод для самого хука:
C#:
static void CreateSpeedHK()
{
fixed (void* ptr = &speedModif_o) //fixed для получения указателя на speedModif_o без удаления сборщиком мусора.
{
void* msgPtr = (delegate*<void*, void*, float>)(GetModuleHandle("GameAssembly.dll") + 0x9C97B0); //Получаем указатель на нашу функцию для хука.
void* detourPtr = (delegate*<void*, void*, float>)(&GetCurrentMoveTypeSpeed); // Указатель на нашу переписанную функцию.
MH_CreateHook(msgPtr, detourPtr, (void**)ptr); //Создание хука
MH_EnableHook(msgPtr); //Актиация хука
}
}
C#:
public static bool DllMain(IntPtr hModule, uint ul_reason_for_call, IntPtr lpReserved)
{
if (ul_reason_for_call == 1)
{
MH_Initialize();
CreateSpeedHK();
}
return true;
}
Дальше осталось просто заинжектировать и вуаля:
Хук работает! На всякий случай оставлю весь код тут:
C#:
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace MinhookPon
{
public unsafe class Main
{
#region DLLImports
[DllImport("Minhook")]
public static extern void MH_Initialize();
[DllImport("Minhook")]
public static extern void MH_CreateHook(void* pTarget, void* myMethod, void** pOriginal);
[DllImport("Minhook")]
public static extern void MH_EnableHook(void* pTarget);
[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
internal static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
#endregion
[UnmanagedCallersOnly(EntryPoint = "DllMain", CallConvs = [typeof(CallConvStdcall)])]
public static bool DllMain(IntPtr hModule, uint ul_reason_for_call, IntPtr lpReserved)
{
if (ul_reason_for_call == 1)
{
MH_Initialize();
CreateSpeedHK();
}
return true;
}
static delegate* unmanaged[Cdecl]<void*, void*, float> speedModif_o = null;
static void CreateSpeedHK()
{
fixed (void* ptr = &speedModif_o)
{
void* msgPtr = (delegate*<void*, void*, float>)(GetModuleHandle("GameAssembly.dll") + 0x9C97B0);
void* detourPtr = (delegate*<void*, void*, float>)(&GetCurrentMoveTypeSpeed);
MH_CreateHook(msgPtr, detourPtr, (void**)ptr);
MH_EnableHook(msgPtr);
}
}
static float GetCurrentMoveTypeSpeed(void* __this, void* methodInfo)
{
*(float*)((ulong)(nint)__this + 0x38) = 15;
return 99;
}
}
}
Последнее редактирование: