首页
社区
课程
招聘
记一次调用ETW-TI
发表于: 2024-10-6 23:24 2763

记一次调用ETW-TI

2024-10-6 23:24
2763

0x00 前言

相信大家都对Microsoft-Windows-Threat-Intelligence这个名字十分熟悉
因为不少杀软都用ETW-TI来进行保护系统,例如Elastic
Microsoft-Windows-Threat-Intelligence调用条件是什么呢
要成功注册的事件使用者,我们至少需要以PPL进程的身份运行,而最优雅的方式是使用Microsoft验证的证书(使用代码签名EKU)对软件进行签名,或者使用测试签名模拟
我使用了前者 给自己加PPL 虽然这不是一个很优雅的方式 但是至少能用
同时我们想要用CPP来调用他 只需要了解一下这个库https://github.com/microsoft/krabsetw
思路大概如下
创建新的跟踪对象->创建新的提供者对象->加过滤器(与回调)->启动ETW-TI
那么话不多说 我们直接开始

0x01 PPL进程

这不是一个困难的任务 基本上会内核的都会一点这个
因为我们没有EKU或者懒得用测试签名模拟
我们可以直接改EPROCESS结构里面的SignatureLevel
我就不班门弄斧了 直接放代码吧

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
typedef struct _PS_PROTECTION
{
    UCHAR Type : 3;
    UCHAR Audit : 1;
    UCHAR Signer : 4;
} PS_PROTECTION, * PPS_PROTECTION;
 
typedef struct _PROCESS_SIGNATURE
{
    UCHAR SignatureLevel;
    UCHAR SectionSignatureLevel;
    PS_PROTECTION Protection;
} PROCESS_SIGNATURE, * PPROCESS_SIGNATURE;
struct ProcessSignature {
    ULONG Pid;
    UCHAR SignerType;
    UCHAR SignatureSigner;
};
NTSTATUS SetProcessSignature(ProcessSignature* ProcessSignature) {
    if (!SignatureLevelOffset) {
        SignatureLevelOffset=GetSignatureLevelOffset();
    }
    if (SignatureLevelOffset) {
        PEPROCESS process;
        NTSTATUS status = STATUS_SUCCESS;
 
        status = PsLookupProcessByProcessId(ULongToHandle(ProcessSignature->Pid), &process);
 
        if (!NT_SUCCESS(status)) {
            return status;
        }
        UCHAR newSignatureLevel = (ProcessSignature->SignerType << 4) | ProcessSignature->SignatureSigner;
        PPROCESS_SIGNATURE processSignature = (PPROCESS_SIGNATURE)(UINT64(process) + SignatureLevelOffset);
        processSignature->SignatureLevel = newSignatureLevel;
        processSignature->Protection.Type = ProcessSignature->SignerType;
        processSignature->Protection.Signer = ProcessSignature->SignatureSigner;
        ObDereferenceObject(process);
        return status;
    }
}

我们只需要在应用层给他填入TYPE和SIGNER就行了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
enum SignatureType
{
    PsProtectedTypeNone = 0,
    PsProtectedTypeProtectedLight = 1,
    PsProtectedTypeProtected = 2
};
 
enum SignatureSigner
{
    PsProtectedSignerNone = 0,      // 0
    PsProtectedSignerAuthenticode,  // 1
    PsProtectedSignerCodeGen,       // 2
    PsProtectedSignerAntimalware,   // 3
    PsProtectedSignerLsa,           // 4
    PsProtectedSignerWindows,       // 5
    PsProtectedSignerWinTcb,        // 6
    PsProtectedSignerWinSystem,     // 7
    PsProtectedSignerApp,           // 8
    PsProtectedSignerMax            // 9
};

0x02 寻找Microsoft-Windows-Threat-Intelligence

你可以去https://github.com/jdu2600/Windows10EtwEvents/blob/main/manifest/Microsoft-Windows-Threat-Intelligence.tsv寻找他
当然.我这里用了一个十分好用的工具(https://github.com/zodiacon/EtwExplorer)

由此可见 我们可以直接找到他!

他提供了很多事件给我们!

0x03 编写调用代码

既然我们找到了他 也知道PPL进程怎么设置了
那么我们开始编写调用ETW-TI的代码吧!

先看到Keywords
转换为CPP如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#define KERNEL_THREATINT_KEYWORD_ALLOCVM_LOCAL 0x1
#define KERNEL_THREATINT_KEYWORD_ALLOCVM_LOCAL_KERNEL_CALLER 0x2
#define KERNEL_THREATINT_KEYWORD_ALLOCVM_REMOTE 0x4
#define KERNEL_THREATINT_KEYWORD_ALLOCVM_REMOTE_KERNEL_CALLER 0x8
#define KERNEL_THREATINT_KEYWORD_PROTECTVM_LOCAL 0x10
#define KERNEL_THREATINT_KEYWORD_PROTECTVM_LOCAL_KERNEL_CALLER 0x20
#define KERNEL_THREATINT_KEYWORD_PROTECTVM_REMOTE 0x40
#define KERNEL_THREATINT_KEYWORD_PROTECTVM_REMOTE_KERNEL_CALLER 0x80
#define KERNEL_THREATINT_KEYWORD_MAPVIEW_LOCAL 0x100
#define KERNEL_THREATINT_KEYWORD_MAPVIEW_LOCAL_KERNEL_CALLER 0x200
#define KERNEL_THREATINT_KEYWORD_MAPVIEW_REMOTE 0x400
#define KERNEL_THREATINT_KEYWORD_MAPVIEW_REMOTE_KERNEL_CALLER 0x800
#define KERNEL_THREATINT_KEYWORD_QUEUEUSERAPC_REMOTE 0x1000
#define KERNEL_THREATINT_KEYWORD_QUEUEUSERAPC_REMOTE_KERNEL_CALLER 0x2000
#define KERNEL_THREATINT_KEYWORD_SETTHREADCONTEXT_REMOTE 0x4000
#define KERNEL_THREATINT_KEYWORD_SETTHREADCONTEXT_REMOTE_KERNEL_CALLER 0x8000
#define KERNEL_THREATINT_KEYWORD_READVM_LOCAL 0x10000
#define KERNEL_THREATINT_KEYWORD_READVM_REMOTE 0x20000
#define KERNEL_THREATINT_KEYWORD_WRITEVM_LOCAL 0x40000
#define KERNEL_THREATINT_KEYWORD_WRITEVM_REMOTE 0x80000
#define KERNEL_THREATINT_KEYWORD_SUSPEND_THREAD 0x100000
#define KERNEL_THREATINT_KEYWORD_RESUME_THREAD 0x200000
#define KERNEL_THREATINT_KEYWORD_SUSPEND_PROCESS 0x400000
#define KERNEL_THREATINT_KEYWORD_RESUME_PROCESS 0x800000
#define KERNEL_THREATINT_KEYWORD_FREEZE_PROCESS 0x1000000
#define KERNEL_THREATINT_KEYWORD_THAW_PROCESS 0x2000000
#define KERNEL_THREATINT_KEYWORD_CONTEXT_PARSE 0x4000000
#define KERNEL_THREATINT_KEYWORD_EXECUTION_ADDRESS_VAD_PROBE 0x8000000
#define KERNEL_THREATINT_KEYWORD_EXECUTION_ADDRESS_MMF_NAME_PROBE 0x10000000
#define KERNEL_THREATINT_KEYWORD_READWRITEVM_NO_SIGNATURE_RESTRICTION 0x20000000
#define KERNEL_THREATINT_KEYWORD_DRIVER_EVENTS 0x40000000
#define KERNEL_THREATINT_KEYWORD_DEVICE_EVENTS 0x80000000


每个事件有很多东西你可以获取
我这里监控了其中几个常用的函数
不用多说 代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include <krabs.hpp>
#define KERNEL_THREATINT_KEYWORD_ALLOCVM_LOCAL 0x1
#define KERNEL_THREATINT_KEYWORD_ALLOCVM_LOCAL_KERNEL_CALLER 0x2
#define KERNEL_THREATINT_KEYWORD_ALLOCVM_REMOTE 0x4
#define KERNEL_THREATINT_KEYWORD_ALLOCVM_REMOTE_KERNEL_CALLER 0x8
#define KERNEL_THREATINT_KEYWORD_PROTECTVM_LOCAL 0x10
#define KERNEL_THREATINT_KEYWORD_PROTECTVM_LOCAL_KERNEL_CALLER 0x20
#define KERNEL_THREATINT_KEYWORD_PROTECTVM_REMOTE 0x40
#define KERNEL_THREATINT_KEYWORD_PROTECTVM_REMOTE_KERNEL_CALLER 0x80
#define KERNEL_THREATINT_KEYWORD_MAPVIEW_LOCAL 0x100
#define KERNEL_THREATINT_KEYWORD_MAPVIEW_LOCAL_KERNEL_CALLER 0x200
#define KERNEL_THREATINT_KEYWORD_MAPVIEW_REMOTE 0x400
#define KERNEL_THREATINT_KEYWORD_MAPVIEW_REMOTE_KERNEL_CALLER 0x800
#define KERNEL_THREATINT_KEYWORD_QUEUEUSERAPC_REMOTE 0x1000
#define KERNEL_THREATINT_KEYWORD_QUEUEUSERAPC_REMOTE_KERNEL_CALLER 0x2000
#define KERNEL_THREATINT_KEYWORD_SETTHREADCONTEXT_REMOTE 0x4000
#define KERNEL_THREATINT_KEYWORD_SETTHREADCONTEXT_REMOTE_KERNEL_CALLER 0x8000
#define KERNEL_THREATINT_KEYWORD_READVM_LOCAL 0x10000
#define KERNEL_THREATINT_KEYWORD_READVM_REMOTE 0x20000
#define KERNEL_THREATINT_KEYWORD_WRITEVM_LOCAL 0x40000
#define KERNEL_THREATINT_KEYWORD_WRITEVM_REMOTE 0x80000
#define KERNEL_THREATINT_KEYWORD_SUSPEND_THREAD 0x100000
#define KERNEL_THREATINT_KEYWORD_RESUME_THREAD 0x200000
#define KERNEL_THREATINT_KEYWORD_SUSPEND_PROCESS 0x400000
#define KERNEL_THREATINT_KEYWORD_RESUME_PROCESS 0x800000
#define KERNEL_THREATINT_KEYWORD_FREEZE_PROCESS 0x1000000
#define KERNEL_THREATINT_KEYWORD_THAW_PROCESS 0x2000000
#define KERNEL_THREATINT_KEYWORD_CONTEXT_PARSE 0x4000000
#define KERNEL_THREATINT_KEYWORD_EXECUTION_ADDRESS_VAD_PROBE 0x8000000
#define KERNEL_THREATINT_KEYWORD_EXECUTION_ADDRESS_MMF_NAME_PROBE 0x10000000
#define KERNEL_THREATINT_KEYWORD_READWRITEVM_NO_SIGNATURE_RESTRICTION 0x20000000
#define KERNEL_THREATINT_KEYWORD_DRIVER_EVENTS 0x40000000
#define KERNEL_THREATINT_KEYWORD_DEVICE_EVENTS 0x80000000
std::string ProtectToString(DWORD protect) {
    switch (protect) {
    case PAGE_NOACCESS:         return "<N/A>";
    case PAGE_READONLY:         return "READ";
    case PAGE_READWRITE:        return "READ_WRITE";
    case PAGE_WRITECOPY:        return "WRITE_COPY";
    case PAGE_EXECUTE:          return "EXECUTE";
    case PAGE_EXECUTE_READ:     return "READ_EXECUTE";
    case PAGE_EXECUTE_READWRITE: return "READWRITE_EXECUTE";
    case PAGE_EXECUTE_WRITECOPY: return "WRITECOPY_EXECUTE";
    case PAGE_GUARD:           return "<G/P>";
    case PAGE_NOCACHE:         return "<N/C>";
    case PAGE_WRITECOMBINE:    return "<W/C>";
    default:                   return "<N/P>";
    }
}
std::string StateToString(DWORD state) {
    switch (state) {
    case MEM_COMMIT:    return "Committed";
    case MEM_RESERVE:   return "Reserved";
    case MEM_FREE:      return "Free";
    default:           return "Unknown State";
    }
}
std::string TypeToString(DWORD type) {
    switch (type) {
    case MEM_PRIVATE:   return "Private Memory";
    case MEM_MAPPED:    return "Mapped Memory";
    case MEM_IMAGE:     return "Image Memory";
    default:           return "Unknown Type";
    }
}
extern krabs::user_trace g_trace(L"EtwTi-CallMonitor");
krabs::event_filter AddRemoteSetThreadContextEventFilter() {
    /*
 PC (Program Counter): 程序计数器,指向下一条将要执行的指令的地址。
Sp (Stack Pointer): 栈指针,指向当前栈的顶部位置,用于管理函数调用和局部变量。
Lr (Link Register): 链接寄存器,通常用于保存返回地址,以便在函数调用完成后能返回到正确的位置。
Fp (Frame Pointer): 帧指针,指向当前函数调用的栈帧,用于访问函数参数和局部变量。
*/
    krabs::event_filter EventFilter(krabs::predicates::id_is(5));
    auto EventCallback = [](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
        FAST_TRY_START
        krabs::schema schema(record, trace_context.schema_locator);
        krabs::parser parser(schema);
        auto ProcessID = parser.parse<DWORD>(L"CallingProcessId");
        auto ThreadID = parser.parse<DWORD>(L"CallingThreadId");
        auto TargetID = parser.parse<DWORD>(L"TargetProcessId");
        auto TargetThreadID = parser.parse<DWORD>(L"TargetThreadProcessId");
        auto Pc = parser.parse<PVOID>(L"Pc");
        auto Sp = parser.parse<PVOID>(L"Sp");
        auto Lr = parser.parse<PVOID>(L"Lr");
        auto Fp = parser.parse<PVOID>(L"Fp");
        std::ostringstream ShowMsg;
        ShowMsg << "[EtwTi]" << "[Remote SetThreadContext] " <<
            "CallingProcessId : " << ProcessID << " | " <<
            "CallThreadId : " << ThreadID << " | " <<
            "TargetProcessId : " << TargetID << " | " <<
            "TargetThreadId : " << TargetThreadID << " | " <<
            "Program Counter : " << std::hex << std::showbase << reinterpret_cast<uintptr_t>(Pc) << " | " <<
            "Stack Pointer : " << std::hex << std::showbase << reinterpret_cast<uintptr_t>(Sp) << " | " <<
            "Link Register : " << std::hex << std::showbase << reinterpret_cast<uintptr_t>(Lr) << " | " <<
            "Frame Pointer : " << std::hex << std::showbase << reinterpret_cast<uintptr_t>(Fp) <<std::endl;
        WriteLogger::WriteLoggerInformation(ShowMsg.str(), WriteLogger::WARNING_TYPE);
        FAST_TRY_END
        };
    EventFilter.add_on_event_callback(EventCallback);
    return EventFilter;
}//以他作为示例 剩下的可以自己写
void RunEtwTi() {
    WriteLogger::WriteLoggerInformation("Try to load EtwTi Service", WriteLogger::INFO_TYPE);
    WriteLogger::WriteLoggerInformation("EtwTi Add Filters Success | Number : 1", WriteLogger::INFO_TYPE);
    krabs::provider<> ti_provider(L"Microsoft-Windows-Threat-Intelligence");
    ti_provider.any(KERNEL_THREATINT_KEYWORD_ALLOCVM_REMOTE |
        KERNEL_THREATINT_KEYWORD_PROTECTVM_REMOTE |
        KERNEL_THREATINT_KEYWORD_MAPVIEW_REMOTE |
        KERNEL_THREATINT_KEYWORD_QUEUEUSERAPC_REMOTE |
        KERNEL_THREATINT_KEYWORD_SETTHREADCONTEXT_REMOTE |
        KERNEL_THREATINT_KEYWORD_ALLOCVM_LOCAL |
        KERNEL_THREATINT_KEYWORD_PROTECTVM_LOCAL |
        KERNEL_THREATINT_KEYWORD_MAPVIEW_LOCAL |
        KERNEL_THREATINT_KEYWORD_WRITEVM_REMOTE |
        KERNEL_THREATINT_KEYWORD_READVM_REMOTE);
    //ti_provider.add_filter(AddRemoteVirtualAllocateEventFilter());
    //ti_provider.add_filter(AddRemoteVirtualProtectEventFilter());
    //ti_provider.add_filter(AddRemoteMapViewEventFilter());
    //ti_provider.add_filter(AddRemoteQueueUserApcEventFilter());
    ti_provider.add_filter(AddRemoteSetThreadContextEventFilter());
    //ti_provider.add_filter(AddRemoteReadProcessMemoryEventFilter());
    //ti_provider.add_filter(AddRemoteWriteProcessMemoryEventFilter());
 
    //ti_provider.add_filter(AddLocalMapViewEventFilter());
    //ti_provider.add_filter(AddLocalVirtualProtectEventFilter());
    //ti_provider.add_filter(AddLocalVirtualAllocateEventFilter());
    g_trace.enable(ti_provider);
    g_trace.start();
    WriteLogger::WriteLoggerInformation("Run EtwTi (Microsoft-Windows-Threat-Intelligence) Service Success", WriteLogger::INFO_TYPE);
}
void StopEtwTi() {
    WriteLogger::WriteLoggerInformation("Stop EtwTi Service Success", WriteLogger::INFO_TYPE);
    g_trace.stop();
}

0x04 引用

https://github.com/zodiacon/EtwExplorer
https://github.com/microsoft/krabsetw
https://github.com/jdu2600/Windows10EtwEvents/blob/main/manifest/Microsoft-Windows-Threat-Intelligence.tsv


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2024-10-6 23:25 被ShaShen4404编辑 ,原因:
收藏
免费 0
支持
分享
最新回复 (1)
雪    币: 182
活跃值: (2576)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
2
有生产环境用这种方式获取PPL的吗
6天前
0
游客
登录 | 注册 方可回帖
返回
//