在Windows中禁用LFH?

我正在寻找禁用我试图debugging的应用程序的LFH。 我能够重build和重新部署应用程序,但我不能附加debugging器或设置任何gflags。

用这些限制禁用LFH的好方法是什么? 有可能是我可以修改的可执行文件本身的属性? 或者我可以添加到程序的一些启动代码?

在Vista和Win7上,我认为可以使用应用程序兼容性工具包对每个可执行文件禁用低碎片堆。

在XP上, 文档建议你默认不会得到LFH 。 所以可能是你的C ++运行时库(你没有命名)打开它。 一旦启用,它就不能被禁用。 因此,请查看您的特定运行时库的文档,看看是否可以告诉它不启用LFH,或者如果有另一个版本的运行时库,则可以链接,但不启用它。

请参阅Microsoft论坛上的此主题

基于Michael Burr关于包含GlobalFlagSet的IMAGE_LOAD_CONFIG_DIRECTORY的评论,我写了下面的代码演示如何启用正确的GlobalFlag来禁用低碎片堆。 关于在编译时编写自己的IMAGE_LOAD_CONFIG_DIRECTORY的一个警告是,它会禁用SafeSEH。

 // editloadconfig.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <windows.h> #include <tchar.h> #include <stdio.h> /* typedef struct { DWORD Size; DWORD TimeDateStamp; WORD MajorVersion; WORD MinorVersion; DWORD GlobalFlagsClear; DWORD GlobalFlagsSet; DWORD CriticalSectionDefaultTimeout; DWORD DeCommitFreeBlockThreshold; DWORD DeCommitTotalFreeThreshold; DWORD LockPrefixTable; // VA DWORD MaximumAllocationSize; DWORD VirtualMemoryThreshold; DWORD ProcessHeapFlags; DWORD ProcessAffinityMask; WORD CSDVersion; WORD Reserved1; DWORD EditList; // VA DWORD SecurityCookie; // VA DWORD SEHandlerTable; // VA DWORD SEHandlerCount; } IMAGE_LOAD_CONFIG_DIRECTORY32, *PIMAGE_LOAD_CONFIG_DIRECTORY32; */ extern "C" IMAGE_LOAD_CONFIG_DIRECTORY _load_config_used = { 0x48, 0, 0, 0,0, 0x00000020/*enable heap free checking*/}; // change the last value to 0 to not enable any globalflags #define HEAP_STANDARD 0 #define HEAP_LAL 1 #define HEAP_LFH 2 #define SIZE 100 int _tmain(int argc, _TCHAR* argv[]) { BOOL bResult; HANDLE hHeap; ULONG HeapInformation; void* allocb[0x12+1]; // based on "Understanding the LFH" paper at // http://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=5&ved=0CE0QFjAE&url=http%3A%2F%2Fillmatics.com%2FUnderstanding_the_LFH.pdf&ei=GlBvT9yrMKHy0gGHpLnaBg&usg=AFQjCNGsvVtl54X7MWGyWYqiSrsdTBrbXQ int i = 0; for(i = 0; i < 0x12; i++) { printf("Allocation 0x%02x for 0x%02x bytes\n", i, SIZE); allocb[i] = HeapAlloc(GetProcessHeap(), 0x0, SIZE); } printf("Allocation 0x%02x for 0x%02x bytes\n", i++, SIZE); printf("\tFirst serviced by the LFH\n"); allocb[i] = HeapAlloc(GetProcessHeap(), 0x0, SIZE); // LFH is now activated so the query below will return 0 or 2. // sample code from MSDN for querying heap information // // Get a handle to the default process heap. // hHeap = GetProcessHeap(); if (hHeap == NULL) { _tprintf(TEXT("Failed to retrieve default process heap with LastError %d.\n"), GetLastError()); return 1; } // // Query heap features that are enabled. // bResult = HeapQueryInformation(hHeap, HeapCompatibilityInformation, &HeapInformation, sizeof(HeapInformation), NULL); if (bResult == FALSE) { _tprintf(TEXT("Failed to retrieve heap features with LastError %d.\n"), GetLastError()); return 1; } // // Print results of the query. // _tprintf(TEXT("HeapCompatibilityInformation is %d.\n"), HeapInformation); switch(HeapInformation) { case HEAP_STANDARD: _tprintf(TEXT("The default process heap is a standard heap.\n")); break; case HEAP_LAL: _tprintf(TEXT("The default process heap supports look-aside lists.\n")); break; case HEAP_LFH: _tprintf(TEXT("The default process heap has the low-fragmentation ") \ TEXT("heap enabled.\n")); break; default: _tprintf(TEXT("Unrecognized HeapInformation reported for the default ") \ TEXT("process heap.\n")); break; } return 0; } 

您可以使用WDK附带的gflags.exe工具(也可能是通过Windows调试工具包的SDK)来操作可执行映像的PE标头中的gflags子集。 只需进入“gflags.exe”中的“图像文件”标签。

正如jcopenha在评论中指出的那样,gflags.exe并不处理PE文件头(我依赖的是第9章的“堆调试功能”一节中的“Windows Internals,Fifth Edition”中的信息) – 显然它只是操作“图像文件执行选项”注册表项。

但是,可能仍然可以设置(或清除)图像中特定可执行文件的gflags位 – 请参阅IMAGE_LOAD_CONFIG_DIRECTORY结构的文档 ; 特别是GlobalFlagsClearGlobalFlagsSet字段:

  • GlobalFlagsClear – 控制系统行为的全局标志。 有关更多信息,请参阅Gflags.exe。
  • GlobalFlagsSet – 控制系统行为的全局标志。 有关更多信息,请参阅Gflags.exe。

您可以使用/loadconfig选项转储这些字段与dumpbin (或link /dump ):

 C:\temp>dumpbin /loadconfig test.exe Microsoft (R) COFF/PE Dumper Version 10.00.40219.01 Copyright (C) Microsoft Corporation. All rights reserved. Dump of file test.exe File Type: EXECUTABLE IMAGE Section contains the following load config: 00000048 size 0 time date stamp 0.00 Version 0 GlobalFlags Clear 0 GlobalFlags Set // <======= 0 Critical Section Default Timeout // remainder of dump snipped... 

您可以使用dumpbin /headers获取“加载配置目录”的RVA

 C:\temp>dumpbin /headers test.exe Microsoft (R) COFF/PE Dumper Version 10.00.40219.01 Copyright (C) Microsoft Corporation. All rights reserved. Dump of file test.exe // ... OPTIONAL HEADER VALUES // ... 142B0 [ 40] RVA [size] of Load Configuration Directory // ^^^^^ ^^^ // ... 

作为兴趣点, /loadconfig/headers选项不同意结构的大小(对于记录,它看起来像/header信息不正确)

不幸的是,我不知道直接支持这些字段的PE编辑器 – 您可能必须使用十六进制编辑器(或PE编辑器的十六进制编辑功能)来更改这些字段。 IMAGE_LOAD_CONFIG_DIRECTORY结构的RVA应该可以帮助您在十六进制编辑器中找到它。

我相信在图像头中设置一个或多个堆调试标志(可能是其中的任何一个,但您可能需要试验)将禁用低碎片堆。 但是我还没有测试过在这些字段中设置位是否有效。 如果你尝试这个,请告诉我们它的票价。

如果无法更改机器上的配置,最简单的方法是设置堆信息。

http://msdn.microsoft.com/en-us/library/windows/desktop/aa366705(v=vs.85).aspx

我相信你可以以这种方式编程禁用LFH堆,虽然我还没有尝试过。