Beginning with Windows Server 2008 and Windows Vista, there are components, such as the Windows Security Center, that will only execute code from a Portable Executable (PE) image if the IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY flag is set in the PE header. When the flag is set, Windows verifies the digital signature of the image prior to loading the image. The PE image will fail to load if the signature cannot be verified. This can occur if the image contains an uninitialized data section, and the PointerToRawData field in the section header for this section is set to a nonzero value.
This failure may occur when using a third-party linker that does not follow the Microsoft Portable Executable and Common Object File Format Specification.
This article describes how to identify this issue and provides both a procedure and example code that update PointerToRawData field values.
When the IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY flag is set, Windows verifies the digital signature of the PE image prior to loading it.
If there is an error generated from verifying the PE image signature, Windows fails to load the image and logs an event.
For each event with Event ID 3002, check the file path in the event description to determine whether it matches the file path of your PE image.
Developers can set the PointerToRawData field to zero by using a binary editor as follows. A Binary Editor is available in Visual Studio.
Note After updating the PointerToRawData field, the PE Header checksum will no longer be valid. However signing the file will set the PE Header checksum to a valid state.
The following example shows how to detect nonzero PointerToRawData fields for uninitialized data sections and set these fields to zero.
// Copyright (c) Microsoft Corporation. All rights reserved. // // Description: // // This example shows how to load a PE image, find the // section headers for all sections containing only uninitialized // data, set nonzero values in the section header PointerToRawData // field to zero, and recalculate the PE header checksum. // // Build Instructions: // // Link with Imagehlp.lib // #include <windows.h> #include <stdio.h> #include <psapi.h> #include <imagehlp.h> BOOL FixPeHeaderOnFile(const wchar_t *szFile) { HANDLE hFile = INVALID_HANDLE_VALUE; HANDLE hMapping = NULL; PVOID pvMap = NULL; PIMAGE_NT_HEADERS pHeader = NULL; ULONG NumberOfSections; ULONG OffsetToSectionTable; PIMAGE_SECTION_HEADER SectionTableEntry; DWORD cbFileSize; DWORD dwPriorCheckSum; DWORD dwNewCheckSum; DWORD dwLastError = ERROR_SUCCESS; BOOL fSuccess = FALSE; hFile = CreateFile(szFile, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if(hFile == INVALID_HANDLE_VALUE) { dwLastError = GetLastError(); goto cleanup; } hMapping = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL); if(hMapping == NULL) { dwLastError = GetLastError(); goto cleanup; } pvMap = MapViewOfFile(hMapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0); if(pvMap == NULL) { dwLastError = GetLastError(); goto cleanup; } pHeader = ImageNtHeader( pvMap ); if(pHeader == NULL) { dwLastError = GetLastError(); goto cleanup; } // Sections where the section header SizeOfRawData field is zero contain // only uninitialized data. // // Look for sections that have SizeOfRawData == 0, and PointerToRawData !=0. // NumberOfSections = pHeader->FileHeader.NumberOfSections; OffsetToSectionTable = FIELD_OFFSET (IMAGE_NT_HEADERS, OptionalHeader) + pHeader->FileHeader.SizeOfOptionalHeader; SectionTableEntry = (PIMAGE_SECTION_HEADER)((PCHAR)pHeader + OffsetToSectionTable); while (NumberOfSections > 0) { // // Where the SizeOfRawData is zero, but the PointerToRawData is not // zero, set PointerToRawData to zero. // if ((SectionTableEntry->SizeOfRawData == 0) && (SectionTableEntry->PointerToRawData != 0)) { printf("Fixing up a section\n"); SectionTableEntry->PointerToRawData = 0; } SectionTableEntry += 1; NumberOfSections -= 1; }; // // Update the OptionalHeader.CheckSum field. // cbFileSize = GetFileSize(hFile, NULL); if(cbFileSize == INVALID_FILE_SIZE) { dwLastError = GetLastError(); goto cleanup; } if(CheckSumMappedFile(pvMap, cbFileSize, &dwPriorCheckSum, &dwNewCheckSum) == NULL) { dwLastError = GetLastError(); goto cleanup; } pHeader->OptionalHeader.CheckSum = dwNewCheckSum; fSuccess = TRUE; cleanup: if(pvMap) { UnmapViewOfFile(pvMap); } if(hMapping) { CloseHandle(hMapping); } if(hFile != INVALID_HANDLE_VALUE) { CloseHandle(hFile); } if(!fSuccess) { char *szErrText = NULL; BOOL fFreeError = TRUE; if (FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwLastError, 0, (char *)&szErrText, 16, NULL ) == 0) { szErrText = "Unknown error"; fFreeError = FALSE; } printf("%s: Can't open file error %x: %s\n", szFile, dwLastError, szErrText); if(fFreeError) { LocalFree(szErrText); } SetLastError(dwLastError); } return fSuccess; } int __cdecl wmain(int argc, wchar_t **argv) { int i; errno_t err; if (argc == 1) { printf("pefix [files... | @filelist]\n"); return 1; } for(i=1;i<argc;i++) { if (argv[i][0] == '@') { FILE *f; wchar_t name[MAX_PATH+1] = {0}; err = _wfopen_s(&f,argv[i] + 1,L"r"); if(err != 0 || f == NULL) { printf("Unable to open filelist %s\n", argv[i]+1); } else { while(fgetws(name,MAX_PATH-1,f)) { name[wcslen(name)-1]=0; if (wcslen(name) > 0) { FixPeHeaderOnFile(name); } } fclose(f); } } else { FixPeHeaderOnFile(argv[i]); } } }
See the Linker Options topic on MSDN for more information on using the link.
Carsten Siemens edited Revision 5. Comment: Added tag: has See Also
Ed Price MSFT edited Revision 1. Comment: Added the "How to" template.
Ed Price MSFT edited Revision 2. Comment: Updated title case.
Ed Price MSFT edited Revision 3. Comment: Minor edit. And added the "See Also" section.
Easy
What if the db table crash ?
Good Article.