Debug information segment, .debug
The debugging information is located in the .debug segment, and the PE file format also supports a separate debug file (usually by .dbg extension) as a method in which the information set will be debugged. The debug segment contains debugging information, but the debug directory is located in the .rdata section mentioned earlier. Each of these directories involves debugging information in the .debug segment. IMAGE_DEBUG_DIRECTORY debug directory structure is defined as: WINNT.Htypedef struct _IMAGE_DEBUG_DIRECTORY {ULONG Characteristics; ULONG TimeDateStamp; USHORT MajorVersion; USHORT MinorVersion; ULONG Type; ULONG SizeOfData; ULONG AddressOfRawData; ULONG PointerToRawData;} IMAGE_DEBUG_DIRECTORY, * PIMAGE_DEBUG_DIRECTORY; This section is divided into Separate parts, each part is a different kind of debug information data. For each part is a debug directory like the top. Different types of debugging information as follows: among WINNT.H # define IMAGE_DEBUG_TYPE_UNKNOWN 0 # define IMAGE_DEBUG_TYPE_COFF 1 # define IMAGE_DEBUG_TYPE_CODEVIEW 2 # define IMAGE_DEBUG_TYPE_FPO 3 # define IMAGE_DEBUG_TYPE_MISC 4 Type field for each directory represents the kind of debugging information directory. As you can see, in the top of the table, PE file format supports many different debug information types, as well as some other information fields. For those, the image_debug_type_misc information is unique. This information is added to the mixed information describing the executable image, which cannot be added to the PE file format any structured data segment. This is the most suitable location in the image file, the image name will definitely appear here. If the image exports information, the exported data segment will also contain this image name. Each debugging information has its own head structure that defines its own data. These structures are listed in Winnt.h. About image_debug_directory One interesting thing is that it includes two domains identifying debug information. The first is AddressofrawData, a data virtual address that is loaded with respect to file; the other is PointertorawData, the actual offset in the PE file where the data is located. This makes it easy to position the debug information specified by the positioning. As a final example, please consider the following function code, which extracts the image name from the image_debug_misc structure.
PEFILE.Cint WINAPI RetrieveModuleName (LPVOID lpFile, HANDLE hHeap, char ** pszModule) {PIMAGE_DEBUG_DIRECTORY pdd; PIMAGE_DEBUG_MISC pdm = NULL; int nCnt; if (! (Pdd = (PIMAGE_DEBUG_DIRECTORY) ImageDirectoryOffset (lpFile, IMAGE_DIRECTORY_ENTRY_DEBUG))) return 0; while (PDD-> SIZEOFDATA) {if (PDD-> Type == Image_Debug_type_misc) {PDM = (PIMAGE_DEBUG_MISC) ((DWORD) PDD-> PointertorawData (DWORD) LPFILE); NCNT = LSTRLEN (PDM-> DATA) * (PDM -> Unicode? 2: 1); * pszmodule = (char *) Heapalloc (hheap, heap_zero_memory, ncnt 1); copyMemory (* pszmodule, pdm-> data, ncnt); Break;} PDD ;} IF PDM! = NULL) RETURN NCNT; Else Return 0;} You see that debugging the directory structure makes it relatively easy to locate a particular kind of debug information. As long as the image_debug_misc structure is positioned, the extraction image name is as simple as calling the CopyMemory function. As described above, the debug information can be stripped to a separate .dbg file. Windows NT SDK contains a program called Rebase.exe to achieve this. For example, the following statement can peel off a debugging information called Test.exe: Rebase -B 40000 -xc: / Samples / TestDir test.exe debugging information is placed in a new file, this file name is Test.dbg Among the C: / Samples / TestDir. This file starts from a separate image_separate_debug_header structure, followed by a copy of the section of the original executable image. After the section, it is the data of the .debug segment. That is to say, after the section head, it is a series of image_debug_directory structures and related data. The debug information itself retains the regular image file debugging information as described above. PE file format summary
Windows NT's PE file format introduces a new structure to developers familiar with Windows and MS-DOS environments. However, developers who are familiar with UNIX environment will find that PE file format is very similar to the COFF specification (if it is not based on Coff). The entire format consists: an MS-DOS MZ header, then a real mode residual program, PE file flag, PE file header, PE Optional head, all segment head, finally all segment entities . The end of the optional head is an array of a data directory entry, these relative virtual addresses point to the data directory in the segment entity. Each data directory represents how a specific segment entity data is organized. The PE file format has 11 predefined segments, which is common to the Windows NT application, but each application can define its own unique segments for its own code and data. The .debug predefined segment can also be separated as a separate debug file. If this is, there will be a specific debug head to resolve this debug file, and there will be a flag in the PE file to indicate that the debug data is separated. PEFILE.DLL function description
Pefile.dll is mainly composed of some functions, or these functions or offsets in a given PE file, or to copy some of the data in the file to a particular structure. Each function has a requirement - the first parameter is a pointer, which points to the beginning of the PE file. That is, this file must first be mapped into the address space of your process, and then map the location of the file to the value of the LPFile of each function, the value of the first parameter. I am intended to make the name of the function allow you to know, and each function will be listed with a detailed description of the comments. If you still don't understand the function of a function after reading the function list, please refer to the exeView.exe example to find out how this function is used. The following function prototype list can be found in PeFile.h: pefile.h / * get pointers pointing to the MS-DOS MZ header * / Bool WinAPI Getdosheader (LPVOID, PIMAGE_DOS_HEADER);
/ * Decide the type of the .exe file * / DWORD WINAPI ImageFileType (LPVOID);
/ * Get pointer to the head of the PE file * / bool WinAPI getPefileHeader (LPVOID, PIMAGE_FILE_HEADER);
/ * Get pointers pointing to PE * / Bool WinAPI getPEOPTIONALHEADER (LPVOID, PIMAGE_OPTIONAL_HEADER);
/ * Return to the address of the module entry point * / lpvoid WinAPi getModuleEntryPoint (LPVOID);
/ * Return to the total number of files * / int WinAPI Numofsections (LPVOID);
/ * Returns the preferred base address when the executable is loaded into the process address * / LPVOID WINAPI GetImageBase (LPVOID);
/ * Decide the location of a specific image data directory in the file * / LPVOID WINAPI ImageDirectoryOffset (LPVOID, DWORD);
/ * Name of all paragraphs in the file * / int WinAPI GetSecionNames (lpvoid, handle, char **);
/ * Copy a specific section of head information * / Bool WinApi getsectionHDRBYNAME (lpvoid, pimage_section_header, char *);
/ * Get the import module name list of empty characters * / int WinAPI GetimportModulen (lpvoid, handle, char **);
/ * Get a module separated by empty character list * / int WINAPI GetImportFunctionNameSbyModule (LPVOID, HANDE, CHAR *, CHAR **); / * Gets a list of exported functions separated by empty characters * / int WinApi getExportFunctionNames (LPVOID, Handle, char **);
/ * Get the total number of export functions * / int WINAPI GetNumberofexPortedFunctions (LPVOID);
/ * Get the virtual address entry point list of the export function * / LPVOID WINAPI GETEXPORTFUNTRYPOINTS (LPVOID);
/ * Get export function sequence list * / lpvoid WinApi getExportFunctionordinals (LPVOID);
/ * Decide the species of the resource object * / int WinAPI GetNumberOfResources (LPVOID);
/ * Returns the kind of all resource objects used in the file * / int WinAPI getListofResourceTypes (lpvoid, handle, char **);
/ * Decide if the debug information has been separated from the file * / BOOL WINAPI ISDEBUGINFSTRIPPED (LPVOID);
/ * Get an image file name * / int WinAPI RetrieveModulenAme (lpvoid, handle, char **);
/ * Decide if the file is a valid debug file * / bool winapi isdebugfile (lpvoid);
/ * Returns the debugging head from the debug file * / Bool WinAPI getSeparateDebughead (lpvoid, pimage_separate_debug_header); In addition to the functions listed above, the macro mentioned in this article is also defined in PeFile.h, the complete list is as follows : / * PE file logo offset * / # define ntsignature (a) ((LPVOID) ((byte *) A / ((pimage_dos_header) a) -> e_lfanew))
/ * MS operating system head identifies the double word NT PE file mark; the head of the PE file is followed by this double word * / # define pefhdroffset (a) ((lpvoid) ((byte *) A / ( (PIMAGE_DOS_HEADER) A) -> E_LFANEW / SIZE_OF_NT_SIGNATURE))))
/ * PE Optional head followed by the head of the PE file * / # define opthdroffset ((LPVOID) ((byte *) A / (pimage_dos_header) A) -> E_LFANEW / SIZE_OF_NT_SIGNATURE / SIZEOF (Image_file_Header))))))))))))))