• HOOK API(四)—— 进程防终止


    HOOK API(四)

    —— 进程防终止

    原文出处:www.cnblogs.com/fanling999/

    源代码:https://github.com/hfl15/windows_kernel_development/tree/master/demo_source_code/ProcessProtecting

    0x00        前言

    这算是一个实战吧,做的一个应用需要实现进程的防终止保护,查了相关资料后决定用HOOK API的方式实现。起初学习HOOK API的起因是因为要实现对剪切板的监控,后来面对进程保护这样一个需求时,综合各方资料并自己动手实现HOOK OpenProcess() 和 TerminateProcess() 来从调用层实现进程的防终止。下面将进一步介绍实现的过程,也算是对学习的一个总结与实战。

    主要参考:http://www.cnblogs.com/delphi7456/archive/2010/10/31/1865729.html

    0x01        实现思路

    大体的HOOK API的实现思路在前面几篇相关文章中已经讲过。大致可分为以下步骤:1.确定要HOOK的API原型,并参照原型定义自己的API。2.在DLL中实现自己的API,并使用新的API入口地址替换原API地址实现HOOK,利用jmp xxxx 指令实现重定向。其中可以利用GetProcAddress()获取系统的API地址,通过WriteProcessMemory将自己写的API地址替换掉原API地址。3.利用鼠标钩子将自己的DLL注入到目标进程中。

    我们这里要实现进程的防终止,设计到的API有两个,分别是OpenProcess() 和 TerminateProcess(),这两个API在Kernel32.dll中。如果只HOOK 其中一个API是不可行的,若只HOOK OpenProcess(),那么任务管理器将无法获取到受保护进程的信息,进而会出错。若只HOOK TerminateProcess也是不可行的,因为一个进程的句柄在本进程与其他进程中是不一样的,因此若是你不知道自己进程在其他进程中的句柄那将无法HOOK TerminateProcess。

    本事例采用的方案是,同时HOOK OpenProcess()和TerminateProcess(),在OpenProcess中获取自己的受保护进程在其他进程中的调用句柄,然后再TerminateProcess进程监控,如果发现有进程调用TerminateProcess并且所借宿的对象是自己要保护的进程,那么就给出禁止关闭的提示窗口。

    OpenProcess()是打开进程,而TerminateProcess()是结束进程,在调用TerminateProcess()结束进程时,必然会先调用OpenProcess()进程打开进程句柄。以下是这两个API的原型:
    
    HANDLE OpenProcess(
      DWORD dwDesiredAccess,     //渴望得到的访问权限(标志)
      BOOL bInheritHandle,         // 是否继承句柄
      DWORD dwProcessId        // 进程标示符
    
    );
    
    BOOL TerminateProcess(
      HANDLE hProcess,        //进程句柄
      UINT uExitCode         //进程终止码
    ); 

    0x02        HOOL DLL的实现

    MonitorDll中的MonitorDll.h源码:

    // MonitorDll.h : MonitorDll DLL 的主头文件
    //
    #pragma once
    #ifndef __AFXWIN_H__
        #error "在包含此文件之前包含"stdafx.h"以生成 PCH 文件"
    #endif
    
    #include "resource.h"        // 主符号
    
    // CMonitorDllApp
    // 有关此类实现的信息,请参阅 MonitorDll.cpp
    //
    class CMonitorDllApp : public CWinApp
    {
    public:
        CMonitorDllApp();
    
    // 重写
    public:
        virtual BOOL InitInstance();
        int ExitInstance();
        DECLARE_MESSAGE_MAP()
    };

    MonitorDll中的MonitorDll.cpp源码:

    // MonitorDll.cpp : 定义 DLL 的初始化例程。
    //
    
    
    #include "stdafx.h"
    #include "MonitorDll.h"
    
    #ifdef _DEBUG
    #define new DEBUG_NEW
    #endif
    
    /*
        全局变量
    */
    // 共享变量 #pragma data_seg("Share") HWND g_hwnd = NULL; // 主窗口句柄,加载HOOK时传入 HINSTANCE hInstance = NULL; // 本DLL的实例句柄 HHOOK hhook = NULL; // 鼠标钩子句柄 DWORD g_dwProcessId; // 进程id HANDLE g_hProcess = NULL; // 保存本进程在远进程中的句柄 #pragma data_seg() #pragma comment(linker,"/section:Share,rws") // 其他变量定义 HANDLE hProcess = NULL; // 当前进程句柄 bool bIsInjected = false; // 保证只注入一次 #define CODE_LENGTH 5 // 入口指令长度 // TerminateProcess typedef BOOL (WINAPI *TypeTerminateProcess)(_In_ HANDLE hProcess, _In_ UINT uExitCode); //Kernel32.dll TypeTerminateProcess oldTerminateProcess = NULL; FARPROC pfOldTerminateProcess = NULL; BOOL WINAPI MyTerminateProcess(_In_ HANDLE hProcess, _In_ UINT uExitCode); BYTE oldCodeTermPro[CODE_LENGTH]; // 原API入口 BYTE newCodeTermpro[CODE_LENGTH]; // 新API入口 // OpenProcess typedef HANDLE(WINAPI *TypeOpenProcess)( _In_ DWORD dwDesiredAccess,_In_ BOOL bInheritHandle,_In_ DWORD dwProcessId); TypeOpenProcess oldOpenProcess = NULL; FARPROC pfOldOpenProcess = NULL; HANDLE WINAPI MyOpenProcess(_In_ DWORD dwDesiredAccess,_In_ BOOL bInheritHandle,_In_ DWORD dwProcessId); BYTE oldCodeOpenPro[CODE_LENGTH]; BYTE newCodeOpenPro[CODE_LENGTH]; BOOL WINAPI HookLoad(HWND hwnd,DWORD dwProcessId); // 关于dll hook 操作 VOID WINAPI HookUnload(); VOID Inject(); VOID HookOn(); VOID HookOff();
    BOOL SetPrivilege( HANDLE hToken,
    // access token handle LPCTSTR lpszPrivilege, // name of privilege to enable/disable BOOL bEnablePrivilege // to enable or disable privilege ) ; LRESULT CALLBACK MouseProc( // 鼠标钩子子过程调用 int nCode, // hook code WPARAM wParam,// message identifier LPARAM lParam // mouse coordinates ); BOOL WriteMemory(LPVOID lpAddress,BYTE* pcode,size_t length); //将长度为 length 的 pcode 写入地址 lpAddress 的进程内存中 // //TODO: 如果此 DLL 相对于 MFC DLL 是动态链接的, // 则从此 DLL 导出的任何调入 // MFC 的函数必须将 AFX_MANAGE_STATE 宏添加到 // 该函数的最前面。 // // 例如: // // extern "C" BOOL PASCAL EXPORT ExportedFunction() // { // AFX_MANAGE_STATE(AfxGetStaticModuleState()); // // 此处为普通函数体 // } // // 此宏先于任何 MFC 调用 // 出现在每个函数中十分重要。这意味着 // 它必须作为函数中的第一个语句 // 出现,甚至先于所有对象变量声明, // 这是因为它们的构造函数可能生成 MFC // DLL 调用。 // // 有关其他详细信息, // 请参阅 MFC 技术说明 33 和 58。 // // CMonitorDllApp BEGIN_MESSAGE_MAP(CMonitorDllApp, CWinApp) END_MESSAGE_MAP() // CMonitorDllApp 构造 CMonitorDllApp::CMonitorDllApp(){ // TODO: 在此处添加构造代码, // 将所有重要的初始化放置在 InitInstance 中 } // 唯一的一个 CMonitorDllApp 对象 CMonitorDllApp theApp; // CMonitorDllApp 初始化 BOOL CMonitorDllApp::InitInstance(){ CWinApp::InitInstance(); hInstance = AfxGetInstanceHandle(); // 获取本dll句柄 /* 先提高权限,再获取进程句柄。 因为只有权限足够,才能获取到当前进程的句柄。 */ HANDLE hToken; BOOL bRet = OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,&hToken); if (bRet == FALSE){ AfxMessageBox(_T("权限提升失败")); } SetPrivilege(hToken,SE_DEBUG_NAME,TRUE); DWORD dwPid = ::GetCurrentProcessId(); hProcess = ::OpenProcess(PROCESS_ALL_ACCESS,0,dwPid); if (hProcess == NULL){ CString str; str.Format(_T("OpenProcess fail!!, error code = [%d]"),GetLastError()); AfxMessageBox(str); return FALSE; } Inject(); // 开始注入 return TRUE; } // // 实例退出函数。退出时,一定要记得恢复原函数地址!!! // int CMonitorDllApp::ExitInstance() { HookOff(); //要记得恢复原函数地址 return CWinApp::ExitInstance(); } /* 鼠标钩子子过程,目的是加载本dll到使用鼠标的程序. 鼠标钩子的作用:当鼠标在某程序窗口中时,就会加载我们这个dll。 即使本DLL随着鼠标钩子注入到目标进程中。 */ LRESULT CALLBACK MouseProc( int nCode, // hook code WPARAM wParam, // message identifier LPARAM lParam // mouse coordinates ) { return CallNextHookEx(hhook,nCode,wParam,lParam); } /* 安装钩子。 主调程序传入窗口句柄和进程id。 */ BOOL WINAPI HookLoad(HWND hwnd,DWORD dwProcessId){ BOOL ret = FALSE; g_hwnd = hwnd; g_dwProcessId = dwProcessId; hhook = ::SetWindowsHookEx(WH_MOUSE,MouseProc,hInstance,0);
    if (hhook == NULL){ return FALSE; } else{ return TRUE; } } /* 卸载钩子。 注:卸载钩子之前,一定要记得恢复原函数地址!!! */ VOID WINAPI HookUnload(){ HookOff(); // 恢复原函数地址 if (hhook != NULL){ UnhookWindowsHookEx(hhook); } if (hInstance != NULL){ FreeLibrary(hInstance); } } /* 注入函数。 主要完成原函数地址的保存,保存到 oldCode_[]中; 新入口地址的计算,保存到newCode_[]中,即 jmp xxxx 指令。 新入口地址 = 新函数地址 - 原函数地址 - 指令长度 最后一定要记得HookOn!! */ VOID Inject(){ if (bIsInjected == TRUE){ return; } bIsInjected = TRUE;// 保证只注入一次
    // TerminateProcess HMODULE hmodleKernel32; hmodleKernel32 = ::LoadLibrary(_T("Kernel32.dll")); if (NULL == hmodleKernel32){ AfxMessageBox(_T("加载Kernel32.dll失败")); return; } // 获取原函数地址 oldTerminateProcess = (TypeTerminateProcess)GetProcAddress(hmodleKernel32,"TerminateProcess"); if (NULL == oldTerminateProcess){ AfxMessageBox(_T("获取TerminateProcess函数失败")); return; } pfOldTerminateProcess = (FARPROC)oldTerminateProcess; // 保存原函数入口 _asm { lea edi,oldCodeTermPro mov esi,pfOldTerminateProcess cld mov ecx,CODE_LENGTH rep movsb } // 替换新函数入口 newCodeTermpro[0] = 0xe9; _asm { lea eax,MyTerminateProcess mov ebx,pfOldTerminateProcess sub eax,ebx sub eax,CODE_LENGTH mov dword ptr [newCodeTermpro+1],eax } // OpenProcess oldOpenProcess = (TypeOpenProcess)GetProcAddress(hmodleKernel32,"OpenProcess"); if (NULL == oldOpenProcess){ AfxMessageBox(_T("获取OpenProcess地址失败")); return; } pfOldOpenProcess = (FARPROC)oldOpenProcess;
    _asm { lea edi,oldCodeOpenPro mov esi,pfOldOpenProcess cld mov ecx,CODE_LENGTH rep movsb }
    newCodeOpenPro[
    0] = 0xe9; _asm { lea eax,MyOpenProcess mov ebx,pfOldOpenProcess sub eax,ebx sub eax,CODE_LENGTH mov dword ptr [newCodeOpenPro+1],eax } HookOn(); //填充完毕,开始HOOK } /* 将长度为 length 的 pcode 写入地址 lpAddress 的进程内存中 */ BOOL WriteMemory(LPVOID lpAddress,BYTE* pcode,size_t length){ ASSERT(hProcess != NULL); DWORD dwtemp,dwOldProtect,dwRet,dwWrited; dwRet = VirtualProtectEx(hProcess,lpAddress,length,PAGE_READWRITE,&dwOldProtect); CString logInfo; if ( 0 == dwRet){ logInfo.Format(_T("WriteMemory :: Call VirtualProtectEx fail, eror code = [%d] "),GetLastError()); AfxMessageBox(logInfo); return FALSE; } dwRet = WriteProcessMemory(hProcess,lpAddress,pcode,length,&dwWrited); if ( 0 == dwRet || 0 == dwWrited){ logInfo.Format(_T("WriteMemory :: Call WriteProcessMomory fail, error code = [%d] "),GetLastError()); AfxMessageBox(logInfo); return FALSE; } dwRet = VirtualProtectEx(hProcess,lpAddress,length,dwOldProtect,&dwtemp); if ( 0 == dwRet ){ logInfo.Format(_T("WriteMemory :: Recover Protect fail, error code = [%d] "),GetLastError()); AfxMessageBox(logInfo); return FALSE; } return TRUE; } /* 开始HOOK。 即,将Inject 初始化好的入口地址进行写入进程内存中。 这里,将新函数入口 newCode_[],写入内存中。 这样一来,在原函数被调用的时候,就会跳转到我们新函数的位置。 注: 这里处理的函数,是当前需要替换的所有函数,所以只在Inject()函数中调用, 即进行初始化的时候用到该函数。 */ VOID HookOn(){ BOOL ret; ret = WriteMemory(pfOldTerminateProcess,newCodeTermpro,CODE_LENGTH); if (FALSE == ret){ AfxMessageBox(_T("HookOn :: Fail to write pfOldTerminateProcess")); } ret = WriteMemory(pfOldOpenProcess,newCodeOpenPro,CODE_LENGTH); if (FALSE == ret){ AfxMessageBox(_T("HookOn :: Fail to write pfOldOpenProcess")); } } /* 停止HOOK。 恢复原函数地址。 注:这里处理的是所有替换的函数,所以一般情况下只有在卸载HOOK函数中调用 */ VOID HookOff(){    ASSERT(hProcess != NULL); BOOL ret; ret = WriteMemory(pfOldTerminateProcess,oldCodeTermPro,CODE_LENGTH); if (FALSE == ret){ AfxMessageBox(_T("HookOff :: fail to recover pfOldTerminateProcess ")); } ret = WriteMemory(pfOldOpenProcess,oldCodeOpenPro,CODE_LENGTH); if (FALSE == ret){ AfxMessageBox(_T("HookOff :: fail to recover pfOldOpenProcess")); } } /* 提升进程权限。 */ BOOL SetPrivilege( HANDLE hToken, // access token handle LPCTSTR lpszPrivilege, // name of privilege to enable/disable BOOL bEnablePrivilege // to enable or disable privilege ){
    TOKEN_PRIVILEGES tp; LUID luid; CString info;
    if ( !LookupPrivilegeValue( NULL, // lookup privilege on local system lpszPrivilege, // privilege to lookup &luid ) ) // receives LUID of privilege { info.Format(_T("LookupPrivilegeValue error: %u "), GetLastError() ); AfxMessageBox(info); return FALSE; } tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; if (bEnablePrivilege) tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; else tp.Privileges[0].Attributes = 0; // Enable the privilege or disable all privileges. if ( !AdjustTokenPrivileges( hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES) NULL, (PDWORD) NULL) ){ info.Format(_T("AdjustTokenPrivileges error: %u "), GetLastError() ); AfxMessageBox(info); return FALSE; } if (GetLastError() == ERROR_NOT_ALL_ASSIGNED){ info.Format(_T("The token does not have the specified privilege. ")); AfxMessageBox(info); return FALSE; } return TRUE; } // // 自己重新定义的进程终止函数。 // 检查当前要终止的进程是否是受保护进程,若是则禁止关闭。 // BOOL WINAPI MyTerminateProcess(_In_ HANDLE hProcess, _In_ UINT uExitCode){ BOOL ret; if (g_hProcess == hProcess){ AfxMessageBox(_T("不能关闭受保护进程哦!!")); ret = TRUE; } else{ WriteMemory(pfOldTerminateProcess,oldCodeTermPro,CODE_LENGTH); ret = oldTerminateProcess(hProcess,uExitCode); WriteMemory(pfOldTerminateProcess,newCodeTermpro,CODE_LENGTH); } return ret; } // // 自己定义的打开进程函数。 // 若当前打开进程为受保护进程,则记录下该远程调用句柄。 // HANDLE WINAPI MyOpenProcess(_In_ DWORD dwDesiredAccess,_In_ BOOL bInheritHandle,_In_ DWORD dwProcessId){ HANDLE hProcess = NULL; WriteMemory(pfOldOpenProcess,oldCodeOpenPro,CODE_LENGTH); hProcess = oldOpenProcess(dwDesiredAccess,bInheritHandle,dwProcessId); if ( dwProcessId == g_dwProcessId){ g_hProcess = hProcess; } WriteMemory(pfOldOpenProcess,newCodeOpenPro,CODE_LENGTH); return hProcess; }

    MonitorDll中的MonitorDll.def

    ; MonitorDll.def : 声明 DLL 的模块参数。
    
    LIBRARY
    EXPORTS
    
    ; 此处可以是显式导出
    
    HookLoad
    HookUnload

    0x03        主调MFC窗口

    MyWindow的MyWindowDlg.h

    // MyWindowDlg.h : 头文件
    //
    
    #pragma once
    // CMyWindowDlg 对话框
    class CMyWindowDlg : public CDialogEx{
    // 构造
    public:
        CMyWindowDlg(CWnd* pParent = NULL);    // 标准构造函数
    // 对话框数据
        enum { IDD = IDD_MYWINDOW_DIALOG };
        protected:
        virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持
    // 实现
    protected:
        HICON m_hIcon;
        HINSTANCE m_hinstHookDll;    //    MonitorDll的实例句柄
    
        void HookLoad();            //    加载HOOK            
        void HookUnload();            //    卸载HOOK
    
        // 生成的消息映射函数
        virtual BOOL OnInitDialog();
        afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
        afx_msg void OnPaint();
        afx_msg HCURSOR OnQueryDragIcon();
        afx_msg void OnClose();        //    关闭程序的时候卸载DLL !!!!!
        DECLARE_MESSAGE_MAP()
    
    };

    MyWindow的MyWindowDlg.cpp

    // MyWindowDlg.cpp : 实现文件
    //
    
    #include "stdafx.h"
    #include "MyWindow.h"
    #include "MyWindowDlg.h"
    #include "afxdialogex.h"
    
    #ifdef _DEBUG
    #define new DEBUG_NEW
    #endif
    
    // 用于应用程序"关于"菜单项的 CAboutDlg 对话框
    class CAboutDlg : public CDialogEx
    {
    public:
        CAboutDlg();
    
    // 对话框数据
        enum { IDD = IDD_ABOUTBOX };
    
        protected:
        virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
    
    // 实现
    
    protected:
        DECLARE_MESSAGE_MAP()
    };
    
    
    CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
    {
    }
    
    void CAboutDlg::DoDataExchange(CDataExchange* pDX)
    {
        CDialogEx::DoDataExchange(pDX);
    }
    
    
    BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
    END_MESSAGE_MAP()
    
    // CMyWindowDlg 对话框
    CMyWindowDlg::CMyWindowDlg(CWnd* pParent /*=NULL*/)
        : CDialogEx(CMyWindowDlg::IDD, pParent)
    {
        m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    }
    
     
    
    void CMyWindowDlg::DoDataExchange(CDataExchange* pDX)
    {
        CDialogEx::DoDataExchange(pDX);
    }
    
    BEGIN_MESSAGE_MAP(CMyWindowDlg, CDialogEx)
        ON_WM_SYSCOMMAND()
        ON_WM_PAINT()
        ON_WM_QUERYDRAGICON()
    END_MESSAGE_MAP()
    
    
    // CMyWindowDlg 消息处理程序
    BOOL CMyWindowDlg::OnInitDialog()
    {
        CDialogEx::OnInitDialog();
        // 将"关于..."菜单项添加到系统菜单中。
    
     
        // IDM_ABOUTBOX 必须在系统命令范围内。
        ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
        ASSERT(IDM_ABOUTBOX < 0xF000);
    
        CMenu* pSysMenu = GetSystemMenu(FALSE);
        if (pSysMenu != NULL)
        {
            BOOL bNameValid;
            CString strAboutMenu;
            bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
            ASSERT(bNameValid);
            if (!strAboutMenu.IsEmpty())
            {
                pSysMenu->AppendMenu(MF_SEPARATOR);
                pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
            }
        }
    // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动 // 执行此操作 SetIcon(m_hIcon, TRUE); // 设置大图标 SetIcon(m_hIcon, FALSE); // 设置小图标 // TODO: 在此添加额外的初始化代码 HookLoad(); // 加载HOOK return TRUE; // 除非将焦点设置到控件,否则返回 TRUE } void CMyWindowDlg::OnClose() { // TODO: 在此添加消息处理程序代码和/或调用默认值 HookUnload(); // 退出窗口,要卸载HOOK CDialogEx::OnClose(); } void CMyWindowDlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX){ CAboutDlg dlgAbout; dlgAbout.DoModal(); } else{ CDialogEx::OnSysCommand(nID, lParam); } } // 如果向对话框添加最小化按钮,则需要下面的代码 // 来绘制该图标。对于使用文档/视图模型的 MFC 应用程序, // 这将由框架自动完成。 void CMyWindowDlg::OnPaint() { if (IsIconic()){ CPaintDC dc(this); // 用于绘制的设备上下文 SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); // 使图标在工作区矩形中居中 int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // 绘制图标 dc.DrawIcon(x, y, m_hIcon); } else{ CDialogEx::OnPaint(); } } //当用户拖动最小化窗口时系统调用此函数取得光标 //显示。 HCURSOR CMyWindowDlg::OnQueryDragIcon(){ return static_cast<HCURSOR>(m_hIcon); } void CMyWindowDlg::HookLoad(){ m_hinstHookDll = ::LoadLibrary(_T("C:\testProject\MonitorDll.dll")); CString loginfo; if ( NULL == m_hinstHookDll){ loginfo.Format(_T("加载 MonitorDll.dll失败,错误代码 = [%d] "),GetLastError()); AfxMessageBox(loginfo); return; }
    typedef BOOL (WINAPI
    * LoadMonitor)(HWND hwnd,DWORD dwProcessId); LoadMonitor loadMonitor = NULL; loadMonitor = (LoadMonitor)::GetProcAddress(m_hinstHookDll,"HookLoad"); if (NULL == loadMonitor) { loginfo.Format(_T("获取函数 HookLoad 失败,错误代码 = [%d]"),GetLastError()); AfxMessageBox(loginfo); } if (loadMonitor(m_hWnd,GetCurrentProcessId())){ loginfo.Format(_T("HOOK加载成功")); AfxMessageBox(loginfo); } else{ loginfo.Format(_T("HOOK加载失败")); AfxMessageBox(loginfo); } } /* 卸载HOOKDLL */ void CMyWindowDlg::HookUnload(){ CString logInfo; if (m_hinstHookDll == NULL){ m_hinstHookDll = LoadLibrary(_T("MonitorDll.dll")); if ( NULL == m_hinstHookDll){ logInfo.Format(_T("加载 MonitorDll.dll失败,错误代码 = [%d]"),GetLastError()); AfxMessageBox(logInfo); return; } } typedef VOID (WINAPI* UnloadHook)(); UnloadHook unloadHook = NULL; unloadHook = (UnloadHook)::GetProcAddress(m_hinstHookDll,"HookUnload"); if (NULL == unloadHook){ logInfo.Format(_T("获取函数 HookUnload 失败,错误代码 = [%d]"),GetLastError()); AfxMessageBox(logInfo); return; } unloadHook(); }

    0x04        测试

    本实例说明:有两个输出文件,一个是MonitorDll.dll,这是编译MFC DLL工程得到的,用来实现HOOK API的功能,由主窗口调用,注入到目标进程中。主窗口程序MyWindow,在窗口初始化时加载HOOK,在窗口进程正常退出时卸载HOOK。实例测试效果如下:

    窗口初始化过程,打印受保护进程id:

    窗口初始化过程中自动加载HOOK,成功:

    点击确定,出现以下对话框:

    打开任务管理器,找到我们的窗口进程MyWindow.exe:

    试图强制关闭我们的进程MyWindow.exe:

    弹出不能关闭对话框,这样也就防止了进程被强制关闭:

  • 相关阅读:
    异常处理
    JPG转换成BMP不成功???
    Vmware 7 下装载的最新Ubuntu10.04镜像会出现无法识别键盘输入的解决方法
    动态IP获取
    最佳Web设计资源
    设置NFS
    Ubuntu设置root用户自动登录
    编译QT4.5
    tq2440修改默认串口不支持打印控制台
    英语作文
  • 原文地址:https://www.cnblogs.com/fanling999/p/4601118.html
Copyright © 2020-2023  润新知