C++ Hook注入DLL 完整例子

包含要注入的Demo与dll,与注入的程序。

要注入的Demo.exe程序代码

#include <iostream>
#include <Windows.h>
using namespace std;
int showAge(int age) {
    int a = 0;
    cout << a << age << endl;
    return age;
}

int main() {
    SetConsoleTitle("Demo");
    cout << "Hello, World!" << endl;
    showAge(18);
    cin.get();
    return 0;
}

注入程序的Dll

#include <Windows.h>
#include <iostream>
#include "tchar.h"
#include "tlhelp32.h"

BOOL getProcessAddr(DWORD dwPID, DWORD &baseAddr);

DWORD retAddr;
char oldCode[5] = {0};
DWORD hookAddr;

/**
 * hook的一个exe中的方法
 * void showAge(int age){
 *   std::cout << age << endl;
 * }
 */
void hookPrint(int age){
    std::cout << "hook age is : " << (int)age << std::endl;
}

void _declspec(naked) print() {
    __asm {
        push ebp
        mov ebp,esp

        mov eax,dword ptr ss:[ebp+8]
        push eax
        call hookPrint
        add esp,0x4

        mov esp,ebp
        pop ebp
        jmp retAddr
    }
}

void hook(DWORD offset) {
    DWORD baseAddr;
    DWORD pid = GetCurrentProcessId();
    getProcessAddr(pid, baseAddr);
    hookAddr = baseAddr + offset;
    /**
     * 不需要权限
     */
    memcpy((LPVOID) oldCode, (LPVOID) hookAddr, 5);
    retAddr = hookAddr + 5;
    char jmpCode[5] = {0};
    jmpCode[0] = 0xE9;//或者0xE8
    *(DWORD *) &jmpCode[1] = (DWORD) print - hookAddr - 5;
    /**
     * 不能替换成memcpy使用
     */
    if (WriteProcessMemory(GetCurrentProcess(), (LPVOID) hookAddr, (LPVOID) jmpCode, 5, nullptr) == 0) {
        std::cout << "hook fail" << std::endl;
    } else {
        std::cout << "hook success" << std::endl;
    }
}

void unhook() {
    std::cout << "unhook" << std::endl;
    if (WriteProcessMemory(GetCurrentProcess(), (LPVOID) hookAddr, (LPVOID) oldCode, 5, nullptr) == 0) {
        std::cout << "unhook fail" << std::endl;
    } else {
        std::cout << "unhook success" << std::endl;
    }
}

BOOL getProcessAddr(DWORD dwPID, DWORD &baseAddr) {
    HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
    MODULEENTRY32 me32;
    hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID);
    me32.dwSize = sizeof(MODULEENTRY32);
    if (!Module32First(hModuleSnap, &me32)) {
        CloseHandle(hModuleSnap);
        return FALSE;
    }
    baseAddr = (DWORD) me32.modBaseAddr;
    CloseHandle(hModuleSnap);
    return TRUE;
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
    switch (ul_reason_for_call) {
        case DLL_PROCESS_ATTACH:
            hook(0x1717);//0x1717是使用x32dbg查到call的位置偏移
            break;
        case DLL_PROCESS_DETACH:
            unhook();
            break;
        case DLL_THREAD_ATTACH:
            break;
        case DLL_THREAD_DETACH:
            break;
    }
    return TRUE;
}

注入Dll的程序

#include <iostream>
#include <Windows.h>
#include "tchar.h"
#include "WindowUtil.h"

DWORD findProcessPid(LPCTSTR name) {
    HANDLE hProcess = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (!hProcess) {
        return FALSE;
    }
    PROCESSENTRY32 info;
    info.dwSize = sizeof(info);
    if (!Process32First(hProcess, &info)) {
        return FALSE;
    }
    while (true) {
        const LPTSTR fName = info.szExeFile;
        if (_tcscmp(fName, name) == 0) {
            CloseHandle(hProcess);
            return info.th32ProcessID;
        }
        if (!Process32Next(hProcess, &info)) {
            CloseHandle(hProcess);
            return FALSE;
        }
    }
}

BOOL getProcessAddr(DWORD pid, LPCTSTR moduleName, DWORD &baseAddr) {
    HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
    MODULEENTRY32 me32;
    hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
    me32.dwSize = sizeof(MODULEENTRY32);
    if (!Module32First(hModuleSnap, &me32)) {
        CloseHandle(hModuleSnap);
        return FALSE;
    }
    do {
        if (_tcscmp(me32.szModule, moduleName) == 0 || _tcscmp(me32.szExePath, moduleName) == 0) {
            break;
        }
    } while (Module32Next(hModuleSnap, &me32));
    baseAddr = (DWORD) me32.modBaseAddr;
    CloseHandle(hModuleSnap);
    return TRUE;
}

void inject(LPCTSTR name, LPCTSTR dllPath) {
    DWORD pid = findProcessPid(name);
    HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
    unsigned int size = strlen(dllPath);
    LPVOID dllPathAddr = VirtualAllocEx(handle, nullptr, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    WriteProcessMemory(handle, dllPathAddr, dllPath, size, nullptr);
    HANDLE remoteHandle = CreateRemoteThread(handle, nullptr, NULL, (PTHREAD_START_ROUTINE) LoadLibraryA, dllPathAddr,
                                             NULL, nullptr);
    WaitForSingleObject(remoteHandle, INFINITE);
    VirtualFreeEx(handle, dllPathAddr, size, MEM_DECOMMIT);
    CloseHandle(remoteHandle);
    CloseHandle(handle);
}

void unject(LPCTSTR name, LPCTSTR dllPath) {
    DWORD pid = findProcessPid(name);
    DWORD dllPathAddr;
    getProcessAddr(pid, dllPath, dllPathAddr);
    std::cout << std::hex << dllPathAddr << std::endl;
    HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
    HANDLE remoteHandle = CreateRemoteThread(handle, nullptr, NULL, (PTHREAD_START_ROUTINE) FreeLibrary,
                                             (LPVOID) dllPathAddr,
                                             NULL, nullptr);
    WaitForSingleObject(remoteHandle, INFINITE);
    CloseHandle(remoteHandle);
    CloseHandle(handle);
}

int main() {
    LPCTSTR name = _T("Demo.exe");
    LPCTSTR dllPath = _T("C:\\Users\\Administrator\\CLionProjects\\Dll2\\cmake-build-release\\Dll2.dll");
    inject(name, dllPath);
    std::cin.get();//输入任意字符回车即可卸载Dll
    unject(name, dllPath);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/dounine/article/details/126456728