|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
#include <iostream.h>
#include <stdio.h>
#include <windows.h>
void DOS_tou(){
FILE *pFile = NULL;
char * buffer;
int nFileLength = 0;
pFile = fopen("mfc001.exe", "r+b");
cout<<"pFile= "<<pFile<<endl;;
/*
原型: long ftell(FILE *stream); 因为 ftell() 返回long型
功能: 返回当前文件位置。使用fseek函数后再调用函数ftell()就能非常容易地确定文件的当前位置。
用法: ftell(fp); 利用函数 ftell() 能方便地知道一个文件的长。如以下语句序列:
fseek(fp, 0L, SEEK_END); 首先将文件的当前位置移到文件的末尾,
len =ftell(fp); 然后调用函数ftell()获得当前位置相对于文件首的位移,该位移值等于文件所含字节数
*/
fseek(pFile,0,SEEK_END); //定位到文件末尾
nFileLength = ftell(pFile); //函数 ftell() 用于得到文件指针当前位置相对于文件首的偏移字节数
cout<<"nFileLength="<<nFileLength<<endl;
rewind(pFile); //将读写位置指针重置到文件开头
//rewind函数作用等同于 (void)fseek(stream, 0L, SEEK_SET); 用 法: void rewind(FILE *stream);
int imageLength = nFileLength * sizeof(char)+1 ;
buffer = (char *)malloc(imageLength); //申请nFileLength*(乘以) char个字节空间
memset(buffer, 0, nFileLength * sizeof(char)+1); //将已开辟内存空间 buffer 的首 nFileLength * sizeof(char)+ 1 个字节的值设为值0。
// cout<<"===="<<pFile<<endl;
fread(buffer, 1, imageLength, pFile);
/*
buffer 指向存储数据的缓冲区
1 读取的基本单元字节大小,单位是字节,一般是 buffer 缓冲的单位大小
imageLength 要读取的数据块数目
pFile 指向文件对象的指针
返回值: 成功读取的元素个数
*/
PIMAGE_DOS_HEADER ReadDosHeader = (PIMAGE_DOS_HEADER)buffer;
cout<< "DOS_e_magic:\t"<<hex<< ReadDosHeader->e_magic<<endl;
cout<<"DOS_e_lfanew:\t"<<hex<< ReadDosHeader->e_lfanew<<endl;
if (buffer != NULL) // 释放内存
{
free(buffer);
buffer = NULL;
}
// 最后不要忘记关闭文件
fclose(pFile);
}
//======================================上面这个dos_tou函数 可以删除 只是注释测试而已=================================================
char* Base_memset(FILE * pFile ){
char * buffer;
int nFileLength = 0;
fseek(pFile,0,SEEK_END);
nFileLength = ftell(pFile);
rewind(pFile);
int imageLength = nFileLength * sizeof(char)+1;
buffer = (char *)malloc(imageLength);
memset(buffer,0,nFileLength * sizeof(char)+1);
fread(buffer,1,imageLength,pFile);
return buffer;
}
PIMAGE_DOS_HEADER DOS_tou2(FILE * pFile){
char * buffer = Base_memset(pFile);
PIMAGE_DOS_HEADER ReadDosHeader = (PIMAGE_DOS_HEADER)buffer;
cout<< "DOS_e_magic:\t"<<hex<< ReadDosHeader->e_magic<<endl;
cout<<"DOS_e_lfanew:\t"<<hex<< ReadDosHeader->e_lfanew<<endl;
return ReadDosHeader;
}
PIMAGE_NT_HEADERS PE_tou(FILE * pFile, PIMAGE_DOS_HEADER ReadDosHeader){
char * buffer = Base_memset(pFile);
PIMAGE_NT_HEADERS ReadNTHeader;
ReadNTHeader = (PIMAGE_NT_HEADERS)(buffer + ReadDosHeader->e_lfanew);
cout<<endl<<"==================PE_Signature标识================="<<endl;
cout<<"PE_biaozhi标志:\t"<<hex<<ReadNTHeader->Signature<<endl;
cout<<endl<<"==================PE_FileHeader标准头================="<<endl;
cout<<"PE_Machine_CPU:\t"<<hex<<ReadNTHeader->FileHeader.Machine<<endl;
cout<<"PE_NumberOfSections区段数:\t\t"<<hex<<ReadNTHeader->FileHeader.NumberOfSections<<endl;
cout<<"PE_SizeOfOptionalHeader扩展头大小:\t"<<hex<<ReadNTHeader->FileHeader.SizeOfOptionalHeader<<endl;
cout<<"PE_Characteristics 文件属性 :\t\t"<<hex<<ReadNTHeader->FileHeader.Characteristics<<endl;
cout<<endl<<"==================PE_OptionalHeader扩展头================="<<endl;
cout<<"PE_Magic 32/64:\t\t\t\t"<<hex<<ReadNTHeader->OptionalHeader.Magic<<endl;
cout<<"PE_AddressOfEntryPoint入口:\t\t"<<hex<<ReadNTHeader->OptionalHeader.AddressOfEntryPoint<<endl;
cout<<"PE_ImageBase 内存基址:\t\t\t"<<hex<<ReadNTHeader->OptionalHeader.ImageBase<<endl;
cout<<"PE_SectionAlignment内齐大小:\t\t"<<hex<<ReadNTHeader->OptionalHeader.SectionAlignment<<endl;
cout<<"PE_FileAlignment 文齐大小:\t\t"<<hex<<ReadNTHeader->OptionalHeader.FileAlignment<<endl;
cout<<"PE_SizeOfImage 内总大小:\t\t"<<hex<<ReadNTHeader->OptionalHeader.SizeOfImage<<endl;
cout<<"PE_SizeOfHeaders 文所头+节表大小:\t"<<hex<<ReadNTHeader->OptionalHeader.SizeOfHeaders<<endl;
cout<<"PE_CheckSum 校验和:\t\t"<<hex<<ReadNTHeader->OptionalHeader.CheckSum<<endl;
cout<<"PE_NumberOfRvaAndSizes 子结构体数组:\t"<<hex<<ReadNTHeader->OptionalHeader.NumberOfRvaAndSizes<<endl;
return ReadNTHeader;
}
void qu_kuai_duan(FILE * pFile, PIMAGE_DOS_HEADER ReadDosHeader){
cout<<endl<<"=======================遍历本程序中存在的区块段==========="<<endl;
char * buffer = Base_memset(pFile);
PIMAGE_NT_HEADERS ReadNTHeader; //PE = MZ+F0
ReadNTHeader = (PIMAGE_NT_HEADERS)(buffer + ReadDosHeader->e_lfanew); // 以上是定位PE头地址
cout<<"88888888888: "<<ReadDosHeader<<endl; //88888888888: 0x00440068
PIMAGE_SECTION_HEADER ReadSectionHeader = IMAGE_FIRST_SECTION(ReadNTHeader); //宏定义中IMAGE_FIRST_SECTION(ntheader)可以直接定位到区块段 PIMAGE_SECTION_HEADER
PIMAGE_FILE_HEADER pFileHeader = &ReadNTHeader->FileHeader; //为获取标准头中的区块段数量 NumberOfSections
for (int i=0; i<pFileHeader->NumberOfSections;i++)
{
cout<<"****************************"<<ReadSectionHeader[i].Name<<"***********************************"<<endl;
cout<<"VirtualSize节内中实大小:"<<ReadSectionHeader[i].Misc.VirtualSize<<"\t";
cout<<"VirtualAddress节区的内中起始地RVA:"<<ReadSectionHeader[i].VirtualAddress<<endl;
cout<<"SizeOfRawData节文中大小:"<<ReadSectionHeader[i].SizeOfRawData<<"\t";
cout<<"PointerToRawData节文中偏:"<<ReadSectionHeader[i].PointerToRawData<<endl;
cout<<"Characteristics节属性:"<<ReadSectionHeader[i].Characteristics<<endl<<endl;
}
/*
if (buffer != NULL) // 释放内存
{
free(buffer);
buffer = NULL;
}
// 最后不要忘记关闭文件
fclose(pFile);
*/
}
DWORD find_pan_yi(DWORD dwRva, char* buffer){
//dwRva 数据目录表中(的某个数据比如.rdata)的 VirtualAddress+xx32
//buffer 读取到的PE文件缓冲区= MZ_tou标识
// 两个头
PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)buffer; // DOS tou
PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)(pDos->e_lfanew + buffer); // (pDos->e_lfanew)F0 + MZ_tou标识 = PE标识地址)
//pSection本程序中区块表中第一个区表比如:[0]=.text, [1]=.rdata 的起始址
//本程序中的区块段
PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNt); //宏定义中IMAGE_FIRST_SECTION(ntheader)可以直接定位到区块段 PIMAGE_SECTION_HEADER
if (dwRva < pSection[0].VirtualAddress) //VirtualAddress节内中RVA 始地址,+ imageBase才是内中的真地
{
return dwRva;
}
for (int i =0; i<pNt->FileHeader.NumberOfSections;i++) //PE头中的标准头成员NumberOfSections区块段数量
{
//VirtualAddress节内中RVA 始地址+ 节内中真实大小
if (dwRva >= pSection[i].VirtualAddress && dwRva <= pSection[i].VirtualAddress+pSection[i].Misc.VirtualSize)
{
//计算 wdRVA 减到 [i]区块段头还肾多远=偏yi
//PointerToRawData区块段在文件中的偏移
//结果是区块段数据始地到文件的偏移
return dwRva- pSection[i].VirtualAddress + pSection[i].PointerToRawData;
}
}
return 0;
}
void ImportTable(FILE * pFile, PIMAGE_DOS_HEADER ReadDosHeader){
char * buffer = Base_memset(pFile);
PIMAGE_NT_HEADERS ReadNTHeader = PE_tou( pFile, ReadDosHeader);
// 1 定位第二张表(导入表): PE扩展头中最后一个成员(16子结构)起始位置+ 导入表的宏(宏=1)
PIMAGE_DATA_DIRECTORY pImportDir = (PIMAGE_DATA_DIRECTORY)(ReadNTHeader->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_IMPORT);
//
PIMAGE_IMPORT_DESCRIPTOR pImport = (PIMAGE_IMPORT_DESCRIPTOR)((pImportDir->VirtualAddress) + buffer); //2 实际入口地址+读取缓存的偏移(进入导入表各种Dll地址)
while(pImport->Name != NULL){
char *szDllName = (char*)((pImport->Name)+buffer); //Name is RVA
cout<<szDllName<<":"<<endl;
cout<<" OriginalFirstThunk指向INT表:\t"<<pImport->OriginalFirstThunk<<endl; // 打印各个dll的 IMAGE_IMPORT_DESCRIPTOR 结构成员
cout<<" FirstThunk指向IAT表: \t"<<pImport->FirstThunk<<endl<<endl;
// cout<<"-----------某dll在INT目录中的所有成员地址RVA:"<<endl;
PIMAGE_THUNK_DATA pInt = (PIMAGE_THUNK_DATA)((pImport->OriginalFirstThunk)+buffer); // 3 从成员 OriginalFirstThunk 进入 IMAGE_THUNK_DATA (INT表)
// IMAGE_THUNK_DATA INT表每个成员4个字节(都是个地址)
DWORD index = 0;
DWORD IprotOffset = 0;
while(pInt->u1.Ordinal != 0){ // 如果IMAGE_THUNK_DATA (INT表某个成员) 是0那么就是结束了
IprotOffset = pImport->OriginalFirstThunk; //以进入IMAGE_DATA_DIRECTORY中的 VirtualAddress 指向的的 OriginalFirstThunk 地址=INT
cout<<"ThunkRva: "<<pImport->OriginalFirstThunk+index<<"\t\t";
cout<<"ThunkOffset: "<<IprotOffset+index<<"\t";
index +=4; // 以上面的做INT做偏移4个字节一个成员 先不取值 【以下先判断在取值=函数地址 】
if((pInt->u1.Ordinal & 0x80000000) != 1){ // 如果是1:函数序号,否则是指向PIMAGE_IMPORT_BY_NAME的函数名称(首字母) [这里只取函数名]
//4 进入 PIMAGE_IMPORT_BY_NAME // 返回实际入口地址 + 缓冲区的偏移读数据(否则读1)
PIMAGE_IMPORT_BY_NAME pName = (PIMAGE_IMPORT_BY_NAME)(find_pan_yi(reinterpret_cast<unsigned long>(pInt->u1.AddressOfData), buffer)+buffer);
cout<<"ThunkValue函数内址:"<<pInt->u1.Function<<"\t"; //函数的内存地址
cout<<"函数序号:"<<pName->Hint<<"\t"; //函数的内存地址取值: 头2个字节就是函数序号接着一个字节是函数名称首字母
cout<<"API: "<<pName->Name<<endl;
}
pInt++;
}
pImport++;
}
}
int main(){
FILE * pFile = NULL;
pFile = fopen("mfc001.exe","r+b");
PIMAGE_DOS_HEADER ReadDosHeader = DOS_tou2(pFile);
PIMAGE_NT_HEADERS ReadNTHeader = PE_tou( pFile, ReadDosHeader);
qu_kuai_duan(pFile, ReadDosHeader);
ImportTable(pFile, ReadDosHeader);
return 0;
}
|
|