编程开源技术交流,分享技术与知识

网站首页 > 开源技术 正文

iMonitorSDK 序列教程一 · 基础教程

wxchong 2024-07-22 22:26:37 开源技术 26 ℃ 0 评论

iMonitorSDK (https://imonitorsdk.com/) 一款为终端、主机提供系统行为监控的开发套件。旨在帮助终端安全、管控、审计、零信任、主机安全等行业应用可以快速实现必要功能,而不用关心底层驱动的开发、维护和兼容性问题,让其可以专注于业务开发。适用于下列场景:零信任、终端管控、行为审计、主机安全、主动防御(HIPS)、终端检测与响应(EDR)、数据防泄密(DLP)、上网行为管理。


本篇教程主要介绍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 + 模板的方式自动生成。

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表