吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1068|回复: 0
收起左侧

[C&C++ 转载] PE文件笔记-代码解析PE

[复制链接]
dragon1996 发表于 2021-6-27 18:44
作为一个java开发人员。再学了一个多月的PE的文件了把PE文件中的一些常识都了解一波;想着继续整理一下PE的知识,但是想着自己的文笔有限,怎么样才能更好的表达自己的想法了。这里就用代码来代替我的想法;我这个exe文件只有导入表;所以这里我就只解析了项目表中导入表.同时我这里使用的是 【吾爱破解论坛学习脱壳实例_VC6.exe】这是站内教学中的一个exe。我这里就直接拿来用了(本来想着上传exe的,但是发现上次失败。。)这里主要是对PE文件中的固定部分进行了解析:
  • dos头部分
  • NT pe文件
  • 节表头

以及在pe文件中会使用到的PE项目表--导入表;
exe一般来说只有导入表,没有导出表,所以没有解析导出表。

----

然后做一个坑两个多月的菜鸡来说,在看了站内的脱壳课程,了解了一些脱基础壳的知识后。在加上一个月PE的学习,稍稍了解了大佬们的那些脱壳操作为什么要这么做了。
对于一些和我一样刚刚入坑的小伙伴们说一声学PE文件真的很有必要。
[C] 纯文本查看 复制代码
#include<Windows.h>
#include<stdio.h>


#define FILE_ANALY_WRAP printf("\n\n");
#define SINGAL_WRAP printf("\n\n");

PIMAGE_SECTION_HEADER nodeArr;
int nodeLength;
int SectionAlignment;

int getFoa(DWORD RVA) {
	int FOA = 0;
	if (SectionAlignment > RVA) {
		return RVA;
	}
	for (int i = 0;i < nodeLength;i++) {
		if (nodeArr[i].VirtualAddress < RVA &&
			(nodeArr[i].VirtualAddress + nodeArr[i].Misc.VirtualSize) > RVA) {
			FOA = nodeArr[i].PointerToRawData + (RVA - nodeArr[i].VirtualAddress);
		}
	}
	return FOA;
}

void AnalyEntryImportFile(int offset, LPVOID pFile) {
	printf("IMAGE_DIRECTORY_ENTRY_IMPORT FOA【%X】\n", offset);
	int count = 0;
	UINT fileStart = (UINT)pFile;
	do {
		PIMAGE_IMPORT_DESCRIPTOR pImport = (PIMAGE_IMPORT_DESCRIPTOR)(fileStart + offset+count*sizeof(_IMAGE_IMPORT_DESCRIPTOR));
		if (pImport->OriginalFirstThunk == NULL)
		{
			printf("import file total 【%d】\n", count);
			break;
		}
		count++;
		int nameAddr = getFoa(pImport->Name);
		int oft = getFoa(pImport->OriginalFirstThunk);
		printf("add dll file name is 【%s】 \t FOA:【%X】\n",(char *)(fileStart +nameAddr),oft);
		int flag = 0;
		do
		{
			PIMAGE_THUNK_DATA32 pThunkData = (PIMAGE_THUNK_DATA32)(fileStart + oft + flag * sizeof(_IMAGE_THUNK_DATA32));
			if (pThunkData->u1.AddressOfData == 0) {
				break;
			}
			flag++;
			/*
			* DWORD最高位为0,那么该数值是一个RVA,指向_IMAGE_IMPORT_BY_NAME结构,表明函数是以字符串类型的函数名导入的
			* DWORD最高位为1,那么该数值的低31位就是函数的导出函数的序号
			*/
			int thunkAddressOfData = getFoa(pThunkData->u1.AddressOfData);
		
			if ((pThunkData->u1.AddressOfData & 0x80000000) > 1) {	
				int addr = pThunkData->u1.AddressOfData & 0x7FFFFFFF;
				printf("\t\t import file method NO 【%d】\n", addr,(WORD*)((UINT)pFile + addr));
			}
			else
			{
				PIMAGE_IMPORT_BY_NAME pImpotName = (PIMAGE_IMPORT_BY_NAME)((UINT)pFile + thunkAddressOfData);
				printf("\t METHOD【%s】 FOA【%X】\n", pImpotName->Name, thunkAddressOfData);
			}
		} while (true);
		SINGAL_WRAP
	} while (true);
	
};

int main() {
	printf("hello PE file.....\n");
	//读取文件,返回文件句柄
	HANDLE hFile = CreateFileA("C:\\Users\\dragon\\Desktop\\吾爱破解论坛学习脱壳实例_VC6.exe"
		, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, 0);
	//根据文件句柄创建映射
	HANDLE hMap = CreateFileMappingA(hFile, NULL, PAGE_READWRITE, 0, 0, 0);
	//映射内容
	LPVOID pFile = MapViewOfFile(hMap, FILE_SHARE_WRITE, 0, 0, 0);
	//创建DOS对应的结构体指针
	_IMAGE_DOS_HEADER* dos;
	//类型转换,用结构体的方式来读取
	//DOS 数据头
	dos = (_IMAGE_DOS_HEADER*)pFile;
	printf("DOS INFO MESSAGE \n");
	printf("dos->e.magic:%X \n", dos->e_magic);
	//输出dos->e_magic,以十六进制输出
	printf("dos->e.magic:%X \n", dos->e_magic);
	//PE文件开头的位置
	printf("dos->PE NT header offset :\t%X", dos->e_lfanew);
	FILE_ANALY_WRAP
	//NT头文件
	//_IMAGE_NT_HEADERS
	PIMAGE_NT_HEADERS32 NT_PeHeader = (PIMAGE_NT_HEADERS32)((UINT)dos + dos->e_lfanew);
	printf("PE NT Signature:%X\n", NT_PeHeader->Signature);

	PIMAGE_FILE_HEADER pFileHeader = &NT_PeHeader->FileHeader;
	printf("Machine 【CPU类型】%X\n", pFileHeader->Machine);
	printf("NumberOfSections 【节表数量】%X\n", pFileHeader->NumberOfSections);
	printf("SizeOfOptionalHeader 【扩展PE头大小】%X\n\n", pFileHeader->SizeOfOptionalHeader);

	PIMAGE_OPTIONAL_HEADER32 pOptionalHeader = &NT_PeHeader->OptionalHeader;
	printf("NT MAGIC【程序类型 (32位则10B,64位则20B)】 : %X \n", pOptionalHeader->Magic);
	printf("program AddressOfEntryPoint :【入口偏移地址】 %X \n", pOptionalHeader->AddressOfEntryPoint);
	printf("ImageBase 【基地址】:%X \n", pOptionalHeader->ImageBase);
	printf(" 【程序实际入口位置】:%X \n", pOptionalHeader->AddressOfEntryPoint + pOptionalHeader->ImageBase);
	printf("SectionAlignment 【内存大小】: %X \n FileAlignment【文件偏移】: %X \n", pOptionalHeader->SectionAlignment, pOptionalHeader->FileAlignment);
	SectionAlignment = pOptionalHeader->SectionAlignment;
	printf("SizeOfImage 【内存大小】: %X \n SizeOfHeaders 【文件大小】: %X \n", pOptionalHeader->SizeOfImage, pOptionalHeader->SizeOfHeaders);
	printf("NumberOfRvaAndSizes : 【项目表类型数量】%X \n", pOptionalHeader->NumberOfRvaAndSizes);
	PIMAGE_DATA_DIRECTORY pDataDirectory = pOptionalHeader->DataDirectory;
	for (int i = 0;i < pOptionalHeader->NumberOfRvaAndSizes;i++) {
		printf("index 【%d】 address 【%X】 size 【%X】\n", i, pDataDirectory[i].VirtualAddress, pDataDirectory[i].Size);
	}
	FILE_ANALY_WRAP
	/**
	节表
	*/
	nodeLength = pFileHeader->NumberOfSections;
	PIMAGE_SECTION_HEADER pNodeStart = (PIMAGE_SECTION_HEADER)((UINT)NT_PeHeader + sizeof(_IMAGE_NT_HEADERS));
	nodeArr = new IMAGE_SECTION_HEADER[nodeLength];
	memcpy(nodeArr, pNodeStart, nodeLength * sizeof(IMAGE_SECTION_HEADER));
	for (int i = 0;i < nodeLength;i++) {
		char* name = new char[sizeof(nodeArr[i].Name)];
		memcpy(name, nodeArr[i].Name, sizeof(nodeArr[i].Name));
		printf("PE NODE 【%s】 virtualAddress 【%X】 virtualSize:【%X】 fileAddress【%X】 fileSize【%X】\n", name,
			nodeArr[i].VirtualAddress + pOptionalHeader->ImageBase,
			nodeArr[i].Misc.VirtualSize,
			nodeArr[i].PointerToRawData,
			nodeArr[i].SizeOfRawData);
		delete [] name;
	}
	FILE_ANALY_WRAP
	/*
	* 项目表信息
	*/
	for (int i = 0; i < pOptionalHeader->NumberOfRvaAndSizes; i++)
	{
		if (pDataDirectory[i].VirtualAddress == 0x0) {
			continue;
		}
	/*	int foa = 0;
		for (int i = 0;i < nodelength;i++) {
			if (nodearr[i].virtualaddress < pdatadirectory[i].virtualaddress &&
				(nodearr[i].virtualaddress + nodearr[i].misc.virtualsize) > pdatadirectory[i].virtualaddress) {
				foa = nodearr[i].pointertorawdata + (pdatadirectory[i].virtualaddress - nodearr[i].virtualaddress);
			}
		}*/
		int FOA= getFoa(pDataDirectory[i].VirtualAddress);
		switch (i) {
		case IMAGE_DIRECTORY_ENTRY_EXPORT:
			printf("this pe file has IMAGE_DIRECTORY_ENTRY_EXPORT\n");
			break;
		case IMAGE_DIRECTORY_ENTRY_IMPORT:
			printf("this pe file has IMAGE_DIRECTORY_ENTRY_IMPORT\n");
			AnalyEntryImportFile(FOA, pFile);
			break;
		case IMAGE_DIRECTORY_ENTRY_BASERELOC:
			printf("this pe file has IMAGE_DIRECTORY_ENTRY_BASERELOC\n");
			break;
	
		};
	}
	delete[] nodeArr;
	return 0;
}

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-4-30 15:54

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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