Export data segment, .edata
The .edata section contains export data of the application or DLL. When this occurs, it will contain an export directory to the export information. WINNT.Htypedef struct _IMAGE_EXPORT_DIRECTORY {ULONG Characteristics; ULONG TimeDateStamp; USHORT MajorVersion; USHORT MinorVersion; ULONG Name; ULONG Base; ULONG NumberOfFunctions; ULONG NumberOfNames; PULONG * AddressOfFunctions; PULONG * AddressOfNames; PUSHORT * AddressOfNameOrdinals;} IMAGE_EXPORT_DIRECTORY, * PIMAGE_EXPORT_DIRECTORY; export directory The NAME domain identifies the name of the executable module. The NumberOffunctions domain and the NumberOfNames domain represents how much exported functions in the module and the names of these functions. The Addressoffunctions domain is an offset to the export function portal list. The AddressOfNames domain is an address of an exported function name list initial offset, which is separated by NULL. AddressOfNameordinals is an offset to the same export function sequence value (2-byte length per value). Three addressof ... domains are relative virtual addresses in the process address space when the module is loaded. Once the module is loaded, the exact address in the process geological space should be obtained, and the base address of the module should be added to the relative virtual address. However, before the file is loaded, it can still determine this address: as long as the virtual address of the section is subtracted from a given domain address, add the offset of the segment entity (PointertorawData), this result is The offset in the image file is.
The following example illustrates this technique: PEFILE.Cint WINAPI GetExportFunctionNames (LPVOID lpFile, HANDLE hHeap, char ** pszFunctions) {IMAGE_SECTION_HEADER sh; PIMAGE_EXPORT_DIRECTORY ped; char * pNames, * pCnt; int i, nCnt; / * get .edata and a head pointer pointing to the data segment of the domain directory * / if ((ped = (PIMAGE_EXPORT_DIRECTORY) ImageDirectoryOffset (lpFile, IMAGE_DIRECTORY_ENTRY_EXPORT)) == NULL) return 0; GetSectionHdrByName (lpFile, & sh, ".edata"); / * Determine the offset of the export function name * / pNames = (char *) (* (int *) ((int) PED-> addressofNames - (int) SH.VIRTUALADDRESS (int) SH.POINTERTORAWDATA (int) lpfile) - (int) sh.virtualaddress (int) sh.pointrtorawdata (int) lpfile); / * calculate how much memory * / PCNT = PNAMES; for (i = 0; i <(int); INT PED-> NUMBEROFNAMES; i ) While (* PCNT ); NCNT = (int)); / * Assign memory on the pile * / * pszfunctions = HeapAlloc (HHEAP, HEAP_ZERO_MEMORY, NCNT); / * Copy all strings to buffer * / copymemory ((lpvoid) * pszfunctions, (lpvoid) PNAMES, NCNT); Return NCNT;} Please note that in this function, the variable pNAMES is determined by the offset address and The method of the current offset position is assigned. The address and offset of the offset itself are relative virtual addresses, so this must be performed before use. Although you can write a similar function to determine the order value or the function entry point, but why don't I do it for you? - GetNumberofexPortedFunctions, getExportFunctionEntryPoints and getExportFunctionOrdinals already exist in the pefile.dll. Import data segment, .idata
.idata segment is imported data, including the import library and import address name table. Although image_directory_entry_import is defined, there is no corresponding import directory structure among Winnt.h. Instead, there are several other structures, named image_import_by_name, image_thunk_data and image_import_descriptor. In my personal opinion, I really don't know how these structures are associated with. IDATA segment, so I spent several hours to decipher .idata segment entity and get a simpler structure, my name is image_import_module_directory. PEFILE.Htypedef struct tagImportDirectory {DWORD dwRVAFunctionNameList; DWORD dwUseless1; DWORD dwUseless2; DWORD dwRVAModuleName; DWORD dwRVAFunctionAddressList;} IMAGE_IMPORT_MODULE_DIRECTORY, * PIMAGE_IMPORT_MODULE_DIRECTORY; catalog and other data segment is different, this is a document in each of the recurring import module . You can see it as an entry in the module data directory list, not a data directory of the entire data segment. Each entry is a directory that points to the specific module import information. A domain in the image_import_module_directory structure DWRvamodulenAME is a relative virtual address, which points to the name of the module. There are two dwuseless parameters in the structure, which are aligned in the segment. The PE file format specification refers to something about import marks, time / date signs, and main / sub-versions, but in my experiment, these two domains are empty, so I still think that they have no usefulness. Based on this configuration, you can get all the modules and function names imported in the executable.
The following demonstrates how to obtain all the functions to import specific function names PE file: PEFILE.Cint WINAPI GetImportModuleNames (LPVOID lpFile, HANDLE hHeap, char ** pszModules) {PIMAGE_IMPORT_MODULE_DIRECTORY pid; IMAGE_SECTION_HEADER idsh; BYTE * pData; int nCnt = 0 , nSize = 0, i; char * pModule [1024]; char * psz; pid = (PIMAGE_IMPORT_MODULE_DIRECTORY) ImageDirectoryOffset (lpFile, IMAGE_DIRECTORY_ENTRY_IMPORT); pData = (BYTE *) pid; / * segment head positioning .idata * / if ( GetsectionHDRBYNAME (LPFILE, & IDSH, ".IData")) Return 0; / * Extract all import modules * / while (pid-> dwrvamodulename) {/ * is an absolute string offset allocation buffer * / pmodule [NCNT] = (Char *) (PDATA (PID-> DWRVAModulenAme-idsh.virtualaddress); nsize = strlen (PModule [NCNT]) 1; / * Increment to the next import directory port * / PID ; NCNT ;} / * Assign all strings to a large block in a plurality of stack memory * / * pszmodules = Heapalloc (hheap, heap_zero_memory, nsize); psz = * pszmodules; for (i = 0; i
As shown in the following data, all import modules are included in the .IDATA segment data: E6A7 0000 F6A7 0000 08A8 0000 1AA8 0000 ................ 28A8 0000 3CA8 0000 4CA8 0000 00 00 00 (... <... L ..... 0000 4765 744F 7065 6E46 696C 654E 616d ..GetopenFileNam6541 0000 636F 6D64 6C67 3332 2E64 6C6C EA..Comdlg32.dll0000 2500 4372 6561 7465 466F 6E74 496E ..%. CreateFontIn6469 7265 6374 4100 4744 4933 322E 646C directA.GDI32.dl6C00 A000 4765 7444 6576 6963 6543 6170 l ... GetDeviceCap7300 C600 4765 7453 746F 636B 4F62 6A65 s ... GetStockObje6374 0000 D500 4765 7454 6578 744D 6574 ct .... GetTextMet7269 6373 4100 1001 5365 6C65 6374 4F62 ricsA ... SelectOb6A65 6374 0000 1601 5365 7442 6B43 6F6C ject .... SetBkCol6F72 0000 3501 5365 7454 6578 7443 6F6C or..5.SetTextCol6F72 0000 4501 5465 7874 4F75 7441 0000 OR..E.TEXTOUTA .. The above data is part of the EXEVIEW.EXE sample program. This special segment represents the start of the import module list and the function name list. If you start checking the data This section, you should recognize some familiar WIN32 API functions and module names. If you read it, you can find getopenfilenamea, followed by comdlg32.dll. Then you can find CreateFontIndirecta, followed by module GDi32.dll , And later getDevicecaps, getStockObject, gettex Tmetrics, etc. Such models will be repeated in. IDATA segment. The first module is COMDLG32.DLL, the second is GDI32.DLL. Note that the first module only extends a function, and the second module exports a lot of functions. In both cases, the method of the function and module is the first function name, followed by the module name, and then other functions (if any). The following functions demonstrate all function names for the specified module.
PEFILE.Cint WINAPI GetImportFunctionNamesByModule (LPVOID lpFile, HANDLE hHeap, char * pszModule, char ** pszFunctions) {PIMAGE_IMPORT_MODULE_DIRECTORY pid; IMAGE_SECTION_HEADER idsh; DWORD dwBase; int nCnt = 0, nSize = 0; DWORD dwFunction; char * psz; / * Location .idata head segment * / if (! GetSectionHdrByName (lpFile, & idsh, ".idata")) return 0; pid = (PIMAGE_IMPORT_MODULE_DIRECTORY) ImageDirectoryOffset (lpFile, IMAGE_DIRECTORY_ENTRY_IMPORT); dwBase = (. (DWORD) pid idsh.VirtualAddress) ; / * Lookup PID * / while (pid-> dwrvamodulename && strcmp (pid-> dwrvamodulen dwbase))))) PID ; / * If the module is not found, you will exit * / if (! PID-> dwrvamodulenAme) return 0; / * Total number and string length * / dwfunction = pid-> dwrvafunctionNameList; while (dwfunction && * (dword *) (DWFunction dwbase) && * ((*) ((*) DWORD *) (dwfunction dwbase)) DWBase 2)) {nsize = strlen ((* (DWFunction dwbase)) 1; dwfunction = 4; NCNT ;} / * Assign a function name on the pile * * / * PszFunctions = HeapAlloc (hHeap, HEAP_ZERO_MEMORY, nSize); psz = * pszFunctions; / * copy the function name memory pointer * / dwFunction = pid-> dwRVAFunctionNameList; while (dwFunction && * (DWORD *) (dwFunction dwBase) && * ((char *) ((DWFunction DWBase)) DWBase 2))) {structure (psz, (char *) ((DWFunction dwbase) DWBase 2))); PSZ = Strlen ((CHAR *) ((DWFunction DWBase)) DWBase 2)) 1; DWFunction = 4;} Return ncnt;} is like getimportModuLenames functions same,