PE文件 得到导入表和导出表 代码加注释


主要目的 熟悉PE文件 创建句柄 映射pe文件到地址空间 创建文件视图 得到文件的首地址 PIMAGE 然后对各个结构进行初始化主要代码导入表void GETIMPORT(PVOID PIMAGE)
{
PBYTE PBIMAGE = (PBYTE)PIMAGE;
DWORD IMPORTRAW = 0;
DWORD CNTDLL=0;
DWORD IMPORTRVA = pe.DATA[1].VirtualAddress;
PIMAGE_SECTION_HEADER PIMPORTSEC;
for (int i=0; iNumberOfSections; i++)
{
if (IMPORTRVA>=a[i] && IMPORTRVA {
IMPORTRAW = IMPORTRVA – pe.SECTION[i].VirtualAddress + pe.SECTION[i].PointerToRawData; //RVA->RAW计算文件偏移
PIMPORTSEC = &pe.SECTION[i]; //记录输入表所在节
}
}
if(!IMPORTRVA)
{
MessageBox(NULL,”IMPORT IS EMOPTY”,”ERROR”,NULL);
return;
}
PIMAGE_IMPORT_DESCRIPTOR IMPORT = PIMAGE_IMPORT_DESCRIPTOR(IMPORTRAW+PBIMAGE); //使用输入表的文件地址
//因为一般OriginalFirstThunk不为0 所以采用这个判断条件 其实是不严谨的
//有的程序OriginalFirstThunk是为0的 这样的话 就采用FIRSTTHUNK来循环遍历 在此未考虑为0的情况
//不过也用了FIRSTTHUNK 目的是利用它得到每个函数的 RVA
while (0 != IMPORT->OriginalFirstThunk) //判断dll是否结束
{
LPDWORD THUNK =(LPDWORD) (IMPORT->OriginalFirstThunk – PIMPORTSEC->VirtualAddress + PIMPORTSEC- >PointerToRawData+PBIMAGE);
LPDWORD FIRSTTHUNK = (LPDWORD)IMPORT->FirstThunk;//THUNK 使用OriginalFirstThunk 来遍历每一个 PIMAGE_THUNK_DATA (四个字节大小) 的结构
//FIRSTTHUNK 使用FirstThunk 来遍历每一个 PIMAGE_THUNK_DATA (四个字节大小) 的结构
//在这里使用它找到每个函数的RVA
/*****************************************************************************************************/
//要想得到dll 或者 函数的名字 都要计算出其在磁盘上的位置 方可取出 LPDWORD DLLNAME = (LPDWORD)(IMPORT->Name – PIMPORTSEC->VirtualAddress + PIMPORTSEC->PointerToRawData + PBIMAGE);
CHAR NAMEBUF[20];
sprintf(NAMEBUF,”%s”,DLLNAME);
DWORD NAMEBUFFER = strlen(NAMEBUF);
DWORD STYLE;
WriteFile(IMPORTHANDLE,”rn”,2,&STYLE,NULL);
WriteFile(IMPORTHANDLE,NAMEBUF,NAMEBUFFER,&NAMEBUFFER,NULL);
WriteFile(IMPORTHANDLE,”rn”,2,&NAMEBUFFER,NULL);
WriteFile(IMPORTHANDLE,”rn”,2,&NAMEBUFFER,NULL);/* 这段代码是 得到每个引入的dll的名字 并且在循环输出函数索引和名字之前 输出此函数所在的这个dll名字*/
/*****************************************************************************************************/
//THUNK指针保存的值是OriginalFirstThunk指向的PIMAGE_THUNK_DATA结构 即这是判断函数是否结束
// *THUNK就是 PIMAGE_THUNK_DATA (四个字节大小) 结构的内容
// 此内容是一个RVA 指向PIMAGE_IMPORT_BY_NAME 转换成 RAW后 所保存的内容就是函数名字和索引 while(*THUNK)
{
if (*THUNK & IMAGE_ORDINAL_FLAG32) //最高位是1 是序号引入
{
DWORD index = (*THUNK & 0x7fffffff);
CHAR BUFFER[20];
DWORD REALBUFFER;
sprintf(BUFFER,”0x%x”,index);
WriteFile(IMPORTHANDLE,BUFFER,4,&REALBUFFER,NULL);
WriteFile(IMPORTHANDLE,”r”,2,&REALBUFFER,NULL);

CHAR FRISTTHUNK[20];
sprintf(FRISTTHUNK,”0x%x”,FIRSTTHUNK);
WriteFile(IMPORTHANDLE,FRISTTHUNK,8,&REALBUFFER,NULL);
WriteFile(IMPORTHANDLE,”rn”,2,&REALBUFFER,NULL);
}
else
{
/*
计算得到 PIMAGE_IMPORT_BY_NAME 结构的磁盘位置
*THUNK就是 PIMAGE_THUNK_DATA (四个字节大小) 结构的内容
此内容是一个RVA 指向PIMAGE_IMPORT_BY_NAME 结构 将其转换成 RAW后 所保存的内容就是索引和函数名字
FIRSTTHUNK 此时也是PIMAGE_THUNK_DATA的内容
当加载到内存后 才会 被换成 函数的真实地址 所以在这里只是取出 FIRSTTHUNK 的值 即一个RVA
因为此时 *FIRSTTHUNK 的内容跟 *THUNK 是一模一样的
*/ PIMAGE_IMPORT_BY_NAME NAME = PIMAGE_IMPORT_BY_NAME(*THUNK – PIMPORTSEC->VirtualAddress + PIMPORTSEC->PointerToRawData + PBIMAGE);
/*********************************************************************************************************************/
// 输出 PIMAGE_IMPORT_BY_NAME 结构中的HINT CHAR BUFFER[10];
DWORD REALBUFFER;
sprintf(BUFFER,”0x%x”,NAME->Hint);
WriteFile(IMPORTHANDLE,BUFFER,5,&REALBUFFER,NULL);
WriteFile(IMPORTHANDLE,”r”,2,&REALBUFFER,NULL);
/*********************************************************************************************************************/
//输出 PIMAGE_IMPORT_BY_NAME 结构中的NAME CHAR BUF[30];
DWORD LEN ;
sprintf(BUF,”%s”,NAME->Name);
LEN=strlen(BUF)+1;
WriteFile(IMPORTHANDLE,NAME->Name,LEN,&REALBUFFER,NULL);

/*********************************************************************************************************************/
//输出 PIMAGE_THUNK_DATA 结构的内容 即 指向 PIMAGE_IMPORT_BY_NAME 结构的RVA CHAR THUNKBUF[20];
sprintf(THUNKBUF,”0x%x”,*THUNK);
WriteFile(IMPORTHANDLE,THUNKBUF,8,&REALBUFFER,NULL);
WriteFile(IMPORTHANDLE,”r”,2,&REALBUFFER,NULL);/*********************************************************************************************************************/
//输出 FRISTTHUNK 的值 即一个当pe加载时指向引入函数真实地址的 RVA 初始值为 IMPORT->FirstThunk; 指针加1即可 CHAR FRISTTHUNK[20];
sprintf(FRISTTHUNK,”0x%x”,FIRSTTHUNK);
WriteFile(IMPORTHANDLE,FRISTTHUNK,6,&REALBUFFER,NULL);
WriteFile(IMPORTHANDLE,”rn”,2,&REALBUFFER,NULL);/*********************************************************************************************************************/
}

THUNK++; // 指针加1 也就是跳过一个 PIMAGE_THUNK_DATA 结构 扫描下一个函数
FIRSTTHUNK++; //获得每个引入函数的RVA
}
IMPORT++;//扫描下一个dll
CNTDLL++; //记录dll个数
}
}导出表
void GETEXPORT(PVOID PIMAGE)
{
PBYTE PBIMAGE = (PBYTE)PIMAGE;
DWORD EXPORTRVA = pe.DATA[0].VirtualAddress;
PIMAGE_SECTION_HEADER EXPORTSECT;
PIMAGE_EXPORT_DIRECTORY EXPORT;
DWORD EXPORTRAW;
for(int i=0; iNumberOfSections; i++)
{
if (EXPORTRVA>=a[i] && EXPORTRVA {
EXPORTRAW = EXPORTRVA – pe.SECTION[i].VirtualAddress + pe.SECTION[i].PointerToRawData; //RVA->RAW
EXPORTSECT = &pe.SECTION[i];
}
}
EXPORT = PIMAGE_EXPORT_DIRECTORY(EXPORTRAW+PBIMAGE); //使用输出表的文件地址 if(!EXPORTRVA)
{
MessageBox(NULL,”EXPORT IS EMOPTY”,”ERROR”,NULL);
return; } printf(“Base = 0x%xn”,EXPORT->Base);
printf(“NumberOfFunctions = 0x%xn”,EXPORT->NumberOfFunctions);
printf(“NumberOfNames = 0x%xn”,EXPORT->NumberOfNames);
printf(“AddressOfFunctions = 0x%xn”,EXPORT->AddressOfFunctions);
printf(“AddressOfNameOrdinals = 0x%xn”,EXPORT->AddressOfNameOrdinals);
printf(“AddressOfNames = 0x%xn”,EXPORT->AddressOfNames);
DWORD DLLNAME = (DWORD)(EXPORT->Name – EXPORTSECT->VirtualAddress + EXPORTSECT->PointerToRawData + PBIMAGE);
//输出名字之前 必须得到名字RVA 的RAW 并加上 文件首地址 得到文件地址
printf(“Name = %sn”,DLLNAME); LPDWORD NAMEADDRESS = (LPDWORD)(EXPORT->AddressOfNames – EXPORTSECT->VirtualAddress + EXPORTSECT->PointerToRawData + PBIMAGE);
LPWORD ADDNAMEORD = (LPWORD)(EXPORT->AddressOfNameOrdinals – EXPORTSECT->VirtualAddress + EXPORTSECT->PointerToRawData + PBIMAGE);
LPDWORD FUNCTIONADDRESS = (LPDWORD)(EXPORT->AddressOfFunctions – EXPORTSECT->VirtualAddress + EXPORTSECT->PointerToRawData + PBIMAGE); for(DWORD j=0; jNumberOfNames; j++) {
// 计算名字所在的文件地址 通过两步找到的 RVA -> RAW(名字的RVA2) RVA2->RAW2(名字)
PDWORD NAME = (PDWORD)(*NAMEADDRESS – EXPORTSECT->VirtualAddress + EXPORTSECT->PointerToRawData + PBIMAGE);

/*********************************************************************************************************************/
/**********************函数的名字 得到其文件地址很重要********************************************************/
DWORD BUF;
CHAR NAMEBUF[50];
DWORD LEN;
sprintf(NAMEBUF,”%s”,NAME);
LEN=strlen(NAMEBUF);
WriteFile(EXPORTHANDLE,NAME,LEN,&BUF,NULL);
WriteFile(EXPORTHANDLE,”r”,2,&BUF,NULL);
WriteFile(EXPORTHANDLE,”r”,2,&BUF,NULL);
/*********************************************************************************************************************/
/**********************索引号 一步可以得到其内容**************************************************************/
sprintf(NAMEBUF,”0x%04x”,*ADDNAMEORD+1);
WriteFile(EXPORTHANDLE,NAMEBUF,6,&BUF,NULL);
WriteFile(EXPORTHANDLE,”r”,2,&BUF,NULL);
WriteFile(EXPORTHANDLE,”r”,2,&BUF,NULL);
/*******************免费云主机域名**************************************************************************************************/
/**********************函数的RVA 类似于索引号的求法**********************************************************************/ sprintf(NAMEBUF,”0x%08x”,*FUNCTIONADDRESS);
WriteFile(EXPORTHANDLE,NAMEBUF,10,&BUF,NULL);
WriteFile(EXPORTHANDLE,”rn”,2,&BUF,NULL);/*********************************************************************************************************************/ NAMEADDRESS++;
ADDNAMEORD++;
FUNCTIONADDRESS++; }}结束。

相关推荐: 利用ext3grep恢复误删除文件

点击下载软件:ext3grep1.查看所需的相关库[root@ns2~]#rpm-qa|grepe2fsprogse2fsprogs-libs-1.39-8.el5e2fsprogs-1.39-8.el5e2fsprogs-devel-1.39-8.el5注:…

免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。

(0)
打赏 微信扫一扫 微信扫一扫
上一篇 02/01 11:58
下一篇 02/01 11:58