[Reverse] Export table: 1. Write a program to print all export table information 2. Write GetFunctionAddrByName 3. Write GetFunctionAddrByOrdinal

This is getting the address of each table from the data directory

void PE::Analyze_Data_Directory(Data & amp; my_data)
{
my_data.my_Data_Directory = nullptr;
my_data.my_Data_Directory = (PIMAGE_DATA_DIRECTORY*)malloc(16 * sizeof(PIMAGE_DATA_DIRECTORY));
void* Temp_ptr = my_data.my_optional->DataDirectory;
for (int i = 0; i < 16; i + + )
{
my_data.my_Data_Directory[i] = (PIMAGE_DATA_DIRECTORY)Temp_ptr;
Temp_ptr = (char*)Temp_ptr + 0x8;
}
}

Print information about all export tables:

void PE::Print_ExportTable(Data & amp; my_data)
{
PIMAGE_EXPORT_DIRECTORY my_export_directory_ptr = (PIMAGE_EXPORT_DIRECTORY)((DWORD)my_data.my_Data_Directory[0]->VirtualAddress + (DWORD)my_data.Stretch_Data);
my_data.my_Export_Directory = my_export_directory_ptr;
DWORD AddressOfFunctions_ptr = (DWORD)((DWORD)my_export_directory_ptr->AddressOfFunctions + (DWORD)my_data.Stretch_Data);
DWORD AddressOfNames_ptr = (DWORD)((DWORD)my_export_directory_ptr->AddressOfNames + (DWORD)my_data.Stretch_Data);
DWORD AddressOfNameOrdinals_ptr = (DWORD)((DWORD)my_export_directory_ptr->AddressOfNameOrdinals + (DWORD)my_data.Stretch_Data);

cout << "---------------AddressOfFunctions------------------" << endl;
int number = my_export_directory_ptr->NumberOfFunctions;
for (int i = 0; i < number; i + + )
{
cout << i << ": " << "0x" << hex << *((DWORD*)AddressOfFunctions_ptr) << endl;
my_data.Export_AddressOfFunction[i] = *((DWORD*)AddressOfFunctions_ptr);
AddressOfFunctions_ptr + = 0x4;
while (*((DWORD*)AddressOfFunctions_ptr) == 0)
{
AddressOfFunctions_ptr + = 0x4;
}
}

cout << "---------------------Names------------------" << endl ;
number = my_export_directory_ptr->NumberOfNames;
for (int i = 0; i < number; i + + )
{
strcpy_s(my_data.my_Export_Name[i], (PCHAR)(*(DWORD*)AddressOfNames_ptr + (DWORD)my_data.Stretch_Data));
cout << i << ": " << (PCHAR)(*(DWORD*)AddressOfNames_ptr + (DWORD)my_data.Stretch_Data) << endl;
AddressOfNames_ptr + = 0x4;
}

cout << "----------------------NameOrdinals---------------" << endl;
cout << "base: " << my_export_directory_ptr->Base << endl;
for (int i = 0; i < number; i + + )
{
cout << i << ": " << *(WORD*)AddressOfNames_ptr << endl;
AddressOfNames_ptr + = 0x2;
}
}

Get the offset of the function in the DLL through the function name:

VOID PE::GetFunctionAddrByName(Data & amp; my_data, char* name)
{
int i = 0;
for (i = 0; i < my_data.my_Export_Directory->NumberOfNames; i + + )
{
if (!strcmp(name, my_data.my_Export_Name[i]))
{
cout << "Successfully matched the function through the function name!" << endl;
break;
}
if (i == my_data.my_Export_Directory->NumberOfNames - 1)
{
cout << "No function name matched!" << endl;
return ;
}
}
cout << "0x" << hex << my_data.Export_AddressOfFunction[i] << endl;
\t
}

Get the offset of the function in the DLL through the function’s serial number

VOID PE::GetFunctionAddrByOrdinal(Data & amp; my_data, int ordinal)
{
DWORD AddressOfNames_ptr = (DWORD)((DWORD)my_data.my_Export_Directory->AddressOfNameOrdinals + (DWORD)my_data.Stretch_Data);
for (int i = 0; i < my_data.my_Export_Directory->NumberOfNames; i + + )
{
if (*(WORD*)AddressOfNames_ptr + my_data.my_Export_Directory->Base == ordinal)
{
cout << "Successfully found the function address through the function's serial number!" << endl;
cout << "0x" << hex << my_data.Export_AddressOfFunction[i] << endl;
return;
}
AddressOfNames_ptr = (DWORD)((char*)AddressOfNames_ptr + 2);
}
cout << "No match!" << endl;
}

The complete code is as follows, you can directly change the DLL name and it will run perfectly:

#include 
#include 
#include 
#include 
#include 
using namespace std;
#pragma comment(lib,"Dll1.lib")
extern __declspec(dllimport) void Print();
int MAX(int a, int b)
{
return a >= b ? a : b;
}

class Data
{
public:
PIMAGE_DOS_HEADER my_dos;//dos header structure
PIMAGE_FILE_HEADER my_file;//file structure
PIMAGE_OPTIONAL_HEADER32 my_optional;//Optional PE header structure
PIMAGE_SECTION_HEADER* my_section;//section table structure
PIMAGE_DATA_DIRECTORY* my_Data_Directory;//data directory structure
//0. Export table 1. Import table 2. Resource table 3. Exception information table 4. Security certificate table 5. Relocation table 6. Debugging information table 7. Copyright table
//8. Global pointer table 9. TLS table 10. Loading configuration table 11. Binding import table 12. IAT table 13. Delayed binding table 14. COM information table 15. Not used
CHAR my_Export_Name[50][30];//The name of the export table
PIMAGE_EXPORT_DIRECTORY my_Export_Directory; //Pointer to the export table structure
DWORD Export_AddressOfFunction[50];



void* Before_Stretch_Data; //Points to the content before stretching
void* Stretch_Data; //Point to the stretched content
void* Shrink_Data; //points to the contents of the shrink PE structure


Data()
{
my_dos = nullptr;//dos header structure
my_file = nullptr;//file structure
my_optional = nullptr;//Optional PE header structure
my_section = nullptr;//section table structure
my_Data_Directory = nullptr;


Before_Stretch_Data = nullptr; //points to the content before stretching
Stretch_Data = nullptr; //Point to the stretched content
Shrink_Data = nullptr; //Point to the content of the shrink PE structure
}

~Data()
{
if (Before_Stretch_Data != nullptr)
{
free(Before_Stretch_Data);
Before_Stretch_Data = nullptr;
}

if (Stretch_Data != nullptr)
{
free(Stretch_Data);
Stretch_Data = nullptr;
}

if (Shrink_Data != nullptr)
{
free(Shrink_Data);
Shrink_Data = nullptr;
}
}


VOID Copy_Before_Strectch_Data(Data my_data); //Only deep copy Before_Strectch_Data
};

VOID Data::Copy_Before_Strectch_Data(Data my_data)
{
int size = _msize(my_data.Before_Stretch_Data);
memcpy_s(this->Before_Stretch_Data, size, my_data.Before_Stretch_Data, size);
}



classPE
{
public:
VOID Readfile(char* filename, Data & amp; my_data); //Read pe file

VOID Analyze_PE(Data & amp; my_data, int num); //Analyze pe structure

VOID Stretch_PE(Data & amp; my_data); //Stretch pe structure

VOID Shrink_PE(Data & amp; my_data); //Shrink the pe structure

VOID New_Section(char* filename, Data & my_data);//Add a new section, not an expanded section, and write it to the new exe file

VOID Expand_Section(Data & amp; my_data, char* filename); //Expand section

int Section_Align(int temp, Data & amp; my_data); //Return the size after memory alignment

int File_Align(int temp, Data & amp; my_data); //Return the size of the file after alignment

VOID Combine_Section(char* filename, Data & amp; my_data);

VOID Copy_Data(Data & amp; my_data);

VOID Print_IMAGE_DATA_DIRECTORY(Data & my_data);

VOID Analyze_Data_Directory(Data & my_data);

DWORD Rva_To_Foa(DWORD Rva_Offset, Data & amp; my_data);

VOID Print_ExportTable(Data & my_data);

VOID GetFunctionAddrByName(Data & my_data, char* name);

VOID GetFunctionAddrByOrdinal(Data & amp; my_data, int ordinal);
};

VOID PE::GetFunctionAddrByOrdinal(Data & amp; my_data, int ordinal)
{
DWORD AddressOfNames_ptr = (DWORD)((DWORD)my_data.my_Export_Directory->AddressOfNameOrdinals + (DWORD)my_data.Stretch_Data);
for (int i = 0; i < my_data.my_Export_Directory->NumberOfNames; i + + )
{
if (*(WORD*)AddressOfNames_ptr + my_data.my_Export_Directory->Base == ordinal)
{
cout << "Successfully found the function address through the function's serial number!" << endl;
cout << "0x" << hex << my_data.Export_AddressOfFunction[i] << endl;
return;
}
AddressOfNames_ptr = (DWORD)((char*)AddressOfNames_ptr + 2);
}
cout << "No match!" << endl;
}


VOID PE::GetFunctionAddrByName(Data & my_data, char* name)
{
int i = 0;
for (i = 0; i < my_data.my_Export_Directory->NumberOfNames; i + + )
{
if (!strcmp(name, my_data.my_Export_Name[i]))
{
cout << "Successfully matched the function through the function name!" << endl;
break;
}
if (i == my_data.my_Export_Directory->NumberOfNames - 1)
{
cout << "No function name matched!" << endl;
return ;
}
}
cout << "0x" << hex << my_data.Export_AddressOfFunction[i] << endl;
\t
}


void PE::Print_ExportTable(Data & my_data)
{
PIMAGE_EXPORT_DIRECTORY my_export_directory_ptr = (PIMAGE_EXPORT_DIRECTORY)((DWORD)my_data.my_Data_Directory[0]->VirtualAddress + (DWORD)my_data.Stretch_Data);
my_data.my_Export_Directory = my_export_directory_ptr;
DWORD AddressOfFunctions_ptr = (DWORD)((DWORD)my_export_directory_ptr->AddressOfFunctions + (DWORD)my_data.Stretch_Data);
DWORD AddressOfNames_ptr = (DWORD)((DWORD)my_export_directory_ptr->AddressOfNames + (DWORD)my_data.Stretch_Data);
DWORD AddressOfNameOrdinals_ptr = (DWORD)((DWORD)my_export_directory_ptr->AddressOfNameOrdinals + (DWORD)my_data.Stretch_Data);

cout << "---------------AddressOfFunctions------------------" << endl;
int number = my_export_directory_ptr->NumberOfFunctions;
for (int i = 0; i < number; i + + )
{
cout << i << ": " << "0x" << hex << *((DWORD*)AddressOfFunctions_ptr) << endl;
my_data.Export_AddressOfFunction[i] = *((DWORD*)AddressOfFunctions_ptr);
AddressOfFunctions_ptr + = 0x4;
while (*((DWORD*)AddressOfFunctions_ptr) == 0)
{
AddressOfFunctions_ptr + = 0x4;
}
}

cout << "---------------------Names------------------" << endl ;
number = my_export_directory_ptr->NumberOfNames;
for (int i = 0; i < number; i + + )
{
strcpy_s(my_data.my_Export_Name[i], (PCHAR)(*(DWORD*)AddressOfNames_ptr + (DWORD)my_data.Stretch_Data));
cout << i << ": " << (PCHAR)(*(DWORD*)AddressOfNames_ptr + (DWORD)my_data.Stretch_Data) << endl;
AddressOfNames_ptr + = 0x4;
}

cout << "----------------------NameOrdinals---------------" << endl;
cout << "base: " << my_export_directory_ptr->Base << endl;
for (int i = 0; i < number; i + + )
{
cout << i << ": " << *(WORD*)AddressOfNames_ptr << endl;
AddressOfNames_ptr + = 0x2;
}
}





DWORD PE::Rva_To_Foa(DWORD Rva_Offset, Data & my_data)
{
int index = 0;
if (Rva_Offset <= my_data.my_optional->SizeOfHeaders)
{
return Rva_Offset;
}
else
{

while (Rva_Offset > my_data.my_section[index]->VirtualAddress)
{
index + + ;
}
index--;
//Calculate the offset in the section
DWORD Section_Offset = Rva_Offset - my_data.my_section[index]->VirtualAddress;
return my_data.my_section[index]->PointerToRawData + Section_Offset;
}
}

void PE::Analyze_Data_Directory(Data & amp; my_data)
{
my_data.my_Data_Directory = nullptr;
my_data.my_Data_Directory = (PIMAGE_DATA_DIRECTORY*)malloc(16 * sizeof(PIMAGE_DATA_DIRECTORY));
void* Temp_ptr = my_data.my_optional->DataDirectory;
for (int i = 0; i < 16; i + + )
{
my_data.my_Data_Directory[i] = (PIMAGE_DATA_DIRECTORY)Temp_ptr;
Temp_ptr = (char*)Temp_ptr + 0x8;
}
}

void PE::Print_IMAGE_DATA_DIRECTORY(Data & my_data)
{
char arr[16][40] = {
"IMAGE_DIRECTORY_ENTRY_EXPORT",
"IMAGE_DIRECTORY_ENTRY_IMPORT",
"IMAGE_DIRECTORY_ENTRY_RESOURCE",
"IMAGE_DIRECTORY_ENTRY_EXCEPTION",
"IMAGE_DIRECTORY_ENTRY_SECURITY",
"IMAGE_DIRECTORY_ENTRY_BASERELOC",
"IMAGE_DIRECTORY_ENTRY_DEBUG",
"IMAGE_DIRECTORY_ENTRY_COPYRIGHT",
"IMAGE_DIRECTORY_ENTRY_GLOBALTR",
"IMAGE_DIRECTORY_ENTRY_TLS",
"IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG",
"IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT",
"IMAGE_DIRECTORY_ENTRY_IAT",
"IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT",
"IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR",
"RESERVED"
};

for (int i = 0; i < 16; i + + )
{
cout << arr[i] << " :" << endl;
cout << "Size: " << hex << my_data.my_Data_Directory[i]->Size << endl;
cout << "Virtual_Address: " << my_data.my_Data_Directory[i]->VirtualAddress << endl;
cout << "------------------------------------------------ --------------------------" << endl;
}
return;
}


void PE::Combine_Section(char* filename, Data & my_data)
{

int Max = MAX(my_data.my_section[my_data.my_file->NumberOfSections - 1]->SizeOfRawData, my_data.my_section[my_data.my_file->NumberOfSections - 1]->Misc.VirtualSize);
int Size = my_data.my_section[my_data.my_file->NumberOfSections - 1]->VirtualAddress + Section_Align(Max, my_data) - Section_Align(my_data.my_optional->SizeOfHeaders, my_data) + MAX(my_data.my_section[0]->SizeOfRawData , my_data.my_section[0]->Misc.VirtualSize);
Data Comebine_Data;
int temp_size = _msize(my_data.Stretch_Data) + Max;
Comebine_Data.Stretch_Data = (void*)malloc(temp_size);
memset(Comebine_Data.Stretch_Data, 0, Size);

temp_size = _msize(my_data.Stretch_Data);
memcpy_s(Comebine_Data.Stretch_Data, temp_size, my_data.Stretch_Data, temp_size);
Analyze_PE(Comebine_Data, 2);

void* temp_ptr = (char*)Comebine_Data.Stretch_Data + Max + my_data.my_section[my_data.my_file->NumberOfSections - 1]->VirtualAddress;
memcpy_s(temp_ptr, MAX(my_data.my_section[0]->SizeOfRawData, my_data.my_section[0]->Misc.VirtualSize), my_data.my_section[0]->VirtualAddress + (char*)my_data.Stretch_Data, MAX(my_data .my_section[0]->SizeOfRawData, my_data.my_section[0]->Misc.VirtualSize));

Comebine_Data.my_optional->SizeOfImage + = Section_Align(MAX(my_data.my_section[0]->SizeOfRawData, my_data.my_section[0]->Misc.VirtualSize), my_data);

Comebine_Data.my_section[my_data.my_file->NumberOfSections - 1]->SizeOfRawData + = File_Align(MAX(my_data.my_section[0]->SizeOfRawData, my_data.my_section[0]->Misc.VirtualSize), my_data);
Comebine_Data.my_section[my_data.my_file->NumberOfSections - 1]->Misc.VirtualSize = Section_Align(Comebine_Data.my_section[my_data.my_file->NumberOfSections - 1]->Misc.VirtualSize, my_data) + Section_Align(MAX(my_data.my_section [0]->SizeOfRawData, my_data.my_section[0]->Misc.VirtualSize), my_data);

FILE* my_file;
if (fopen_s( & amp;my_file, filename, "wb") != 0)
{
cout << "Failed to open file" << endl;
return;
}

Shrink_PE(Comebine_Data);
Analyze_PE(Comebine_Data, 3);

fwrite(Comebine_Data.Shrink_Data, 1, _msize(Comebine_Data.Shrink_Data), my_file);
cout << "Write successfully!" << endl;

fclose(my_file);
}


void PE::Expand_Section(Data & my_data, char* filename)
{
this->Stretch_PE(my_data);
unsigned Size = 0;//Expand the new file size after the holiday
Size = my_data.my_optional->ImageBase + Section_Align(MAX(my_data.my_section[0]->SizeOfRawData, my_data.my_section[0]->Misc.VirtualSize), my_data);

Data Expand_Data;
Expand_Data.Stretch_Data = (void*)malloc(Size);
memset(Expand_Data.Stretch_Data, 0, Size);
memcpy_s(Expand_Data.Stretch_Data, _msize(my_data.Stretch_Data), my_data.Stretch_Data, _msize(my_data.Stretch_Data));

Analyze_PE(Expand_Data, 2);

Expand_Data.my_section[my_data.my_file->NumberOfSections - 1]->SizeOfRawData = Section_Align(MAX(my_data.my_section[0]->SizeOfRawData, my_data.my_section[0]->Misc.VirtualSize), my_data) + Section_Align(MAX (my_data.my_section[my_data.my_file->NumberOfSections - 1]->SizeOfRawData, my_data.my_section[my_data.my_file->NumberOfSections - 1]->Misc.VirtualSize), my_data);
Expand_Data.my_section[my_data.my_file->NumberOfSections - 1]->Misc.VirtualSize = Expand_Data.my_section[my_data.my_file->NumberOfSections - 1]->SizeOfRawData;

Expand_Data.my_optional->SizeOfImage + = Section_Align(MAX(my_data.my_section[0]->SizeOfRawData, my_data.my_section[0]->Misc.VirtualSize), my_data);

void* Temp_Ptr = (char*)Expand_Data.Stretch_Data + Expand_Data.my_section[Expand_Data.my_file->NumberOfSections - 1]->VirtualAddress + Section_Align(MAX(my_data.my_section[Expand_Data.my_file->NumberOfSections - 1]->SizeOfRawData, my_data.my_section[Expand_Data.my_file->NumberOfSections - 1]->Misc.VirtualSize), my_data);
int temp_size = Section_Align(MAX(my_data.my_section[0]->SizeOfRawData, my_data.my_section[0]->Misc.VirtualSize), my_data);
void* Temp_Ptr2 = (char*)my_data.Stretch_Data + my_data.my_section[0]->VirtualAddress;

memcpy_s(Temp_Ptr, temp_size, Temp_Ptr2, temp_size);


Shrink_PE(Expand_Data);

FILE* my_file;
if (fopen_s( & amp;my_file, filename, "wb") != 0)
{
cout << "Failed to open file!" << endl;

}
else
{
Size = _msize(Expand_Data.Shrink_Data);
fwrite(Expand_Data.Shrink_Data, 1, Size, my_file);
cout << "Write successfully!" << endl;
}
fclose(my_file);
}


int PE::Section_Align(int temp, Data & my_data)
{
int i = 0;
while (temp > i * my_data.my_optional->SectionAlignment)
{
i + + ;
}
return i * my_data.my_optional->SectionAlignment;

}

int PE::File_Align(int temp, Data & my_data)
{
int i = 0;
while (temp > i * my_data.my_optional->FileAlignment)
{
i + + ;
}
return i * my_data.my_optional->FileAlignment;
}

void PE::New_Section(char* filename, Data & my_data)
{
unsigned int Size; //Size is the size of the new file, which is the larger of the original file size plus .VirtualSize and SizeOfRawData
Size = my_data.my_optional->SizeOfHeaders;
for (int i = 0; i < my_data.my_file->NumberOfSections; i + + )
{
Size + = my_data.my_section[i]->SizeOfRawData;
}
Size + = my_data.my_section[0]->SizeOfRawData;//This is the final size of the new file

Data New_Data;
New_Data.Before_Stretch_Data = (void*)malloc(Size * 1);
memset(New_Data.Before_Stretch_Data, 0, Size);
memcpy_s(New_Data.Before_Stretch_Data, Size, my_data.Before_Stretch_Data, Size - my_data.my_section[0]->SizeOfRawData);//Copy the original file over

Analyze_PE(New_Data, 1);//Let the dos, file, optional, section of New_Data have data

//Copy the new section table
void* Temp_ptr1 = (char*)my_data.Before_Stretch_Data + 0x98 + my_data.my_file->SizeOfOptionalHeader;
void* Temp_ptr2 = (char*)New_Data.Before_Stretch_Data + 0x98 + my_data.my_file->SizeOfOptionalHeader + my_data.my_file->NumberOfSections * 0x28;
memcpy_s(Temp_ptr2, 0x28, Temp_ptr1, 0x28);
//Copy new section
Temp_ptr1 = (char*)my_data.Before_Stretch_Data + my_data.my_optional->SizeOfHeaders;//points to the .text segment
Temp_ptr2 = (char*)New_Data.Before_Stretch_Data + Size - my_data.my_section[0]->SizeOfRawData;

memcpy_s(Temp_ptr2, my_data.my_section[0]->SizeOfRawData, Temp_ptr1, my_data.my_section[0]->SizeOfRawData);//Copy the .text section as a new section

//Next, we need to change the various data of the Header
New_Data.my_file->NumberOfSections + + ;
New_Data.my_optional->SizeOfImage + = my_data.my_section[0]->SizeOfRawData;

Analyze_PE(New_Data, 1);
New_Data.my_section[New_Data.my_file->NumberOfSections - 1]->PointerToRawData = New_Data.my_section[New_Data.my_file->NumberOfSections - 2]->PointerToRawData + New_Data.my_section[New_Data.my_file->NumberOfSections - 2]->SizeOfRawData ;
int size;
if (New_Data.my_section[New_Data.my_file->NumberOfSections - 2]->Misc.VirtualSize >= New_Data.my_section[New_Data.my_file->NumberOfSections - 2]->SizeOfRawData)
{
size = New_Data.my_section[New_Data.my_file->NumberOfSections - 2]->Misc.VirtualSize;
}
else
{
size = New_Data.my_section[New_Data.my_file->NumberOfSections - 2]->SizeOfRawData;
}
size = size / my_data.my_optional->SectionAlignment + my_data.my_optional->SectionAlignment;
New_Data.my_section[New_Data.my_file->NumberOfSections - 1]->VirtualAddress = New_Data.my_section[New_Data.my_file->NumberOfSections - 2]->VirtualAddress + size;

FILE* my_file;
if (fopen_s( & amp;my_file, filename, "wb") == 0)
{
fwrite(New_Data.Before_Stretch_Data, 1, Size, my_file);
cout << "Write successfully!" << endl;
return;
}
else
{
cout << "Failed to open file" << endl;
return;
}
fclose(my_file);
}


void PE::Readfile(char* filename, Data & my_data)
{
unsigned int size;
FILE* datafile;
void* data;
\t//open a file
if (fopen_s( & amp;datafile, filename, "rb") != 0)
{
cout << "Failed to open file" << endl;
return;
}


else
{
//Get the size of the file
cout << "Open file successfully!" << endl;
fseek(datafile, 0, SEEK_END);
size = ftell(datafile);
fseek(datafile, 0, SEEK_SET);
if (size == -1L)
{
cout << "File size judgment failed!" << endl;
return;
}

//Apply for memory space to save the file content
my_data.Before_Stretch_Data = (void*)malloc(size * sizeof(char));

if (fread_s(my_data.Before_Stretch_Data, size, sizeof(char), size, datafile) == 0)
{
cout << "Failed to write data!" << endl;
return;
}
cout << "Writing data successfully, obtaining Data successfully!" << endl;
return;
}

}

//Analyze PE structure
void PE::Analyze_PE(Data & amp; data, int num)
{
if (num == 1)
{
if (data.Before_Stretch_Data != nullptr)
{
DWORD* Temp_ptr = (DWORD*)data.Before_Stretch_Data;
data.my_dos = (PIMAGE_DOS_HEADER)Temp_ptr;

Temp_ptr = (DWORD*)((char*)data.Before_Stretch_Data + data.my_dos->e_lfanew);
Temp_ptr + + ;
data.my_file = (PIMAGE_FILE_HEADER)Temp_ptr;

Temp_ptr = (DWORD*)((char*)Temp_ptr + 0x14);
data.my_optional = (PIMAGE_OPTIONAL_HEADER)Temp_ptr;


Temp_ptr = (DWORD*)((char*)data.my_optional + data.my_file->SizeOfOptionalHeader);
data.my_section = (PIMAGE_SECTION_HEADER*)malloc(sizeof(PIMAGE_SECTION_HEADER) * data.my_file->NumberOfSections);
memset(data.my_section, 0, sizeof(PIMAGE_SECTION_HEADER) * data.my_file->NumberOfSections);
for (int i = 0; i < data.my_file->NumberOfSections; i + + )
{
data.my_section[i] = (PIMAGE_SECTION_HEADER)Temp_ptr;
Temp_ptr = (DWORD*)((char*)Temp_ptr + 0x28);
}
return;
}
cout << "Failed to analyze PE structure!" << endl;
}

if (num == 2)
{
if (data.Stretch_Data != nullptr)
{
DWORD* Temp_ptr = (DWORD*)data.Stretch_Data;
data.my_dos = (PIMAGE_DOS_HEADER)Temp_ptr;

Temp_ptr = (DWORD*)((char*)data.Stretch_Data + data.my_dos->e_lfanew);
Temp_ptr + + ;
data.my_file = (PIMAGE_FILE_HEADER)Temp_ptr;

Temp_ptr = (DWORD*)((char*)Temp_ptr + 0x14);
data.my_optional = (PIMAGE_OPTIONAL_HEADER)Temp_ptr;

Temp_ptr = (DWORD*)((char*)data.my_optional + data.my_file->SizeOfOptionalHeader);
data.my_section = nullptr;
data.my_section = (PIMAGE_SECTION_HEADER*)malloc(sizeof(PIMAGE_SECTION_HEADER) * data.my_file->NumberOfSections);
for (int i = 0; i < data.my_file->NumberOfSections; i + + )
{
data.my_section[i] = (PIMAGE_SECTION_HEADER)Temp_ptr;
Temp_ptr = (DWORD*)((char*)Temp_ptr + 0x28);
}
return;
}
cout << "Failed to analyze PE structure!" << endl;
}

if (num == 3)
{
if (data.Shrink_Data != nullptr)
{
DWORD* Temp_ptr = (DWORD*)data.Shrink_Data;
data.my_dos = (PIMAGE_DOS_HEADER)Temp_ptr;

Temp_ptr = (DWORD*)((char*)data.Shrink_Data + data.my_dos->e_lfanew);
Temp_ptr + + ;
data.my_file = (PIMAGE_FILE_HEADER)Temp_ptr;

Temp_ptr = (DWORD*)((char*)Temp_ptr + 0x14);
data.my_optional = (PIMAGE_OPTIONAL_HEADER)Temp_ptr;

Temp_ptr = (DWORD*)((char*)data.my_optional + data.my_file->SizeOfOptionalHeader);
data.my_section = (PIMAGE_SECTION_HEADER*)malloc(sizeof(PIMAGE_SECTION_HEADER) * data.my_file->NumberOfSections);
for (int i = 0; i < data.my_file->NumberOfSections; i + + )
{
data.my_section[i] = (PIMAGE_SECTION_HEADER)Temp_ptr;
Temp_ptr = (DWORD*)((char*)Temp_ptr + 0x28);
}
return;
}
cout << "Failed to analyze pe structure!" << endl;
}

}

//Stretch the PE structure. Pay attention to the definition of PIMAGE_XXX_HEADER. They are pointers to the structure.
void PE::Stretch_PE(Data & my_data)
{
unsigned Memory_Size = 0;
Memory_Size = my_data.my_optional->SizeOfImage;
my_data.Stretch_Data = (void*)malloc(sizeof(char) * Memory_Size);
memset(my_data.Stretch_Data, 0, Memory_Size);
void* temp_before_stretch_data_ptr = my_data.Before_Stretch_Data;
int size_of_dos = 0x40;
int size_of_junk = 0x40;
int size_of_file = 0x18;
unsigned Size_Of_Optional = my_data.my_file->SizeOfOptionalHeader;
unsigned Size_Of_Section = 0x28;
unsigned Size_Of_Header = my_data.my_optional->SizeOfHeaders;//Not yet aligned
memcpy_s(my_data.Stretch_Data, Memory_Size, my_data.Before_Stretch_Data, Size_Of_Header);
void* temp_stretch_data = my_data.Stretch_Data;
//Now calculate the size of the head after alignment
int Size = Size_Of_Header % my_data.my_optional->SectionAlignment;
Size_Of_Header = my_data.my_optional->SectionAlignment * Size;


for (int i = 0; i < my_data.my_file->NumberOfSections; i + + )
{
temp_stretch_data = (void*)((char*)my_data.Stretch_Data + my_data.my_section[i]->VirtualAddress);
temp_before_stretch_data_ptr = (void*)((char*)my_data.Before_Stretch_Data + my_data.my_section[i]->PointerToRawData);
memcpy_s(temp_stretch_data, my_data.my_section[i]->SizeOfRawData, temp_before_stretch_data_ptr, my_data.my_section[i]->SizeOfRawData);
}
cout << "Stretching successfully" << endl;
}



void PE::Shrink_PE(Data & amp; my_data)
{
unsigned int Size = 0;
Size = my_data.my_section[my_data.my_file->NumberOfSections - 1]->PointerToRawData + my_data.my_section[my_data.my_file->NumberOfSections - 1]->SizeOfRawData;
my_data.Shrink_Data = (void*)malloc(Size);
memset(my_data.Shrink_Data, 0, Size);
//Shrink from Stretch_Data

//Copy Heads
memcpy_s(my_data.Shrink_Data, my_data.my_optional->SizeOfHeaders, my_data.Stretch_Data, my_data.my_optional->SizeOfHeaders);

//Copy section
void* temp_shrink_data_ptr = my_data.Shrink_Data;
void* temp_stretch_data_ptr = my_data.Stretch_Data;
for (int i = 0; i < my_data.my_file->NumberOfSections; i + + )
{
temp_shrink_data_ptr = (void*)((char*)my_data.Shrink_Data + my_data.my_section[i]->PointerToRawData);
temp_stretch_data_ptr = (void*)((char*)my_data.Stretch_Data + my_data.my_section[i]->VirtualAddress);
memcpy_s(temp_shrink_data_ptr, my_data.my_section[i]->SizeOfRawData, temp_stretch_data_ptr, my_data.my_section[i]->SizeOfRawData);
}
cout << "Reduce successfully" << endl;
return;

}


int main()
{
char filename[100] = "Dll1.dll";
PE my_pe;
Data my_data;
my_pe.Readfile(filename, my_data);
my_pe.Analyze_PE(my_data, 1); //char* & amp; Data, PIMAGE_DOS_HEADER & amp; dos, PIMAGE_FILE_HEADER & amp; file, PIMAGE_OPTIONAL_HEADER32 & amp; optional, PIMAGE_SECTION_HEADER* & amp; section
my_pe.Stretch_PE(my_data);
my_pe.Shrink_PE(my_data);
my_pe.Analyze_Data_Directory(my_data);
my_pe.Print_IMAGE_DATA_DIRECTORY(my_data);
my_pe.Print_ExportTable(my_data);
cout << "The converted file offset is" << hex << my_pe.Rva_To_Foa(0x3100, my_data) << endl;
//((void(*)())addr)();//Call
HMODULE hDll = GetModuleHandleA("Dll1.dll");
my_pe.GetFunctionAddrByName(my_data, (char*)"Print");
my_pe.GetFunctionAddrByOrdinal(my_data, 14);
return 0;
}

Note: There is a pitfall that I have stepped into and I want to share it with you.
This is what I originally wanted to do:
Apply for a heap, which stores Dll data. Through analysis, you can find the offset of the function in the Dll file. Then I thought, this offset, plus the base address of the heap, is assigned to a function pointer. Isn’t that straightforward? Can it be called?
As a result, I tried for a long time, and finally obtained the real address of the function, which was correct. The result was that it could not run, tnnd. After working on it for a long time, I finally found out after some advice from an expert that the heap also needed to have permission to run. It seemed that the heap was not running. permissions. Hey, it’s fucked up, woo hoo.

The knowledge points of the article match the official knowledge files, and you can further learn related knowledge. Algorithm skill tree Home page Overview 56,481 people are learning the system