此代码主要是分析dll的导入和导出部分。
在读取各区段时判断import_table 和export_table,并实现VirtualAddress到实地址的转换
参考:http://www.heibai.net/article/info/info.php?infoid=38920
#include <Windows.h>
#include <iostream>
#include <string>
#include <io.h>
#include <fcntl.h>
using namespace std;
int main()
{
string path;
cout<<"输入dll文件路径:";
getline(cin, path);
HFILE file = _open(path.c_str(), _O_RDWR | _O_BINARY);
if(-1 == file)
{
cout<<"文件打开失败!"<<endl;
system("pause");
return 0;
}
_IMAGE_DOS_HEADER dos_header;
if(_read(file, &dos_header, sizeof(dos_header)) <= 0)
{
cout<<"Dos文件头读取失败!"<<endl;
system("pause");
return 0;
}
if(dos_header.e_magic != IMAGE_DOS_SIGNATURE)
{
cout<<"DOS_HEADER 错误的dos_magic标记!"<<endl;
system("pause");
return 0;
}
LONG peHeaderPtr = dos_header.e_lfanew;
_lseek(file, peHeaderPtr, SEEK_SET);
_IMAGE_NT_HEADERS pe_header;
if(_read(file, &pe_header, sizeof(pe_header)) <= 0)
{
cout<<"PE文件头读取失败!"<<endl;
system("pause");
return 0;
}
if(pe_header.Signature != IMAGE_NT_SIGNATURE)
{
cout<<"PE_HEADER 错误的pe_magic标记!"<<endl;
system("pause");
return 0;
}
DWORD numberOfSections = 0;// 区段的个数
DWORD sizeOfCode = 0;// 代码长度和
DWORD sectionAlignment = 0;// 内存中区段排列基数
DWORD fileAlignment = 0;// 磁盘上区段排列基数
DWORD exportVptr = pe_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
DWORD dx = 0;
DWORD exportPtr = 0;
DWORD importVptr = pe_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
DWORD importTableSize = pe_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size;
DWORD importDllNum = importTableSize / sizeof(_IMAGE_IMPORT_DESCRIPTOR);
importDllNum--;// 减1是因为Import_table的最后一个总为0
DWORD importDx = 0;
DWORD importPtr = 0;
numberOfSections = pe_header.FileHeader.NumberOfSections;
sizeOfCode = pe_header.OptionalHeader.SizeOfCode;
sectionAlignment = pe_header.OptionalHeader.SectionAlignment;
fileAlignment = pe_header.OptionalHeader.FileAlignment;
// 读取各区段
for(DWORD i = 0; i < numberOfSections; i++)
{
_IMAGE_SECTION_HEADER section_header;
if(_read(file, §ion_header, sizeof(section_header)) <= 0)
{
cout<<"SECTION头读取失败!"<<endl;
system("pause");
return 0;
}
cout<<"区段"<<i<<": "<<section_header.Name<<endl;
if(section_header.Characteristics & IMAGE_SCN_MEM_EXECUTE)
{
cout<<"此区段为可执行代码"<<endl;
}
// 判断export所在区域
if(section_header.VirtualAddress < exportVptr && exportPtr == 0)
{
if(section_header.VirtualAddress + section_header.SizeOfRawData > exportVptr)
{
dx = section_header.VirtualAddress - section_header.PointerToRawData;
exportPtr = exportVptr - dx;
cout<<"export_table在此区段"<<endl;
}
}
// 判断import所在区域
if(section_header.VirtualAddress < importVptr && importPtr == 0)
{
if(section_header.VirtualAddress + section_header.SizeOfRawData > importVptr)
{
importDx = section_header.VirtualAddress - section_header.PointerToRawData;
importPtr = importVptr - importDx;
cout<<"import_table在此区段"<<endl;
}
}
cout<<"区段大小:"<<section_header.SizeOfRawData<<endl<<endl;
}
_lseek(file, exportPtr, SEEK_SET);
_IMAGE_EXPORT_DIRECTORY export_header;
if(_read(file, &export_header, sizeof(export_header)) < 0)
{
cout<<"EXPORT头读取失败!"<<endl;
system("pause");
return 0;
}
cout<<"-----------------------导出信息-----------------------"<<endl;
cout<<"导出函数:"<<export_header.NumberOfFunctions<<endl;
DWORD seek = export_header.AddressOfNames - dx;
DWORD* arrNames = new DWORD[export_header.NumberOfNames];
_lseek(file, seek, SEEK_SET);
if(_read(file, arrNames, sizeof(DWORD) * export_header.NumberOfNames) < 0)
{
cout<<"name_table读取失败!"<<endl;
system("pause");
return 0;
}
char c;
for(DWORD i = 0; i < export_header.NumberOfNames; i++)
{
seek = arrNames[i] - dx;
_lseek(file, seek, SEEK_SET);
_read(file, &c, 1);
while(c != '\0')
{
cout<<c;
_read(file, &c, 1);
}
cout<<endl;
}
cout<<endl<<"-----------------------引用信息-----------------------"<<endl;
cout<<"引用Dll数:"<<importDllNum <<endl;
for(DWORD i = 0; i < importDllNum ; i++)
{
_lseek(file, importPtr + i * sizeof(_IMAGE_IMPORT_DESCRIPTOR), SEEK_SET);
_IMAGE_IMPORT_DESCRIPTOR import_header;
if(_read(file, &import_header, sizeof(import_header)) < 0)
{
cout<<"EXPORT头读取失败!"<<endl;
system("pause");
return 0;
}
seek = import_header.Name - importDx;
_lseek(file, seek, SEEK_SET);
_read(file, &c, 1);
while(c != '\0')
{
cout<<c;
_read(file, &c, 1);
}
cout<<endl;
}
cout<<endl;
system("pause");
return 0;
}