PEtools
// PETools.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
#include <malloc.h>
DWORD len=0; //记录文件读取时的大小 作为还原内存镜像缓冲区时的长度
//=======================================================================================================================================
/*将文件从硬盘读取到缓冲区中
参数1 :文件路径 参数2:接受读取数据的缓冲区的地址的指针【指针的指针】
读取成功返回文件的长度 读取失败则返回0
文件缓冲区用于存储读入的文件,这里需要注意malloc申请的空间即使是在函数内部,其申请的空间在函数返回时,也不会被销毁,而是什么时候调用free函数什么时候被销毁
*/
DWORD ReadFileToBuffer(IN LPSTR FilePath,OUT LPVOID* PFileBuffer);
//========================================================================================================================================
//将文件从文件缓冲区拷贝到镜像缓冲区中
//读取成功则返回镜像的大小,如果读取事变则返回0
//虽然第二个参数是二级指针,但是,取一级指针的地址便可
DWORD CopyFromFileBufferToImageBuffer(IN LPVOID pFileBuffer,OUT LPVOID* pImageBuffer);
//==========================================================================================================================================
//从镜像缓冲区还原到文件缓冲区中
//参数1:内存镜像缓冲区地址
//参数2:文件缓冲区地址的地址 是个二级指针
//返回值 还原成功则返回新文件缓冲区的大小 还原失败则返回0
DWORD CopyFromImageBufferToFileBuffer(IN PVOID pImageBuffer,OUT LPVOID* pNewFileBuffer );
//========================================================================================================================================
//将内存总的虚拟地址转化为文件中的偏移地址
//参数1 文件缓冲区地址
//参数2 内存偏移地址RVA
//Rva地址转文件偏移地址
DWORD RvaToOffset(LPVOID pFileBuffer,DWORD dwRva);
//====================================================================================================================================
//手动修复IAT表 根据倒入表修复IAT表
//参数 文件读入缓冲区地址
//返回值 修复成功则返回TRUE 修复失败则返回FALSE
BOOL ReparIATTable(LPVOID pFileBuffer);
//==================================================================================================================================
//打印DLL文件的导入表内容
BOOL DLLExPortTable(LPVOID pFileBuffer);
//=====================================================================================================================================
//测试将文件读取到文件缓冲区
//参数无
void TestReadFileToBuffer();
//=======================================================================================================================================
//测试将PE拉伸到镜像缓冲区中
void TestCopyFromFileBufferToImageBuffer();
//=======================================================================================================================================
//测试将内存镜像缓冲区还原到新的文件缓冲区并写出到磁盘文件中测试是够能够成功运行
void TestCopyFromImageBufferToFileBuffer();
//=======================================================================================================================================
//测试将RVA转化为FileOffset
void TestRvaToOffset();
//=====================================================================================================================================
//测试修复IAT表
void TestReparIATTable();
//=========================================================================================================================================
//测试打印DLL输出表
void TestDLLExPortTable();
DWORD main(int argc, char* argv[])
{
//TestReadFileToBuffer(); //当从镜像缓冲区拷贝到文件缓冲区的时候需要运行TestReadFileToBuffer()获取len
//TestCopyFromFileBufferToImageBuffer();
//TestCopyFromImageBufferToFileBuffer();
//TestRvaToOffset();
//TestReparIATTable();
TestDLLExPortTable();
getchar();
return 0;
}
//将文件读取到文件缓冲区中
DWORD ReadFileToBuffer(IN LPSTR FilePath,OUT LPVOID* pFileBuffer){
FILE* pFile=NULL;
DWORD fileSize=0;
LPVOID pTempFileBuffer=NULL;
pFile=fopen(FilePath,"rb");
if(!pFile){
printf("无法打开该文件\n");
return 0;
}
fseek(pFile,0,SEEK_END);
fileSize=ftell(pFile);
len=fileSize;
fseek(pFile,0,SEEK_SET);
//分配内存空间
pTempFileBuffer=malloc(fileSize);
//强申请的空间初始化为0
memset(pTempFileBuffer,0,fileSize);
if(!pTempFileBuffer){
printf("申请空间失败\n");
fclose(pFile);
return 0;
}
int n=fread(pTempFileBuffer,fileSize,1,pFile);
if(!n){
printf("读取文件失败\n");
fclose(pFile);
free(pTempFileBuffer);
return 0;
}
*pFileBuffer=pTempFileBuffer;
pTempFileBuffer=NULL;
/* fclose(pFile);
FILE* outputStream=NULL;
outputStream=fopen("E:/miaobijing.exe","w+");
if(!outputStream){
printf("无法创建写入文件,请重新打开一个文件\n");
return 0;
}
else{
fwrite(pTempFileBuffer,fileSize,1,outputStream);
}
*/
return fileSize;
}
DWORD CopyFromFileBufferToImageBuffer(IN LPVOID pFileBuffer,OUT LPVOID* pImageBuffer){
PIMAGE_DOS_HEADER pDosHeader=NULL;
PIMAGE_NT_HEADERS pNTHeaders=NULL;
PIMAGE_FILE_HEADER pPEHeader=NULL;
PIMAGE_OPTIONAL_HEADER pOptionalHeader=NULL;
PIMAGE_SECTION_HEADER pSectionHeader=NULL;
DWORD ImageSize=0;
//判断文件缓冲区是否有效
if(pFileBuffer==NULL){
printf("文件缓冲区指针无效\n");
return 0;
}
//判断该文件是否是PE文件
if(*((PWORD)pFileBuffer)!=IMAGE_DOS_SIGNATURE){
printf("不是有效的DOS文件\n");
return 0;
}
pDosHeader=(PIMAGE_DOS_HEADER)(pFileBuffer);
if(*((PDWORD)((DWORD)pFileBuffer+pDosHeader->e_lfanew))!=IMAGE_NT_SIGNATURE){ //这里注意:FileBuffer是一个指针,也就是一个地址,所以转型为DWROD与pDosHeader->e_lfanew相加
printf("该文件不是有效的PE文件");
return 0;
}
// printf("DOS的开始地址是:%x\n",pDosHeader);
//NT头指针
pNTHeaders=(PIMAGE_NT_HEADERS)((DWORD)pDosHeader+pDosHeader->e_lfanew);
// printf("NT的开始地址是:%x\n",pNTHeaders);
//PE头指针等于NT头指针加四
pPEHeader=(PIMAGE_FILE_HEADER)(((DWORD)pFileBuffer+pDosHeader->e_lfanew)+4);
// printf("PE的开始地址是:%x\n",pPEHeader);
//血的教训,一个指针加上一个整数,加上的实际的大小是该指针表示的数据类型【去掉一个*】乘以整数
pOptionalHeader=(PIMAGE_OPTIONAL_HEADER)((DWORD)pPEHeader+IMAGE_SIZEOF_FILE_HEADER);//指针在加数时务必将其转化为整形
// printf("optional的开始地址是:%x\n",pOptionalHeader);
pSectionHeader=(PIMAGE_SECTION_HEADER)((DWORD)pOptionalHeader+pPEHeader->SizeOfOptionalHeader);
// printf("section表的开始地址是:%x\n",pSectionHeader);
//根据SIZE_OF_IMAGE来分配内存缓冲区的大小,虽然每一个应用程序在理论上都拥有独立的4GB虚拟内存,但是还是根据SIZE FOF IMAGE来分配内存大小
LPVOID pTempImageBuffer=NULL;
pTempImageBuffer=malloc(pOptionalHeader->SizeOfImage);
printf("文件的sizeofImage为%x\n",pOptionalHeader->SizeOfImage);
if(pTempImageBuffer==NULL){
printf("分配内存镜像文件失败\n");
}
memset(pTempImageBuffer,0,pOptionalHeader->SizeOfImage);
//开始从文件缓冲区拷贝到镜像缓冲区中 1:第一步:将所有的头拷贝到镜像缓冲区中 DosHeader+NTHeader+SectionHeader
memcpy(pTempImageBuffer,pFileBuffer,pOptionalHeader->SizeOfHeaders);
int i;
PIMAGE_SECTION_HEADER pTempSectionHeader=pSectionHeader;
for(i=0;i<pPEHeader->NumberOfSections;i++,pTempSectionHeader++){
memcpy((void*)((DWORD)pTempImageBuffer+pTempSectionHeader->VirtualAddress),(void*)((DWORD)pDosHeader+pTempSectionHeader->PointerToRawData),pTempSectionHeader->SizeOfRawData);
}
//临时打印测试代码
/* FILE* testStream=NULL;
testStream=fopen("E:/tempImageprint.exe","w+");
if(!testStream){
printf("文件打开失败\n");
}
fwrite(pTempImageBuffer,pOptionalHeader->SizeOfImage,1,testStream);*/
// printf("ImageBuffer的大小是:%d\n",pOptionalHeader->SizeOfImage);
// printf("malloc申请到的空间的大小是:%d\n");
*pImageBuffer=pTempImageBuffer;
pTempImageBuffer=NULL;
return pOptionalHeader->SizeOfImage;
}
void TestReadFileToBuffer(){
LPVOID pFileBuffer=NULL;
DWORD len= ReadFileToBuffer("E:/ReverseMe.exe",&pFileBuffer);
if(len!=0){
printf("文件读取成功,文件的长度为:%xh\n",len);
}
else{
printf("文件读取失败\n");
return;
}
}
void TestCopyFromFileBufferToImageBuffer(){
LPVOID pImageBuffer=NULL;
LPVOID pFileBuffer=NULL;
DWORD FileLen=0;
DWORD ImageLen=0;
FileLen= ReadFileToBuffer("E:/ReverseMe.exe",&pFileBuffer);
if(FileLen!=0){
printf("文件读取成功,文件的长度为:%xh\n",FileLen);
}
else{
printf("文件读取失败\n");
return;
}
ImageLen=CopyFromFileBufferToImageBuffer(pFileBuffer,&pImageBuffer);
if(!ImageLen){
printf("从文件缓冲区拷贝到镜像缓冲区失败\n");
return;
}
else{
printf("从文件缓冲区拷贝到镜像缓冲区成功\r\n镜像缓冲区的长度为%x\n",ImageLen);
}
}
DWORD CopyFromImageBufferToFileBuffer(IN PVOID pImageBuffer,OUT LPVOID* pNewFileBuffer ){
PIMAGE_DOS_HEADER pDosHeader=NULL;
PIMAGE_NT_HEADERS pNTHeaders=NULL;
PIMAGE_FILE_HEADER pPEHeader=NULL;
PIMAGE_OPTIONAL_HEADER pOptionalHeader=NULL;
PIMAGE_SECTION_HEADER pSectionHeader=NULL;
// DWORD ImageSize=0;
//判断文件缓冲区是否有效
if(pImageBuffer==NULL){
printf("内存镜像缓冲区指针无效\n");
return 0;
}
//判断该文件是否是PE文件
if(*((PWORD)pImageBuffer)!=IMAGE_DOS_SIGNATURE){
printf("不是有效的DOS内存镜像缓冲区\n");
return 0;
}
pDosHeader=(PIMAGE_DOS_HEADER)(pImageBuffer);
if(*((PDWORD)((DWORD)pImageBuffer+pDosHeader->e_lfanew))!=IMAGE_NT_SIGNATURE){ //这里注意:FileBuffer是一个指针,也就是一个地址,所以转型为DWROD与pDosHeader->e_lfanew相加
printf("该文件不是有效的PE文件");
return 0;
}
// printf("DOS的开始地址是:%x\n",pDosHeader);
//NT头指针
pNTHeaders=(PIMAGE_NT_HEADERS)((DWORD)pDosHeader+pDosHeader->e_lfanew);
// printf("NT的开始地址是:%x\n",pNTHeaders);
//PE头指针等于NT头指针加四
pPEHeader=(PIMAGE_FILE_HEADER)(((DWORD)pDosHeader+pDosHeader->e_lfanew)+4); // pPEHeader=(PIMAGE_FILE_HEADER)(((DWORD)pFileBuffer+pDosHeader->e_lfanew)+4);
// printf("PE的开始地址是:%x\n",pPEHeader);
//血的教训,一个指针加上一个整数,加上的实际的大小是该指针表示的数据类型【去掉一个*】乘以整数
pOptionalHeader=(PIMAGE_OPTIONAL_HEADER)((DWORD)pPEHeader+IMAGE_SIZEOF_FILE_HEADER);//指针在加数时务必将其转化为整形
// printf("optional的开始地址是:%x\n",pOptionalHeader);
pSectionHeader=(PIMAGE_SECTION_HEADER)((DWORD)pOptionalHeader+pPEHeader->SizeOfOptionalHeader);
// printf("section表的开始地址是:%x\n",pSectionHeader);
//根据SIZE_OF_IMAGE来分配内存缓冲区的大小,虽然每一个应用程序在理论上都拥有独立的4GB虚拟内存,但是还是根据SIZE FOF IMAGE来分配内存大小
PVOID pTempFileBuffer=NULL;
pTempFileBuffer=malloc(len);
printf("文件的大小为%x\n\r",len);
if(pTempFileBuffer==NULL){
printf("新的文件缓冲区申请失败\r\n");
free(pTempFileBuffer);
return 0;
}
memset(pTempFileBuffer,0,len);
//开始从文件缓冲区拷贝到镜像缓冲区中 1:第一步:将所有的头拷贝到镜像缓冲区中 DosHeader+NTHeader+SectionHeader
memcpy(pTempFileBuffer,pImageBuffer,pOptionalHeader->SizeOfHeaders);
int i;
PIMAGE_SECTION_HEADER pTempSectionHeader=pSectionHeader;
for(i=0;i<pPEHeader->NumberOfSections;i++,pTempSectionHeader++){
memcpy((void*)((DWORD)pTempFileBuffer+pTempSectionHeader->PointerToRawData),(void*)((DWORD)pDosHeader+pTempSectionHeader->VirtualAddress),pTempSectionHeader->SizeOfRawData);
}
//临时打印测试代码
/* FILE* testStream=NULL;
testStream=fopen("E:/tempImageprint.exe","w+");
if(!testStream){
printf("文件打开失败\n");
}
fwrite(pTempImageBuffer,pOptionalHeader->SizeOfImage,1,testStream);*/
// printf("ImageBuffer的大小是:%d\n",pOptionalHeader->SizeOfImage);
// printf("malloc申请到的空间的大小是:%d\n");
*pNewFileBuffer=pTempFileBuffer;
pTempFileBuffer=NULL;
return len;
}
void TestCopyFromImageBufferToFileBuffer(){
LPVOID pImageBuffer=NULL;
LPVOID pFileBuffer=NULL;
LPVOID pNewFileBuffer=NULL;
DWORD FileLen=0;
DWORD ImageLen=0;
DWORD NewFileLen=0;
FileLen= ReadFileToBuffer("E:/ReverseMe.exe",&pFileBuffer);
if(FileLen!=0){
printf("文件读取成功,文件的长度为:%xh\n",FileLen);
}
else{
printf("文件读取失败\n");
return;
}
ImageLen=CopyFromFileBufferToImageBuffer(pFileBuffer,&pImageBuffer);
if(!ImageLen){
printf("从文件缓冲区拷贝到镜像缓冲区失败\n");
return;
}
else{
printf("从文件缓冲区拷贝到镜像缓冲区成功\r\n镜像缓冲区的长度为%x\n",ImageLen);
}
NewFileLen=CopyFromImageBufferToFileBuffer(pImageBuffer,&pNewFileBuffer);
if(!NewFileLen){
printf("内存镜像还原失败\n\r");
return;
}
FILE* OutputStream=NULL;
OutputStream=fopen("E:/hah.exe","w+");
if(!OutputStream){
printf("写出文件打开失败\n\r");
return;
}
fwrite(pNewFileBuffer,NewFileLen,1,OutputStream);
}
//=====================================================================================================================================
DWORD RvaToOffset(LPVOID pFileBuffer,DWORD dwRva)
{
int i;
DWORD Offset;
int NumberOfSection;
PIMAGE_NT_HEADERS lpPeHeader;
PIMAGE_SECTION_HEADER lpSection;
Offset=NULL;
lpPeHeader=(PIMAGE_NT_HEADERS)((DWORD)pFileBuffer+PIMAGE_DOS_HEADER(pFileBuffer)->e_lfanew);
NumberOfSection=lpPeHeader->FileHeader.NumberOfSections;
lpSection=(PIMAGE_SECTION_HEADER) ((DWORD)lpPeHeader + sizeof(IMAGE_NT_HEADERS));
//首先判断该RVA是位于Section中还是位于HEADERS中,也就是说,如果RVA是小于第一个区块的VirtualAddress的那么它在文件中的偏移和在内存镜像中的偏移是一样的,都是应该小于SizeOfHeaders
if(dwRva<lpSection->VirtualAddress){
return dwRva;
}
for(i=0;i<NumberOfSection;i++){
if((dwRva>=lpSection->VirtualAddress)&&(dwRva<(lpSection->VirtualAddress+lpSection->SizeOfRawData))){//if((dwRva>=lpSection->VirtualAddress)&&(dwRva<(lpSection->VirtualAddress+lpSection->SizeOfRawData))){
Offset=lpSection->PointerToRawData+dwRva-lpSection->VirtualAddress;
return Offset;
}
lpSection++;
}
return Offset;
}
void TestRvaToOffset(){
LPSTR FilePath="C:\\Users\\。\\Desktop\\ReverseMe.exe";
LPVOID FileBuffer=NULL;
LPVOID pImageBuffer=NULL;
DWORD ReadLen=ReadFileToBuffer(FilePath,&FileBuffer);
if(!ReadLen){
printf("文件读入失败\n\r");
return;
}
// DWORD ImageLen=CopyFromFileBufferToImageBuffer(FileBuffer,&pImageBuffer);
DWORD FileOffset=RvaToOffset(FileBuffer,0x1030);
printf("1030 RVA 在文件中的偏移地址为:%x\r\n",FileOffset);
}
BOOL ReparIATTable(LPVOID pFileBuffer){
PIMAGE_NT_HEADERS lpNTHeader;
PIMAGE_FILE_HEADER lpFileHeader;
PIMAGE_OPTIONAL_HEADER lpOptionHeader;
PIMAGE_SECTION_HEADER lpSectionHeader;
PIMAGE_DATA_DIRECTORY lpDataDirectory;//这里使用数组指针去访问数组元素 而数组元素也是一个结构体
PIMAGE_IMPORT_DESCRIPTOR lpImportDescriptor;
//PIMAGE_THUNK_DATA lpThunkData;
lpNTHeader=(PIMAGE_NT_HEADERS)((DWORD)pFileBuffer+PIMAGE_DOS_HEADER(pFileBuffer)->e_lfanew);
lpFileHeader=(PIMAGE_FILE_HEADER)&lpNTHeader->FileHeader;
lpOptionHeader=(PIMAGE_OPTIONAL_HEADER)&lpNTHeader->OptionalHeader;
lpDataDirectory=(PIMAGE_DATA_DIRECTORY)lpOptionHeader->DataDirectory;
lpSectionHeader=(PIMAGE_SECTION_HEADER) ((DWORD)lpNTHeader + sizeof(IMAGE_NT_HEADERS));
lpImportDescriptor=(PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pFileBuffer+RvaToOffset(pFileBuffer,lpDataDirectory[1].VirtualAddress));//数据目录表中第二项描述的是导入表
DWORD i=0;
//先循环打印出导入表所中OriginalFirstTHUNK和FirstTHUNK两个表中地址所指向的API函数名,因为在程序加载到内存之前这两项的数据是完全一样的
//导入表是一个接着一个的最后会用相同大小空白大小来表示结束,所以只要判断倒入白中的OriginalFirstTHUNK和FirstTHUNK为0则表示导入表结束
while(!((lpImportDescriptor->FirstThunk==0)&&(lpImportDescriptor->OriginalFirstThunk==0))){
//打印每个导入模块的地址 需要将RVA转化为FileOffset
printf("=======第%d个模块为======%s=============\n",i,(LPVOID)((DWORD)pFileBuffer+(RvaToOffset(pFileBuffer,lpImportDescriptor->Name))));
//获取该模块的地址 也就是传说中每个.exe或者是每个DLL的IMAGEBASE
HMODULE hModule=LoadLibrary((CHAR*)((DWORD)pFileBuffer+(RvaToOffset(pFileBuffer,lpImportDescriptor->Name))));
//指向IMAGE_THUNK_DATA表的指针
PDWORD pOriginalThunk=(PDWORD)((DWORD)pFileBuffer+RvaToOffset(pFileBuffer,lpImportDescriptor->OriginalFirstThunk));//直接转化为在文件中的地址
printf("ORIGINAL THUNK 00000000000000000000000000000000000000\n");
while(*pOriginalThunk){
//先判断该函数市按照名字导出的还是按照序号导出的//判断第32位是0还是1 如果是1按照名称导出的,该数值为指向名称的一个指针 如果是0则是按照序号导出的 该数值的低31位为序号
if(*pOriginalThunk & IMAGE_ORDINAL_FLAG32){
printf("导出序号为:%d====================>>",*pOriginalThunk & 0x0fff);
printf("函数地址为%6x\n\r",GetProcAddress(hModule,(CHAR*)(*pOriginalThunk & 0x0fff)));
}
else{
PIMAGE_IMPORT_BY_NAME lpImportByName=(PIMAGE_IMPORT_BY_NAME)((DWORD)pFileBuffer+RvaToOffset(pFileBuffer,*pOriginalThunk));
printf("函数名称为%s==================>>",lpImportByName->Name);
printf("函数地址为%6x\n\r",GetProcAddress(hModule,(CHAR*)lpImportByName->Name));
//Sleep(100);
}
pOriginalThunk++;
}
PDWORD pFirstlThunk=(PDWORD)((DWORD)pFileBuffer+RvaToOffset(pFileBuffer,lpImportDescriptor->FirstThunk));//直接转化为在文件中的地址
printf("FIRST THUNK fffffffffffffffffffffffffffffffffffffff\n");
while(*pFirstlThunk){
//先判断该函数市按照名字导出的还是按照序号导出的
if(*pFirstlThunk & IMAGE_ORDINAL_FLAG32){//判断第32位是0还是1 如果是1按照名称导出的 如果是0则是按照序号导出的低31位为序号
printf("导出序号为:%d\n\r",*pFirstlThunk & 0x0fff);
}
else{
PIMAGE_IMPORT_BY_NAME lpImportByName=(PIMAGE_IMPORT_BY_NAME)((DWORD)pFileBuffer+RvaToOffset(pFileBuffer,*pFirstlThunk));
printf("%s\n",lpImportByName->Name);
//Sleep(100);
}
pFirstlThunk++;
}
i++;
lpImportDescriptor++;
}
return TRUE;
}
void TestReparIATTable(){
LPSTR FilePath="C:\\Users\\。\\Desktop\\shutdown_10.0.6.0_setup_5.exe";
LPVOID FileBuffer=NULL;
DWORD ReadLen=ReadFileToBuffer(FilePath,&FileBuffer);
if(!ReadLen){
printf("文件读入失败\n\r");
return;
}
ReparIATTable(FileBuffer);
}
BOOL DLLExPortTable(LPVOID pFileBuffer){
if(pFileBuffer==NULL){
printf("文件为空\n");
return FALSE;
}
PIMAGE_NT_HEADERS lpNTHeader;
PIMAGE_FILE_HEADER lpFileHeader;
PIMAGE_OPTIONAL_HEADER lpOptionHeader;
PIMAGE_DATA_DIRECTORY lpDataDirectory;//这里使用数组指针去访问数组元素 而数组元素也是一个结构体
PIMAGE_EXPORT_DIRECTORY lpExportDirectory;
lpNTHeader=(PIMAGE_NT_HEADERS)((DWORD)pFileBuffer+PIMAGE_DOS_HEADER(pFileBuffer)->e_lfanew);
lpFileHeader=(PIMAGE_FILE_HEADER)&lpNTHeader->FileHeader;
lpOptionHeader=(PIMAGE_OPTIONAL_HEADER)&lpNTHeader->OptionalHeader;
lpDataDirectory=(PIMAGE_DATA_DIRECTORY)lpOptionHeader->DataDirectory;//数组名就是一个地址,所以这里不需要再像上面一样区地址
lpExportDirectory=(PIMAGE_EXPORT_DIRECTORY)((DWORD)pFileBuffer+RvaToOffset(pFileBuffer,lpDataDirectory[0].VirtualAddress));
//获取函数名称表的地址并将其转化为一个指针类型
PDWORD pAddressOfNames=(PDWORD)((DWORD)pFileBuffer+RvaToOffset(pFileBuffer,lpExportDirectory->AddressOfNames));
printf("下列为函数名称表为:==========================NAME=============================\n");
while(*pAddressOfNames){
CHAR* pStrName=(CHAR*)((DWORD)pFileBuffer+RvaToOffset(pFileBuffer,*pAddressOfNames));
printf("%s\n",pStrName);
pAddressOfNames++;
}
PDWORD pAddressOFOrdianl=(PDWORD)((DWORD)pFileBuffer+RvaToOffset(pFileBuffer,lpExportDirectory->AddressOfNameOrdinals));
printf("函数到处序号表为============Ordianls===================:\n");
while(*pAddressOFOrdianl){
printf("%8x\n",*pAddressOFOrdianl);
pAddressOFOrdianl++;
}
PDWORD pAddressOfFunctionTable=(PDWORD)((DWORD)pFileBuffer+RvaToOffset(pFileBuffer,lpExportDirectory->AddressOfFunctions));
printf("导出函数地址表为:================================\n");
while(*pAddressOfFunctionTable){
printf("%d\n",*pAddressOfFunctionTable);
pAddressOfFunctionTable++;
}
printf("导出函数的起始序号为==============:%x",lpExportDirectory->Base);
printf("到处函数的数目为:=============%d",lpExportDirectory->NumberOfFunctions);
printf("按名字到处的函数数目为:================%d",lpExportDirectory->NumberOfNames);
return TRUE;
}
void TestDLLExPortTable(){
LPSTR FilePath="C:\\Users\\。\\Desktop\\wiadss.dll";
LPVOID FileBuffer=NULL;
DWORD ReadLen=ReadFileToBuffer(FilePath,&FileBuffer);
if(!ReadLen){
printf("文件读入失败\n\r");
return ;
}
BOOL Result=DLLExPortTable(FileBuffer);
if(!Result){
return;
}
}
PEtools的更多相关文章
- PEtools PE操作工具类C++
源码来自各大网友并非原创修改了部分函数 仅供参考(PE没源码参考应该是很吃力的) 暂未更新完持续更新中....... PETools.h //函数头 int GetFileLength(FILE *p ...
- WIM镜像添加多语言支持
起初的想法: intel 600p虽然速度一般,但pcie还是值得一试的.购买后发现原来的win7版本无法识别就找了KB2990941和KB3087873两个补丁,成功识别出了硬盘.期间通过dezor ...
- 使用 Windows AIK 创建自定的客户端系统WIM文件
Windows 7/2008 的AIK 3.0下载页面:地址链接 1.8G [3.1补充包为1.4G] 安装3.0后,升级为3.1方法: xcopy E:\ "C:\Program File ...
- DIY_hlstudio_WIN7PE【69M】网络版【89M】
DIY_hlstudio_WIN7PE[69M]网络版[89M] hlstudio的骨头版PE非常精简,由于启动方式和用法不同,个人进行了如下修改:1.原来的合盘修改为bootmgr直接起动ISO镜像 ...
- 通用 PE 工具箱1.9.6(XP内核)by Uepon(李培聪)
通用 PE 工具箱1.9.6(XP内核)by Uepon(李培聪)官网:http://hi.baidu.com/uepon?page=21.8版论坛帖子:http://bbs.wuyou.net/fo ...
- 制作Win7(x86)PE ISO文件
WinPE3.1 —Win7 x86 PE V3.1: waik_supplement_zh-cn.isoDVD: cn_windows_7_professional_with_sp1_x86 ...
- PE格式的理解(待补充)
PE文件格式 一.基本结构 1.DOS头一般到节区头成为PE头部分,其下称为PE体.文件的内容一般可分为代码(.text).数据(.data).资源(.rsrc),分别保存. 2.PE头与各节区的尾部 ...
- 手动修复IAT
现在我们已经了解了IAT的的工作原理,现在我们来一起学习手动修复IAT,一方面是深入了解运行过程一方面是为了避免遇到有些阻碍自动修复IAT的壳时不知所措. 首先我们用ESP定律找到加了UPX壳后的OE ...
- 动手制作属于你自己的WIN PE3.0
最近想要更新公司的网Ghost系统,所以小研究一下win pe ,在网上看见一个很不错的教程,在这里分享给大家! 并非原创,纯属转载!!O(∩_∩)O~天缘的作品,很是佩服这个哥们啊..... 一.W ...
随机推荐
- cocos2d-x 帧动画
ani = cc.Animation:create(); ...... local animate = cc.Animate:create(ani); s:runAction(animate); 发现 ...
- jQuery实现二级菜单
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- eclipse 中过滤空包,目录树中不显示。
1.导入maven工程,目录树中显示空包. 在Package Explorer的左上角,有个倒三角形,点开,有Fileters 选项,点开, Filters 中,勾上 Empty packages.即 ...
- Javascript数值转换(string,int,json)
数值: 在JavaScript中,数值转换一般有三种方式: 一.Number(param)函数:param可以用于任何数据类型 1.1 param是Boolean值,true和false分别转换为1和 ...
- 【总结】.Net面试题集锦(一)
一.背景 最近一直在准备面试,收到的面试邀请邮件里还有面试题,真是要当面霸的节奏,不过看看也好,一方面能够锻炼锻炼生锈的脑子,查缺补漏一下,另一方面,万一靠这几个面试题拿到offer呢,哈哈.开个玩笑 ...
- Linux查看tomcat 控制台输出命令
用远程登陆客户端登陆linux进入tomcat/logs/文件夹下键入指令:tail -f catalina.out
- EntityFramework 优化建议
Entity Framework目前最新版本是6.1.3,当然Entity Framework 7 目前还是预览版,并不能投入正式生产环境,估计正式版16年第一季度会出来,了解过EF7的部分新特性后, ...
- struts.xml
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE struts PUBLIC " ...
- svn检出的时候报 Unable to connect to a repository at URL错误(摘自CSDN)
背景:1. SVN服务器:VisualSVN-Server-2.5.5: 2. SVN客户端:TortoiseSVN-1.7.6.22632-x64-svn-1.7.4.msi: 在S ...
- jvm--4垃圾收集
6. 垃圾收集GC (1)当需要排查各种内存溢出,内存泄漏等问题,当GC成为系统达到更高性能的瓶颈时,我们就需要对这些自动化的GC进行监控和调节. (2)PC计数器.本地方法栈.虚拟机栈,随方法或者线 ...