写了一个像杀毒软件的软件,不能让别人结束这个程序的进程。
有一种方法是将自己进程提升为系统进程的,这种没有试过
另外一种方法,拦截API函数,有两种方法:
1.在强行关闭一个进程时系统调用的是
BOOL WINAPI TerminateProcess(
HANDLE hProcess,
UINT uExitCode
);
我们如果利用钩子拦截TerminateProcess这个API函数,在系统调用这个函数是先判断是不是我们不让关闭进程的句柄就行了。
2.在调用BOOL WINAPI TerminateProcess(
HANDLE hProcess,
UINT uExitCode
);之前系统必须要先用
HANDLE WINAPI OpenProcess(
DWORD dwDesiredAccess,
BOOL bInheritHandle,
DWORD dwProcessId
);在开进程的句柄,如果我们发现第一参数是PROCESS_TERMINATE方式,说明是要强行结束此进程,我们可以这以这种方打开的调用进程分析,看进程ID是不是我们不让关闭的进程的ID,下面我们着重来讲一下这种方法:
因为要用到钩子,所以们先来创建一个DLL工程,创建的过程我在这里就不说了。在这里我使用了windows核心编程里面的APIHOOK类,将这个类拷贝到工程目录下,加入自己的工程。
在DLL工程里加入一个WH_SHELL的钩子,它的作用是进程创建时将DLL文件插入到每一个进程里面,从而达到拦截API函数的目的。
下面是钩子实现部分代码:
// Defines
#pragma data_seg(".SHARED")
HHOOK glhHook = NULL; //安装勾子句柄
#pragma data_seg()
#pragma comment( linker, "/section:shared,rws" )
HINSTANCE glhInstance = NULL; //DLL实例句柄
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
glhInstance = (HINSTANCE)hModule;
return TRUE;
}
static LRESULT WINAPI ShellHookProc(int code, WPARAM wParam, LPARAM lParam)
{
return ::CallNextHookEx(glhHook, code, wParam, lParam);
}
extern "C"__declspec(dllexport) BOOL StartHook(DWORD pid)
{
BOOL bResult=FALSE;
if(!glhHook)
{
glhHook = SetWindowsHookEx(WH_SHELL,ShellHookProc,glhInstance, 0);
if(glhHook!=NULL)
{
bResult=TRUE;
}
}
return bResult;
}
extern "C"__declspec(dllexport) BOOL StopHook()
{
BOOL bResult=FALSE;
if(glhHook)
{
bResult= UnhookWindowsHookEx(glhHook);
if(bResult)
{
glhHook=NULL;
}
}
return bResult;
}
DLL文件插入其它进程里了,下面的工作就是替换OpenProcess函数了
//...............................................................................................*/
typedef HANDLE (WINAPI *PFNOPENPROCESS)(DWORD,BOOL,DWORD);
extern CAPIHook g_OpenProcess;
// 自定义OpenProcess函数
HANDLE WINAPI Hook_OpenProcess(DWORD dwDesiredAccess,BOOL bInheritHandle,DWORD dwProcessId);
//.............................................................................................../*
HANDLE WINAPI Hook_OpenProcess(DWORD dwDesiredAccess,BOOL bInheritHandle,DWORD dwProcessId)
{
if(dwDesiredAccess == PROCESS_TERMINATE && dwProcessId == dwProcessId == lpData->dwProcessId/*这个值是不让关闭进程的ID*/)
{
char sz[2048];
wsprintf(sz, "%d,%d,%d",dwDesiredAccess,dwProcessId,lpData->dwProcessId);
MessageBox(NULL,sz,"d",MB_OK);
return NULL;
}
return ((PFNOPENPROCESS)(PROC)g_OpenProcess)(dwDesiredAccess,bInheritHandle,dwProcessId);
}
// 挂钩OpenProcess函数
CAPIHook g_OpenProcess("kernel32.dll", "OpenProcess",(PROC)Hook_OpenProcess,TRUE);
把上面这代码加入到刚才创建的DLL里就行了。
刚才大家在查看上面代码时看到了lpData->dwProcessId这个参数,这就是我不让关闭的进程ID,那么这个值怎么得到呢。当然方法很多,可以通过窗口名获取窗口句柄
HWND hwnd = ::FindWindow(NULL,"你程序窗口名");
DWORD hpid;//进程ID
GetWindowThreadProcessId( hwnd , &hpid );
但如果你的进程没有窗口应该怎么办呢?那么就只能在进程运行时用::GetCurrentProcessId(); 取得,然后通过内存映射的方式传给DLL文件。如下面的代码
typedef struct SHWP_STRUCT_ {
DWORD dwProcessId;
char szModuleFileName[MAX_PATH];
} SHWP_STRUCT, *LPSHWP_STRUCT;
//全局变量定义
HANDLE hMapping;//内存映射名柄
LPSHWP_STRUCT lpData; //共享内存
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
//创建内存共享
hMapping=CreateFileMapping((HANDLE)0xFFFFFFFF,NULL,PAGE_READWRITE,0,0x100,"PCMONITOR.");
if(hMapping != NULL)
{
lpData=(LPSHWP_STRUCT)MapViewOfFile(hMapping,FILE_MAP_ALL_ACCESS,0,0,0);
}
lpData->dwProcessId = ::GetCurrentProcessId(); //当前进程ID
...............................其它代码
}DLL里面的内存映射部分代码
//全局变量定义
HANDLE hMapping;//内存映射名柄
LPSHWP_STRUCT lpData; //共享内存
//........................................................................../*
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
//创建内存共享
hMapping=CreateFileMapping((HANDLE)0xFFFFFFFF,NULL,PAGE_READWRITE,0,0x100,"PCMONITOR.");
if(hMapping != NULL)
{
lpData=(LPSHWP_STRUCT)MapViewOfFile(hMapping,FILE_MAP_ALL_ACCESS,0,0,0);
}
return TRUE;
}
这样我们的进程在运行时它的进程ID通过lpData->dwProcessId = ::GetCurrentProcessId(); 得到并以内存映射的方式传给DLL文件。
DLL里面拦截了OpenProcess函数里面的DWORD dwProcessId参数,如果这个数据是我们自己进程的ID就直接反回一个NULL值,也就是打开我们进程失败,这样系统就没有办法掉用TerminateProcess强行关闭我们的进程了。如果我们直接拦截TerminateProcess函数,然后不管哪个函数掉用它直接返回TRUE值,那完了,你就永远没想在你机子上强行关闭任何程序,呵,我说的是强行,发送WM_CLOSE消息关了不算哟。
拦截TerminateProcess函数部分代码:
//...............................................................................................*/
typedef BOOL (WINAPI *PFNTERMINATEPROCESS)(HANDLE, UINT);
extern CAPIHook g_TerminateProcess;
BOOL WINAPI Hook_TerminateProcess(HANDLE hProcess, UINT uExitCode);// 自定义TerminateProcess函数
//.............................................................................................../*
// 自定义TerminateProcess函数
BOOL WINAPI Hook_TerminateProcess(HANDLE hProcess, UINT uExitCode)
{
// 取得主模块的文件名称
char szPathName[MAX_PATH];
::GetModuleFileName(NULL, szPathName, MAX_PATH);
// 构建发送给主窗口的字符串
char sz[2048];
wsprintf(sz, " 进程:(%d)%s 进程句柄:%X 退出代码:%d (%x)",::GetCurrentProcessId(), szPathName, hProcess, uExitCode,lpData->dwProcessId);
MessageBox(NULL,sz,"d",MB_OK);
return ((PFNTERMINATEPROCESS)(PROC)g_TerminateProcess)(hProcess, uExitCode);
}
// 挂钩TerminateProcess函数
CAPIHook g_TerminateProcess("kernel32.dll", "TerminateProcess",(PROC)Hook_TerminateProcess,TRUE);
原文: http://blog.csdn.net/panpanloveruth/article/details/1659236