如何在 Windows 7 中更改休眠文件的位置?

如何在 Windows 7 中更改休眠文件的位置?

我无法在 Windows 7 中启用休眠功能,因为我的 C: 驱动器上没有足够的空间来创建休眠文件。我该如何让 Windows 将文件放在其他地方?

答案1

不能,它必须位于启动驱动器的根目录中(在您的情况下为 C: 驱动器)。

Raymond Chen 在 Windows Confidential 文章中解释了原因:文件系统悖论

休眠遵循类似的模式。休眠操作系统意味着将内存中的所有内容转储到休眠文件中;从休眠状态恢复则需要将该文件重新吸入内存并假装什么都没发生。同样,这又是一个先有鸡还是先有蛋的问题:要加载休眠文件,您需要文件系统驱动程序,但文件系统驱动程序位于休眠文件中。如果您将休眠文件保存在启动驱动器的根目录中,则可以改用微型文件系统驱动程序。

答案2

好的,要移动 hiberfil.sys,需要解决 2 件事

  1. 告诉作为进程“系统”运行的“ntoskrnl.exe”打开/保存休眠数据到 D:\hiberfil.sys 而不是 C:\-> 尚未解决!

  2. 要将此机会也应用于启动配置数据文件 (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 完成,所以没有必要再进行更改,因为更改将被覆盖。

但是第一种情况更糟糕,也更难改变。嗯,让我们将 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,
...

好的,简而言之,路径是硬编码的,如下所示: IoArcBootDeviceName + “\hiberfil.sys” 没有一些讨厌的二进制修补,就没有办法改变这一点。除了触及圣杯之外,修补“ntoskernel”可能会导致更新撤消补丁或防病毒程序可能变得疯狂等问题……但是让我们看看对 IoArcBootDeviceName 的引用是什么:

IopLoadCrashdumpDriver PopDeleteHiberFile PopCreateHiberFile PopBcdSetupResumeObject PopBcdSetDefaultResumeObjectElements PopBcdSetPendingResume PopBcdRegenerateResumeObject PopBcdEstablishResumeObject PopAllocateHiberContext IopCreateArcNames PopBcdSetupResumeObject

哇,改变这个似乎没问题(唯一有点不对劲的是 IopLoadCrashdumpDriver System32\Drivers\crashdmp.sys,但是谁需要崩溃转储 - 如果我们在那里破坏了某些东西也没关系)

因此修补创建弧名称创造ArcBoot设备名称会没事的:

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     }

...

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

因此,在 ntoskrnl.exe 中的两个位置将 4C8B4B78 替换为 4C8B4B80。之后不要忘记修复 PE-Checksum。

相关内容