Windows本地操作系统服务API由一系列以NtZw为前缀的函数实现的,这些函数以内核模式运行,内核驱动可以直接调用这些函数,而用户层程序只能通过系统进行调用。通常情况下用户层应用程序不会直接调用NtZw系函数,更多的是通过直接调用Win32函数,这些Win32函数内部会调用NtZw系函数,但也仅限于通常情况下,当Win32函数不支持一些操作时,用户层也会直接调用这些本地系统服务函数。

Nt前缀是Windows NT的缩写,但Zw前缀并没有任何意义,使用Zw只是避免跟其他已存在和未来可能出现的API有命名冲突而已。很多Windows驱动支持函数都以两到三个特定的简称字母为前缀进行命名,以此来表示这些例程都是由哪些内核系统组件实现的,比如CmRegisterCallbackEx中的Cm就表示配置管理器(Configuration manager

每个本地系统服务例程都有两个有着不同前缀的相似名称的函数版本,比如NtCreateFileZwCreateFile,两者执行相同的操作,并且事实上两者也都服务于相同的内核模式系统例程。对于用户层的系统调用,NtZw系函数是没有什么区别的,但对于来自于内核驱动的调用,NtZw系函数对传入参数的处理方式有些不一样。

如果传入参数是来自于可信任的内核层,那么内核模式驱动则调用Zw版本的本地系统服务例程来通知其他例程,在这种情况下,例程都是不经过验证就直接使用这些参数。反而,如果这些参数可能来自用户层或者内核层,那么驱动则调用Nt版本的例程,这取决于调用线程的历程——这些参数是从用户层还是内核层发起的,线程对象中有个PreviousMode的属性可用于判断参数是否从用户层过来的,关于例程如何判断参数是来自用户层还是内核层,详细内容请参见预先模式

当一个用户层应用程序调用NtZw系函数,这些本地系统服务函数始终会认为它接收到的参数来自于不可信任的用户层,在使用前必先验证参数的有效性。特别是对于由调用者提供的缓存区,这些函数将会探测其内存地址是否有效并且是否正常对齐。

本地系统服务例程对于接收到参数值还会做额外的设定。如果一个例程接收到一个由指向由内核驱动分配的缓存区指针,它会认为这缓存区是从系统内存而不是从用户层内存分配的,如果例程接收到一个由用户层应用程序打开的句柄类型参数,那么例程就会从用户层句柄表中查找句柄而不是从内核层。

在一些情况下,从用户层调用还是从内核层调用对传入参数的意义和后续的使用影响重要。比如说ZwNotifyChangeKey(或说NtNotifyChangeKey)这个函数,其中有两个输入参数ApcRoutineAPCContext,从用户层和从内核层传过来分别代表不同的意义。如果其从用户层被调用,ApcRoutine指向一个APC例程,ApcContext则指向一个由操作系统在调用APC例程时分配的上下文;如果其从内核层被调用,ApcRoutine指向一个WORK_QUEUE_ITEM结构,而ApcContext则表示WORK_QUEUE_ITEM队列项的类型。

用户层不支持调用Zw系函数,而在内核层调用Zw系函数时,上面也稍微提到过,系统不检测调用者的访问权限,调用之前必须检测从用户模式下传来的参数的有效性

大多数Zw 系函数的声明在Wdm.h中可以找得到,少部分散落在其他头文件里如Ntddk.hNtifs.h

用户层可通过引用Ntdll.lib静态库(在WDK中可以找到)来调用这些本地系统服务例程,大多数文档化的Nt系函数声明在Windows SDKWinternl.h头文件中,对于未文档化的Nt系函数,微软一直不建议开发者进行调用,因为在未来的Windows版本中这些函数接口可能会有所改动或者直接被废除,这对使用了这些未文档化函数的应用程序的稳定运行造成一定的影响,但往往是这些未文档化的函数和结构体能够获取更多的系统权限,这也是众多的Windows应用开发者不听劝告反而乐此不疲地去挖掘的原因。

内核驱动可通过调用NtZwNtoskrnl.exe的动态链接库的入口点(entry points)来使用这些本地系统服务例程的,该DLL(动态链接库)包含这些服务例程的具体实现,要访问这些入口点,驱动程序需要静态链接到Ntoskrnl.lib(在WDK中也可以找到)

对于Nt*Xxx* and Zw*Xxx* 的具体函数列表可查看此处

本地系统服务例程:Nt和Zw系列函数的更多相关文章

  1. linux系统编程之进程(五):exec系列函数(execl,execlp,execle,execv,execvp)使用

    本节目标: exec替换进程映像 exec关联函数组(execl.execlp.execle.execv.execvp) 一,exec替换进程映像 在进程的创建上Unix采用了一个独特的方法,它将进程 ...

  2. PHP进程通信基础——shmop 、sem系列函数使用

    PHP进程通信基础--shmop .sem系列函数使用 进程通信的原理就是在系统中开辟出一个共享区域,不管是管道也好,还是共享内存,都是这个原理.如果心中有了这个概念,就会很方便去理解代码.由于官网上 ...

  3. 第8章 用户模式下的线程同步(1)_Interlocked系列函数

    8.1 原子访问:Interlocked系列函数(Interlock英文为互锁的意思) (1)原子访问的原理 ①原子访问:指的是一线程在访问某个资源的同时,能够保证没有其他线程会在同一时刻访问该资源. ...

  4. linux tricks 之VA系列函数.

    VA函数(variable argument function),参数个数可变函数,又称可变参数函数.C/C++编程中,系统提供给编程人员的va函数很少.*printf()/*scanf()系列函数, ...

  5. Winsock系列函数 及 Socket通信流程

    Socket是一种网络通信机制   Winsock系列函数   1. Socket 创建socket   2. Connect 尝试连接远端Socket   3. Send 在某个Socket 向远端 ...

  6. 原子操作 Interlocked系列函数

    上一篇<多线程第一次亲密接触 CreateThread与_beginthreadex本质区别>中讲到一个多线程报数功能.为了描述方便和代码简洁起见,我们可以只输出最后的报数结果来观察程序是 ...

  7. posix 线程(一):线程模型、pthread 系列函数 和 简单多线程服务器端程序

    posix 线程(一):线程模型.pthread 系列函数 和 简单多线程服务器端程序 一.线程有3种模型,分别是N:1用户线程模型,1:1核心线程模型和N:M混合线程模型,posix thread属 ...

  8. (转)原子操作 Interlocked系列函数

    上一篇<多线程第一次亲密接触 CreateThread与_beginthreadex本质区别>中讲到一个多线程报数功能.为了描述方便和代码简洁起见,我们可以只输出最后的报数结果来观察程序是 ...

  9. 多线程笔记--原子操作Interlocked系列函数

    前面写了一个多线程报数的功能,为了描述方便和代码简洁起见,只输出最后的报数结果来观察程序运行结果.这非常类似一个网站的客户访问统计,每个用户登录用一个线程模拟,线程运行时将一个表示计数的变量递增.程序 ...

随机推荐

  1. [Reversing.kr] Easy ELF Writeup

    IDA打开,看到main()函数,当sub_8048451() 返回1 是flag正确. 跟踪函数. 脚本: #!usr/bin/env python #!coding=utf-8 __author_ ...

  2. python学习笔记(十)、文件操作

    在前面我们了解到了没得模块,其中有一个模块为fileinput,为文件操作模块,不知道小伙伴们是否还记得? 1 打开文件 要打开文件,可以使用fileinput中的fileinput.input函数进 ...

  3. CKEditor上传视频(java)

    CKEditor上传视频 CKEditor批量上传图片flvplayer.swf播放器CKEditor整合包(v4.6.1) ------------------------------------ ...

  4. python连接Linux命令行

    #!/usr/bin/python # -*- coding: utf-8 -*- '''https://www.ibm.com/developerworks/cn/linux/l-cn-pexpec ...

  5. 网络协议 5 - ICMP 与 ping:投石问路的侦察兵

        日常开发中,我们经常会碰到查询网络是否畅通以及域名对应 IP 地址等小需求,这时候用的最多的应该就是 ping 命令了. 那你知道 ping 命令是怎么工作的吗?今天,我们就来一起认识下 pi ...

  6. 死磕 java集合之CopyOnWriteArrayList源码分析

    欢迎关注我的公众号"彤哥读源码",查看更多源码系列文章, 与彤哥一起畅游源码的海洋. 简介 CopyOnWriteArrayList是ArrayList的线程安全版本,内部也是通过 ...

  7. asp.net core 系列 13 日志

    一.概述 ASP.NET Core 支持适用于各种内置和第三方日志记录, 供程序的日志记录 API,本文介绍了如何将日志记录 API 与内置提供程序一起使用.对于第三方日志记录提供程序使用,文章最后有 ...

  8. (四)五种IO模型

    基本概念 我们之前编写的套接字程序都是阻塞式的,其实这也是默认的形式.现在我们需要明确一些概念: 用户空间和内核空间 首先要明确,用户启动的应用程序在系统中以一个进程的形式存在,而无论对于网络数据还是 ...

  9. Asp.Net SignalR 集群会遇到的问题

    SignalR集群 当客户端数量上来,一台server自然是吃不消的.多个server集群部署是必然的解决方案.再通过负载均衡,嗯 简直是完美.但是问题也接踵而来.每个server只能管理到当前ser ...

  10. PE知识复习之PE的导出表

    PE知识复习之PE的导出表 一丶简介 在说明PE导出表之前.我们要理解.一个PE可执行程序.是由一个文件组成的吗. 答案: 不是.是由很多PE文件组成.DLL也是PE文件.如果我们PE文件运行.那么就 ...