内核态调用Nt*函数

新手向:用Windows调试工具WinDbg分析ntdll.dll调用栈(附PDB配置攻略) 本文详细介绍了如何使用Windows调试工具WinDbg分析ntdll.dll调用栈,并提供了PDB符号配置的实用攻略。通过实战案例和高级调试技巧,帮助开发者深入理解Windows系统底层运作,提升调试效率。 阅读详情
2007-11-18 22:27
我先简单介绍一下Nt系列函数与Zw系列函数的区别 以ReadFile为例   ntdll.dll导出了ZwReadFile和NtReadFile 以下是反汇编代码
.text:7C92E27C ; __stdcall NtReadFile(x, x, x, x, x, x, x, x, x)
.text:7C92E27C                 public _NtReadFile@36
.text:7C92E27C _NtReadFile@36 proc near               ; CODE XREF: RtlGetSetBootStatusData(x,x,x,x,x,x)+5F p
.text:7C92E27C                                         ; RtlGetSetBootStatusData(x,x,x,x,x,x):loc_7C95170D p ...
.text:7C92E27C                 mov     eax, 0B7h       ; NtReadFile
.text:7C92E281                 mov     edx, 7FFE0300h
.text:7C92E286                 call    dword ptr [edx]
.text:7C92E288                 retn    24h
.text:7C92E288 _NtReadFile@36 endp
.text:7C92E288
.text:7C92E288 ; ---------------------------------------------------------------------------
.text:7C92E28B                 db 6 dup(90h)
.text:7C92E291 ; Exported entry 274. NtReadFileScatter
.text:7C92E291 ; Exported entry 1083. ZwReadFileScatter
.text:7C92E291
我们可以看到 ZwReadFile和NtReadFile函数指向同一段代码....
也就是说在用户态 不管你调用ZwReadFile还是NtReadFile都是一样的 因为他们是同一个函数的两个不同名称而已.... 而且他们最终都会调用到ntoskrnl中的NtReadFile中去

而ntoskrnl.exe导出的ZwReadFile和NtReadFile却是不同的
.text:00406508 ; NTSTATUS __stdcall ZwReadFile(HANDLE FileHandle,HANDLE Event,PIO_APC_ROUTINE ApcRoutine,PVOID ApcContext,PIO_STATUS_BLOCK IoStatusBlock,PVOID Buffer,ULONG Length,PLARGE_INTEGER ByteOffset,PULONG Key)
.text:00406508                 mov     eax, 0B7h
.text:0040650D                 lea     edx, [esp+FileHandle]
.text:00406511                 pushf
.text:00406512                 push    8
.text:00406514                 call    _KiSystemService
.text:00406519                 retn    24h
.text:00406519 _ZwReadFile@36 endp

PAGE:004990D8 ; NTSTATUS __stdcall NtReadFile(HANDLE FileHandle,HANDLE Event,PIO_APC_ROUTINE ApcRoutine,PVOID ApcContext,PIO_STATUS_BLOCK IoStatusBlock,PVOID Buffer,ULONG Length,PLARGE_INTEGER ByteOffset,PULONG Key)
PAGE:004990D8                 push    68h
PAGE:004990DA                 push    offset stru_418748
PAGE:004990DF                 call    __SEH_prolog
PAGE:004990E4                 xor     esi, esi
PAGE:004990E6                 mov     [ebp+var_20], esi
PAGE:004990E9                 mov     [ebp+var_34], esi
PAGE:004990EC                 mov     [ebp+var_70], esi
PAGE:004990EF                 mov     [ebp+var_6C], esi
PAGE:004990F2                 mov     eax, large fs:124h
PAGE:004990F8                 mov     [ebp+var_58], eax
PAGE:004990FB                 mov     al, [eax+140h]
PAGE:00499101                 mov     [ebp+WaitMode], al
PAGE:00499104                 push    esi             ; HandleInformation
PAGE:00499105                 lea     eax, [ebp+FileObject]
PAGE:00499108                 push    eax             ; Object
PAGE:00499109                 push    dword ptr [ebp+WaitMode] ; AccessMode
PAGE:0049910C                 push    _IoFileObjectType ; ObjectType
PAGE:00499112                 push    1               ; DesiredAccess
PAGE:00499114                 push    [ebp+Handle]    ; Handle
PAGE:00499117                 call    _ObReferenceObjectByHandle@24 ; ObReferenceObjectByHandle(x,x,x,x,x,x)
PAGE:0049911C                 cmp     eax, esi
PAGE:0049911E                 jl      loc_49928C
...
...
...

Ntoskrnl导出的NtReadFile是真正的执行函数 而ZwReadFile仍然是一个stub函数
内核态调用ZwReadFile 会将Previous Mode设置为Kernel Mode 然后再调用到NtReadFile中 而在内核态直接调用NtReadFile 不会改变Previous Mode     . 而在NtReadFile中 会检测当前调用来自用户态还是内核态 如果是来自内核态 不会检测参数 而如果是来自用户态 就会做一系列的参数检测 而我们知道 内核组件可能运行在任意进程的上下文中 当它调用NtReadFile时 因为Previous Mode很可能是User Mode ....    而我们的参数请求的内核态的地址 这时通常就会产STATUS_ACCESS_VIOLATION
错误 ..  
所以内核态一般用Zw*系列的函数
关于Nt*与Zw*更为详细的介绍请参考 [URL="http://www.osronline.com/article.cfm?id=257"]Nt vs. Zw - Clearing Confusion On The Native API [/URL]
那我们为什么还要在内核态直接调用Nt*函数呢?
大家都知道很多杀毒软件hook了ssdt 对系统进行监控....   现在比如我们已经进入了Ring0(这个不在本文介绍的范围内) 然后想干一些猥琐的事情 那么怎样绕过监控呢 ? 一种方法先恢复被ssdt
然后再调用我们要用到的Zw*函数 ,不过这种方法不太好 不够隐藏 而且有很多监控程序 会定时检测ssdt表的
那么我们可不可以直接调用 Nt函数呢? 如果可以的话 那么监控对我们就失去作用了 .
直接调用Nt*函数要解决几个问题 第一个就是Nt*函数在内存中的地址 只有有了地址我们才能调用啊 而ssdt表已经被hook了 所以我们不能直接从ssdt中获得 而要从磁盘文件ntoskrnl.exe中得到它
第二个问题是系统会在Nt*函数中检查当前线程结构的PreviousMode 来确定调用是来自用户态还是内核态 如果是来自用户态 函数会检测参数地址是否小于_MmUserProbeAddress.如果不是 将会产生一个错误..   所以我们的目标就是把PreviousMode改为Kernel Mode
下面看NtReadFile的代码
PAGE:004990D8 ; NTSTATUS __stdcall NtReadFile(HANDLE FileHandle,HANDLE Event,PIO_APC_ROUTINE ApcRoutine,PVOID ApcContext,PIO_STATUS_BLOCK IoStatusBlock,PVOID Buffer,ULONG Length,PLARGE_INTEGER ByteOffset,PULONG Key)
PAGE:004990D8                 push    68h
PAGE:004990DA                 push    offset stru_418748
PAGE:004990DF                 call    __SEH_prolog
PAGE:004990E4                 xor     esi, esi
PAGE:004990E6                 mov     [ebp+var_20], esi
PAGE:004990E9                 mov     [ebp+var_34], esi
PAGE:004990EC                 mov     [ebp+var_70], esi
PAGE:004990EF                 mov     [ebp+var_6C], esi
PAGE:004990F2                 mov     eax, large fs:124h           ;内核态fs指向KPCR
/*                                                                                              ;fs:120为KPRCB
lkd> dt _kprcb
nt!_KPRCB
   +0x000 MinorVersion     : Uint2B
   +0x002 MajorVersion     : Uint2B
   +0x004 CurrentThread    : Ptr32 _KTHREAD                       ;fs:124
   +0x008 NextThread  
*/                                                                                         

PAGE:004990F8                 mov     [ebp+var_58], eax
PAGE:004990FB                 mov     al, [eax+140h]             
/*
lkd> dt _kthread
nt!_KTHREAD
   +0x000 Header           : _DISPATCHER_HEADER
   +0x010 MutantListHead   : _LIST_ENTRY
   +0x018 InitialStack     : Ptr32 Void
   +0x01c StackLimit       : Ptr32 Void
........
+0x140 PreviousMode     : Char                                                ;al =PreviousMode
......................................
*/
PAGE:00499101                 mov     [ebp+WaitMode], al         
PAGE:00499104                 push    esi             ; HandleInformation
PAGE:00499105                 lea     eax, [ebp+FileObject]
PAGE:00499108                 push    eax             ; Object
PAGE:00499109                 push    dword ptr [ebp+WaitMode] ; AccessMode
PAGE:0049910C                 push    _IoFileObjectType ; ObjectType
PAGE:00499112                 push    1               ; DesiredAccess
PAGE:00499114                 push    [ebp+Handle]    ; Handle
PAGE:00499117                 call    _ObReferenceObjectByHandle@24 ; ObReferenceObjectByHandle(x,x,x,x,x,x)
PAGE:0049911C                 cmp     eax, esi
PAGE:0049911E                 jl      loc_49928C
PAGE:00499124                 mov     ebx, [ebp+FileObject]
PAGE:00499127                 push    ebx             ; FileObject
PAGE:00499128                 call    _IoGetRelatedDeviceObject@4 ; IoGetRelatedDeviceObject(x)
PAGE:0049912D                 mov     [ebp+var_28], eax
PAGE:00499130                 cmp     [ebp+WaitMode], 0                 ;如果调用来处内核态
                                                                                                      ;则不作后面的检查     
PAGE:00499134                 jz      loc_4A9553
PAGE:0049913A                 mov     [ebp-4], esi
PAGE:0049913D                 mov     edi, [ebp+IoStatusBlock]
PAGE:00499140                 mov     eax, _MmUserProbeAddress
PAGE:00499145                 cmp     edi, eax
PAGE:00499147                 jnb     loc_50EBDC
PAGE:0049914D
PAGE:0049914D loc_49914D:                             ; CODE XREF: NtReadFile(x,x,x,x,x,x,x,x,x)+75B06 j
PAGE:0049914D                 mov     eax, [edi]
PAGE:0049914F                 mov     [edi], eax
PAGE:00499151                 mov     eax, [edi+4]
PAGE:00499154                 mov     [edi+4], eax
..............
我们只要把kthread中的PreviousMode值设为0就可以了
而PreviousMode在kthread中的偏移在各个系统版本中是不一样的 我们可以硬编码之
也可以在NtAdjustPrivilegesToken函数中得到这个偏移
PAGE:004B7BB2 loc_4B7BB2:                             ; CODE XREF: NtAdjustPrivilegesToken(x,x,x,x,x,x)+23 j
PAGE:004B7BB2                 mov     eax, large fs:124h
PAGE:004B7BB8                 mov     al, [eax+140h]                      ;这个140h就是偏移量
PAGE:004B7BBE                 mov     [ebp+AccessMode], al
PAGE:004B7BC1                 test    al, al
PAGE:004B7BC3                 jz      loc_4B8F67
 
Nt内核函数大全 Nt内核函数大全 Nt内核函数功能和函数原型定义 立即下载

相关推荐

部署Doris

本文详细介绍了Apache Doris三节点集群(3 FE + 3 BE)的部署流程。首先从硬件配置、系统参数调优等准备工作入手,然后分步说明FE和BE节点的配置方法,包括端口设置、存储路径规划等关键参数。部署完成后提供SQL测试用例和数据一致性验证方法,并总结常见问题解决方案,如节点加入失败、磁盘容量异常等。文档包含完整的命令和配置示例,强调高可用配置和监控建议,为生产环境部署提供实用指导。

神棍之路 1714

Nt内核函数原型and中文

NtLoadDriver 服务控制管理器加载设备驱动. NtUnloadDriver 服务控制管理器支持卸载指定的驱动程序. NtRegisterNewDevice 加载新驱动文件. NtQueryIntervalProfile 返回数据. NtSetIntervalProfile 指定采样间隔. NtStartProfile 开始取样. NtStopProfile 停止...

dengjiatao9832的博客 738

深入解析达梦数据库核心技术:检查点、redo、undo、MVCC与内存缓存刷盘

MVCC 依赖 undo 日志:通过 undo 日志构建版本链,实现 “读不加锁”;刷盘依赖检查点:检查点批量清理脏页,redo 日志通过检查点释放空间;日志保障刷盘安全:redo 日志先行写入,确保未刷盘脏页可恢复;刷盘优化 MVCC 性能:优先刷冷区脏页,减少对高频访问数据的影响。例如,一个完整的 “查询 - 修改 - 提交 - 恢复” 流程中:查询时,MVCC 通过 undo 日志获取可见版本,无需等待锁;修改时,redo/undo 日志先记录,缓冲池生成脏页;

tangyuan12345678的博客 1416

C语言在用户模式使用NT函数

C语言要使用NT函数并不像使用库函数那么简单,下面介绍一下使用方法,以NtSetInformationFile为例:#include <windows.h> #include <stdio.h>//因为NtSetInformationFile方法要用到FILE_INFORMATION_CLASS的值,所以这里全部枚举出来 //当然你也可以直接使用1,2,3,这样值代替,只是这样定义以后在后面使用更接

u011311291的博客 2819

Sigmastar平台WDR调试实战:从参数解析到鬼影消除的完整指南

本文提供了Sigmastar平台宽动态(WDR)技术的实战调试指南。针对逆光、运动场景下的核心痛点,系统性地解析了从多曝光采集、HDR融合到色调映射的完整管线,并重点阐述了如何通过调整曝光比、运动阈值与调整曲线等关键参数,有效消除运动鬼影、平衡暗部噪声与细节,最终实现清晰稳定的图像效果。

Jerry的专栏 930

Flutter加载本地HTML的优雅解决方案:轻松实现富文本展示

通过以上步骤,我们实现了Flutter加载本地HTML的完整流程,并简单介绍了如何通过WebView与HTML页面进行交互。HTML文件作为一种灵活、易维护的富文本展示方式,能有效提升Flutter应用的内容呈现能力。这种方法在展示新闻、资讯或帮助文档等内容时非常有用,能够让开发者灵活调整内容的样式和排版。希望这篇文章能对你在Flutter开发中的HTML加载有所帮助!

四楼没电梯的专栏 3649

NT 函数原型

NTSYSAPI NTSTATUS NTAPI NtAcceptConnectPort( OUT PHANDLE PortHandle, IN PVOID PortIdentifier, IN PPORT_MESSAGE Message, IN BOOLEAN Accept, IN OUT PPORT_VIEW ServerView OPTIONAL, OUT PREMOTE_P

lei35151的专栏 4508

Win10/Win11系统下,用VSCode编译Betaflight固件最全避坑指南(从GCC安装到HEX生成)

本文详细介绍了在Win10/Win11系统下使用VSCode编译Betaflight固件的完整流程,包括GCC安装、环境变量配置、终端选择、Make工具安装等关键步骤,帮助开发者避开常见陷阱,高效生成HEX文件。特别针对VSCode环境优化和编译错误排查提供了实用解决方案。

weixin_42557803的博客 416

NT 内核函数原型大全

原文地址:

lwqamm的博客 1393

Centos7搭建OpenStack+创建iaas云主机

主要说明在控制节点和计算节点上,通过脚本的形式,安装OpenStack的iaas安装步骤和创建可运行的云主机。提供实施简单、可大规模扩展、丰富、标准统一的云计算管理平台。

weixin_48218106的博客 1万+

YOLO11改进-模块-引入多尺度差异融合模块MDFM

MDFM主要用于融合双时相图像特征并生成带有丰富上下文信息的差异特征,其过程包含以下步骤:1. 特征提取与差异特征生成首先从双时相图像中提取特征f1和f2,然后将f1和f2进行像素级别的相减,再对相减结果取绝对值,最后通过一个3x3的卷积操作得到Di。2. 多尺度特征融合(MSFF)接着利用多尺度特征学习机制来增强特征融合效果。该机制通过不同核大小的卷积构建多尺度融合过程,具体是通过一个名为 MSFF 单元来实现的。

qq_64693987的博客 4380

Nt*和Zw*开头的函数

原文 Ring3中的NATIVE API,和Ring0的系统调用,都有同名的Zw和Nt系列函数,这些Zw*和Nt*函数既在ntdll.dll(Ring3)中导出又在ntoskrnl.exe(Ring0)中导出,他们有什么区别呢? 我们先来看看ntdll.dll和ntoskrnl.exe的关系。 Win32 API中的所有调用最终都转向了ntdll.dll,再由它转发至ntoskrnl

qiaoli的知识备忘录 2591

上午题目复习ing

无线局域网,11b是常用的,2.4ghz,后来改进5ghz,有些字段可以工作在5g的字段802.11/11a/1h/11n,,,,,11b和11g还在2.4ghz工作。数据链路层 传输服务,数据链路维护,差错控制,arp ip到mac,rarp反过来,token ring,x.25,atm,ethernet,蓝牙10m,简化因特网,分散式网,快调频,短包,点对点,点多多点,2.4ghz,最高速率1mb/s。gsm:是时分多址,900m-1800m,微蜂窝是市区,微微风是室内,伞是盲点,

weixin_47120900的博客 894

ntdll.dll和ntoskrnl.exe中的NT*和ZW*函数区别

[菜文]ntdll.dll和ntoskrnl.exe中的NT*和ZW*函数区别以NtOpenProcess和ZwOpenProcess为例,结合Windbg的lkd调试来说明 1、Q:ntdll.dll中的Nt*和Zw*区别? lkd> u ntdll!zwopenprocess l4ntdll!ZwOpenProcess:7c92d5fe b87a000000  

620

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

ZW与NT函数区别

区别: Ntdll.dll中:完全一样 Ntoskrnl.exe中: Zw*nt*,即nt函数更底层 Zw*函数会把PreviousMode设置为KernelMode  然后再调用Nt*函数,因此在Nt*函数中就不会进行参数检查。而如果直接调用Nt*函数的话 , 必须自己将PreviousMode设置为KernelMode,否则PreviousMode很可能仍然是UserMode, 这样

zhuhuibeishadiao 3185

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

Zw*与Nt*的区别

<br />某些Zw*和Nt*函数既在ntdll.dll中导出又在ntoskrnl.exe中导出,他们有什么区别呢?<br />我们分三部分比较:<br />step 1: ntdll.dll中的Zw*和Nt*有什么区别?<br />step 2: ntoskrnl.exe中的Zw*和Nt*有什么区别?<br />step 3: ntdll.dll中的Zw*与ntoskrnl.exe中的Zw*有什么区别? <br />        ntdll.dll中的Nt*与ntoskrnl.exe中的Nt*有什么区别

十年磨一剑,霜刃未曾试! 1553

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

WinVisor 开发者指南:如何为任意 Nt* 系统调用编写 Hook 的完整教程

**WinVisor** 是一个基于 **Windows Hypervisor Platform(WHP)API** 构建的 Windows x64 用户态可执行文件**虚拟化模拟器(Hypervisor 模拟器)**。它把目标进程注入到一个虚拟 CPU 中运行,所有 `Nt*` **系统调用(Syscall)** 都会经过宿主的代理层。这个"必经之路"正是我们做 Hook 的切入点——本教程将带

gitblog_00716的博客 287

Windows API 理解----Nt* Zw*

在你要理解Zw和Nt 系列API时,你首先要知道一点,那就是系统调用。什么是系统调用呢? 系统调用:操作系统为应用程序提供的可被调用的一组函数,也叫“System Call”。 从软件角度来看,这些系统调用都是操作系统为软件提供的服务,所以也称“系统服务”,也可以说两个名词是同名词。 系统调用所提供的服务都是在内核中实现的,而软件是在用户空间运行的,其实两者就是CP...

qq_42021840的博客 1041

Nt* 与 Zw* 区别

以ReadFile为例 ntdll.dll导出了ZwReadFile和NtReadFile 在用户态 不管你调用ZwReadFile还是NtReadFile都是一样的 因为他们是同一个函数的两个不同名称而已.... 而且他们最终都会调用到ntoskrnl中的NtReadFile中去 在内核态 ntoskrnl.exe导出了ZwReadFile和NtReadFil...

weixin_30701575的博客 238

彻底弄懂:什么是用户态和内核态?

摘要: 用户态和内核态是操作系统的核心概念。用户态是应用程序运行的低权限环境,无法直接操作硬件;内核态是操作系统内核运行的高权限模式,可直接控制硬件资源。两者通过系统调用进行切换,确保安全、稳定和抽象性。用户态程序需通过系统调用"陷入"内核态完成特权操作,切换过程存在性能开销。这种设计防止程序错误影响系统,并提供统一的硬件访问接口。理解二者区别对掌握计算机工作原理至关重要。

Chinese_chen_的博客 939

ntoskrnl.exe中Zw*与Nt*的区别

某些Zw*和Nt*函数既在ntdll.dll中导出又在ntoskrnl.exe中导出,他们有什么区别呢? 我们分三部分比较: step 1: ntdll.dll中的Zw*和Nt*有什么区别? step 2: ntoskrnl.exe中的Zw*和Nt*有什么区别? step 3: ntdll.dll中的Zw*与ntoskrnl.exe中的Zw*有什么区别?          ntdll.d

shenjianxz的博客 974

Zw函数与Nt函数的分别与联系

in ring3: lkd&gt; ? ntdll!ZwOpenProcess Evaluate expression: 2089999739 = 7c92dd7b lkd&gt; ?ntdll!NtOpenProcess Evaluate expression: 2089999739 = 7c92dd7b 可以看到,在ntdll中,ZwOpenProcess和NtOpenProce...

huobengle 354

Windows NT System-Call Hooking (Dr. Dobb's Journal)

---------------------------------------------------------------------Notes from "Windows NT System-Call Hooking" (Dr. Dobbs Journal, 97)----------------------------------------------------------

2073

[转]Nt**、Zw**和Rtl** 开头的函数介绍

  首先他们都是微软未公开的函数,之所以未公开主要是因为这些函数大部分功能太强大了,把他们公开会让一些别有用心的人利用。9x下的我不知道,NT(含2000/xp)下你可以参考《Windows NT Native API》,他们中的大部分函数几乎就从来没有变过。而几乎所有从Kenerl.dll中引出的Win32API,都是通过调用的Native API(NTDLL.DLL中导出)实现系统调用的。举一...

weixin_34029680的博客 259
上一篇: Windows软件防火墙实现技术简述
下一篇: 内核驱动与文件创建读写
iiprogram
博客等级 码龄25年 1068粉丝 1515原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值