HOOK API(四)—— 進程防終止

HOOK API(四) html

—— 進程防終止git

 

原文出處:www.cnblogs.com/fanling999/github

源代碼:https://github.com/hfl15/windows_kernel_development/tree/master/demo_source_code/ProcessProtectingwindows

0x00        前言

這算是一個實戰吧,作的一個應用須要實現進程的防終止保護,查了相關資料後決定用HOOK API的方式實現。起初學習HOOK API的原由是由於要實現對剪切板的監控,後來面對進程保護這樣一個需求時,綜合各方資料並本身動手實現HOOK OpenProcess() 和 TerminateProcess() 來從調用層實現進程的防終止。下面將進一步介紹實現的過程,也算是對學習的一個總結與實戰。框架

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

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]\n\n"),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]\n\n"),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]\n\n"),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 \n\n")); } 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\n"), 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\n"), GetLastError() ); AfxMessageBox(info); return FALSE; } if (GetLastError() == ERROR_NOT_ALL_ASSIGNED){ info.Format(_T("The token does not have the specified privilege. \n")); 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.defui

; 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:

 

彈出不能關閉對話框,這樣也就防止了進程被強制關閉:

相關文章
相關標籤/搜索