3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Dllinjectっていいよね(2)

Last updated at Posted at 2021-05-18

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

#関数がいくつかあるプロジェクトを作る

#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

#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という関数の中を見ていきましょう

std::cout << "Dll injected" << std::endl;

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

c++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という変数はターゲットとなるプロジェクトのFunction1と同じものとなりますね。
あとは呼び出すだけ

_Function1();

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

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

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

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

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

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

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?