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;
}

}

时间: 2024-10-13 15:38:32

PEtools的相关文章

PEtools PE操作工具类C++

源码来自各大网友并非原创修改了部分函数 仅供参考(PE没源码参考应该是很吃力的) 暂未更新完持续更新中....... PETools.h //函数头 int GetFileLength(FILE *pf, DWORD *Length); int ReadFileByPathToBuffer(IN LPSTR FilePath, OUT LPVOID* pFileAddress); int PrintPEFileHeader(void* pFileAddress); int PrintPESect

PE文件基础

① PE (Portable Executable):微软参考COFF(Common Object File Format)规范,在Windows NT系统上制定的一种标准, 用于exe可执行文件.obj目标文件和dll动态链接库等文件格式.PE32+是PE的64位扩展,其并未添加额外结构,只是把原来32位的字段变成了64位. 与COFF一样,PE也是基于段(Segment,注:有时也被叫节Section)的结构, 按照不同属性将信息分段存放,常见的段有:代码段(.text).数据段(.data

DIY_hlstudio_WIN7PE【69M】网络版【91M】

DIY_hlstudio_WIN7PE[69M]网络版[91M] hlstudio的骨头版PE非常精简,由于启动方式和用法不同,个人进行了如下修改:1.原来的合盘修改为bootmgr直接起动ISO镜像.2.修改BCD菜单,修改强制开启主板PAE功能为缺省,从网虫2008PE中提取\Windows\System32\ntoskrnl.exe,恢复到BOOT.WIM中,确保不支持PAE的主板顺利启动WIN7PE.3.把MMC组件(含内置格式化功能)回复到\Windows\System32\,右击我的

手动脱壳—dump与重建输入表

http://blog.csdn.net/ccnyou/article/details/7930817 很久没玩逆向了,今天权当复习,顺便做个笔记 文章中用到的demo下载地址: http://download.csdn.net/detail/ccnyou/4540254 附件中包含demo以及文章word原稿 用到工具: Ollydbg LordPE ImportREC 这些工具请自行下载准备 Dump原理这里也不多做描述,想要了解google it!常见的dump软件有LordPE,Proc

逆向与反汇编工具

http://blog.163.com/[email protected]/blog/static/823405412012930555115/ 第 1 章           逆向与反汇编工具 了解反汇编的一些背景知识后,再深入学习IDA Pro之前,介绍其他一些用于二进制文件的逆向工程工具,会对我们学习有所帮助.这些工具大多在IDA之前发布,并且仍然可用于快速分析二进制文件,以及审查IDA的分析结果.如我们所见,IDA将这些工具的诸多功能整合到它的用户界面中,为逆向工程提供了一个集成环境.最

crackme160--(5)

这里不打算贴图.因为这个我压根就没破解出来啊--! 不管怎么样还是试了下.说是dephi程序那么直接上dede吧.无法解析.用OL说是selfmodify的文件.那么有壳.现在阶段作为新手应该手动脱壳. OL打开第一便是pushad这样在ESP处下硬件断点F9跑起来停在Jmp语句上.这样就开心了.直接跳到OEP.用PETOOLS dump进程.不过这里有个小插曲 dump出来的程序修复IAT后无法正常运行.于是我就将原程序与脱壳后的一步步F8比较.后发现在原程序处一个调用系统函数的地方.脱壳之后

PE工具列表(看雪学院)

PE编辑工具 Stud_PE v. 2.6.0.5 Stud_PE v.2.6.1.0 (2.61汉化版)   PE工具,用来学习PE格式十分方便. LordPE DLX增强版(2008.5.31)   2008.5.31资源名溢出漏洞.缓冲区长度检测是char,但是拷贝的时候是wchar,所以溢出了.by somuchhttp://bbs.pediy.com/showthread.php?t=64935 2006.11.30更新freecat制作的功能插件LordPeFix.dll,修正Lor

病毒木马查杀实战第016篇:U盘病毒之逆向分析

       本系列教程版权归"i春秋"所有,转载请标明出处.        本文配套视频教程,请访问"i春秋"(www.ichunqiu.com). 比对脱壳前后的程序 我们这次所要研究的是经过上次的脱壳操作之后,所获取的无壳病毒样本.其实我们这里可以先进行一下对比,看看有壳与无壳的反汇编代码的区别.首先用IDA Pro载入原始病毒样本: 图1 可以发现此时IDA Pro的Functionwindow是空的,说明很多函数没能解析出来,并且还无法切换到图形模式,而图

通用 PE 工具箱1.9.6(XP内核)by Uepon(李培聪)

通用 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/forum.php?mod=viewthread&tid=119749通用PE1.9.6介绍:http://hi.baidu.com/uepon/item/ceafeb322ba148b9633affd3通用PE V1.9.6(XP内核