一个简易版的 PE View
没什么技术含量,就是学习PE结构写的一个小工具]// PE View.cpp : 定义控制台应用程序的入口点。
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 头文件
#include "stdafx.h"
#include "stdio.h"
#include <time.h>
#include <malloc.h>
#include <Shlwapi.h>
#include <Windows.h>
#pragma comment( lib, "Shlwapi.lib")
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 定义声明
using namespace std;
void GetMachine(WORD wMachine);//打印运行平台
void stamp_to_standard(int stampTime);//时间戳到标准时间
DWORD RVAToRAW(DWORD dwRVA);//转换到文件偏移
FILE *fpPeFile;
_TCHAR szFileName = {0};
IMAGE_DOS_HEADER DosHander;
IMAGE_NT_HEADERS32 NtHander32; //x32 NT头
PIMAGE_SECTION_HEADER pSectionHander;//节区头指针
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//开始位置
int _tmain(int argc, _TCHAR* argv[])
{
#if _DEBUG //调试环境下读取自身
argv = argv;
argc = 2;
#endif
////////////////////////////////////////////
if (argc < 2)
{
printf("Not File Analysis\n");
system("pause");
exit(EXIT_FAILURE);
}
SetConsoleTitle(argv);
strcpy_s(szFileName, argv);
PathStripPath(szFileName);//取文件名
fopen_s(&fpPeFile, argv, "rb");// 以二进制方式打开文件
if (!fpPeFile)
{
fprintf (stderr, "Error Open File \n");
exit (EXIT_FAILURE);
}
fread_s(&DosHander.e_magic,sizeof(DosHander), 1, sizeof(DosHander), fpPeFile);//读取DOS头
if (DosHander.e_magic!=IMAGE_DOS_SIGNATURE)//DOS 签名 "MZ"
{
fprintf(stderr, "Error Dos e_magic \n");
exit(EXIT_FAILURE);
}
fseek (fpPeFile, DosHander.e_lfanew, SEEK_SET);//移动文件指针到NT头
fread_s(&NtHander32.Signature,sizeof(NtHander32), 1, sizeof(NtHander32), fpPeFile);//读取NT头
if (NtHander32.Signature!=IMAGE_NT_SIGNATURE)//签名 "PE"
{
fprintf(stderr, "Error Signature \n");
exit(EXIT_FAILURE);
}
//fseek(fpPeFile, sizeof(NtHander32), SEEK_CUR);//移动文件指针到节区头
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//打印PE信息
printf("File Name:%s \n", szFileName);//文件名
if (NtHander32.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) //PE
{
printf("File Type: PE \n");
} else if (NtHander32.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC){ //PE+
printf("File Type: PE++ \n");
}
GetMachine(NtHander32.FileHeader.Machine);//运行平台
printf("ImageBase:%08X\n", NtHander32.OptionalHeader.ImageBase);//基址
printf("EntryPoint:%08X\n", NtHander32.OptionalHeader.AddressOfEntryPoint);//入口地址
printf("SizeOfHeaders%08X\n",NtHander32.OptionalHeader.SizeOfHeaders);//PE大小
printf("SectionAlignment:%08X\n",NtHander32.OptionalHeader.SectionAlignment);//节区在内存中对齐大小
printf("FileAlignment%08X\n", NtHander32.OptionalHeader.FileAlignment);//节区在文件中对齐大小
stamp_to_standard(NtHander32.FileHeader.TimeDateStamp);//时间戳打印标准时间
printf("\n==================================SectionS=======================================\n=");
//申请区段内存
pSectionHander = (IMAGE_SECTION_HEADER*)malloc(NtHander32.FileHeader.NumberOfSections*sizeof(IMAGE_SECTION_HEADER));
printf("\tName\t\tRVA\t\tV.Size\t\tOffset\t\tR.size\t=\n");
for (int i = 0; i < NtHander32.FileHeader.NumberOfSections; i++)//区段数量
{
//fread_s(&SectionHander, sizeof(SectionHander), 1, sizeof(SectionHander), fpPeFile);//读取节区头
fread_s(&pSectionHander, sizeof(IMAGE_SECTION_HEADER), 1, sizeof(IMAGE_SECTION_HEADER), fpPeFile);
printf("=\t%-8s\t", pSectionHander.Name);//MSDN定义 8BYTE
printf("%X\t\t", pSectionHander.VirtualAddress);
printf("%X\t\t",pSectionHander.Misc.VirtualSize);
printf("%X\t\t",pSectionHander.PointerToRawData);
printf("%X\t=\n",pSectionHander.SizeOfRawData);
}
printf("==================================Section End====================================\n");
system("pause");
free(pSectionHander);
fclose(fpPeFile);//关闭文件
return 0;
}
void GetMachine(WORD wMachine)
{
_TCHAR szType;
if (wMachine==IMAGE_FILE_MACHINE_UNKNOWN)
strcpy_s(szType, "Machine: Unknwn \n");
else if (wMachine==IMAGE_FILE_MACHINE_I386)
strcpy_s(szType, "Machine: Intel x86 \n");
else if (wMachine==IMAGE_FILE_MACHINE_IA64)
strcpy_s(szType, "Machine: Intel x64 \n");
else if (wMachine==IMAGE_FILE_MACHINE_AMD64)
strcpy_s(szType, "Machine: AMD64 (K8) \n");
printf("%s", szType);
//cout << szType;
//其他未补充
/*
#define IMAGE_FILE_MACHINE_UNKNOWN 0
#define IMAGE_FILE_MACHINE_I386 0x014c // Intel 386.
#define IMAGE_FILE_MACHINE_R3000 0x0162 // MIPS little-endian, 0x160 big-endian
#define IMAGE_FILE_MACHINE_R4000 0x0166 // MIPS little-endian
#define IMAGE_FILE_MACHINE_R10000 0x0168 // MIPS little-endian
#define IMAGE_FILE_MACHINE_WCEMIPSV2 0x0169 // MIPS little-endian WCE v2
#define IMAGE_FILE_MACHINE_ALPHA 0x0184 // Alpha_AXP
#define IMAGE_FILE_MACHINE_SH3 0x01a2 // SH3 little-endian
#define IMAGE_FILE_MACHINE_SH3DSP 0x01a3
#define IMAGE_FILE_MACHINE_SH3E 0x01a4 // SH3E little-endian
#define IMAGE_FILE_MACHINE_SH4 0x01a6 // SH4 little-endian
#define IMAGE_FILE_MACHINE_SH5 0x01a8 // SH5
#define IMAGE_FILE_MACHINE_ARM 0x01c0 // ARM Little-Endian
#define IMAGE_FILE_MACHINE_THUMB 0x01c2 // ARM Thumb/Thumb-2 Little-Endian
#define IMAGE_FILE_MACHINE_ARMNT 0x01c4 // ARM Thumb-2 Little-Endian
#define IMAGE_FILE_MACHINE_AM33 0x01d3
#define IMAGE_FILE_MACHINE_POWERPC 0x01F0 // IBM PowerPC Little-Endian
#define IMAGE_FILE_MACHINE_POWERPCFP 0x01f1
#define IMAGE_FILE_MACHINE_IA64 0x0200 // Intel 64
#define IMAGE_FILE_MACHINE_MIPS16 0x0266 // MIPS
#define IMAGE_FILE_MACHINE_ALPHA64 0x0284 // ALPHA64
#define IMAGE_FILE_MACHINE_MIPSFPU 0x0366 // MIPS
#define IMAGE_FILE_MACHINE_MIPSFPU16 0x0466 // MIPS
#define IMAGE_FILE_MACHINE_AXP64 IMAGE_FILE_MACHINE_ALPHA64
#define IMAGE_FILE_MACHINE_TRICORE 0x0520 // Infineon
#define IMAGE_FILE_MACHINE_CEF 0x0CEF
#define IMAGE_FILE_MACHINE_EBC 0x0EBC // EFI Byte Code
#define IMAGE_FILE_MACHINE_AMD64 0x8664 // AMD64 (K8)
#define IMAGE_FILE_MACHINE_M32R 0x9041 // M32R little-endian
#define IMAGE_FILE_MACHINE_CEE 0xC0EE*/
}
typedef struct times
{
int Year; //年
int Mon; //月
int Day; //日
int Hour; //时
int Min; //分
int Second; //秒
}Times;
void stamp_to_standard(int stampTime)
{
time_t tick = (time_t)stampTime;
struct tm tm;
char s;
Times standard;
//tick = time(NULL);
localtime_s(&tm,&tick);
strftime(s, sizeof(s), "Create Date: %Y-%m-%d %H:%M:%S", &tm);
printf("%s\n", s);
standard.Year = atoi(s);
standard.Mon = atoi(s + 5);
standard.Day = atoi(s + 8);
standard.Hour = atoi(s + 11);
standard.Min = atoi(s + 14);
standard.Second = atoi(s + 17);
/*wsprintf(szBuffer, "%d-%d-%d %d:%d:%d",
standard.Year,
standard.Mon,
standard.Day,
standard.Hour,
standard.Min,
standard.Second);*/
}
IAT和EAT的话用这个函数获取到它的RVA 在转换到RAW读取就是了
]//转换到文件偏移
DWORD RVAToRAW(DWORD dwRVA)
{
DWORD dwOffset;
DWORD dwRAW;
for (int i = 1; i < NtHander32.FileHeader.NumberOfSections; i++)
{
if (pSectionHander.VirtualAddress>dwRVA&&i>0)
{
if (pSectionHander.VirtualAddress<=dwRVA)
{
// //RAW=RVA-VirtualAddress+PointerToRawData
dwOffset = dwRVA - pSectionHander.VirtualAddress;
dwRAW = dwOffset + pSectionHander.PointerToRawData;
return dwRAW;
}
}
}
return -1;
}
如获得INI表第一个函数名就这样写:
//设置文件指针为导入表起始地址
fseek(fpPeFile, RVAToRAW(NtHander32.OptionalHeader.DataDirectory.VirtualAddress), SEEK_SET);
//读取导入表
fread_s(&ImportDescpiptor, sizeof(IMAGE_IMPORT_DESCRIPTOR), 1, sizeof(IMAGE_IMPORT_DESCRIPTOR), fpPeFile);
dwThunkINI = RVAToRAW(ImportDescpiptor.OriginalFirstThunk);
//设置文件指针为INI地址
fseek(fpPeFile, dwThunkINI, SEEK_SET);
DWORD addr;
fread_s(&addr, sizeof(addr), 1, sizeof(addr), fpPeFile);
addr = RVAToRAW(addr);
fseek(fpPeFile, addr, SEEK_SET);
struct MyStruct
{
WORD Hint;
CHAR Name;
}TEST;
fread_s(&TEST, sizeof(TEST), 1, sizeof(TEST), fpPeFile);
printf("%s\n", TEST.name);
到时候我整理一下个人学习PE结构的资料分享给各位坛友!! 学习学习,楼主辛苦 每一次都是离大神好近。 谢谢@Thanks! 楼主原创的吗?
页:
[1]