Windows上的ntoskrnl.exe学习
一、概念
ntoskrnl.exe(Windows 启动内核)是用于基于 NT 的 Microsoft 操作系统的启动过程中的重要组件。它还负责一系列系统服务,例如进程和内存管理、安全管理、对象管理、硬件虚拟化等。它包含几个子系统:缓存管理器、I/O 管理器、配置管理器、本地过程调用、内存管理器、进程结构、对象管理器和安全引用监视器。它们共同构成执行服务和系统服务的一部分。由于这些关键职责,ntoskrnl.exe 是 Windows 操作系统的基本组成部分。
在基于 NT 的 Windows 操作系统中,ntoskrnl.exe 是内核模式的一部分。内核模式可以完全访问系统的硬件和软件组件。它充当用户模式服务和应用程序与系统关键模块之间的中介。如果需要执行任何重要操作,用户模式服务和应用程序必须利用内核模式与系统关键模块间接通信。内核模式包含执行服务、内核、内核驱动程序和硬件抽象层 (HAL)。
输入输出管理器:I/O 管理器授权设备与用户模式子系统进行通信。它将用户模式读取和写入命令解释为读取和写入 IRP,然后将其传递给设备驱动程序。
流程结构:进程结构负责进程和线程的形成和终止。它应用了 Job 的概念,它是可以作为一个整体停止或置于共享限制下的进程的集合。
二、其导出函数
1.进程创建监控
PsSetCreateProcessNotifyRoutine / PsSetCreateProcessNotifyRoutineEx
NTSTATUS PsSetCreateProcessNotifyRoutine( [in] PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine, [in] BOOLEAN Remove );
NotifyRoutine指向一个函数,用于回调,当操作系统中创建新进程时,操作系统将调用此回调函数。
Remove指定是从回调函数列表中删除还是添加该回调函数,若为TRUE,则删除指定回调函数;反之,则添加。
回调函数定义:
PCREATE_PROCESS_NOTIFY_ROUTINE PcreateProcessNotifyRoutine; void PcreateProcessNotifyRoutine( [in] HANDLE ParentId, [in] HANDLE ProcessId, [in] BOOLEAN Create ) {...}
2.模块加载监控
PsSetLoadImageNotifyRoutine / PsSetLoadImageNotifyRoutineEx
NTSTATUS PsSetLoadImageNotifyRoutine( [in] PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine );
NotifyRoutine指向一个函数,用于回调,当系统中加载驱动模块和dll模块时,操作系统将调用此回调函数。
回调函数定义:
PLOAD_IMAGE_NOTIFY_ROUTINE PloadImageNotifyRoutine; void PloadImageNotifyRoutine( [in, optional] PUNICODE_STRING FullImageName, [in] HANDLE ProcessId, [in] PIMAGE_INFO ImageInfo ) {...}
ImageInfo指向包含执行映像信息的结构体。
typedef struct _IMAGE_INFO { union { ULONG Properties; struct { ULONG ImageAddressingMode : 8; ULONG SystemModeImage : 1; ULONG ImageMappedToAllPids : 1; ULONG ExtendedInfoPresent : 1; ULONG MachineTypeMismatch : 1; ULONG ImageSignatureLevel : 4; ULONG ImageSignatureType : 3; ULONG ImagePartialMap : 1; ULONG Reserved : 12; }; }; PVOID ImageBase; ULONG ImageSelector; SIZE_T ImageSize; ULONG ImageSectionNumber; } IMAGE_INFO, *PIMAGE_INFO;
3.SetWindowsHookEx的实现
SetWindowsHookEx由win32u.dll中的NtUserSetWindowsHookEx函数实现,而该函数最终会调用系统调用号为0x1089的syscall。
4.创建线程的实现
CreateThread函数是由CreateRemoteThread函数实现的。CreateRemoteThread函数是由NtCreateThreadEx函数实现的。
所以,无论是CreateThread函数,还是CreateRemoteThread函数,最终都是调用NtCreateThreadEx函数创建线程(也就是ZwCreateThreadEx函数)。
ZwCreateThreadEx函数调用系统调用号为0xC1的syscall。
4.创建进程的实现
恶意样本中常用来启动恶意进程的方法有:WinExec、ShellExecute,以及CreateProcess。其中,CreateProcess函数是基于CreateProcessInternalW函数实现的,而该函数是由NtCreateUserProcess函数或NtVdm64CreateProcessInternalW函数实现的。
在创建进程的过程中,除了会调用Etw相关API进行记录外,还会对父进程的进程信息进行检查,这就会用到FS或GS寄存器的信息。
关于FS与GS寄存器值的介绍如下:
32位程序使用FS寄存器: FS:[0x00] : Current SEH Frame FS:[0x18] : TEB (Thread Environment Block) FS:[0x20] : PID FS:[0x24] : TID FS:[0x30] : PEB (Process Environment Block) FS:[0x34] : Last Error Value 64位程序使用GS寄存器: GS:[0x20] : PRCB GS:[0x30] : TEB GS:[0x40] : PID GS:[0x48] : TID GS:[0x60] : PEB GS:[0x188]:_ethread
(未完待续)
参考
https://eprajesh.wordpress.com/2012/05/03/what-is-ntoskrnl-exe/