Windows Practice_Dll&Hook_封装IAT Hook

进程保护器的实现

本程序实现了一个简单的暴力的进程保护器,其原理也很简单,就是修改导入表,挂钩TerminateProcess函数,因为这个函数可以远程无条件的结束其它进程,所以我们要挂钩这个函数。
因为每一个程序都有可能结束要保护的程序,所以我们必须以Dll的形式注入到每一个进程中,这就涉及到注入的问题了,而Windows给我们提供了一个简单的全局挂钩的函数,即SetWindowsHook函数。
本工程主要有三个程序,分别是ProcessProtectorDll、ProcessProtectorExe以及TerminateProcessExe,从这三个程序的名字相信大家也都知道这些程序的作用了,就不再多做解释了。
下面我们一一将它们的源代码附上并稍作解释。

ProcessProtectorDll动态链接库程序

该程序主要是用来被其它的可执行程序调用,从而达到全局挂钩并保护相应进程的目的。代码如下:

// IATHook.h文件
#pragma once
#include <string>

namespace PoEdu
{
    class CIATHook
    {
    public:
        // 初始化即Hook
        // 挂哪个Dll的哪个函数的钩
        // 新的函数的地址
        // 现有的所有Module
        CIATHook(const std::string &dll_name, const std::string &func_name, void *new_func_addr);


        HMODULE WINAPI LoadLibraryA(_In_ LPCSTR lpFileName);
        HMODULE WINAPI LoadLibraryW(_In_ LPCWSTR lpFileName);
        HMODULE WINAPI LoadLibraryExA(_In_ LPCSTR lpFileName, _Reserved_ HANDLE hFile, _In_ DWORD dwFlags);
        HMODULE WINAPI LoadLibraryExW(_In_ LPCWSTR lpFileName, _Reserved_ HANDLE hFile, _In_ DWORD dwFlags);


        FARPROC WINAPI GetProcAddress(_In_ HMODULE hModule, _In_ LPCSTR lpProcName ) const;


    private:
        void HookAllModule() const;
        void HookOneModule(HMODULE hModule) const;

    private:
        std::string dll_name_;
        void *new_func_addr_;
        void *old_func_addr_;
    };
}
//IATHook.cpp文件

#include "stdafx.h"
#include "IATHook.h"
#include <TlHelp32.h>
#include <DbgHelp.h>
#include <winbase.h>

#pragma comment(lib, "DbgHelp.lib")


// 这个类还有有些不足
// 在启用新进程的时候还是挂不上


namespace PoEdu
{
    CIATHook::CIATHook(const std::string& dll_name, const std::string& func_name, void* new_func_addr) :
    dll_name_(dll_name), new_func_addr_(new_func_addr)
    {
        old_func_addr_ = GetProcAddress(GetModuleHandleA(dll_name.c_str()), func_name.c_str());

        // 开始挂钩
        // 每个Module都有自己的IAT,所以需要遍历所有的Module
        HookAllModule();
    }

    HMODULE CIATHook::LoadLibraryA(LPCSTR lpFileName)
    {
        HMODULE hModule = ::LoadLibraryA(lpFileName);
        HookOneModule(hModule);
        return hModule;
    }

    HMODULE CIATHook::LoadLibraryW(LPCWSTR lpFileName)
    {
        HMODULE hModule = ::LoadLibraryW(lpFileName);
        HookOneModule(hModule);
        return hModule;
    }

    HMODULE CIATHook::LoadLibraryExA(LPCSTR lpFileName, HANDLE hFile, DWORD dwFlags)
    {
        HMODULE hModule = ::LoadLibraryExA(lpFileName, hFile, dwFlags);
        HookOneModule(hModule);
        return hModule;
    }

    HMODULE CIATHook::LoadLibraryExW(LPCWSTR lpFileName, HANDLE hFile, DWORD dwFlags)
    {
        HMODULE hModule = ::LoadLibraryExW(lpFileName, hFile, dwFlags);
        HookOneModule(hModule);
        return hModule;
    }

    FARPROC CIATHook::GetProcAddress(HMODULE hModule, LPCSTR lpProcName) const
    {
        FARPROC pAddr = ::GetProcAddress(hModule, lpProcName);
        if (pAddr == old_func_addr_)
        {
            return static_cast<FARPROC>(new_func_addr_);
        }
        else
        {
            return pAddr;
        }
    }

    void CIATHook::HookAllModule() const
    {
        HANDLE hSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());
        MODULEENTRY32 me32 = { sizeof(MODULEENTRY32) };
        BOOL bNext = ::Module32FirstW(hSnap, &me32);

        while (bNext)
        {
            // 给每个Module挂钩
            HookOneModule(me32.hModule);

            bNext = Module32NextW(hSnap, &me32);
        }
        CloseHandle(hSnap);
    }

    void CIATHook::HookOneModule(HMODULE hModule) const
    {
        ULONG ulSize = 0;
        PIMAGE_IMPORT_DESCRIPTOR pImageImportDescriptor = static_cast<PIMAGE_IMPORT_DESCRIPTOR>(ImageDirectoryEntryToData(hModule, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &ulSize));
        if (!pImageImportDescriptor)
        {
            return;
        }

        while (pImageImportDescriptor->Name)
        {
            char *pDllName = reinterpret_cast<char *>(reinterpret_cast<BYTE *>(hModule) + pImageImportDescriptor->Name);
            if (dll_name_.compare(pDllName) == 0)
            {
                break;
            }

            ++pImageImportDescriptor;
        }

        if (pImageImportDescriptor->Name)
        {
            PIMAGE_THUNK_DATA pImageThunkData = reinterpret_cast<PIMAGE_THUNK_DATA>(reinterpret_cast<BYTE *>(hModule) + pImageImportDescriptor->FirstThunk);

            while (pImageThunkData->u1.Function)
            {
                DWORD *pDwAddr = &(pImageThunkData->u1.Function);

                if (*pDwAddr == reinterpret_cast<DWORD>(old_func_addr_))
                {
                    MEMORY_BASIC_INFORMATION mbi;
                    VirtualQuery(pDwAddr, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
                    DWORD dwOldProtection = 0;
                    VirtualProtect(pDwAddr, sizeof(DWORD_PTR), PAGE_READWRITE, &dwOldProtection);

                    // 为了安全起见,可以使用WriteProcessMemory函数进行远进程写入,这样即使权限不够,也不会报异常
                    if (!WriteProcessMemory(GetCurrentProcess(), pDwAddr, &new_func_addr_, sizeof(DWORD_PTR), nullptr))
                    {
                        MessageBoxW(nullptr, L"WriteProcessMemory", L"WriteProcessMemory", MB_OK);
                    }

                    VirtualProtect(pDwAddr, sizeof(DWORD_PTR), dwOldProtection, nullptr);
                    break;
                }
                ++pImageThunkData;
            }
        }
    }
}
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "stdafx.h"
#include "IATHook.h"

// 找到当前注入后的 IAT 表 Hook TerminateProcess
//PoEdu::CIATHook g_MyHook;


DWORD g_dwPID = 0;
HHOOK g_hHook = nullptr;


BOOL WINAPI MyTerminateProcess(_In_ HANDLE hProcess, _In_ UINT uExitCode)
{
    return FALSE;

//  DWORD dwPID = GetProcessId(hProcess);
//  if (g_dwPID == dwPID)
//  {
//      MessageBoxW(nullptr, L"这是我要保护的进程,请不要无条件终止它!", L"警告", MB_OK);
//      return TRUE;
//  }

    //return TerminateProcess(hProcess, uExitCode);
}



PoEdu::CIATHook g_MyHook("KERNEL32.dll", "TerminateProcess", MyTerminateProcess);


BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    default:
        break;
    }
    return TRUE;
}

HMODULE GetFuncModule(void * pFuncAddr)
{
    HMODULE hRet = nullptr;
    MEMORY_BASIC_INFORMATION mbi;
    if (VirtualQuery(pFuncAddr, &mbi, sizeof(MEMORY_BASIC_INFORMATION)) != 0)
    {
        hRet = static_cast<HMODULE>(mbi.AllocationBase);
    }

    return hRet;
}


LRESULT CALLBACK GetMsgProc(_In_ int code, _In_ WPARAM wParam, _In_ LPARAM lParam)
{
    //MessageBoxW(nullptr, L"GetMsgProc", L"GetMsgProc", MB_OK);
    return CallNextHookEx(g_hHook, code, wParam, lParam);
}

// 用SetWindowsHook做的注入
extern "C" _declspec(dllexport) BOOL StartProtecting(DWORD dwPID)
//extern "C" _declspec(dllexport) BOOL StartProtecting()
{
    BOOL bRet = FALSE;

    if (g_hHook == nullptr)
    {
        g_hHook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, GetFuncModule(GetMsgProc), 0);
        if (g_hHook != nullptr)
        {
            g_dwPID = dwPID;
            bRet = TRUE;
        }
    }

    return bRet;
}

extern "C" _declspec(dllexport) BOOL EndProtecting()
{
    BOOL bRet = FALSE;

    if (g_hHook != nullptr)
    {
        if (UnhookWindowsHookEx(g_hHook))
        {
            bRet = TRUE;
        }
    }

    return bRet;
}

上面主要有问题的是MyTerminateProcess函数,从这个函数的实现可以看出,我们屏蔽的是所有的TerminateProcess,因为每一个进程在调用ProcessProtectorDll动态链接库的时候都是重新复制一份,所以没法简单的在挂钩的时候传递一个要保护的进程ID,因为在新的进程调用该动态链接库的时候,一切都是初始化状态,并没有要保护的进程ID,只能通过共享空间实现所有进程的数据共享,这里我们没有实现,感兴趣的朋友可以实现一下。。。

ProcessProtectorExe程序源码

该程序主要是加载ProcessProtectorDll动态链接库从而达到保护进程不被远程无条件结束的目的。

// ProcessProtectorExe.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <Windows.h>
#include <clocale>


// 选择需要保护的进程
// 启动Hook



typedef BOOL(*FUNC)(DWORD dwPID);

void PrintErrorMessage(DWORD dwErrorCode)
{
    setlocale(LC_ALL, "chs");
    TCHAR strErrorMessage[MAXBYTE] = { 0 };
    FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, dwErrorCode, 0, strErrorMessage, MAXBYTE, nullptr);
    wprintf(L"错误代码是:%d    %s\r\n", dwErrorCode, strErrorMessage);
}


int main()
{
    HMODULE hDllModule = nullptr;
    FUNC StartProtecting = nullptr;
    FARPROC EndProtecting = nullptr;
    do
    {
        // 查找窗口
        char strProcessName[MAXBYTE] = "计算器";
        HWND hWnd = FindWindowA(nullptr, strProcessName);
        if (hWnd == nullptr)
        {
            printf("the handle of window do not found!\r\n");
            break;
        }

        // 根据窗口句柄查找进程ID
        DWORD dwProcessId = 0;
        GetWindowThreadProcessId(hWnd, &dwProcessId);
        if (dwProcessId == NULL)
        {
            printf("process Id do not found!\r\n");
            break;
        }

        // 打开进程
        HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
        if (hProcess == nullptr)
        {
            printf("open the process failed!\r\n");
            break;
        }

        // LoadLibray
        hDllModule = LoadLibrary(L"ProcessProtectorDll.dll");
        if (hDllModule == nullptr)
        {
            PrintErrorMessage(GetLastError());
            break;
        }

        // SetHook
        StartProtecting = reinterpret_cast<FUNC>(GetProcAddress(hDllModule, "StartProtecting"));
        if (StartProtecting == nullptr)
        {
            PrintErrorMessage(GetLastError());
            break;
        }
        if (!StartProtecting(dwProcessId))
        {
            PrintErrorMessage(GetLastError());
            break;
        }

        printf("进程保护成功!\r\n");

        MSG msg;
        BOOL ret;
        while ((ret = GetMessage(&msg, nullptr, 0, 0)))
        {
            if (ret == -1)
                break;
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        // UnHook
        EndProtecting = GetProcAddress(hDllModule, "EndProtecting");
        if (EndProtecting == nullptr)
        {
            PrintErrorMessage(GetLastError());
            break;
        }
        if (!EndProtecting())
        {
            PrintErrorMessage(GetLastError());
            break;
        }
    } while (false);

    if (hDllModule)
    {
        FreeLibrary(hDllModule);
    }

    system("pause");
    return 0;
}

由于动态链接库是被所有进程调用的,所以这里保护的是所有的进程不被远程无条件结束掉,而不只是计算器这个程序,这个需要注意一下。

**
// TerminateProcessExe.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <Windows.h>


int main()
{
    do
    {
        // 查找窗口
        char strProcessName[MAXBYTE] = "计算器";
        HWND hWnd = FindWindowA(nullptr, strProcessName);
        if (hWnd == nullptr)
        {
            printf("the handle of window do not found!\r\n");
            break;
        }

        // 根据窗口句柄查找进程ID
        DWORD dwProcessId = 0;
        GetWindowThreadProcessId(hWnd, &dwProcessId);
        if (dwProcessId == NULL)
        {
            printf("process Id do not found!\r\n");
            break;
        }

        // 打开进程
        HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
        if (hProcess == nullptr)
        {
            printf("open the process failed!\r\n");
            break;
        }

        MessageBoxW(nullptr, L"", L"", MB_OK);

        if (TerminateProcess(hProcess, 1))
        {
            printf("已经被终止运行!\r\n");
        }
        else
        {
            printf("没有被终止运行!\r\n");
        }
    } while (false);

    system("pause");
    return 0;
}

本程序就是尝试远程结束计算器程序,当开启了我们的进程保护器后,我们是无法终止计算器的,这也就达到了要保护的目的。

当然了,这种全局挂钩的方式是存在问题的,它会使我们的系统变得非常的慢。我们的这个进程保护器目的只是让大家了解一下什么是IAT Hook,它的原理是什么,实际上基本上不会用这种方式来实现进程保护器的。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目前最好的EasyHook的完整Demo程序,包括了Hook.dll动态库和Inject.exe注入程序。 Hook.dll动态库封装了一套稳定的下钩子的机制,以后对函数下钩子,只需要填下数组表格就能实现了,极大的方便了今后的使用。 Inject.exe是用MFC写的界面程序,只需要在界面上输入进程ID就能正确的HOOK上相应的进程,操作起来非常的简便。 这个Demo的代码风格也非常的好,用VS2010成功稳定编译通过,非常值得下载使用。 部分代码片段摘录如下: //【Inject.exe注入程序的代码片段】 void CInjectHelperDlg::OnBnClickedButtonInjectDllProcessId() { ////////////////////////////////////////////////////////////////////////// //【得到进程ID值】 UINT nProcessID = 0; if (!GetProcessID(nProcessID)) { TRACE(_T("%s GetProcessID 失败"), __FUNCTION__); return; } ////////////////////////////////////////////////////////////////////////// //【得到DLL完整路径】 CString strPathDLL; if (!GetDllFilePath(strPathDLL)) { TRACE(_T("%s GetDllFilePath 失败"), __FUNCTION__); return; } ////////////////////////////////////////////////////////////////////////// //【注入DLL】 NTSTATUS ntStatus = RhInjectLibrary(nProcessID, 0, EASYHOOK_INJECT_DEFAULT, strPathDLL.GetBuffer(0), NULL, NULL, 0); if (!ShowStatusInfo(ntStatus)) { TRACE(_T("%s ShowStatusInfo 失败"), __FUNCTION__); return; } } //【Hook.dll动态库的代码片段】 extern "C" __declspec(dllexport) void __stdcall NativeInjectionEntryPoint(REMOTE_ENTRY_INFO* InRemoteInfo) { if (!DylibMain()) { TRACE(_T("%s DylibMain 失败"), __FUNCTION__); return; } } FUNCTIONOLDNEW_FRMOSYMBOL array_stFUNCTIONOLDNEW_FRMOSYMBOL[]= { {_T("kernel32"), "CreateFileW", (void*)CreateFileW_new}, {_T("kernel32"), "CreateFileA", (void*)CreateFileA_new}, {_T("kernel32"), "ReadFile", (void*)ReadFile_new} }; BOOL HookFunctionArrayBySymbol() { /////////////////////////////////////////////////////////////// int nPos = 0; do { /////////////////////////////// FUNCTIONOLDNEW_FRMOSYMBOL* stFunctionOldNew = &g_stFUNCTIONOLDNEW_FRMOSYMBOL[nPos]; if (NULL == stFunctionOldNew->strModuleName) { break; } /////////////////////////////// if (!HookFunctionBySymbol(stFunctionOldNew->strModuleName, stFunctionOldNew->strNameFunction, stFunctionOldNew->pFunction_New)) { TRACE(_T("%s HookFunctionBySymbol 失败"), __FUNCTION__); return FALSE; } } while(++nPos); /////////////////////////////////////////////////////////////// return TRUE; } HANDLE WINAPI CreateFileW_new( PWCHAR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile ) { TRACE(_T("CreateFileW_new. lpFileName = %s"), lpFileName); return CreateFileW( lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值