学习

原创 2007年09月16日 14:17:00
公司让我写了一个软件,并且不能让别人结束这个程序的进程。前面看到我过一些相关的文章,有创建一个线程不停检测进程名(通过枚举进程列表)的方法,但我觉得这种方法可能有些占资源。还有将自己进程提升为系统进程的,这种我也没有试过,如果谁有这种方法的实现代码给我一份将不甚感激,我今天用到是另外一种方法,拦截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);
 
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

深入学习mongodb

  • 2017-08-21 10:33
  • 9.05MB
  • 下载

【学习笔记】 使用Maven+SSM框架 + MySQL写一个小案例

Maven+SSM+MySQL的简单案例

ROS学习笔记-2: 编写服务端与客户端

定义srv服务 roscd beginner_tutorials mkdir srv cd srv touch AddTwoInts.srv rosed beginner_tutorials AddT...

机器学习实战

  • 2017-08-16 22:41
  • 13.41MB
  • 下载

NSGA-II算法的学习笔记

1.    算法优劣性(相较于第一代NSGA) ① NSGA-II添加了精英策略,即保存群体中适应度在第一层级的个体。 ②NSGA-II提出了新的给群体按照非支配关系排序的方法,提高了算法速度。其中又...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)