HOOK API(四)

—— 进程防终止

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 调用。

//

//        有关其他详细信息,

//

// 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.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:

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

HOOK API(四)—— 进程防终止的更多相关文章

  1. HOOK API(四) —— 进程防终止

    0x00        前言 这算是一个实战吧,做的一个应用需要实现进程的防终止保护,查了相关资料后决定用HOOK API的方式实现.起初学习HOOK API的起因是因为要实现对剪切板的监控,后来面对 ...

  2. HOOK API (一)——HOOK基础+一个鼠标钩子实例

    HOOK API (一)——HOOK基础+一个鼠标钩子实例 0x00 起因 最近在做毕业设计,有一个功能是需要实现对剪切板的监控和进程的防终止保护.原本想从内核层实现,但没有头绪.最后决定从调用层入手 ...

  3. EasyHook远程进程注入并hook api的实现

    EasyHook远程进程注入并hook api的实现 http://blog.csdn.net/v6543210/article/details/44276155

  4. HOOK API(三)—— HOOK 所有程序的 MessageBox

    HOOK API(三) —— HOOK 所有程序的 MessageBox 0x00 前言 本实例要实现HOOK MessageBox,包括MessageBoxA和MessageBoxW,其实现细节与H ...

  5. HOOK API(二)—— HOOK自己程序的 MessageBox

    HOOK API(二) —— HOOK自己程序的 MessageBox 0x00 前言 以下将给出一个简单的例子,作为HOOK API的入门.这里是HOOK 自己程序的MessageBox,即将自己程 ...

  6. HOOK API(二) —— HOOK自己程序的 MessageBox

    转载来源:https://www.cnblogs.com/hookjc/ 0x00 前言 以下将给出一个简单的例子,作为HOOK API的入门.这里是HOOK 自己程序的MessageBox,即将自己 ...

  7. HOOK API(三) —— HOOK 所有程序的 MessageBox

    转载来源:https://www.cnblogs.com/hookjc/ 0x00 前言 本实例要实现HOOK MessageBox,包括MessageBoxA和MessageBoxW,其实现细节与H ...

  8. HOOK API 在多线程时应该注意的问题点

    在使用INLINE HOOK API实现对系统API的拦截时,正常情况下并没有太大问题,但一旦涉及到多线程,不管是修改IAT还是JMP,2种方法均会出现不可预料的问题,特别是在HOOK一些复杂的大型系 ...

  9. 汇编Ring 3下实现 HOOK API

    [文章标题]汇编ring3下实现HOOK API [文章作者]nohacks(非安全,hacker0058) [作者主页]hacker0058.ys168.com [文章出处]看雪论坛(bbs.ped ...

随机推荐

  1. iOS6 旋转

    iOS 6的rotation改变了很多.先来看看官方的描述  http://www.bgr.com/2012/08/06/ios-6-beta-4-change-log-now-available/ ...

  2. 清风注解-Swift程序设计语言:Point11~15

    目录索引 清风注解-Swift程序设计语言 Point 11. 数值型字面量 代码事例: let decimalInteger = // 十进制的17 let binaryInteger = 0b10 ...

  3. extend vg(pv,lv)use HotPlug Storage PV for VMI(ECC Env)

    Preface: 前期存储未规划好,业务快速扩展,数据高安全需求(异地,More one copy),需求多多?NM干着干着活就会时不时的坑爹起来了!particularly Real Product ...

  4. configure mount nfs

    qemu-img convert -f raw -O qcow2 nix.img ruiynix.qcow2 1,yum createrepo

  5. C语言 大小端 字节对齐

    参考:http://www.cnblogs.com/graphics/archive/2011/04/22/2010662.html 1. 大端序:数据的高位字节存放在地址的低端,低位字节存放在地址的 ...

  6. SDOTOJ2088 refresh的停车场(栈和队列)

     refresh的停车场 Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu Submit S ...

  7. XX秘籍

    第一课 一个男人在他妻子洗完澡后准备进浴室洗澡.这时,门铃响了. 妻子迅速用浴巾裹住自己冲到门口. 当她打开门时,邻居鲍勃站在那儿. 在她开口前,鲍勃说,“你如果把浴巾拿掉,我给你800美元.” 想了 ...

  8. 基于Nodejs开发的web即时聊天工具

    由于公司需要开发web即时聊天的功能,开始时我们主要的实施方法是用jquery的ajax定时(10秒)轮询向服务器请求,由于是轮询请求,对 服务器的压力比较大.我们网站上线的时间不长,访问量不是很大, ...

  9. telnet测试端口号

    telnet Ip 端口号 如:telnet localhost 1433 详见此链接(转) http://www.3lian.com/edu/2012/11-08/43232.html

  10. webpack和webpack-dev-server的区别

    第一: webpack只是构建 webpack-dev-server除了构建,还提供web服务   第二:webpack.config.json的路径参数 显然,entry都一样,因为都要知道需要构建 ...