Hello everyone, now continue our Tour of the PE file, the secret of DLL - output table. First look at the preparatory knowledge. Output table in <
> There is not much pen ink in the information, ranking in my contact, it is indeed intuitive, there is no complex structure as inputting tables, so this may also be less than a less than. The structure of the output table can be referred to <
". First position the output table. In the image_optional_header.dataDirectory structure, pay attention to this is also an array of structures. Each element of it is an image_data_directory structure. This structure is defined as follows: typedef struct _IMAGE_DATA_DIRECTORY {DWORD VirtualAddress; DWORD Size;} IMAGE_DATA_DIRECTORY, * PIMAGE_DATA_DIRECTORY; DataDirectory first element of an array of structures described in the table is output, the second input element of the table is described, Oh, this is our Next research object. So, the VirtualAddress here is the offset address of the output table, and size does not have to say, the size of the output table. Note: Some variables of the following code are in previous articles <
> It has been defined, here is no longer redefined, please refer to the previous article.
Core code: // first positioning structure IMAGE_OPTIONAL_HEADER32 IMAGE_OPTIONAL_HEADER32 myOptionalHeader; fseek (pFile, (e_lfanew sizeof (DWORD) sizeof (IMAGE_FILE_HEADER)), SEEK_SET); // Causes so positioned refer to FIG PE paper fread (& myOptionalHeader, sizeof (Image_optional_header32), 1, pfile; // data catalog table The first element of the output table printf ("Output Table Offset Address:% 08X / N", MyOptionalHeader.DataDirectory [0] .virtualAddress; Printf "the magnitude of the output table:% 04x / n", myOptionalHeader.DataDirectory [0] .Size); DWORD dwFileOffset; if (myOptionalHeader.DataDirectory [0] .VirtualAddress = 0) {// OnConvertVAToRawA () function is to VirtualAddress! File offset conversion function, the specific code is shown in DWFILEOFFSET = ONCONVERTVATORAWA (MyOptionalHeader.DataDirectory; if (-1 == dwfileoffset) {Printf ("Output Table Location Error / N");} else {printf ("The output table is offset from:% 08x / n", dwfileoffset); // ------------------ Here has obtained the file offset of the output table, The output table starts by the IED array ---------------- // int nNumberoffunctions = 0; int nNumberOfnames = 0; // is calculated from the offset (VA) of the output table File offset, then locate it here is the output table // output table starts by image_export_directory, image_export_directory * PIED = (Image_Export_Directory *) malloc (sizeof (IMAGE_EXPORT_DIRECTORY)); // Memory 17 fseek (pFile, dwFileOffset, SEEK_SET); fread (pIED, sizeof (IMAGE_EXPORT_DIRECTORY), 1, pFile); printf ( "IMAGE_EXPORT_DIRECTORY following structure: / n"); printf ( " Characteristics:% 08X (no use, always 0) / n ", Pied-> Characteristics; printf (" TIMEDATESTAMP:% 08X (file is generated) / n ", Pied-> Timedatestamp); Printf (" MajorVersion :% 08X (no use, always 0) / n ", Pied-> Majorversion); Printf (" Minorversion:% 08X (no use, always 0) / n ", Pied-> minorversion); Printf "Name:% 08X (RVA, pointing to a DLL file name) / N", PIED-> name);
// read the DLL name char chDLNAME [64] = {0}; // Here you have a lot of space to give a function name, prevent errors, I have seen the function name, 30 char, huh, huh, huh, 指 指 指 将VA of file names into file offset DWTEMP = ONCONVERTVATORAWA (Pied-> Name); // Read DLL file name FSeek; FREAD (CHDLNAME, 64, 1, PFILE); Printf (" The DLL file name is:% s / n ", chDLNAME); Printf (" Base:% 08X (start number (start number) / n ", pied-> base); // The start number of the function output by this module Word WBASE = (Word) PIED-> Base; Printf ("NumberOffunctions:% D (Output Function Number) / N", PIED-> NumberOffunctions); // AddressOffunctions array (later described) Elements in the elements. This value is also the number of output functions. / / Usually this value is the same as the NumberOfNames field, but it can also be different. NNumberoffunctions = Pied-> Numberoffunctions; Printf ("NumberOfNames:% D (number of functions output) / n", pied-> numberofnames); // addressofNames array (later described) Elements in the elements. This value represents the number of functions output by name. // Typically (but not always) and the total number of output functions is the same. NNumberOfnames = Pied-> NumberOfNames; // This is a RVA (Relative Virtual Address) value, pointing to an array composed of a function address. // I have called the RVA value of the entry point of each output function in this module. Printf ("Addressoffunctions: 08X (RVA, array points to a function address) / n", Pied-> addressoffunctions; // Here to convert to file offset address DWORD DWADDRESSOFFUNCTIONS = ONCONVERTVATORAWA (Pied-> Addressoffunctions ); // This is a RVA value, pointing to an array composed of a string pointer. // The content of the string is the name Printf of each "output function" in this module "in this module. Printf (" AddressOfNames:% 08X (RVA, array points to a string pointer) / N ", PIED -> addressofnames); // Translate into file offset address DWORD DWNAMEADDRESSOFFUNCTIONS = ONCONVERTVATORAWA (Pied-> AddressOfnames); // This is a RVA value, pointing to a Word array. // Word content is the serial number of each "output function" in the name output in this module. Don't forget to add the starting number in the base field.
printf ( "AddressOfNameOrdinals:% 08x (RVA, points to a DWORD array) / n", pIED-> AddressOfNameOrdinals); // offset into the file DWORD dwAddressOfNameOrdinals = OnConvertVAToRawA (pIED-> AddressOfNameOrdinals); if (pIED = NULL! ) // Release memory 17 {free (PIED); PIED = null;} // dynamically open memory to store function of VirtualAddress DWORD * pdwaddressoffunctions = (dword *) Calloc (nnumberoffunctions, sizeof (dword)); // Memory 18 fseek (pFile, dwAddressOfFunctions, SEEK_SET); fread (pdwAddressOfFunctions, sizeof (DWORD), nNumberOfFunctions, pFile); // open memory used to store the dynamic function RawAddress DWORD * pRowAddressOfFunctions = (DWORD *) calloc (nNumberOfFunctions, sizeof (DWORD) ); // Memory 19 for (int i = 0; i * PFunctionsName = (DWORD *) pchFunctionName;} // restore pointer pFunctionsName - = nNumberOfNames; // read function name for (i = 0; i // used here high efficiency quicksort (detailed code see below) QuickSort (pwFunctionsOrdinals, pFunctionsName, nNumberOfNames); // print information for (i = 0; i > Respect to the output section of the table) DWORD OnConvertVAToRawA (DWORD dwFileOffset) {IMAGE_SECTION_HEADER * pmySectionHeader = (IMAGE_SECTION_HEADER *) calloc (nSectionCount, sizeof (IMAGE_SECTION_HEADER)); // prince 14 fseek (pFile, (e_lfanew 4 sizeof (IMAGE_FILE_HEADER) sizeof (IMAGE_OPTIONAL_HEADER32)), SEEK_SET); fread (pmySectionHeader, sizeof (IMAGE_SECTION_HEADER), nSectionCount, pFile); DWORD dwFilePos; DWORD dwOffset; DWORD * pdwVA = (DWORD *) malloc (sizeof (DWORD) * nSectionCount); // prince 15 DWORD * pdwRowA = (DWORD *) malloc (sizeof (DWORD) * nSectionCount); // prince 16 for (int i = 0; i