跳至主要內容

基础入门


本篇教程主要介绍iMonitorSDK基础概念和接入过程。

SDK目录说明

  • bin SDK二进制
  • inc SDK头文件
  • sample SDK示例代码
  • build.bat SDK示例代码编译脚本

SDK头文件说明

  • iMonitor.h 内核头文件,包括所有的监控消息、内核通讯协议、其他声明等。
  • iMonitorSDK.h 应用层SDK声明头文件,包括接口、接口的封装。
  • iMonitorSDKExtension.h 应用层扩展能力声明头文件,包括代理引擎、规则引擎等。
  • iMonitorProtocol.h 监控消息协议封装,把原始的消息封装成更加容易使用的结构体。

使用的时候,只需要包含iMonitorSDK.h、iMonitorProtocol.h就好了。

#include <iMonitorSDK.h>
#include <iMonitorProtocol.h>

SDK接入过程

继承IMonitorCallback,实现相应的函数,核心是OnCallback函数

所有监控到的消息,都会通过OnCallback通知过来,具体消息的类型、字段可以参考IMonitorMessasge接口

class MonitorCallback : public IMonitorCallback
{
public:
	void OnCallback(IMonitorMessage* Message) override
	{
	}
};

使用MonitorManager对象来启动并注册接口

	MonitorManager manager;
	MonitorCallback callback;

	HRESULT hr = manager.Start(&callback);

如果返回成功,初始化就完成了。

接下来根据实际需要,可以通过cxMSGUserSetMSGConfig设置不同的消息监控,比如要监控进程启动,可以设置下面的参数:

	cxMSGUserSetMSGConfig config;
	config.Config[emMSGProcessCreate] = emMSGConfigSend;
	manager.InControl(config);

cxMSGUserSetMSGConfig的使用说明

所有的监控都通过cxMSGUserSetMSGConfig来设置。

struct cxUserMSGConfig
{
    ULONG        Config[emMSGMax];
    ULONG        Fields[emMSGMax];
}

typedef cxMSGUser<emUserSetMSGConfig, cxUserMSGConfig> cxMSGUserSetMSGConfig;

Config说明

字段说明
emMSGConfigPost表示监控是异步消息,不会阻塞操作(也就无法拦截阻断)
emMSGConfigSend表示监控是同步等待,会阻塞操作者,可以在回调里面通过SetBlock拦截操作的发生
emMSGConfigIncludeKernelEvent表示监控是否要支持内核(System进程)触发的消息,默认不监控

注意:如果设置了emMSGConfigSend,最好不要开启调试,不然容易导致系统卡死。(因为同步等待会阻塞其他进程的操作,需要监控程序返回后才能继续执行,而调试器会挂起监控程序,导致没法处理监控消息而卡死系统)

Fields说明

Fields字段表示监控需要哪些字段,各个类型支持的字段可以参考 iMonitorProtocol.h

按需设置不同的字段,某些不需要的字段不设置,这样可以优化一些性能。

全部消息类型

进程相关消息

消息类型说明
emMSGProcessCreate进程创建事件,返回拦截可以阻止进程的创建
emMSGProcessExit进程退出事件
emMSGProcessOpen打开进程事件,可以拦截打开用于保护进程
emMSGThreadCreate线程创建事件
emMSGThreadExit线程退出事件
emMSGThreadOpen打开线程事件
emMSGImageLoad加载模块事件,返回拦截可以阻止某个模块、某个驱动的加载
emMSGProcessStart(模拟事件)进程启动事件
emMSGThreadStart(模拟事件)线程启动事件

文件相关消息(带Post的表示动作已经完成)

消息类型说明
emMSGFileCreate打开、创建文件事件,返回拦截可以阻止文件的打开、创建
emMSGFilePostCreate
emMSGFileQueryOpen打开文件事件
emMSGFilePostQueryOpen
emMSGFileCleanup
emMSGFileCreateSection映射文件事件
emMSGFilePostCreateSection
emMSGFileRead读取文件事件
emMSGFilePostRead
emMSGFileWrite写文件事件
emMSGFilePostWrite
emMSGFileCreateHardLink创建文件硬链接事件
emMSGFilePostCreateHardLink
emMSGFileRename文件重命名事件
emMSGFilePostRename
emMSGFileDelete删除文件事件
emMSGFilePostDelete
emMSGFileSetSize设置文件大小事件
emMSGFilePostSetSize
emMSGFileSetBasicInfo设置文件基本信息事件
emMSGFilePostSetBasicInfo
emMSGFileFindFile查找文件、遍历文件事件
emMSGFilePostFindFile

注册表相关消息(带Post的表示动作已经完成)

消息类型说明
emMSGRegCreateKey打开、创建注册表键
emMSGRegPostCreateKey
emMSGRegOpenKey打开注册表键
emMSGRegPostOpenKey
emMSGRegDeleteKey删除注册表键
emMSGRegPostDeleteKey
emMSGRegRenameKey重命名注册表键
emMSGRegPostRenameKey
emMSGRegEnumKey查找遍历注册表键
emMSGRegPostEnumKey
emMSGRegLoadKey加载文件映射成注册表键
emMSGRegPostLoadKey
emMSGRegReplaceKey加载文件替换注册表键
emMSGRegPostReplaceKey
emMSGRegDeleteValue删除注册表值
emMSGRegPostDeleteValue
emMSGRegSetValue设置注册表值
emMSGRegPostSetValue
emMSGRegQueryValue查询注册表值内容
emMSGRegPostQueryValue

网络相关消息

基于AFD过滤驱动方式实现,所有操作同socket操作,可以获取套接字的调用回调

消息类型说明
emMSGSocketCreate
emMSGSocketControl
emMSGSocketPostControl
emMSGSocketConnect
emMSGSocketPostConnect
emMSGSocketSend
emMSGSocketRecv
emMSGSocketPostRecv
emMSGSocketSendTo
emMSGSocketPostSendTo
emMSGSocketRecvFrom
emMSGSocketPostRecvFrom
emMSGSocketListen
emMSGSocketPostListen
emMSGSocketAccept
emMSGSocketPostAccept

基于WFP过滤驱动实现

消息类型说明
emMSGWFPTcpConnect
emMSGWFPUdpConnect
emMSGWFPTcpAccept
emMSGWFPUdpAccept
emMSGWFPICMPConnect
emMSGWFPICMPAccept
emMSGWFPSend
emMSGWFPRecv
emMSGWFPSendTo
emMSGWFPRecvFrom
emMSGWFPICMPSendTo
emMSGWFPICMPRecvFrom

IMonitorCallback 接口说明

interface IMonitorCallback
{
	//
	//	DisableXxxMonitor: (在驱动启动前设置生效) 表示是否关闭Xxx的监控,如果只需要部分能力,建议关闭其他不需要的监控。一般用于优化性能,解决冲突。
	//	InternalCallback: 内部使用,接管原始的消息
	//	ExtensionFieldTable: 消息扩展字段
	//
	struct GlobalConfig {
			bool			DisableFileMonitor	= false;
			bool			DisableRegMonitor	= false;
			bool			DisableSocketMonitor= false;
			bool			DisableWFPMonitor	= false;
			bool			DisableNPMSMonitor	= false;

			bool			InternalCallback	= false;

			MonitorExtensionFieldTable ExtensionFieldTable;
	};

	virtual void			OnConfig			(GlobalConfig& Config) {}
	virtual void			OnCustomEvent		(ULONG Type, PVOID Context) {}
	virtual bool			OnInternalCallback	(cxMSGHeader* Header, HANDLE FilterHandle, ULONGLONG MessageId) { return false; }
	virtual void			OnCallback			(IMonitorMessage* Message) = 0;
};
函数说明
OnCallback【核心】监控消息回调函数,所有的消息都会通过这个回调触发
OnInternalCallback内部接口,可以获取原始驱动通讯的协议
OnCustomEvent自定义事件:消息回调都在同一个线程,有时候为了避免多线程,可以通过SendCustomEvent发送事件到消息回调的线程执行
OnConfig全局配置,可以用于关闭某些监控开关,或者设置字段扩展

IMonitorMessage 接口说明

interface IMonitorMessage
{
	struct Binary {
		PVOID Data;
		ULONG Length;
	};

	//
	// 基础字段
	//

	virtual cxMSGHeader*	GetHeader			(void) = 0;
	inline ULONG			GetType				(void) { return GetHeader()->Type; }
	inline ULONG			GetStatus			(void) { return GetHeader()->Status; }
	inline ULONG			GetCurrentProcessId	(void) { return GetHeader()->CurrentProcessId; }
	inline ULONG			GetCurrentThreadId	(void) { return GetHeader()->CurrentThreadId; }

	virtual IMonitorMessageProcess* GetProcess	(void) = 0;

	virtual LPCWSTR			GetTypeName			(void) = 0;
	virtual ULONG			GetFieldCount		(void) = 0;
	virtual emMSGDataType	GetFieldType		(ULONG Index) = 0;
	virtual LPCWSTR			GetFieldName		(ULONG Index) = 0;
	virtual ULONG			GetFieldIndex		(LPCWSTR Name) = 0;

	virtual ULONG			GetULONG			(ULONG Index) = 0;
	virtual ULONGLONG		GetULONGLONG		(ULONG Index) = 0;
	virtual cxMSGDataIPRef	GetIP				(ULONG Index) = 0;
	virtual Binary			GetBinary			(ULONG Index) = 0;
	virtual LPCWSTR			GetString			(ULONG Index) = 0;
	virtual LPCWSTR			GetFormatedString	(ULONG Index) = 0;

	virtual bool			IsMatch				(ULONG Index, LPCWSTR Pattern, bool IgnoreCase = true) = 0;

	//
	// 扩展字段,由开发者自行定义的字段,这些字段可以用于规则引擎,详细参考MonitorExtensionFieldTable
	//	HasValue: 表示是否有值,如果没有字段则返回默认值并且HasValue = false
	//

	virtual ULONGLONG		GetNumber			(LPCWSTR Name, bool* HasValue = nullptr) = 0;
	virtual LPCWSTR			GetString			(LPCWSTR Name, bool* HasValue = nullptr) = 0;

	//
	// Action 相关操作,用于返回消息结果给驱动:需要Waiting状态才能设置返回结果
	//

	virtual bool			IsWaiting			(void) = 0;
	virtual bool			SetAction			(const cxMSGAction& Action) = 0;
	virtual bool			SetBlock			(void) = 0;
	virtual bool			SetGrantedAccess	(ULONG Access) = 0;
	virtual bool			SetIPRedirect		(ULONG IP, USHORT Port, ULONG ProcessId = ::GetCurrentProcessId()) = 0;
	virtual bool			SetTerminateProcess	(void) = 0;
	virtual bool			SetTerminateThread	(void) = 0;
	virtual bool			SetInjectDll		(LPCWSTR Path) = 0;
	virtual bool			SetFileRedirect		(LPCWSTR Path) = 0;

	//
	//	异步处理:
	//		设置Pending成功后,可以拥有IMonitorMessage的生命周期,允许在回调返回后继续使用。
	//		使用完毕,一定需要使用CompletePending来恢复状态,不然内核等待事件需要超时才能返回。
	//
	//	使用场景:需要弹框交互确认、或者是多线程处理的场景。
	//

	virtual bool			Pending				(void) = 0;
	virtual void			CompletePending		(void) = 0;

	virtual void			SetCustomContext	(PVOID Context) = 0;
	virtual PVOID			GetCustomContext	(void) = 0;
};

核心函数说明

函数说明
GetType返回消息类型
GetULONG、GetULONGLONG、GetString获取消息字段
IsWaiting判断是否同步消息
SetAction设置消息响应动作,具体参考cxMSGAction
SetBlock设置拦截,阻止事件发生
SetIPRedirect设置网络重定向
SetTerminateProcess结束当前操作进程
SetInjectDll注入动态库
Pending设置延迟处理,Pending成功后可以抛到其他线程处理消息,比如异步弹框

消息协议

为了更加方便获取消息的各个字段,SDK对所有的消息都进行了封装。

比如emMSGProcessCreate对应的协议封装是cxMSGProcessCreate,转换成协议封装后就可以更加方便获取字段。

	void OnCallback(IMonitorMessage* Message) override
	{
		if (Message->GetType() == emMSGProcessCreate) {
				cxMSGProcessCreate* msg = (cxMSGProcessCreate*)Message;
		}
	}
class cxMSGProcessCreate : public MonitorMessage
{
public:
	enum {
		emMSGFieldCallstack,
		emMSGFieldCurrentProcessCreateTime,
		emMSGFieldCurrentProcessName,
		emMSGFieldCurrentProcessPath,
		emMSGFieldCurrentProcessCommandline,
		emMSGFieldPath,
		emMSGFieldProcessId,
		emMSGFieldCommandline,
		emMSGFieldCreateTime,
		emMSGFieldParentPath,
		emMSGFieldParentProcessId,
		emMSGFieldParentCommandline,
		emMSGFieldParentCreateTime,
	};

public:
	auto Path() { return GetPath(emMSGFieldPath); }
	auto ProcessId() { return GetULONG(emMSGFieldProcessId); }
	auto Commandline() { return GetString(emMSGFieldCommandline); }
	auto CreateTime() { return GetTime(emMSGFieldCreateTime); }
	auto ParentPath() { return GetPath(emMSGFieldParentPath); }
	auto ParentProcessId() { return GetULONG(emMSGFieldParentProcessId); }
	auto ParentCommandline() { return GetString(emMSGFieldParentCommandline); }
	auto ParentCreateTime() { return GetTime(emMSGFieldParentCreateTime); }

	bool IsMatchPath(LPCWSTR Pattern, bool IgnoreCase = true) { return IsMatch(emMSGFieldPath, Pattern, IgnoreCase); }
	bool IsMatchCommandline(LPCWSTR Pattern, bool IgnoreCase = true) { return IsMatch(emMSGFieldCommandline, Pattern, IgnoreCase); }
	bool IsMatchParentPath(LPCWSTR Pattern, bool IgnoreCase = true) { return IsMatch(emMSGFieldParentPath, Pattern, IgnoreCase); }
	bool IsMatchParentCommandline(LPCWSTR Pattern, bool IgnoreCase = true) { return IsMatch(emMSGFieldParentCommandline, Pattern, IgnoreCase); }
};

如果想定制自己的封装,可以通过IDL + 模板的方式自动生成。