Гайд Переносим Minhook на C# и хукаем с помощью него функцию

Начинающий
Статус
Оффлайн
Регистрация
29 Июл 2022
Сообщения
101
Реакции[?]
28
Поинты[?]
29K
Привет. У dotnet есть технология NativeAOT которая позволяет компилировать нашу .NET сборку сразу в машинный код и вместе с этим у него появилось одно преимущество.

😎С ним можно линковать другие статические библиотеки. Этим я сегодня воспользуюсь и покажу тебе самый крутой хук. Будем хукать скорость в одной игре на IL2CPP виде функции и в ней же получим поле на высоту прыжка и изменим его значение тоже.

1. Создание статической библиотеки:

С этим не должно быть никаких проблем.
1713435066081.png
Просто компилируем статическую библиотеку вместе с MinHook.

2. Создание DLL на C#:

Для компиляции в нативный формат нашего .net, нам нужен sdk не ниже .NET 7. На более ранних версиях компиляция недоступна. И так:
1713435183767.png
Дальше выбираем версию .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 и всё остальное
Будем мы ломать игрушку под названием Paint The Town Red. А именно скорость персонажа и высоту его прыжка.

Создаем делегат под нашу функцию:

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;
        }
Всё. Теперь осталось только открыть проект в терминале (правой кнопкой мыши на проект -> Открыть в терминале). И написать команду "dotnet publish -r win-x64 -c Release". Наша DLL появиться в папке bin\Release\net<version>\native.

Дальше осталось просто заинжектировать и вуаля:

1713436644735.png


Хук работает! На всякий случай оставлю весь код тут:


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;
        }
    }
}
 
Последнее редактирование:
Эксперт
Статус
Оффлайн
Регистрация
29 Мар 2021
Сообщения
1,605
Реакции[?]
607
Поинты[?]
48K
так а где перенос минхука на шарп, ты сделал байндинги к экспорту minhook.dll

статья с переносом минхука на питон когда ждать?
 
Начинающий
Статус
Оффлайн
Регистрация
29 Июл 2022
Сообщения
101
Реакции[?]
28
Поинты[?]
29K
так а где перенос минхука на шарп, ты сделал байндинги к экспорту minhook.dll

статья с переносом минхука на питон когда ждать?
Под переносом можно подразумевать что угодно. Хватить притягивать слова по каждой мелочи.
 
Эксперт
Статус
Оффлайн
Регистрация
29 Мар 2021
Сообщения
1,605
Реакции[?]
607
Поинты[?]
48K
Начинающий
Статус
Оффлайн
Регистрация
29 Июл 2022
Сообщения
101
Реакции[?]
28
Поинты[?]
29K
да нихуя подобного

перенос на шарп это именно что перенос на шарп, а не натягивание на шарп
Это конечно замечательно что для тебя отличается значение слова переноса, но твоя попытка написать комментарий уж больно смахивает на говнопопытку обосрать пост в некомпетентной для тебя среде. Так что давай, гуляй
 
Эксперт
Статус
Оффлайн
Регистрация
29 Мар 2021
Сообщения
1,605
Реакции[?]
607
Поинты[?]
48K
Начинающий
Статус
Оффлайн
Регистрация
29 Июл 2022
Сообщения
101
Реакции[?]
28
Поинты[?]
29K
а какова среда данного поста? абуз волшебного дотнета для вызова экспорта согласно си аби? че ты несёшь ахахах

on topic:
Посмотреть вложение 275892
"Перенос" в том числе можно интерпретировать и как линковку статической библиотеки. Каждый может понимать это по разному.
а какова среда данного поста? абуз волшебного дотнета для вызова экспорта согласно си аби? че ты несёшь ахахах

on topic:
Посмотреть вложение 275892
И я не понял, к чему эти стрелки про среду поста. Я ещё в названии заявил тебе о переносе минхука (именно переносе, не переписи), потому что я связываю статическую библиотеку, а не переписываю все на си шарп код. Даже этим можно было понять что под "переносом" я имею в виду именно это.

Но нет, какому-то старперу понадобилось доебаться к мизерной хуйне и попытаться обосрать рандом юзера на югейме. Ещё и мемы на месте фотошопит. Курам насмех)
 
Эксперт
Статус
Оффлайн
Регистрация
29 Мар 2021
Сообщения
1,605
Реакции[?]
607
Поинты[?]
48K
"Перенос" в том числе можно интерпретировать и как линковку статической библиотеки. Каждый может понимать это по разному.
ты не с той ноги проснулся или че дедуля

перенос минхук на шарп != туториал как линкануть мингук точка либ к проекту дотнет


И я не понял, к чему эти стрелки про среду поста.
некомпетентной для тебя среде
буквально прямая твоя цитата

(именно переносе, не переписи)
читай первый пункт

связываю статическую библиотеку, а не переписываю все на си шарп код
в таком случае в чем смысл твоего гайда ебучего?

забилдим чужую библиотеку, с этим у вас не должно возникнуть проблем
распишем поминутно блядь все шаги с фулл пастой враппера получившейся статической либы
 
Начинающий
Статус
Оффлайн
Регистрация
21 Апр 2024
Сообщения
33
Реакции[?]
22
Поинты[?]
21K
Байдинг не плох,пригодится тем кто пишет софт на c#.Не слушай клоунов сверху,которые думают что байдинг это переписывать полностью библиотеку с одного языка на другой.Эти клоуны походу репозитории некоторых библиотек на гитхабе в глаза не видлеи
 
Начинающий
Статус
Оффлайн
Регистрация
25 Июл 2017
Сообщения
87
Реакции[?]
12
Поинты[?]
0
Разве с IL2CPP нужно не StdCall для хуков использовать? И
GetCurrentMoveTypeSpeed тоже нужно пометить UnmanagedCallersOnly
 
Сверху Снизу