c ++ - Deaktiver LFH i Windows?

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg søger at deaktivere LFH til et program, jeg forsøger at fejle. Jeg kan genopbygge og omfordele applikationen, men jeg kan ikke vedhæfte en debugger eller sætte nogen gflags.


Hvad er en god måde at deaktivere LFH på med disse begrænsninger? Er der måske en egenskab, jeg kan ændre på den eksekverbare selv? Eller nogle opstartskoder, jeg kan tilføje til programmet?

Bedste reference


På Vista og Win7 tror jeg, at du kan deaktivere Low-Fragmentation Heap på et eksekverbart grundlag med Application Compatibility Toolkit.


På XP foreslår dokumentationen, at du ikke får en LFH som standard. Så sandsynligvis er det dit C ++ runtime bibliotek (som du ikke har heddet), der tænder det. Og det kan ikke deaktiveres, når det er aktiveret. Så kontroller dokumentationen for dit bestemte runtime bibliotek for at se, om du kan fortælle om ikke at aktivere LFH, eller hvis der er en anden version af det runtime bibliotek, du kan linke med, gør det ikke muligt. [17] [18]


Se også denne tråd på Microsoft forums [19]

Andre referencer 1


Baseret på Michael Burrs kommentar ovenfor om IMAGE\_LOAD\_CONFIG\_DIRECTORY indeholdende GlobalFlagSet skrev jeg følgende kode for at demonstrere, at den korrekte GlobalFlag kunne deaktivere Low Fragmentation Heap. En advarsel om at skrive din egen IMAGE\_LOAD\_CONFIG\_DIRECTORY på kompileringstid er, at den deaktiverer 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
", i, SIZE); 
        allocb[i] = HeapAlloc(GetProcessHeap(), 0x0, SIZE); 
   }

   printf("Allocation 0x\%02x for 0x\%02x bytes
", i++, SIZE); 
   printf("	First serviced by the LFH
"); 
   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.
"),
                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.
"),
                GetLastError());
       return 1;
   }

   //
   // Print results of the query.
   //
   \_tprintf(TEXT("HeapCompatibilityInformation is \%d.
"), HeapInformation);
   switch(HeapInformation)
   {
   case HEAP\_STANDARD:
       \_tprintf(TEXT("The default process heap is a standard heap.
"));
       break;
   case HEAP\_LAL:
       \_tprintf(TEXT("The default process heap supports look-aside lists.
"));
       break;
   case HEAP\_LFH:
       \_tprintf(TEXT("The default process heap has the low-fragmentation ") 
                TEXT("heap enabled.
"));
       break;
   default:
       \_tprintf(TEXT("Unrecognized HeapInformation reported for the default ") 
                TEXT("process heap.
"));
       break;
    }

   return 0; 
}

Andre referencer 2


Du kan bruge værktøjet gflags.exe, som er inkluderet i WDK'en (måske også SDK'en via Debugging Tools for Windows-pakken) til at manipulere en delmængde af gflags i det eksekverbare billede 's PE header. Gå bare til fanen 'Billedfil' i 'gflags.exe'.


Som påpeget af jcopenha i en kommentar, ser det ud til gflags.exe manipulerer ikke PE-filoverskriften (jeg var afhængig af oplysninger fra 'Windows Internals, 5. udgave' i kapitel 9 's' Heap Debugging Features '-afsnittet) - tilsyneladende det manipulerer kun registreringsdatabasenøglen 'Image File Execution Options'.


Det kan dog stadig være muligt at indstille (eller rydde) gflags-bitene til en bestemt eksekverbar i billedet - se docs for strukturen IMAGE\_LOAD\_CONFIG\_DIRECTORY; især felterne GlobalFlagsClear og GlobalFlagsSet: [20]



  • GlobalFlagsClear - De globale flag, der styrer systemadfærd. For mere information, se Gflags.exe.

  • GlobalFlagsSet - De globale flag, der styrer systemadfærd. For mere information, se Gflags.exe.



Du kan dumpe disse felter med dumpbin (eller link /dump) ved hjælp af indstillingen /loadconfig:


C:	emp>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...


Du kan få RVA af 'Load Configuration Directory' ved hjælp af dumpbin /headers:


C:	emp>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
//         ^^^^^            ^^^
// ...


Som et interessepunkt er alternativet /loadconfig og /headers uenig om størrelsen af ​​strukturen (for posten ser det ud til, at /header info ikke er korrekt)


Desværre er jeg ikke klar over PE editor, der direkte understøtter disse felter - du skal nok bruge en hex editor (eller hex redigeringsfunktionen i en PE editor) for at ændre disse felter. RVA i strukturen IMAGE\_LOAD\_CONFIG\_DIRECTORY skal hjælpe dig med at finde den i hex-editoren.


Jeg tror, ​​at indstilling af et eller flere af de bunkefejlflagge i billedoverskriften (måske nogen af ​​dem, men du skal muligvis eksperimentere) deaktiverer den lave fragmenteringshøje. Men jeg har ikke testet, om det ikke er muligt at indstille bits i disse felter rent faktisk fungerer. Hvis du prøver det, så lad os vide, hvordan det går.

Andre referencer 3


Den enkleste måde, hvis du ikke kan ændre konfigurationen på maskinen, er at indstille bunkeinformationen.


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


Jeg tror, ​​at du kan deaktivere LFH-bunken programmatisk på denne måde, selvom jeg ikke har prøvet det.