PE file format detailed (5)

zhaozj2021-02-16  49

Predefined segment

A Windows NT application typically has 9 predefined segments, which are .Text, .bss, .rdata, .data, .rsrc, .edata, .idata, .pdata and .debug. Some applications don't need all of them, and there are also some applications to define more segments for their own special needs. This approach is similar to code segments and data segments in MS-DOS and Windows 3.1. In fact, the application defines a unique segment to use a standard compiler to indicate naming for code segments and data segments, or use Name Section Compiler Options -NT - and WINDOWS 3.1 Display Unique Code Segment and data segments are the same. The following is a discussion of some interesting public segments among the Windows NT PE files.

Executable code segment, .text

One difference between Windows 3.1 and Windows NT is that Windows NT default is to form a separate segment (as they mentioned in Windows 3.1), named ".text". Since Windows NT uses a page-based virtual memory management system, it is not wise to put separate code in different segments. Therefore, it is very convenient to have a large code segment for operating systems and application developers. The .TEXT segment also contains the early mentioned entry points. IAT also exists before the .Text paragraph of the module entry point. (IAT is very meaningful in .Text paragraphs, because this table is actually a series of jump instructions, and their jump target locations are fixed addresses.) When Windows NT's executable image loading When the address space of the process, IAT is determined with the physical address of each import function. To find IAT in the .Text paragraph, the loader only positions the entry point of the module, and the IAT appears before the entry point. Since each entrance has the same size, it is easy to find the starting position of this table backwards.

Data segment, .bss, .rdata, .data

The .BSS segment indicates the unintrodunled data of the application, including all functions or variables declared in STATIC in the source module. .Rdata segment represents read-only data, such as string, constant, and debug directory information. All other variables (except for automatic variables on the stack) are stored in the .data paragraph. Basically, these are global variables for applications or modules.

Resource segment, .rsrc

The .RSRC section contains the resource information of the module. It starts from a resource directory structure, which is like most other structures, but its data is further organized in a resource tree. The following image_resource_directory structure forms the root and each node of this tree. WINNT.Htypedef struct _IMAGE_RESOURCE_DIRECTORY {ULONG Characteristics; ULONG TimeDateStamp; USHORT MajorVersion; USHORT MinorVersion; USHORT NumberOfNamedEntries; USHORT NumberOfIdEntries;} IMAGE_RESOURCE_DIRECTORY, * PIMAGE_RESOURCE_DIRECTORY; Look at this directory structure, you will find that there is not even where a pointer to the next node . However, there are two domains NumberOfNamedentries and NumberOfidentries in this structure instead of pointers, which are used to indicate how many portals attached to this directory. Incidentally, I mean that the directory entrance is behind the directory in the segment data. The entrance to the name appears in order, and then the ID entry arranged in an ascending order of numerical value is. A directory entry consists of two domains, as described below IMAGE_RESOURCE_DIRECTORY_ENTRY structure above: WINNT.Htypedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY {ULONG Name; ULONG OffsetToData;} IMAGE_RESOURCE_DIRECTORY_ENTRY, * PIMAGE_RESOURCE_DIRECTORY_ENTRY; depending on the level of the tree, which also has two different domains the use of. The NAME domain is used to identify a resource type, or a resource name, or a language ID of a resource. Offsettodata is often used in the tree to point to the brother node - ie a directory node or a leaf node. The leaf node is the bottom of the resource tree, which defines the size and location of current resource data. IMAGE_RESOURCE_DATA_ENTRY structure is for describing each leaf node: WINNT.Htypedef struct _IMAGE_RESOURCE_DATA_ENTRY {ULONG OffsetToData; ULONG Size; ULONG CodePage; ULONG Reserved;} IMAGE_RESOURCE_DATA_ENTRY, * PIMAGE_RESOURCE_DATA_ENTRY; OffsetToData and Size field indicates the location of the two current resource data And size. Since this information is mainly used by the function after the application is loaded, it will make OffsetTodata as a relatively virtual address more meaningful. - Fortunately, it's true that it is right. Very interesting is that all other offsets, such as pointers from the entrance to other directories, are all offset relative to the root point position. To understand these content more clearly, please refer to FIG. 2.

Figure 2. A simple resource tree structure Figure 2 depicts a very simple resource tree, which contains only two resource objects: a menu and a string table. A deeper point of view, they each have a child. However, you can still see how complicated resource tree - even if it is only a little resource like this. At the root of the tree, the first directory has an entry of all resource types included in a file regardless of the resources species. In Figure 2, there are two portions identified by the tree root, one is the menu, and the other is the string table. If you have one or more dialog resources in the file, the root node will have an entry, so there is another branch of the dialog resource. The basic resources are identified in WinUser.h, I will list them below: WinUser.h / ** predefined resource type * / # define rt_cursor makeintResource (1) #define rt_bitmap makeintresource (2) #define rt_icon makeintResource ( 3) #define RT_MENU MAKEINTRESOURCE (4) #define RT_DIALOG MAKEINTRESOURCE (5) #define RT_STRING MAKEINTRESOURCE (6) #define RT_FONTDIR MAKEINTRESOURCE (7) #define RT_FONT MAKEINTRESOURCE (8) #define RT_ACCELERATOR MAKEINTRESOURCE (9) #define RT_RCDATA MAKEINTRESOURCE (10 #define RT_MESSAGETABLE MAKEINTRESOURCE (11) At the first level of the tree, the MakeintResource value listed above is placed at the Name of each type of entry, which identifies the different resources type. Each root of the root directory points to a brother node in the tree, which is also a directory, and each has their own entrance. At this level, the directory is used to identify each resource type at a given species. If there are multiple menus in your application, the second level in the tree will prepare an entry for each menu. You may be aware that resources can be identified by names or integers. At this level, they are distinguished by the NAME domain of the directory structure. If the most important bit of the Name field is set, the other 31 bits will be used as an offset to the image_resource_dir_string_u structure. WINNT.Htypedef struct _IMAGE_RESOURCE_DIR_STRING_U {USHORT Length; WCHAR NameString [1];} IMAGE_RESOURCE_DIR_STRING_U, * PIMAGE_RESOURCE_DIR_STRING_U; This structure is only a 2-byte UNICODE characters Length field and a Length thereof. On the other hand, if the most important bit of the Name field is emptied, its low 31 bits are used to represent the integer ID of the resource. Figure 2 shows the menu resource as a named resource, as well as a string table as an ID resource. If there are two menu resources, a name identifier, the other is identified by the resource, then they have two entrances after the menu resource directory. There is a nameful resource entry in the first place, and then the resource identified by an integer. Directory Domain NumberOfNamedenTries and NumberOfidENTRIES contain values ​​1, indicating the current one entry. In the second level, the resource tree will no longer expand a branch more step by step. The first level is branch to the directory representing each resource type, and the second level branch is directorized by the identifier, and the third level is a pair between the individual identified resources and their respective language IDs. One mapping.

To represent a language ID of a resource, the NAME domain of the directory entry structure is used to represent the primary language ID of the resource and the sub-language ID. The default value resource is listed in the WIN32 SDK development package of Windows NT, for example, 0x0409, 0x09 indicates the main language lang_english, 0x04 is defined as subordinates Sublang_english_can. All language ID values ​​are defined in the file winnt.h of the Windows NT Win32 SDK development package. Since the language ID node is the final directory node in the tree, the OFFSetTodata domain of the inlet structure is the offset of a leaf node (i.e., the image_resource_data_entry structure) mentioned earlier). Go back and refer to Figure 2, you will find that each language directory entry corresponds to a data entry. This node only indicates the size of resource data and the relative virtual address of resource data. There is a benefit of having such a multi-structure in the resource data segment (.RSRC), that is, you can collect a lot of information directly from this paragraph without accessing the resource itself. For example, how many resources you can get, which resources (if any) use special language ID, whether the specific resource exists and the size of individual resources. For demonstration of the use of this information, the following function shows how different kinds of decisions a resource file contains: PEFILE.Cint WINAPI GetListOfResourceTypes (LPVOID lpFile, HANDLE hHeap, char ** pszResTypes) {PIMAGE_RESOURCE_DIRECTORY prdRoot; PIMAGE_RESOURCE_DIRECTORY_ENTRY prde; char * pMem; int nCnt, i; / * get the resource tree root directory * / if ((prdRoot = (PIMAGE_RESOURCE_DIRECTORY) ImageDirectoryOffset lpFile, IMAGE_DIRECTORY_ENTRY_RESOURCE)) == NULL) return 0; / * sufficient space allocated on the heap to include All types * / nCnt = prdRoot-> NumberOfIdEntries * (MAXRESOURCENAME 1); * pszResTypes = (char *) HeapAlloc (hHeap, HEAP_ZERO_MEMORY, nCnt); if ((pMem = * pszResTypes) == NULL) return 0; / * Point pole points to the entry * / prde = ((DWORD_RESOURCE_DIRECTORY_ENTRY) of the first resource type ((image_resource_directory)); / * Circulation * / for in all resource directory entry types (i = 0; i < PRDROOT-> NUMBEROFIDENTRIES; i ) {IF (LoadString (HDLL, PrDE-> Name, PMEM, MaxResourceName)) PMEM = Strlen (PMEM) 1; PrDE ;} return ncnt;} This function will list a list of resources name Write a variable identified by Pszrestypes. Note that on the core part of this function, LoadString is a Name domain that uses the entry of the respective resource type directory into a string ID.

转载请注明原文地址:https://www.9cbs.com/read-22548.html

New Post(0)