| 
TA的每日心情|  | 怒 2020-9-15 19:59
 | 
|---|
 签到天数: 166 天 [LV.7]常住居民III | 
 
| 没什么技术含量,就是学习PE结构写的一个小工具   
 
 [C] 纯文本查看 复制代码 // 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[MAX_PATH] = {0};
IMAGE_DOS_HEADER DosHander;
IMAGE_NT_HEADERS32 NtHander32;	//x32 NT头
PIMAGE_SECTION_HEADER pSectionHander;//节区头指针
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//开始位置
int _tmain(int argc, _TCHAR* argv[])
{
#if _DEBUG	//调试环境下读取自身
	argv[1] = argv[0];
	argc = 2;
#endif
	////////////////////////////////////////////
	if (argc < 2)
	{
		printf("Not File Analysis\n");
		system("pause");
		exit(EXIT_FAILURE);
	}
	SetConsoleTitle(argv[1]);
	strcpy_s(szFileName, argv[1]);
	PathStripPath(szFileName);//取文件名
	fopen_s(&fpPeFile, argv[1], "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[i], sizeof(IMAGE_SECTION_HEADER), 1, sizeof(IMAGE_SECTION_HEADER), fpPeFile);
		printf("=\t%-8s\t", pSectionHander[i].Name);//MSDN定义 8BYTE
		printf("%X\t\t", pSectionHander[i].VirtualAddress);
		printf("%X\t\t",pSectionHander[i].Misc.VirtualSize);
		printf("%X\t\t",pSectionHander[i].PointerToRawData);
		printf("%X\t=\n",pSectionHander[i].SizeOfRawData);
	}
	printf("==================================Section End====================================\n");
	system("pause");
	free(pSectionHander);
	fclose(fpPeFile);//关闭文件
	return 0;
}
void GetMachine(WORD wMachine)
{
	_TCHAR szType[50];
	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[100];
	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读取就是了
 
 [AppleScript] 纯文本查看 复制代码 //转换到文件偏移
DWORD RVAToRAW(DWORD dwRVA)
{
	DWORD dwOffset;
	DWORD dwRAW;
	for (int i = 1; i < NtHander32.FileHeader.NumberOfSections; i++)
	{
		if (pSectionHander[i].VirtualAddress>dwRVA&&i>0)
		{
			if (pSectionHander[i-1].VirtualAddress<=dwRVA)
			{
				//	//RAW=RVA-VirtualAddress+PointerToRawData
				dwOffset = dwRVA - pSectionHander[i-1].VirtualAddress;
				dwRAW = dwOffset + pSectionHander[i-1].PointerToRawData;
				return dwRAW;
			}
		}
	}
	return -1;
}
 如获得INI表第一个函数名就这样写:
 
 [C] 纯文本查看 复制代码 	//设置文件指针为导入表起始地址
	fseek(fpPeFile, RVAToRAW(NtHander32.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].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[20];
	}TEST;
	fread_s(&TEST, sizeof(TEST), 1, sizeof(TEST), fpPeFile);
	printf("%s\n", TEST.name);
 到时候我整理一下个人学习PE结构的资料分享给各位坛友!!
 
 
 | 
 评分
查看全部评分
 |