收藏 分享(赏)

Windows系统服务调用new.doc

上传人:dreamzhangning 文档编号:2333307 上传时间:2018-09-10 格式:DOC 页数:11 大小:56.50KB
下载 相关 举报
Windows系统服务调用new.doc_第1页
第1页 / 共11页
Windows系统服务调用new.doc_第2页
第2页 / 共11页
Windows系统服务调用new.doc_第3页
第3页 / 共11页
Windows系统服务调用new.doc_第4页
第4页 / 共11页
Windows系统服务调用new.doc_第5页
第5页 / 共11页
点击查看更多>>
资源描述

1、一 序言Windows 系统服务调用是存在于 Windows 系统中的一个关键接口,常常称作 System Call ,Sysem Service Call 或 System Service Dispatching 等,在此我们就权且称之为 Windows 系统服务调用,它提供了操作系统环境由用户态切换到内核态的功能。虽然在国外关于 Windows 系统服务调用的讨论比较多,但却很少看到比较详细的中文资料,希望本文能够为和作者一样对 Windows 底层感兴趣并且是刚刚接触的朋友提供一些帮助。文章中将以一个内核级的进程监视/隐藏工具 T-ProcMon 为例来详细讨论 Windows 系统服务

2、调用的相关技术细节。另需注意本文讨论的技术仅适用于基于 Windows NT 内核的操作系统,并以 Windows 2000 为例。二 Windows 2000 系统体系结构微软 Windows 2000 是一个主要面向网络服务器的操作系统,因此它和以前大家比较熟悉的 Windows 9x 有很大的区别。但是对于讨论一个因商业策略而出现的个人桌面操作系统的确没有太大的价值。所以我们将主要介绍一些关于 NT 系统内部结构的细节。Windows 2000 在实现其自身目标的过程中,我们有必要讲解一些它的特性。1. 可扩展性(Extensibility)Windows 2000 操作系统是一个面向未

3、来的系统,所以它非常注重自身的扩展性,因为在将来可能有许多市场等方面的原因导致我们必须添加或删除目前操作系统的一些组件,这就必须要求操作系统有较强的可扩展性。为了满足扩充/删除的各种需求,Windows 2000 提供了一个重要的设计思想就是子系统(Subsystem)。我们可以将一些需要扩展的操作系统功能作为一个子系统添加到 Windows 2000 内,就像 OS/2,POSIX 等一样。当然还有一个特性就是,我们可以通过为系统服务调用添加钩子来修改系统的各项行为,这就为我们提供了一个了解系统内部并扩展系统功能的机会。2. 可靠性和健壮性(Reliability and Robust)一个

4、系统存在的最基本的要求就是它的稳定性,没有稳定的环境就做不出任何满意的产品。为了满足这项要求,Windows 2000 提出了基于对象的访问控制权限的措施。现代的大多数微处理器都支持两种模式:用户模式(User/Normal)和内核模式(Kernel/Privileged)。操作系统组件和关键的系统组件处于内核模式,而一般用户模式的程序只能访问私有地址空间和执行非特权等级的指令。如果用户要调用一些内核组件的功能,就得通过系统服务调用来实现。3. 兼容性(Compatibility)Intel 和 Microsoft 能够做到今天的一个很重要的因素就是他们支持对过去存在系统的兼容。这一点非常的关

5、键,没有人愿意三天两头的更换系统,当然也很少有人有这个经济实力。Windows 2000 为了实现对其他系统的兼容,如 Dos,16 位 Windows 等,出现了环境子系统。而在 Windows 2000 中必须存在的环境子系统是 Win32,它是其他子系统的基础,其他子系统都是一些表面的接口,而实际上是调用了 Win32 提供的接口,而 Win32 最终也是通过系统服务调用来与内核联系的。虽然操作系统为各种环境子系统提供了不同的动态链接库,而且其中的 API 函数名称往往也是不同的,不过这个函数的最终都是通过相同的系统服务调用进入内核来实现的。4. 易维护性(Maintainability

6、)作为一个大型的项目,Windows 2000 的维护也成为了一个大型的工程。而如此巨大的项目没有很好的维护性是无法发展下去的。为此,Windows 2000 使用了分层的思想,这也是一种操作系统体系结构模型。其中,系统服务调用将系统的内核模式代码和用户模式代码隔离开来,子系统使用系统服务调用为用户提供应用程序编程接口(API),而系统服务调用向下调用执行体实现各项功能。就像在上文我们提到的操作系统存在的两种模式,这是建立在处理器的基础之上的。按理说,一般处理器可以提供从 Ring0 到 Ring3 的四种处理器模式,但是它们必须提供至少两种,那就是 Ring0 和 Ring3。而一些特殊处理

7、器指令只能在内核模式执行,而一些地址空间必须在内核模式才可以被访问。Windows 2000 就利用了这个特点,将操作系统和其他关键组件保护起来,只有在内核模式才可以访问执行,而一般的用户程序就只能在用户态执行咯,这样就可以避免一些用户程序对操作系统代码的破坏,也就是大家看到的 Windows 2000 明显比 Windows 9x 稳定得多的主要原因。下面我们给出了 Windows 2000 的体系结构简图:系统支持进程,服务进程,应用程序,环境子系统应用程序编程接口基于 NTDLL.dll 的本地系统服务 (用户模式)-系统服务调用 (内核模式)执行体系统内核,设备驱动程序硬件抽象层三 W

8、indows 2000 本机系统服务(Native API)Windows 2000 本机系统服务又称为 Windows 本机应用程序编程接口,它是由执行体(Executive)为用户模式和内核模式的程序提供的系统服务集。它包含两种类型的函数:Windows 执行系统服务的系统服务调度占位程序;子系统,子系统 DLL 和其他本机映像使用的内部支持函数。从用户模式调用本机系统服务是通过 NTDLL.dll 来实现的。表面上,Win32 函数为编程人员提供了很多接口来实现我们想要的功能,但是这些 Win32 函数只不过是本机应用程序编程接口的一个包装器而已,它们将本机 API 包装起来,调用本机系

9、统服务来实现用户期望的功能。也就是说 NTDLL.dll 只是系统服务调用接口在用户模式下的一个外壳。关于用户模式下的 Windows 本机系统服务的相关信息,请参见我以前写的一篇文章探测Windows2K/XP/2003 本机系统信息。我们再谈谈从内核模式调用系统服务吧,这时就不是由 NTDLL.dll 导出系统服务调用的函数接口了,而是由 ntoskrnl.exe 来实现的,它会提供两种形式的函数:ZwXxx 和 NtXxx,在此我们就不多说了。大家应该注意到了,在上面我们介绍的 Windows 2000 系统体系结构中的系统服务调用,执行体和内核都是存在于 ntoskrnl.exe(在多

10、处理器中为 ntkrnlmp.exe)之中,并且是分层的。四 Windows 2000 系统服务调用机制Windows 2000 的陷阱调度 (Trap Dispatching)机制包括了:中断(Interrupt),延迟过程调用(Deferred Procedure Call),异步过程调用(Asynchronous Procedure Call),异常调度(Exception Dispatching)和系统服务调用。在 Intel x86 的 Windows 2000 系统中,处理器执行 int 0x2e 指令来激活 Windows 系统服务调用;在 Intel x86 的 Windows

11、 XP 系统中处理器却是通过执行 sysenter 指令使系统陷入系统服务调用程序中;而在 AMD的Windows XP 中使用了指令 syscall 来实现同样的功能。我们暂时使用 x86 的 Windows 2000为例来演示。我们先给出一个系统服务调用的模型:mov eax, ServiceId lea edx, ParameterTableint 2ehret ParamTableBytes其中,ServiceId 清楚的说明了传递给系统服务调用的系统服务号,内核使用这个标识符来查找系统服务调度表(System Service Dispath Table)中的对应系统服务信息。在系统服

12、务调度表中的每一项包含了一个指向系统服务程序的指针,我们 Hook 时就是修改这个指针使其指向我们自定义的系统服务的地址。ParameterTable 是传递的参数,系统服务调用程序 KiSystemService 必须严格校验传递的每一个参数,并将其参数从线程的用户堆栈中复制到系统的核心堆栈以备使用。由于执行 int 指令会导致陷阱发生,所以在Windows 2000 内的中断描述表 (IDT = Interrupt Descriptor Table)中的 0x2e 项指向了系统服务调用程序。最后返回的 ParamTableBytes 是关于参数个数的信息。现在我们已经看得出来了,系统服务调

13、用只是一个接口,它提供了将用户模式下的请求转发到 Windows 2000 内核的功能,并引发处理器模式的切换。在用户看来,系统服务调用接口就是 Windows 内核组件功能实现对外的一个界面。系统服务调用接口定义了Windows 内核提供的大量服务。五 Windows 2000 系统服务调用类型在 Windows 2000 中默认存在两个系统服务调度表,它们对应了两类不同的系统服务。这两个系统服务调度表分别是:KeServiceDescriptorTable 和 KeServiceDescriptorTableShadow。Windows 2000 执行程序服务对应于 NTDLL.dll 为

14、我们提供的系统服务调用。子系统通过调用 NTDLL.dll 中的函数接口来实现它们需要的功能。系统服务调度表 KeServiceDescriptorTable 定义了在 ntoskrln.exe 中实现的系统服务,通常在 kernel32.dll/advapi32.dll 中提供的函数接口均是调用的这个系统服务调度表中。同时存在于 Windows 2000 操作系统中还有在 Win32k.sys 中实现的相关 Win32USER和 GDI 函数,它们是属于另一类系统服务调用。与之对应的系统服务调度表为 KeServiceDescriptorTableShadow,它提供了内核模式实现的 USE

15、R 和 GDI 服务。函数KeAddSystemServiceTable 允许 Win32.sys 和其他设备驱动程序添加系统服务表。除了 Win32k.sys 服务表外,使用 KeAddSystemServiceTable 添加的服务表会被同时复制到 KeServiceDescriptorTable和 KeServiceDescriptorTableShadow 中去。我们可以看出这两类函数实现在服务调度上的区别:Win32 内核 API 经过 Kernel32.dll/advapi32.dll 进入 NTDLL.dll 后使用 int 0x2e 中断进入内核,最后在 Ntoskrnl.ex

16、e 中实现了真正的函数调用;Win32 USER/GDI API 直接通过 User32.dll/Gdi32.dll 进入了内核,最后却是在 Win32k.sys 中实现了真正的函数调用。在此我们只讨论与 NTDLL.dll 相关的函数,也就是我们例子中处理的函数。六 Hook 系统服务调用的作用钩子(Hooking)是一种拦截/监听可执行代码在执行过程中相关信息的一种通用机制。它使我们了解系统内部结构,运作机制甚至修改系统行为的想法成为可能。在一个像 M$存在的世界里,Windows 的很多内部信息我们都是无法得知的,因为 Windows 不是Linux,但这并不意味着我们就此放弃!只要开动

17、你的大脑,很多事情都会变成可能。1. 事件追踪你想知道 Windows 在什么时候会打开一个进程吗?你想知道 Windows 任务管理器中进程相关信息的获取调用了哪些函数吗?我们都可以使用 Hook 技术来实现这些你想要的信息。我们可以追踪 ZwOpenProcess 的执行情况,我们同样也可以追踪 ZwQueryInformationProcess 的执行情况,包括传递的参数和返回的结果。大家可以看到本文相关的程序 T-ProcMon 就是一个进程监视工具,它会追踪系统中与进程相关的各种信息。在某些我们期望的事件发生时,程序会通知用户发生了什么,这也是我们期望看到的结果。2. 修改系统行为操

18、作系统为我们提供了一些通用的功能,如查询系统进程信息 ZwQuerySystemInformation(SystemInformationClass = 5),它会返回系统中当前所有进程 /线程的相关信息。如果我们希望隐藏一些特殊的进程那该怎么办呢?那就是修改系统服务调用,也就是修改 ZwQuerySystemInformation 的行为。在查询系统进程时,系统会返回一个进程信息队列,每个单元对应一个进程,如果我们想隐藏其中的某个进程,只须修改队列中的某些数据,然后返回给上层函数,它们就不会发现 Xxx.exe 进程存在于系统之中了。 3. 研究系统内部机制微软提供的 Windows 操作系

19、统是一个 “封闭”的系统,很多内部资料都没有公布,我们可以通过 Hook 技术来探测系统的内部数据结构和运行机制,学习操作系统内部的操作方式。基于 Hook 的 Windows 内核黑客技术(Kernel Hacking)是非常之流行和有效,在我们探测系统的一些未公开,未文档化的技术细节时我们都可以使用钩子技术。4. 其他其他如我们要调试一个非常麻烦的程序时就可以使用 Hook 技术,这样就可以更好的帮助我们追踪系统的行动,更好的了解程序内部的执行过程。同样,为了获取系统的一些特殊性能数据,我们也可以在特定的情况下使用 Hook 技术。七 Hook 系统服务调用的实现在此我们讨论 Hook 的

20、对象仅限于由 Windows 2000 的 ntoskrnl.exe 提供的系统服务调用。Windows 2000 系统服务调用为内核模式的代码,所以我们必须书写设备驱动程序来访问系统服务调度表。如果你对 Windows 2000 下基本设备驱动程序的书写不太清楚,请查阅相关的书籍,此处不做介绍。我们先回顾一下 Win32 内核 API 的实现流程。Windows 2000 系统服务调用向用户提供了经过包装的用户模式的函数接口( 由 NTDLL.dll 提供)。当 Kernel32.dll/Advapi32.dll 中的函数执行时,先调用 NTDLL.dll 中对应的相关接口,经过参数检查后使

21、用 int 0x2e 指令进入内核模式,传递相关的服务号和参数列表。在 ntoskrnl.exe 中维护着两个表系统服务调度表(System Service Dispath Table)和系统服务参数表(System Service Parameter Table),其中 int 0x2e 指令就是通过服务号在 SSDT 中查询相关系统服务程序指针的。现在我们已经清楚了每个系统服务调用都对应一个服务号,同时也对应一个服务程序的地址!如果我们修改 SSDT 中的某个系统服务程序的入口地址为指向我们自定义的函数地址,在执行完我们的代码后再执行原始系统服务地址处的代码,这不就实现了对系统服务调用的了

22、 Hook 吗?对我们来说,定位系统服务调度表是实现 Hook 的关键。在 Windows 2000 中有一个未公开的由 ntoskrnl.exe 导出的单元:KeServiceDescriptorTable,我们可以通过它来完成对 SSDT 的访问与修改。 KeServiceDescriptorTable 对应于一个数据结构,定义如下:typedef struct SystemServiceDescriptorTableUINT *ServiceTableBase;UINT *ServiceCounterTableBase;UINT NumberOfService;UCHAR *Parame

23、terTableBase;SystemServiceDescriptorTable,*PSystemServiceDescriptorTable;其中 ServiceTableBase 指向系统服务程序的地址,ParameterTableBase 则指向 SSPT中的参数地址,它们都包含了 NumberOfService 这么多个单元。我们只要由 KeServiceDescriptorTable 找到了我们关注的系统服务调用程序,就可以修改它的 ServiceTableBase参数来实现对相关系统服务调用的 Hook 了!八 T-ProcMon-1.0 关键源码分析1. 基于 CUI 的用户模

24、式控制程序由于在此之前我已经对 Win32 的系统服务进行了详细的介绍,现在就不做多说了,大家如果有什么疑问请参阅我以前写的文章,你可以到 FZ5FZ 的主页(http:/www.fz5fz.org)阅读相关文章,或下载相关源代码。2. 基于设备驱动的 Hook 代码定义在用户模式与内核模式程序间通信的命令代码:#define PROCMON_MONITOR (ULONG) CTL_CODE(FILE_DEVICE_PROCMON,0x01,METHOD_BUFFERED,FILE_ANY_ACCESS)#define PROCMON_HIDDEN (ULONG) CTL_CODE(FILE_

25、DEVICE_PROCMON,0x02,METHOD_BUFFERED,FILE_ANY_ACCESS)#define PROCMON_HOOK (ULONG) CTL_CODE(FILE_DEVICE_PROCMON,0x03,METHOD_BUFFERED,FILE_ANY_ACCESS)#define PROCMON_UNHOOK (ULONG) CTL_CODE(FILE_DEVICE_PROCMON,0x04,METHOD_BUFFERED,FILE_ANY_ACCESS)将 KeServiceDescriptorTable 与相关数据结构联系起来,定义系统调用:_declspec(

26、dllimport) ServiceDescriptorTableEntry KeServiceDescriptorTable;#define SYSCALL(_function) KeServiceDescriptorTable.ServiceTableBase*(PULONG)(PUCHAR)_function+1)定义各种未公开的函数,如 ZwQuerySystemInformation:typedef NTSTATUS (*ZWQUERYSYSTEMINFORMATION)(IN ULONG SystemInformationClass,IN OUT PVOID SystemInfor

27、mation,IN ULONG SystemInformaitonLength,OUT PULONG ReturnLength OPTIONAL);修改系统服务调用,保存原始的入口地址,修改为我们自定义的程序入口地址,如 ZwQuerySystemInformation:OldZwQuerySystemInformation = (ZWQUERYSYSTEMINFORMATION)(SYSCALL(ZwQuerySystemInformation);_asm cli(ZWQUERYSYSTEMINFORMATION)(SYSCALL(ZwQuerySystemInformation) = Ne

28、wZwQuerySystemInformation;_asm sti解除钩子,还原系统服务调用:_asm cli(ZWQUERYSYSTEMINFORMATION)(SYSCALL(ZwQuerySystemInformation) = OldZwQuerySystemInformation;_asm sti调用原始的系统服务程序代码:NtStatus = (OldZwQuerySystemInformation)(SystemInformationClass,SystemInformation,SystemInformaitonLength,ReturnLength);隐藏进程,既是修改系统

29、返回的数据队列中相关项的偏移量使起指向需要隐藏进程的下一个单元,也就是说跳过我们需要隐藏进程的单元:if(RtlCompareUnicodeString(DbgPrint(“Hidden Process Name: %sn“,ProcNameA.Buffer);if(ProcPre != NULL)if(ProcCur-NextEntryDelta != 0)ProcPre-NextEntryDelta += ProcCur-NextEntryDelta;elseProcPre-NextEntryDelta = 0;elseif(ProcCur-NextEntryDelta != 0)SystemInformation = (PSYSTEM_PROCESSES)(PTSTR)ProcCur + ProcCur-NextEntryDelta);elseSystemInformation = NULL; break;-

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 大学课件

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报