Dllinjectっていいよね(2)

#前回の記事の続き
前回はdllinjectで簡単なゲームハッキングをつくりましたが、今回はdllinjectの一番いいところ、関数の呼び出しを書いていきます。

#関数がいくつかあるプロジェクトを作る
```c++
#include <iostream>
#include <string>
#include <Windows.h>

void Function1() {
    std::cout << "Function1 called" << std::endl;
}

void Function2(std::string Str) {
    std::cout << Str << std::endl;
}

int Function3(int a, int b) {
    return a + b;
}

int main()
{
    std::cout << "Base Address:" << GetModuleHandle(NULL) << std::endl;//ベースアドレス 

    std::cout << "Function1 Address:" << "base address + " << (uintptr_t)&Function1 - (uintptr_t)GetModuleHandle(NULL) << std::endl;//Function1のアドレス

    std::cout << "Function2 Address:" << "base address + " << (uintptr_t)&Function2 - (uintptr_t)GetModuleHandle(NULL) << std::endl;//Function2のアドレス

    std::cout << "Function3 Address:" << "base address + " << (uintptr_t)&Function3 - (uintptr_t)GetModuleHandle(NULL) << std::endl;//Function2のアドレス


    while (true)
    {
        if (GetAsyncKeyState(VK_ESCAPE)) //Escが押されたら終了
        {
            break;
        };
        Sleep(100);
    }
}
```
適当に書いてみました。このコードが今回のターゲットです、、、かわいそうに、、

上からじゅんに

 - ただの関数
 - 引数がある関数
 - 返り値がある関数

です。わざわざアドレスを探すのは面倒なので、それぞれのアドレスを出力させておきます。

#Dllinject用のDll
```c++
#include <Windows.h>
#include <TlHelp32.h>
#include <Psapi.h>
#include <iostream>

uintptr_t GetProcId(const wchar_t* procname) {
    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;
}

int Loaded() {
    std::cout << "Dll injected" << std::endl;
    DWORD procId = GetProcId(L"target.exe");
    uintptr_t BaseAddress = GetModuleBaseAddress(procId, L"target.exe");


    using Function1 = void(__thiscall*)();
    static Function1 _Function1 = reinterpret_cast<Function1>((uintptr_t)(BaseAddress + 69847));
    _Function1();

    using Function2 = void(__thiscall*)(std::string);
    static Function2 _Function2 = reinterpret_cast<Function2>((uintptr_t)(BaseAddress + 69742));
    _Function2("Hi from dll");

    using Function3 = int(__thiscall*)(int a, int b);
    static Function3 _Function3 = reinterpret_cast<Function3>((uintptr_t)(BaseAddress + 70462));
    int ret = _Function3(10, 4);
    std::cout << ret << std::endl;


    return 0;
}

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)Loaded, hModule, 0, nullptr);
        //FreeLibraryAndExitThread(hModule, 1);
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

```

初めのGetProcIdとGetModuleBaseAddressはインジェクトした先のプロセスのベースアドレスを取得するための関数です。

それではLoadedという関数の中を見ていきましょう

```c++
std::cout << "Dll injected" << std::endl;
```

でインジェクトしたよーという確認ログ。

```c++DWORD procId = GetProcId(L"target.exe");
uintptr_t BaseAddress = GetModuleBaseAddress(procId, L"target.exe");
```

でベースアドレス取得。

ここからが重要です!

```c++
using Function1 = void(__thiscall*)();
```
このコードで未知の関数を定義します。
そして、、

```c++
static Function1 _Function1 = reinterpret_cast<Function1>((uintptr_t)(BaseAddress + 69847));
```
で無理やりキャスト。アドレスを間違えないようにしましょう。
アドレスは、今回ターゲットにしているプロジェクトに出力させています。人によって違う場合があるので、絶対にコピペをしてコードを実行しようとはしないでください。

さてさてこれで関数を定義して無理やりキャストしたので、_Function1という変数はターゲットとなるプロジェクトのFunction1と同じものとなりますね。
あとは呼び出すだけ

```c++
_Function1();
```
うまく動いているなら、ターゲットの関数がしっかり仕事をして、Function1 calledと出力されているはずです。

引数がある場合も全く同じですが、引数を定義するときに入れておくだけです。

```c++
using Function2 = void(__thiscall*)(std::string);
```

返り値がある場合も全く同じようにできます。

#一応injectの仕方
お好きなインジェクターを使えばいいです。
cheat engineとかウサミミハリケーンなどはウィルスがなさそうで安心なので重宝しています。

#最後に
Dllinjectって最高ですよね。
次回は、virtual tableによる関数の呼び出しか、プロセスの関数のフッキングのどちらかを書きます。