reactos操作系统实现(84)

在系统里User32.dllkernel32.dllshell32.dllgdi32.dllrpcrt4.dllcomctl32.dlladvapi32.dllversion.dlldll代表了Win32 API的基本提供者。Win32 API中的所有调用最终都转向了ntdll.dll,再由它转发至ntoskrnl.exentdll.dll是本机 API用户模式的终端。真正的接口在ntoskrnl.exe里完成。事实上,内核模式的驱动大部分时间调用这个模块,如果它们请求系统服务。Ntdll.dll的主要作用就是让内核函数的特定子集可以被用户模式下运行的程序调用。Ntdll.dll通过软件中断int 2Eh进入ntoskrnl.exe,就是通过中断门切换CPU特权级。比如kernel32.dll导出的函数DeviceIoControl()实际上调用ntdll.dll中导出的NtDeviceIoControlFile(),反汇编一下这个函数可以看到,EAX载入magic0x38,实际上是系统调用号,然后EDX指向堆栈。目标地址是当前堆栈指针ESP+4,所以EDX指向返回地址后面一个,也就是指向在进入NtDeviceIoControlFile()之前存入堆栈的东西。事实上就是函数的参数。下一个指令是int 2Eh,转到中断描述符表IDT位置0x2E处的中断处理程序。

下面就来分析怎么样加载NTDLL.DLL,具体实现代码始下:

#001 NTSTATUS

#002 NTAPI

#003 PsLocateSystemDll(VOID)

#004 {

#005 OBJECT_ATTRIBUTES ObjectAttributes;

#006 IO_STATUS_BLOCK IoStatusBlock;

#007 HANDLE FileHandle, SectionHandle;

#008 NTSTATUS Status;

#009 ULONG_PTR HardErrorParameters;

#010 ULONG HardErrorResponse;

#011

初始化NTDLL.DLL的对象,其中PsNtDllPathName是它的名称//SystemRoot//system32//ntdll.dll。在前面已经把系统路径设置好了。

#012 /* Locate and open NTDLL to determine ImageBase and LdrStartup */

#013 InitializeObjectAttributes(&ObjectAttributes,

#014 &PsNtDllPathName,

#015 0,

#016 NULL,

#017 NULL);

打开文件NTDLL.DLL

#018 Status = ZwOpenFile(&FileHandle,

#019 FILE_READ_ACCESS,

#020 &ObjectAttributes,

#021 &IoStatusBlock,

#022 FILE_SHARE_READ,

#023 0);

#024 if (!NT_SUCCESS(Status))

#025 {

#026 /* Failed, bugcheck */

#027 KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED, Status, 2, 0, 0);

#028 }

#029

检查NTDLL.DLL文件是否合法。

#030 /* Check if the image is valid */

#031 Status = MmCheckSystemImage(FileHandle, TRUE);

#032 if (Status == STATUS_IMAGE_CHECKSUM_MISMATCH)

#033 {

#034 /* Raise a hard error */

#035 HardErrorParameters = (ULONG_PTR)&PsNtDllPathName;

#036 NtRaiseHardError(Status,

#037 1,

#038 1,

#039 &HardErrorParameters,

#040 OptionOk,

#041 &HardErrorResponse);

#042 return Status;

#043 }

#044

NTDLL.DLL文件创建代码和数据段。

#045 /* Create a section for NTDLL */

#046 Status = ZwCreateSection(&SectionHandle,

#047 SECTION_ALL_ACCESS,

#048 NULL,

#049 NULL,

#050 PAGE_EXECUTE,

#051 SEC_IMAGE,

#052 FileHandle);

#053 ZwClose(FileHandle);

#054 if (!NT_SUCCESS(Status))

#055 {

#056 /* Failed, bugcheck */

#057 KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED, Status, 3, 0, 0);

#058 }

#059

添加引用段对象。

#060 /* Reference the Section */

#061 Status = ObReferenceObjectByHandle(SectionHandle,

#062 SECTION_ALL_ACCESS,

#063 MmSectionObjectType,

#064 KernelMode,

#065 (PVOID*)&PspSystemDllSection,

#066 NULL);

#067 ZwClose(SectionHandle);

#068 if (!NT_SUCCESS(Status))

#069 {

#070 /* Failed, bugcheck */

#071 KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED, Status, 4, 0, 0);

#072 }

#073

NTDLL.DLL映射到内核空间。PspSystemDllBase是动态连接库的基地址。

#074 /* Map it */

#075 Status = PspMapSystemDll(PsGetCurrentProcess(), &PspSystemDllBase, FALSE);

#076 if (!NT_SUCCESS(Status))

#077 {

#078 /* Failed, bugcheck */

#079 KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED, Status, 5, 0, 0);

#080 }

#081

#082 /* Return status */

#083 return Status;

#084 }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值