分享
 
 
 

检测WINDOWS NT/2K下进程的执行

王朝vc·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

文/Ivo Ivanov

摘要

拦截和追踪进程的执行对实现NT任务管理器——像需要外部进程处理的应用程序和系统——是非常有用的。在新进程的开始之上通知感兴趣的部分是开发进程监视系统和全系统钩子的一个典型问题。WIN32 API提供了一个很好的库(PSAPI and ToolHelp [1])的集合,这些库允许你列举当前在系统中运行的进程。虽然这些API非常有用,但当一个新的进程开始或结束时它们不允许你获得通知。这篇文章提供了一个有效而且完整的技术,为了完成这个目标,它基于一个公开的接口。

解决方案

幸运地,NT/2K提供了一个API集合,知道的像“Process Structure Routines“[2]通过NTOSKRNL输出。一个API函数PsSetCreateProcessNotifyRoutine()提供了注册全系统回叫函数的能力,每次当一个进程开始,存在或已经终止时这些回叫函数都会被OS呼叫。上面提到的API函数对简单地通过执行一个NT核心模式的驱动程序和用户模式的WIN32控制程序追捕进程时可以作为一个容易实现的方法来使用。驱动程序的角色是检测进程的执行和通知控制程序这些事件。

要求

● 为监视进程的执行提供一个简单,有效,可靠和线程安全机制

● 在驱动程序和用户的应用程序之间解决同步问题

● 打造一个易于使用和扩展的OOP用户模式的框架

● 允许回叫函数的注册和解注册,还要有动态加载和卸载核心驱动程序的能力

它怎样工作

控制程序在HKLM\SYSTEM\CurrentControlSet\Services下注册核心模式驱动程序,并且动态加载。核心驱动程序然后建立一个指定的事件对象,当新的事件已经触发时(如进程开始或结束),这个事件对象就向用户模式的应用程序发出信号。控制程序打开相同的事件对象,然后建立一个等待这个事件的监听线程。接下来,用户模式的应用程序发送一个请求给驱动程序来开始监视。驱动程序调用PsSetCreateProcessNotifyRoutine(),这个函数接受两个参数。一个指定呼叫者提供的回叫程序的入口指针,责任是从WINDOWS接受所有的通知。在回叫时发生的一个通知上面,驱动程序发出那个信号事件是为了通知用户模式应用程序说有事情发生了。控制程序然后从驱动程序中得到那个特定事件的数据,然后为了更多的进程,将它存储进一个特殊的列队容器。如果不再检测进程执行,用户模式应用程序发送一个请求给驱动程序来停止监视。然后驱动程序释放观察机制。再后来,控制模式应用程序可以卸载驱动程序和对它解注册。

设计和实现

NT模式驱动程序(ProcObsrv)

入口指针DriverEntry() (ProcObsrv.c)只执行驱动程序的初始化。当驱动程序加载时,I/O管理器呼叫这个函数。既然PsSetCreateProcessNotifyRoutine()允许解注册回叫,这些回叫是我在驱动程序的调度程序中执行的已注册或解注册的实际的进程。这就允许我通过使用一个单独的IOCTL(控制代码IOCTL_PROCOBSRV_ACTIVATE_MONITORING)来动态地开始和停止监视活动。一旦回叫被注册,每次当一个进程开始或终止时,OS就呼叫用户提供的ProcessCallback()。这个函数被植入一个会通过用户模式应用程序选择的缓冲区中。接下来发出指定的事件对象信号,因此等待它的用户模式应用程序会被通知说有可利用的信息检索。

控制程序(ConsCtl)

为了简单的缘故,我决定提供一个简单的控制台应用程序,把想象的GUI要素的实现留给你。设计一个多线程的应用程序允许那个应用程序调整和更易于作出反应。在另一方面,考虑一些与同步存取信息相关的考虑非常重要,这些信息是出版者(如核心模式)提供的和用户(如控制程序)检索的信息。另一重要的关键点是一个检测系统必须可靠,而且确信没有事件漏掉。为了简化进程的设计,首先我需要在用户模式应用程序的不同实体间分配责任,责任是处理驱动程序。然而回答了这些问题,就不难办到了[5]:

1. 系统里的进程是什么?

2. 在框架里的作用是什么?

3. 谁做什么,4. 怎样合作?

下面是一个UML类图,它说明了类之间的关系:

CapplicationScope实现了一个单元集,而且包含了框架主要的接口。它暴露了两个公共方法,它们开始和结束监视进程:

class CApplicationScope

{

... Other Other details ignored for the sake of simplicity ...

public:

// Initiates process of monitoring process

BOOL StartMonitoring(PVOID pvParam);

// Ends up the whole process of monitoring

void StopMonitoring();

};

CprocessThreadMonitor是等待通过驱动程序事件发出信号来创建的一个线程。当进程已经创建或结束,驱动程序发出这个事件对象信号,CprocessThreadMonitor的线程被唤醒。然后用户模式应用程序从驱动程序检索数据。接下来,数据被附加给使用它的方法Append()的(CQueueContainer) 列队容器。

CqueueContainer是一个线程安全列队控制器,它提供一个Monitor/Condition变量模式的执行。它主要的目的是提供一个列队容器的线程安全信号。这是方法Append()怎样工作的:

1. 锁住对集合的STL列队对象的访问

2. 添加数据项

3. 发出m_evtElementAvailable事件对象信号

4. 解锁列队

这是它实际的执行:

// Insert data into the queue

BOOL CQueueContainer::Append(const QUEUED_ITEM& element)

{

BOOL bResult = FALSE;

DWORD dw = ::WaitForSingleObject(m_mtxMonitor, INFINITE);

bResult = (WAIT_OBJECT_0 == dw);

if (bResult)

{

// Add it to the STL queue

m_Queue.push_back(element);

// Notify the waiting thread that there is

// available element in the queue for processing

::SetEvent(m_evtElementAvailable);

}//

::ReleaseMutex(m_mtxMonitor);

return bResult;

}

既然它是设计来当列队里有可利用的元素时发出通知的,它就集合了一个CretreivalThread的例子,CretreivalThread等待直到一个元素在本地存储器中变的可用。这是它的伪执行:

1. 等待m_evtElementAvailable事件对象

2. 锁住对STL列队对象的访问

3. 抽取数据项目

4. 解锁列队

5. 处理已经从列队中检索出的信息。

这是当有东西增加进列队时的方法调用:

// Implement specific behavior when kernel mode driver

// notifies the user-mode app

void CQueueContainer::DoOnProcessCreatedTerminated()

{

QUEUED_ITEM element;

// Initially we have at least one element for processing

BOOL bRemoveFromQueue = TRUE;

while (bRemoveFromQueue)

{

DWORD dwResult = ::WaitForSingleObject( m_mtxMonitor,

INFINITE );

if (WAIT_OBJECT_0 == dwResult)

{

bRemoveFromQueue = (m_Queue.size() > 0);

// Is there anything in the queue

if (bRemoveFromQueue)

{

// Get the element from the queue

element = m_Queue.front();

m_Queue.pop_front();

} // if

else

// Let's make sure that the event hasn't been

// left in signaled state if there are no items

// in the queue

::ResetEvent(m_evtElementAvailable);

} // if

::ReleaseMutex(m_mtxMonitor);

// Process it only there is an element

// that has been picked up

if (bRemoveFromQueue)

m_pHandler->OnProcessEvent( &element, m_pvParam );

else

break;

} // while

}

CcustomThread——帮助管理保持原始线程的复杂性。我在抽象类里面封装了所有线程的相关活动。它提供了一个纯虚方法Run(),Run()必须被任何一个特别的线程类(如CretrievalThread和CProcessThreadMonitor)执行。Ccustom线程是设计来保证当你想线程终止时线程函数的返回,这是作为确保所有线程的资源都被适当地清除干净的唯一方式。它提供一个均值,通过发出m_hShutdownEvent事件信号来关闭它的任何实例。

CcallbackHandler是一个抽象类,它设计来在线程已创建或终止时为执行用户提供的行为提供接口。它暴露了一个纯虚方法OnProcessEvent(),这个方法必须根据系统特定的要求执行。在示例代码中你将看见一个类CmyCallbackHandler,它从CcallbackHandler继承,而且执行方法OnProcessEvent()。OnProcessEvent()方法的一个参数pvParam允许你传递任何种类的数据,那就是为什么要申明为PVOID。在示例代码中一个指向CwhatheverYouWantToHold实例的指针传递给OnProcessEvent().你也许想使用这个参数只传递一个句柄给窗口,那为了传递一个消息给它可以在OnProcessEvent()的执行内部来使用。

class CCallbackHandler

{

public:

CCallbackHandler();

virtual ~CCallbackHandler();

// Define an abstract interface for receiving notifications

virtual void OnProcessEvent(

PQUEUED_ITEM pQueuedItem,

PVOID pvParam

) = 0;

};

编译示例代码

你需要在你的机器上安装MS Platform SDK。提供用户模式应用程序的示例代码能被编译为ANSI或UNICODE。如果你要编译驱动程序,你还要安装Windows DDK。

运行示例

不用担心你是否安装Windows DDK,因为示例代码包含一个ProcObsrv.sys的核心驱动程序和它的源代码的编译调试版本。仅仅在单个目录中沿驱动程序放置控制程序,然后让它运行。为了表明目的,用户模式应用程序动态地安装驱动程序,然后启动监视进程。接下来你将会看到10个notepad.exe的例子运行,而且以后关闭。其间你能看到控制台窗口,看到进程监视器怎样工作。如果你想启动某些程序,看控制台怎样沿着它的名字显示它的进程ID。

结论

这篇文章说明为了检测NT/2K进程的执行,你怎样使用一个公开的接口。但是这并不是这个问题唯一的解决方案,而且它的确错过了一些细节。但是你会发现它对一些真实的情况是有用的。

参考

1. Single interface for enumerating processes and modules under NT and Win9x/2K, Ivo Ivanov

2. Windows DDK Documentation, Process Structure Routines

3. Nerditorium, Jim Finnegan, MSJ January 1999

4. Windows NT Device Driver Development, Peter G. Viscarola and W. Anthony Mason

5. Applying UML and Patterns, Craig Larman

6. Using predicate waits with Win32 threads, D. Howard, C/C++ Users Journal, May 2000

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有