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

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

//

//        有关其他详细信息,

//        请参阅 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.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:

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

时间: 2024-10-11 23:03:31

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

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

HOOK API (一)——HOOK基础+一个鼠标钩子实例 0x00 起因 最近在做毕业设计,有一个功能是需要实现对剪切板的监控和进程的防终止保护.原本想从内核层实现,但没有头绪.最后决定从调用层入手,即采用HOOK API的技术来挂钩相应的API,从而实现预期的功能.在这样的需求下,就开始学习了HOOK API. 0x01什么是HOOK API HOOK(钩子,挂钩)是一种实现Windows平台下类似于中断的机制[24].HOOK机制允许应用程序拦截并处理Windows消息或指定事件,当指定的

本地无法启动MySQL服务,报的错误:1067,进程意外终止---解决

在本地计算机无法启动MYSQL服务错误1067进程意外终止 这种情况一般是my.ini文件配置出错了 首先找到这个文件: 默认安装路径 C:/Program Files/MySQL/MySQL Server 5.1/my.ini 打开此文件找到:default-storage-engine=INNODB   大概在84行. 将default-storage-engine的值改为:MYISAM,这个时候,MYSQL服务可以启动. 但是还有问题:因为以前你创建的那些数据库还是存在的(如果没有删除),

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

HOOK API(二) —— HOOK自己程序的 MessageBox 0x00 前言 以下将给出一个简单的例子,作为HOOK API的入门.这里是HOOK 自己程序的MessageBox,即将自己程序对MessageBox API的调用重定向到自己实现的API中,在自己定义的API中实现内容的替换. 需要注意的是,本例子的HOOK仅仅对自己实现的MFC窗口程序,当开始HOOK 后,自己的程序调用MessageBox将被重定向,但其他程序滴啊用MessageBox时是正常的. 在Windows中

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

HOOK API(三) —— HOOK 所有程序的 MessageBox 0x00 前言 本实例要实现HOOK MessageBox,包括MessageBoxA和MessageBoxW,其实现细节与HOOK API(二)中介绍的基本类似,唯一不同的是,本实例要实现对所有程序的HOOK MessageBox,即无论系统中哪一个程序调用MessageBox都会被重定向到我们实现的新的API中. 之前说过,在Windows中,每个进程都有自己的地址空间,进程不能调用别的进程中的函数.这里涉及到一个关键

无法启动MYSQL服务”1067 进程意外终止”解决办法——汇总及终极方法

自己一开始按照百度经验里的方法--<MySQL下载安装.配置与使用(win7x64)>去安装和配置,但是到后面步骤总是出现1067代号的错误.慢慢折腾去解决. 这里汇总各种导致mysql提示无法启动MYSQL服务"1067 进程意外终止"的一些解决办法.自己遇到这个问题是查了很多方法不行,最后看到一个论坛的讨论,试了一下竟然可以.一下是网上的部分方法,最后可以的那个方法我放在最后面: 启用MySql服务的时候出现"windows无法启动mysql服务(位于本地计算

汇编Ring 3下实现 HOOK API

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

钩子编程(HOOK) 安装进程内鼠标钩子

作者 : 卿笃军 钩子函数: WINDOWS的钩子函数可以认为是WINDOWS的主要特性之一.利用它们,您可以捕捉您自己进程或其它进程发生的事件.通过"钩挂",您可以给WINDOWS一个处理或过滤事件的回调函数,该函数也叫做"钩子函数",当每次发生您感兴趣的事件时,WINDOWS都将调用该函数. 下面介绍如何安装一个进程内的鼠标钩子. 第一步:打开VC6.0,新建一个基于对话框的MFC应用程序. 第二步:将如下代码拷贝到BOOL CInnerHookDlg::OnI

无法启动MYSQL服务”1067 进程意外终止”解决的方法——汇总及终极方法

自己一開始依照百度经验里的方法--<MySQL下载安装.配置与使用(win7x64)>去安装和配置,可是到后面步骤总是出现1067代号的错误. 慢慢折腾去解决. 这里汇总各种导致mysql提示无法启动MYSQL服务"1067 进程意外终止"的一些解决的方法.自己遇到这个问题是查了非常多方法不行,最后看到一个论坛的讨论.试了一下居然能够.一下是网上的部分方法.最后能够的那个方法我放在最后面: 启用MySql服务的时候出现"windows无法启动mysql服务(位于本

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

在使用INLINE HOOK API实现对系统API的拦截时,正常情况下并没有太大问题,但一旦涉及到多线程,不管是修改IAT还是JMP,2种方法均会出现不可预料的问题,特别是在HOOK一些复杂的大型系统软件时,会被时不时的一个内存错误搞得心浮气躁. HOOK API数量越多,需要注意的内容越多,最近实现HOOK FileSystem API,由于是Kernel32中的函数,所有涉及到文件(filename,filehandle)的API均要被HOOK,同时需要在HOOK中实现overlapped