飘云阁

 找回密码
 加入我们

QQ登录

只需一步,快速开始

查看: 3352|回复: 5

[C/C++] 一个简易版的 PE View

[复制链接]
  • TA的每日心情

    2020-9-15 19:59
  • 签到天数: 166 天

    [LV.7]常住居民III

    发表于 2017-10-4 14:45:47 | 显示全部楼层 |阅读模式
    没什么技术含量,就是学习PE结构写的一个小工具 捕获.PNG

    [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结构的资料分享给各位坛友!!

    评分

    参与人数 3威望 +44 飘云币 +44 收起 理由
    lucky_789 + 20 + 20 赞一个!
    1715173329 + 4 + 4 感谢发布原创作品!
    不破不立 + 20 + 20 感谢发布原创作品!

    查看全部评分

    本帖被以下淘专辑推荐:

    PYG19周年生日快乐!
  • TA的每日心情
    开心
    昨天 09:42
  • 签到天数: 956 天

    [LV.10]以坛为家III

    发表于 2017-10-5 10:50:47 | 显示全部楼层

    向楼主学习!向楼主致敬!
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    2024-4-11 15:00
  • 签到天数: 99 天

    [LV.6]常住居民II

    发表于 2017-10-6 18:43:03 | 显示全部楼层
    楼主很厉害,加油
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2019-10-5 17:17
  • 签到天数: 10 天

    [LV.3]偶尔看看II

    发表于 2017-10-8 10:43:19 | 显示全部楼层
    前排支持一下
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2024-3-8 10:38
  • 签到天数: 1774 天

    [LV.Master]伴坛终老

    发表于 2017-10-12 09:09:13 | 显示全部楼层
    楼主是高人啊
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 登录 | 加入我们

    本版积分规则

    快速回复 返回顶部 返回列表