Dllinjectっていいよね

#はじめに
メモリハックだけじゃつまらない！！そんなあなたにDllを使ったゲームハッキングの方法を紹介します。
今回はマインクラフトWindows10版でやっていきます。
#dllinjectとは
dllinjectとは外部のアプリから勝手に強制的にdllをロードさせることで、自分のコードを実行することです。
#言語
dllinjectではcまたはc++で書いたdllしか動きません.
#プロジェクトの作成
Visual Studioで新しいプロジェクト→ダイナミック リンク ライブラリ(DLL)を選択して、新しいプロジェクトを作成してください。ダイナミック リンク ライブラリ(DLL)はこの画像のやつですね。
![スクリーンショット 2021-05-04 095148.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626228/f7a0ce0a-93a5-6187-a603-5f2b939b14e2.png)
プロジェクトが作成されたら、ソリューションエクスプローラーから全体のプロジェクトを右クリックして、一番下にあるプロパティを開きましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626228/7f701e26-f549-601f-bf9d-9051fc3901ea.png)
そうしたら、C/C++の中のプリコンパイル済みヘッダーを選択してプリコンパイル済みヘッダーを使用しないにしておきましょう。
適用させたら、ヘッダーファイルとソースファイルに入っているpch.cppおよびpch.hを削除しましょう。dllmain.cppの

```cpp
#include "pch.h"
```
を削除して、

```cpp
#include <Windows.h>
```
を追加しましょう。

#早速コードを書いていく
Dllがロードされた時に最初に実行されるのが、

```c++
case DLL_PROCESS_ATTACH:
```
です。なのでここから自分のコードに連れて行きましょう。やり方はCreateThread関数です。

```cpp
HMODULE hMod = 0;
int Loaded() {
    return 0;
}

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        hMod = hModule;
        CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)Loaded, hModule, 0, nullptr);
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}
```
これでLoadedという関数で自分のコードを書けるようになります。
#ゲームハック
昔書いた記事と同じことをしていきます。ズームですね
することは大して変わりません。アドレスを見つけて書き換えるだけです。アドレスを見つける関数もDllnject流に書いてもよかったんですが、めんどくさくなったので前の記事と全く同じものを使用します。[前の記事](https://qiita.com/360tetsu360/items/ac5caab7d407ba8d8485)

```cpp
#include <vector>
#include <TlHelp32.h>
///

uintptr_t GetProcId(const wchar_t* procname) //プロセスID取得
{
    DWORD ProcId = 0;
    HANDLE hSnap = (CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0));
    if (hSnap != INVALID_HANDLE_VALUE)
    {
        PROCESSENTRY32 procentry;
        procentry.dwSize = sizeof(procentry);

        if (Process32First(hSnap, &procentry))
        {

            do
            {
                if (!_wcsicmp(procentry.szExeFile, procname))
                {
                    ProcId = procentry.th32ProcessID;
                    break;
                }
            } while (Process32Next(hSnap, &procentry));
        }
    }
    CloseHandle(hSnap);
    return ProcId;
}
uintptr_t GetModuleBaseAddress(DWORD procId, const wchar_t* modName)//ベースアドレス取得
{
    uintptr_t modBaseAddr = 0;
    HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, procId);
    if (hSnap != INVALID_HANDLE_VALUE)
    {
        MODULEENTRY32 modEntry;
        modEntry.dwSize = sizeof(modEntry);
        if (Module32First(hSnap, &modEntry))
        {
            do
            {
                if (!_wcsicmp(modEntry.szModule, modName))
                {
                    modBaseAddr = (uintptr_t)modEntry.modBaseAddr;
                    break;
                }
            } while (Module32Next(hSnap, &modEntry));
        }
    }
    CloseHandle(hSnap);
    return modBaseAddr;
}

uintptr_t FindDMAAddy(HANDLE hProc, uintptr_t ptr, std::vector<unsigned int> offsets)
{
    uintptr_t addr = ptr;
    for (unsigned int i = 0; i < offsets.size(); ++i)
    {
        ReadProcessMemory(hProc, (BYTE*)addr, &addr, sizeof(addr), 0);
        addr += offsets[i];
    }
    return addr;
}
```
ではズームを作っていきましょう。
FOVのアドレスを取得しましょう

```c++
DWORD procId = GetProcId(L"Minecraft.Windows.exe");//実行中のMinecraft.Windows.exeのプロセスID
uintptr_t BaseAddress = GetModuleBaseAddress(procId, L"Minecraft.Windows.exe");//ベースアドレスの取得
if (BaseAddress != NULL) {
    uintptr_t fovdirectadd = 0x03948840;
    vector<unsigned int> fovoffset = { 0x18,0x130,0x18 };
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, NULL, procId);//プロセスハンドル取得
    uintptr_t fovaddr = FindDMAAddy(hProcess, BaseAddress + fovdirectadd, fovoffset);
}
```
さあ早速書き込んでいきましょう。ここがDllinjectの最大のいいところです。
***なんと！！！！アドレスがわかればそのアドレスを自分の変数のように使うことが可能になるのです！！！***
やり方はreinterpret_castという強制的にキャストする関数です。コードはこうなります

```c++
float* fov = reinterpret_cast<float*>(アドレス);
*fov = 30.0f;
```
これでfovという変数を使えるようになります。

#ビルドと実行
ビルドするときは
x64になっていることを確かめてビルドしてください。
Dllinjectは自作してもいいですが、Minecraft Windows10用のとても使いやすいインジェクターがあるので、そちらを使ってインジェクトします。
[FateInjector](https://github.com/fligger/FateInjector/releases/latest/download/FateInjector.exe)

#最後に
Dllinjectのいいところはまだまだあるので次回書いていきます。