系统调用之SysWhispers

news/2025/2/8 16:43:23/文章来源:https://www.cnblogs.com/websecyw/p/18704592

一、介绍

SysWhispers 是一个通过直接系统调用绕过系统调用钩子的工具。SysWhispers 有多个版本,具有不同的特性。本文将分析各个版本之间的改进。

 SysWhispers是64 位系统生成了支持直接系统调用的头文件/ASM 文件植入。它支持从 Windows XP 到 Windows 10 19042(20H2)的系统调用。受支持的 Windows 版本受到限制,因为系统调用号 (SSN) 会随着每次 Windows 更新而更改。因此,在 Windows 10 1903 上针对特定系统调用的直接系统调用实现可能与 Windows 10 1909 上的相同系统调用不兼容,由于在不同版本的 Windows 中相同的系统调用可能具有不同的 SSN,因此 SysWhispers 在运行时检查目标系统的 Windows 版本,并将 SSN 手动设置到正确版本。

二、SysWhispers分析

SysWhispers项目的当中提供一个示例:https://github.com/jthuraisamy/SysWhispers/blob/master/example-output/syscalls.asm

SysWhispers - NtMapViewOfSection 示例

NtMapViewOfSection PROCmov rax, gs:[60h]                             ; 将 PEB 加载到 RAX 中。
NtMapViewOfSection_Check_X_X_XXXX:                ; 检查主版本号。cmp dword ptr [rax+118h], 5je  NtMapViewOfSection_SystemCall_5_X_XXXXcmp dword ptr [rax+118h], 6je  NtMapViewOfSection_Check_6_X_XXXXcmp dword ptr [rax+118h], 10je  NtMapViewOfSection_Check_10_0_XXXXjmp NtMapViewOfSection_SystemCall_Unknown
NtMapViewOfSection_Check_6_X_XXXX:               ; 检查 Windows Vista/7/8 的次版本号。cmp dword ptr [rax+11ch], 0je  NtMapViewOfSection_Check_6_0_XXXXcmp dword ptr [rax+11ch], 1je  NtMapViewOfSection_Check_6_1_XXXXcmp dword ptr [rax+11ch], 2je  NtMapViewOfSection_SystemCall_6_2_XXXXcmp dword ptr [rax+11ch], 2je  NtMapViewOfSection_SystemCall_6_3_XXXXjmp NtMapViewOfSection_SystemCall_Unknown
NtMapViewOfSection_Check_6_0_XXXX:               ; 检查 Windows Vista 的内部版本号。cmp dword ptr [rax+120h], 6000je  NtMapViewOfSection_SystemCall_6_0_6000cmp dword ptr [rax+120h], 6001je  NtMapViewOfSection_SystemCall_6_0_6001cmp dword ptr [rax+120h], 6002je  NtMapViewOfSection_SystemCall_6_0_6002jmp NtMapViewOfSection_SystemCall_Unknown
NtMapViewOfSection_Check_6_1_XXXX:               ; 检查 Windows 7 的内部版本号。cmp dword ptr [rax+120h], 7600je  NtMapViewOfSection_SystemCall_6_1_7600cmp dword ptr [rax+120h], 7601je  NtMapViewOfSection_SystemCall_6_1_7601jmp NtMapViewOfSection_SystemCall_Unknown
NtMapViewOfSection_Check_10_0_XXXX:              ; 检查 Windows 10 的内部版本号。cmp dword ptr [rax+120h], 10240je  NtMapViewOfSection_SystemCall_10_0_10240cmp dword ptr [rax+120h], 10586je  NtMapViewOfSection_SystemCall_10_0_10586cmp dword ptr [rax+120h], 14393je  NtMapViewOfSection_SystemCall_10_0_14393cmp dword ptr [rax+120h], 15063je  NtMapViewOfSection_SystemCall_10_0_15063cmp dword ptr [rax+120h], 16299je  NtMapViewOfSection_SystemCall_10_0_16299cmp dword ptr [rax+120h], 17134je  NtMapViewOfSection_SystemCall_10_0_17134cmp dword ptr [rax+120h], 17763je  NtMapViewOfSection_SystemCall_10_0_17763cmp dword ptr [rax+120h], 18362je  NtMapViewOfSection_SystemCall_10_0_18362cmp dword ptr [rax+120h], 18363je  NtMapViewOfSection_SystemCall_10_0_18363jmp NtMapViewOfSection_SystemCall_Unknown
NtMapViewOfSection_SystemCall_5_X_XXXX:          ; Windows XP 和 Server 2003mov eax, 0025hjmp NtMapViewOfSection_Epilogue
NtMapViewOfSection_SystemCall_6_0_6000:          ; Windows Vista SP0mov eax, 0025hjmp NtMapViewOfSection_Epilogue
NtMapViewOfSection_SystemCall_6_0_6001:          ; Windows Vista SP1 和 Server 2008 SP0mov eax, 0025hjmp NtMapViewOfSection_Epilogue
NtMapViewOfSection_SystemCall_6_0_6002:          ; Windows Vista SP2 和 Server 2008 SP2mov eax, 0025hjmp NtMapViewOfSection_Epilogue
NtMapViewOfSection_SystemCall_6_1_7600:          ; Windows 7 SP0mov eax, 0025hjmp NtMapViewOfSection_Epilogue
NtMapViewOfSection_SystemCall_6_1_7601:          ; Windows 7 SP1 和 Server 2008 R2 SP0mov eax, 0025hjmp NtMapViewOfSection_Epilogue
NtMapViewOfSection_SystemCall_6_2_XXXX:          ; Windows 8 和 Server 2012mov eax, 0026hjmp NtMapViewOfSection_Epilogue
NtMapViewOfSection_SystemCall_6_3_XXXX:          ; Windows 8.1 和 Server 2012 R2mov eax, 0027hjmp NtMapViewOfSection_Epilogue
NtMapViewOfSection_SystemCall_10_0_10240:        ; Windows 10.0.10240 (1507)mov eax, 0028hjmp NtMapViewOfSection_Epilogue
NtMapViewOfSection_SystemCall_10_0_10586:        ; Windows 10.0.10586 (1511)mov eax, 0028hjmp NtMapViewOfSection_Epilogue
NtMapViewOfSection_SystemCall_10_0_14393:        ; Windows 10.0.14393 (1607)mov eax, 0028hjmp NtMapViewOfSection_Epilogue
NtMapViewOfSection_SystemCall_10_0_15063:        ; Windows 10.0.15063 (1703)mov eax, 0028hjmp NtMapViewOfSection_Epilogue
NtMapViewOfSection_SystemCall_10_0_16299:        ; Windows 10.0.16299 (1709)mov eax, 0028hjmp NtMapViewOfSection_Epilogue
NtMapViewOfSection_SystemCall_10_0_17134:        ; Windows 10.0.17134 (1803)mov eax, 0028hjmp NtMapViewOfSection_Epilogue
NtMapViewOfSection_SystemCall_10_0_17763:        ; Windows 10.0.17763 (1809)mov eax, 0028hjmp NtMapViewOfSection_Epilogue
NtMapViewOfSection_SystemCall_10_0_18362:        ; Windows 10.0.18362 (1903)mov eax, 0028hjmp NtMapViewOfSection_Epilogue
NtMapViewOfSection_SystemCall_10_0_18363:        ; Windows 10.0.18363 (1909)mov eax, 0028hjmp NtMapViewOfSection_Epilogue
NtMapViewOfSection_SystemCall_Unknown:           ; 未知/不支持的版本。ret
NtMapViewOfSection_Epilogue:mov r10, rcxsyscallret
NtMapViewOfSection ENDP

PEB 结构包含三个可用于确定 Windows 操作系统版本信息成员:

1. OSMajorVersion

  • 类型: DWORD
  • 作用: 该字段存储 Windows 操作系统的主版本号。例如:
    • Windows 7 对应的主版本号是 6
    • Windows 10 对应的主版本号是 10

2. OSMinorVersion

  • 类型: DWORD
  • 作用: 该字段存储 Windows 操作系统的次版本号。例如:
    • Windows 7 SP1 对应的次版本号是 1
    • Windows 8 对应的次版本号是 2
    • Windows 10 对应的次版本号可能为 0 或更高的版本号(取决于 Windows 10 的不同版本)。

3. OSBuildNumber

  • 类型: DWORD
  • 作用: 该字段存储操作系统的构建号,也就是操作系统的具体版本。例如:
    • Windows 7 SP1 的构建号是 7601
    • Windows 10 版本 15063(1703)对应的构建号是 15063
    • Windows 10 版本 1909 对应的构建号是 18363

SysWhispers 生成的 64 位汇编函数使用这些成员跳转到硬编码值 SSN 所在的位置。使用的逻辑本质上是若干 if 和 else if 语句。例如,如果目标计算机是 Windows 10 1809,则出现以下逻辑:

  1. 由于 PEB 的 主版本 成员等于 10,执行 NtMapViewOfSection_Check_10_0_XXXX 标签。

  2. 此标签接着检查系统的 生成版本号。在这个示例中,这个数字是 1809,这会使其跳转到 NtMapViewOfSection_SystemCall_10_0_17763 标签。

  3. 然后,SSN 设置为 0028h

  4. 最终跳转到 NtMapViewOfSection_Epilogue 标签,在那里执行剩余的系统调用指令。回忆一下,系统调用函数的格式如下:

mov r10, rcx
mov eax, SSN
syscall
ret

三、SysWhispers2分析

SysWhispers2采用了名为“按系统调用地址排序”的方法。此方法消除了汇编指令在运行时手动选择 SSN 的需要,从而缩小了系统调用存根。 按系统调用地址排序

按系统调用地址排序是一种在运行时获取系统调用 SSN 的方法。此方法通过查找所有以 “Zw” 开头的系统调用并将其地址存储在一个数组中,然后按升序(最小地址到最大地址)对这些地址进行排序来实现。SSN 将成为存储在数组中系统调用的索引。

举例说明:

将系统调用号(SSN)作为数组的索引:由于这些系统调用的地址已经按升序排列,现在可以将它们的“索引”作为它们的 SSN。例如,假设我们为这些地址分配一个索引:索引 0 对应 ZwCreateFile 地址 0x7FFD12345678
索引 1 对应 ZwQuerySystemInformation 地址 0x7FFD12345690
索引 2 对应 ZwReadFile 地址 0x7FFD12345700
索引 3 对应 ZwWriteFile 地址 0x7FFD12345750
在这种情况下,SSN 就是这个数组的索引。因此:SSN 为 0 的系统调用是 ZwCreateFile
SSN 为 1 的系统调用是 ZwQuerySystemInformation
SSN 为 2 的系统调用是 ZwReadFile
SSN 为 3 的系统调用是 ZwWriteFile

https://github.com/jthuraisamy/SysWhispers2/blob/main/example-output/Syscalls.c  

 

SW2_PopulateSyscallList 函数对系统调用地址进行排序,该函数 获取 NTDLL 的基地址和其导出目录。利用该信息,它 计算导出函数的 VA(地址、名称、序号) ,接下来,SysWhispers2 检查导出的函数名称,寻找以 Zw 为前缀的函数名称。这些函数名称会被哈希,并与它们的地址一起保存在 数组中。之后,SW2_PopulateSyscallList 会按 升序对收集到的地址进行排序

 为了找到系统调用的 SSN,SW2_GetSyscallNumber函数会获取目标系统调用名称的哈希,并返回索引,表示在数组中找到此系统调用哈希的位置。此索引值是系统调用的 SSN

 SysWhispers2 用于为 NtMapViewOfSection 生成直接系统调用。

.data
currentHash DWORD 0.code
EXTERN SW2_GetSyscallNumber: PROCWhisperMain PROCpop raxmov [rsp+ 8], rcx             ; 保存寄存器。mov [rsp+16], rdxmov [rsp+24], r8mov [rsp+32], r9sub rsp, 28hmov ecx, currentHashcall SW2_GetSyscallNumberadd rsp, 28hmov rcx, [rsp+ 8]             ; 还原寄存器。mov rdx, [rsp+16]mov r8, [rsp+24]mov r9, [rsp+32]mov r10, rcxsyscall                     ; 发出系统调用ret
WhisperMain ENDPNtMapViewOfSection PROCmov currentHash, 060C9AE95h ; 将函数哈希加载到全局变量中。call WhisperMain            ; 将函数哈希解析为系统调用号并进行调用
NtMapViewOfSection ENDPend

060C9AE95h 是 ZwMapViewOfSection 字符串的十六进制哈希值。调用 NtMapViewOfSection 时,会先将该哈希值加载到全局变量 currentHash 中,然后调用 WhisperMainWhisperMain 函数负责调用前面介绍的 C 函数 SW2_GetSyscallNumber,该函数将使用哈希值为 currentHash 的系统调用返回 SSN

mov [rsp+XX], XXX 指令用于在调用 SW2_GetSyscallNumber 之前将寄存器保存到堆栈中,而 mov XXX, [rsp+ XX] 指令用于将寄存器恢复到调用 SW2_GetSyscallNumber 之前的状态。之所以需要这样做,是因为调用 SW2_GetSyscallNumber 会更改这些寄存器的值。最后,在 WhisperMain 函数的末尾,出现了常见的系统调用指令:

mov r10, rcx
syscall                      
ret

请注意,这里缺少 mov eax, SSN 指令。这是因为当一个函数被调用时,其返回输出会存储在 eax 寄存器中。由于在这些指令之前已经调用了 SW2_GetSyscallNumber,这意味着 SSN 已经存储在 eax 寄存器中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/880876.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

服务部署操作之nssm

1、使用背景: 之前在windows server IIS管理器中部署程序操作复杂,参考各位大佬以后发现还有更好的方法;2、nssm介绍: 作为服务封装程序,可以将exe封装成服务,实现开机自启动,简单易上手,功能强大;3、nssm配置详情: 官网地址:https://nssm.cc/download 下载完成以后…

[羊城杯 2024]你这主函数保真么 _wp

main函数确实没有什么内容但是看函数名的时候可以发现有encrypt和rot13两种加密 还有tcf在_GLOBAL__sub_I_flag中,可以看到程序的执行逻辑,但是顺序是不对的,大概也猜得出来是什么样的顺序首先输入并且判断长度rot13加密一维DCT加密 DCT加密的特点就是嵌套循环里面的内容将加…

乐刻运动:基于 RocketMQ + MQTT 实现健身产业数字化升级

乐刻运动通过采用阿里云的云消息队列 RocketMQ 版和云消息队列 MQTT 版,不仅提升了系统的实时数据处理能力,还增强了系统的可扩展性、可靠性和性能,为业务的持续发展和流畅的用户体验,提供了坚实的技术支持,进一步推动了数字经济与健身产业的深度融合。作者:吉宪、稚柳 乐…

AI 在软件测试中的应用

软件测试人员,在工作中的任务流程: 测试计划-测试用例设计(脚本)-测试执行-测试报告一个新的技术, 带来的变革分为四种:替代,加强, 修改, 重塑 目前AI并不能替代软件测试人员, 但可以对测试流程进行加强, 修改, 和重塑 加强:把AI当做测试助手, 帮助解决一些测试…

30N06-ASEMI中低压N沟道MOS管30N06

30N06-ASEMI中低压N沟道MOS管30N06编辑:ll 30N06-ASEMI中低压N沟道MOS管30N06 型号:30N06 品牌:ASEMI 封装:TO-252 批号:最新 最大漏源电流:30A 漏源击穿电压:60V RDS(ON)Max:24mΩ 引脚数量:3 芯片个数: 沟道类型:N沟道MOS管、中低压MOS管 漏电流:ua 特性:N沟道…

P5266 【深基17.例6】学籍管理(map)

首先要注意score的范围,所以要用long long int,其次OK两个字母都是大写,并且插入和修改后都要输出Ok #include<iostream> #include<set> #include<map> #define int long long using namespace std; signed main() {map<string, int>mapstudent;int…

Rust编程Bug解决

Brainfuck工程,遇到版本以来错误: https://github.com/mohanson/brainfuck/tree/master1. cargo update 的详细解释 cargo update 是 Cargo(Rust 的包管理器)的一个命令,用于更新项目的依赖版本。以下是它的具体行为和作用: (1) 更新 Cargo.lock 文件Rust 项目有两个关键…

唯品会联盟唯享客-各种广告平台推广下的DeepLink链接与UniversalLink链接生成及下单转化归因ROI联调等对接技术的实现

唯品会联盟&唯享客-各种广告平台推广下的DeepLink链接与UniversalLink链接生成及下单转化归因ROI联调等对接技术的实现。 唯品会电商作为国内第四大电商平台,以做品牌为主,佣金相当与淘宝京东拼多多较高一些。但是限制也较多点。比如不允许投流推广,发现了轻则警告扣除部…

.Net9中通过HttpClient简单调用Ollama中的DeepSeek R1模型

本文主要使用.Net9中的HttpClient组件,调用本地部署的Ollama提供的API接口,获取对应的问答信息。1、🥇测试环境VS2022;.Net9控制台程序;HttpClient组件;本地部署的Ollama环境DeepSeek R1模型(deepseek-r1:1.5b)关于本地部署的Ollama环境,可参见文章【通过Ollama本地部…

变革管理的黄金法则:五大模型+工具,助你轻松应对项目管理挑战

变革模型与项目管理工具的结合运用可以形成一个系统化、高效化的变革管理体系。通过明确变革需求与目标、执行变革计划、评估与反馈以及持续优化改进等步骤,可以确保变革的顺利实施和成功落地。项目管理中的变革模型是指一系列指导和管理组织内部变革过程的框架和方法。这些模…

ollama部署本地模型的一些坑

1.ollama pull时进度回退:不知是否最近太多人下载导致服务器问题,下载大点的模型经常进度条往回退,解决方法就是每隔一会关闭进程重新下载,断点续传可以继续下载# 用法:python .\run.py 模型名字import subprocess import time import os import sys import signaldef run…

P5250 【深基17.例5】木材仓库(set)

由于题目保证木材的长度互不相同所以很自然的想到要用set op=1时 使用find函数查找length 如果it==s.end(),说明仓库里没有该长度的木材,应该insert 反之输出“Already Exist” op=2时 使用lower_bound 函数查找第一个大于等于length的木材,如果*it=length说明该仓库中有与…