dll 分析

     此代码主要是分析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, &section_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;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值