2 *pesect.c - PE image header routines
4 * Copyright (c) Microsoft Corporation. All rights reserved.
7 * Defines routines that query info from a PE image header. Because
8 * one of these queries the current PE image, via the linker-defined
9 * variable __ImageBase, this object must be a static-link component
10 * of any C Runtime library.
12 *******************************************************************************/
16 #if defined (_WIN64) && defined (_M_IA64)
17 #pragma section(".base", long, read)
18 __declspec(allocate(".base"))
19 extern IMAGE_DOS_HEADER __ImageBase
;
20 #else /* defined (_WIN64) && defined (_M_IA64) */
21 extern IMAGE_DOS_HEADER __ImageBase
;
22 #endif /* defined (_WIN64) && defined (_M_IA64) */
24 #pragma optimize("t", on) // optimize for speed, not space
27 *BOOL _ValidateImageBase
30 * Check if a PE image is located at a potential image base address.
33 * pImageBase - pointer to potential PE image in memory
36 * TRUE PE image validated at pImageBase
37 * FALSE PE image not found
39 *******************************************************************************/
41 BOOL __cdecl
_ValidateImageBase(
45 PIMAGE_DOS_HEADER pDOSHeader
;
46 PIMAGE_NT_HEADERS pNTHeader
;
47 PIMAGE_OPTIONAL_HEADER pOptHeader
;
49 pDOSHeader
= (PIMAGE_DOS_HEADER
)pImageBase
;
50 if (pDOSHeader
->e_magic
!= IMAGE_DOS_SIGNATURE
)
55 pNTHeader
= (PIMAGE_NT_HEADERS
)((PBYTE
)pDOSHeader
+ pDOSHeader
->e_lfanew
);
56 if (pNTHeader
->Signature
!= IMAGE_NT_SIGNATURE
)
61 pOptHeader
= (PIMAGE_OPTIONAL_HEADER
)&pNTHeader
->OptionalHeader
;
62 if (pOptHeader
->Magic
!= IMAGE_NT_OPTIONAL_HDR_MAGIC
)
71 *PIMAGE_SECTION_HEADER _FindPESection
74 * Given an RVA (Relative Virtual Address, the offset from the Image Base
75 * for a PE image), determine which PE section, if any, includes that RVA.
78 * pImageBase - pointer to PE image in memory
79 * rva - RVA whose enclosing section is to be found
82 * NULL RVA is not part by any section in the PE image
83 * non-NULL Pointer to IMAGE_SECTION_HEADER describing the section holding
86 *******************************************************************************/
88 PIMAGE_SECTION_HEADER __cdecl
_FindPESection(
93 PIMAGE_NT_HEADERS pNTHeader
;
94 PIMAGE_SECTION_HEADER pSection
;
95 unsigned int iSection
;
99 (pImageBase
+ ((PIMAGE_DOS_HEADER
)pImageBase
)->e_lfanew
);
102 // Find the section holding the desired address. We make no assumptions
103 // here about the sort order of the section descriptors (though they
104 // always appear to be sorted by ascending section RVA).
106 for (iSection
= 0, pSection
= IMAGE_FIRST_SECTION(pNTHeader
);
107 iSection
< pNTHeader
->FileHeader
.NumberOfSections
;
108 ++iSection
, ++pSection
)
110 if (rva
>= pSection
->VirtualAddress
&&
111 rva
< pSection
->VirtualAddress
+ pSection
->Misc
.VirtualSize
)
127 *BOOL _IsNonwritableInCurrentImage
130 * Check if an address is located within the current PE image (the one
131 * starting at __ImageBase), that it is in a proper section of the image,
132 * and that section is not marked writable. This routine must be
133 * statically linked, not imported from the CRT DLL, so the correct
134 * __ImageBase is found.
137 * pTarget - address to check
140 * 0 Address is either not in current image, not in a section, or
141 * in a writable section.
142 * non-0 Address is in a non-writable section of the current image.
144 *******************************************************************************/
146 BOOL __cdecl
_IsNonwritableInCurrentImage(
152 PIMAGE_SECTION_HEADER pSection
;
154 pImageBase
= (PBYTE
)&__ImageBase
;
158 // Make sure __ImageBase does address a PE image. This is likely an
159 // unnecessary check, since we should be running from a normal image,
160 // but it is fast, this routine is rarely called, and the normal call
161 // is for security purposes. If we don't have a PE image, return
164 if (!_ValidateImageBase(pImageBase
))
170 // Convert the targetaddress to a Relative Virtual Address (RVA) within
171 // the image, and find the corresponding PE section. Return failure if
172 // the target address is not found within the current image.
174 rvaTarget
= pTarget
- pImageBase
;
175 pSection
= _FindPESection(pImageBase
, rvaTarget
);
176 if (pSection
== NULL
)
182 // Check the section characteristics to see if the target address is
183 // located within a writable section, returning a failure if yes.
185 return (pSection
->Characteristics
& IMAGE_SCN_MEM_WRITE
) == 0;
187 __except (GetExceptionCode() == STATUS_ACCESS_VIOLATION
)
190 // Just return failure if the PE image is corrupted in any way that