您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
   
 
 
     
   
 订阅
  捐助
HOOK API(四)——进程防终止
 
来自于:工匠若水 发布于 2016-2-19
  3297  次浏览      16
 

0x00 前言

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

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:

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

   
3297 次浏览       16
 
相关文章

手机软件测试用例设计实践
手机客户端UI测试分析
iPhone消息推送机制实现与探讨
Android手机开发(一)
 
相关文档

Android_UI官方设计教程
手机开发平台介绍
android拍照及上传功能
Android讲义智能手机开发
相关课程

Android高级移动应用程序
Android系统开发
Android应用开发
手机软件测试
最新课程计划
信息架构建模(基于UML+EA)3-21[北京]
软件架构设计师 3-21[北京]
图数据库与知识图谱 3-25[北京]
业务架构设计 4-11[北京]
SysML和EA系统设计与建模 4-22[北京]
DoDAF规范、模型与实例 5-23[北京]

android人机界面指南
Android手机开发(一)
Android手机开发(二)
Android手机开发(三)
Android手机开发(四)
iPhone消息推送机制实现探讨
手机软件测试用例设计实践
手机客户端UI测试分析
手机软件自动化测试研究报告
更多...   

Android高级移动应用程序
Android应用开发
Android系统开发
手机软件测试
嵌入式软件测试
Android软、硬、云整合

领先IT公司 android开发平台最佳实践
北京 Android开发技术进阶
某新能源领域企业 Android开发技术
某航天公司 Android、IOS应用软件开发
阿尔卡特 Linux内核驱动
艾默生 嵌入式软件架构设计
西门子 嵌入式架构设计
更多...