Phe*_*nom 46 windows-7 hibernate
我无法在 Windows 7 中启用休眠,因为我的 C: 驱动器上没有足够的空间来创建休眠文件。如何让 Windows 将文件放在其他地方?
Sna*_*ark 42
你不能,它必须在引导驱动器的根目录中(在你的情况下是 C: 驱动器)。
Raymond Chen 在这篇 Windows 机密文章中解释了原因:文件系统悖论。
休眠遵循类似的模式。使操作系统休眠意味着将内存的全部内容转储到休眠文件中;从休眠状态恢复需要将该文件吸回内存并假装什么也没发生。同样,这是另一个鸡与蛋的问题:要加载休眠文件,您需要文件系统驱动程序,但文件系统驱动程序在休眠文件中。如果将休眠文件保存在引导驱动器的根目录中,则可以使用微型文件系统驱动程序。
好的,移动 hiberfil.sys 需要解决两件事
告诉作为进程“系统”运行的“ntoskrnl.exe”将休眠数据打开/保存到 D:\hiberfil.sys 而不是 C:\ -> 尚未解决!
将此机会也应用于启动配置数据文件 (c:\BOOT\BCD) -> 使用 VisualBCD 之类的工具相对容易https://www.boyans.net/DownloadVisualBCD.html -> 甚至只使用 regedit编辑 HKLM\BCD00000000\Objects{71575733-c376-11e4-80ea-806e6f6e6963}\Elements\21000001 即 ResumeLoader 的 HiberFileDrive 或 \22000002 HiberFilePath。也许你需要使用 'File/Load hive' c:\BOOT\BCD 来挂载 'BCD00000000' 分支。(光标需要在 HKLM 上,否则菜单项是灰色的) -> 因为看起来这已经完成了通过 ntosknl.exe,因此无需更改此设置,因为您的更改将被覆盖。
然而,1. 是更糟糕、更难以改变的事情。嗯,让我们将 ntoskrnl.exe 加载到 IDA 并找到处理 /hiberfil.sys 的函数并反编译它以查看那里到底发生了什么......
__int64 __fastcall PopCreateHiberFile(LARGE_INTEGER *a1)
{
...
RtlInitUnicodeString(&Source, L"\\hiberfil.sys");
...
RtlAppendUnicodeStringToString(&Destination, &IoArcBootDeviceName);
RtlAppendUnicodeStringToString(&Destination, &Source);
...
ObjectAttributes.RootDirectory = 0i64;
ObjectAttributes.Attributes = 576;
ObjectAttributes.ObjectName = &Destination;
ObjectAttributes.SecurityDescriptor = v5;
ObjectAttributes.SecurityQualityOfService = 0i64;
ret_2 = IoCreateFile(
&FileHandle,
0x100003u,
&ObjectAttributes,
...
Run Code Online (Sandbox Code Playgroud)
好吧,简而言之,路径是这样硬编码的: IoArcBootDeviceName + "\hiberfil.sys" 没有一些讨厌的二进制补丁,没有办法改变它。好吧,除了接触神圣的窗口之外,修补“ntoskernel”可能会导致诸如更新撤消补丁或防病毒程序可能会变得疯狂等问题……但是让我们看看对 IoArcBootDeviceName 的引用是什么:
IopLoadCrashdumpDriver PopDeleteHiberFile PopCreateHiberFile PopBcdSetupResumeObject PopBcdSetDefaultResumeObjectElements PopBcdSetPendingResume PopBcdRegenerateResumeObject PopBcdEstablishResumeObject PopAllocateHiberContext IopCreateArcNames PopBcdSetupResumeObject
哇,改变这似乎很好(唯一有点不正常的是 IopLoadCrashdumpDriver System32\Drivers\crashdmp.sys 但是谁需要崩溃转储 - 如果我们在那里破坏一些东西并不重要)
所以修补IopCreateArcNames创建ArcBootDeviceName将被罚款:
NTSTATUS INIT_FUNCTION NTAPI IopCreateArcNames ( IN PLOADER_PARAMETER_BLOCK LoaderBlock )
...
/* Create the global system partition name */
63 sprintf(Buffer, "\\ArcName\\%s", LoaderBlock->ArcBootDeviceName);
64 RtlInitAnsiString(&ArcString, Buffer);
65 RtlAnsiStringToUnicodeString(&IoArcBootDeviceName, &ArcString, TRUE);
66
67 /* Allocate memory for the string */
68 Length = strlen(LoaderBlock->ArcBootDeviceName) + sizeof(ANSI_NULL);
69 IoLoaderArcBootDeviceName = ExAllocatePoolWithTag(PagedPool,
70 Length,
71 TAG_IO);
72 if (IoLoaderArcBootDeviceName)
73 {
74 /* Copy the name */
75 RtlCopyMemory(IoLoaderArcBootDeviceName,
76 LoaderBlock->ArcBootDeviceName,
77 Length);
78 }
...
Run Code Online (Sandbox Code Playgroud)
https://doxygen.reactos.org/d3/d82/ntoskrnl_2io_2iomgr_2arcname_8c.html 顺便说一句,我正在使用 Win7 64 位的 ntkrnlmp.exe 6.1.7601.19045 并针对 ReactOS 检查了此代码。(然而,休眠部分尚未在 Reactos 源代码中实现) 请注意 ArcBootDeviceName 将类似于:\Device\Harddisk1\Partition0
嗯,让我们将 ArcBootDeviceName(LoaderBlock + 0x78) 修补为 ArcHalDeviceName(LoaderBlock + 0x80)
因此,如果 bootmgr 加载程序位于与 windows 不同的分区上,希望 hibernate.sys 是 bootmgr 所创建的。
1405A9C15 4C 8B 4B 78 mov r9, [rbx+78h]
Patch #1 80
1405A9C19 4C 8D 05 30 06+ lea r8, aArcnameS ; "\\ArcName\\%s"
1405A9C20 48 8D 4C 24 40 lea rcx, [rsp+0D8h+pszDest] ; pszDest
1405A9C25 48 8B D7 mov rdx, rdi ; cchDest
1405A9C28 E8 E3 AE B6 FF call RtlStringCchPrintfA
...
1405A9C41 48 8D 0D C0 E7+ lea rcx, IoArcBootDeviceName ; DestinationString
1405A9C48 41 B0 01 mov r8b, 1 ; AllocateDestinationString
1405A9C4B E8 60 13 DB FF call RtlAnsiStringToUnicodeString
1405A9C50 48 8B 7B 78 mov rdi, [rbx+78h]
Patch #2 80
Run Code Online (Sandbox Code Playgroud)
因此,在 ntoskrnl.exe 中,在两个位置将 4C8B4B78 替换为 4C8B4B80。之后不要忘记修复 PE-Checksum。
| 归档时间: |
|
| 查看次数: |
65763 次 |
| 最近记录: |