WinPE基础知识之代码解析

void CMyPE::OnClickedButton1()
{
	// TODO:  在此添加控件通知处理程序代码

	// 打开一个文件夹选择对话框
	CFileDialog dlg(TRUE);
	dlg.DoModal();
	// 将文件路径显示到编辑框
	CString path = dlg.GetFolderPath();
	CString path1 = dlg.GetFileName();
	m_Edit.SetWindowText(path + L"\" + path1);

	// 将PE文件读到缓冲区
	HANDLE hFile = CreateFile(path + L"\" + path1,
		GENERIC_WRITE | GENERIC_READ,
		FILE_SHARE_READ,
		NULL,
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		NULL);
	if (hFile == (HANDLE)-1)
	{
		printf("文件不存在!
");
		return;
	}
	DWORD size = GetFileSize(hFile, NULL);
	LPBYTE pBuff = new BYTE[size];
	DWORD dwRead = 0;
	ReadFile(hFile, pBuff, size, &dwRead, 0);

	// 使用对应的结构体解析内存中的数据
	IMAGE_DOS_HEADER* pDos = NULL;
	pDos = (IMAGE_DOS_HEADER*)pBuff;
	if (pDos->e_magic != IMAGE_DOS_SIGNATURE)
	{
		MessageBox(L"不是有效的PE格式!
");
		return;
	}
	// 找到NT头
	IMAGE_NT_HEADERS* pNt = NULL;
	pNt = (IMAGE_NT_HEADERS*)(pDos->e_lfanew + pBuff);
	if (pNt->Signature != IMAGE_NT_SIGNATURE)
	{
		MessageBox(L"不是有效的PE格式!
");
		return;
	}
	// 找到文件头
	IMAGE_FILE_HEADER pFile = pNt->FileHeader;
	m_FileTree.DeleteAllItems();
	// 添加区段数量
	CString str1;
	str1.Format(L"区段数量:%d", pFile.NumberOfSections);
	m_FileTree.InsertItem(str1, NULL, TVI_LAST);
	// 添加扩展头大小
	CString str2;
	str2.Format(L"扩展头大小:%d", pFile.SizeOfOptionalHeader);
	m_FileTree.InsertItem(str2, NULL, TVI_LAST);

	// 找到扩展头
	IMAGE_OPTIONAL_HEADER pOptional = pNt->OptionalHeader;
	m_OptTree.DeleteAllItems();
	// OEP
	CString str3;
	str3.Format(L"OEP:%x", pOptional.AddressOfEntryPoint);
	m_OptTree.InsertItem(str3, NULL, TVI_LAST);
	// 镜像基址
	CString str4;
	str4.Format(L"镜像基址:%x", pOptional.ImageBase);
	m_OptTree.InsertItem(str4, NULL, TVI_LAST);
	// 块对齐数
	CString str5;
	str5.Format(L"块对齐数%x", pOptional.SectionAlignment);
	m_OptTree.InsertItem(str5, NULL, TVI_LAST);
	// 文件对齐数
	CString str6;
	str6.Format(L"文件对齐数:%x", pOptional.FileAlignment);
	m_OptTree.InsertItem(str6, NULL, TVI_LAST);
	// 内存大小
	CString str7;
	str7.Format(L"内存大小:%x", pOptional.SizeOfImage);
	m_OptTree.InsertItem(str7, NULL, TVI_LAST);

	// 找到数据目录表
	m_List3.DeleteAllItems();
	PIMAGE_DATA_DIRECTORY dData = pOptional.DataDirectory;
	DWORD dwIndex2 = 0;
	for (DWORD i = 0; i < pOptional.NumberOfRvaAndSizes; i++)
	{
		// 先插入一个item 到列表
		m_List3.InsertItem(dwIndex2, L"");
		CString str8;
		str8.Format(L"%x", dData[i].VirtualAddress);
		m_List3.SetItemText(dwIndex2, 0, str8);
		CString str9;
		str9.Format(L"%x", dData[i].Size);
		m_List3.SetItemText(dwIndex2, 1, str9);
		dwIndex2++;
	}

	// 区段表
	// 使用宏来找到区段头数组的首地址
	// 首地址 = NT头的首地址 + NT头的总字节数
	IMAGE_SECTION_HEADER* pScnHdr = NULL;
	// 使用宏来找到区段头数组的首地址
	pScnHdr = IMAGE_FIRST_SECTION(pNt);
	// 得到区段头的个数
	DWORD scnHdrCount = pNt->FileHeader.NumberOfSections;
	m_SCNTree.DeleteAllItems();
	for (DWORD i = 0; i < scnHdrCount; i++)
	{
		HTREEITEM hItem;
		CStringW str10(pScnHdr[i].Name);
		hItem = m_SCNTree.InsertItem(L"区段名称:" + str10, NULL, TVI_LAST);
		
		CString str11;
		str11.Format(L"区段大小:%x", pScnHdr[i].Misc.VirtualSize);
		m_SCNTree.InsertItem(str11, hItem);

		CString str12;
		str12.Format(L"RVA:%x", pScnHdr[i].VirtualAddress);
		m_SCNTree.InsertItem(str12, hItem);

		CString str13;
		str13.Format(L"文件大小:%x", pScnHdr[i].SizeOfRawData);
		m_SCNTree.InsertItem(str13, hItem);

		CString str14;
		str14.Format(L"文件偏移:%x", pScnHdr[i].PointerToRawData);
		m_SCNTree.InsertItem(str14, hItem);
	}

	/*导入表*/
	// 1:获取导入表的首地址
	DWORD dwImpTabRva = pNt->OptionalHeader.DataDirectory[1].VirtualAddress;
	// 将RVA转换为FOA
	DWORD dwImpTabFoa = rva2foa(pNt, dwImpTabRva);
	// 得到导入表数组的首地址
	IMAGE_IMPORT_DESCRIPTOR* pImp =
		(IMAGE_IMPORT_DESCRIPTOR*)(dwImpTabFoa + pBuff);
	// 2:遍历导入表数组,数组以0结尾
	m_ImportTree.DeleteAllItems();
	while (pImp->Name != 0)
	{
		// 3:在遍历出每一个导入表后,遍历它的INT或者IAT
		// 3.1 获取导入表DLL的名字
		DWORD dwNameFoa = rva2foa(pNt, pImp->Name);
		char* pDllName = (char*)(dwNameFoa + pBuff);
		HTREEITEM hItem;
		CStringW str15(pDllName);
		hItem = m_ImportTree.InsertItem(L"模块名称:" + str15, NULL, TVI_LAST);
		// 3,2 从INT中得到所有的导入函数的名字/序号
		IMAGE_THUNK_DATA* pInt = 0;
		DWORD dwIntFoa = rva2foa(pNt, pImp->OriginalFirstThunk);
		pInt = (IMAGE_THUNK_DATA*)(dwIntFoa + pBuff);

		while (pInt->u1.Function != 0)
		{
			// 判断导入的方式:序号导入还是名称导入
			if (IMAGE_SNAP_BY_ORDINAL(pInt->u1.Ordinal))
			{
				CString str16;
				str16.Format(L"函数序号:%x", pInt->u1.Ordinal & 0xFFFF);
				m_ImportTree.InsertItem(str16, hItem);
			}
			else
			{
				IMAGE_IMPORT_BY_NAME* pImpName = 0;
				DWORD dwNameFoa1 = rva2foa(pNt, pInt->u1.AddressOfData);
				pImpName = (IMAGE_IMPORT_BY_NAME*)(dwNameFoa1 + pBuff);
				CString str17(pImpName->Name);
				m_ImportTree.InsertItem(L"函数名称:" + str17, hItem);
			}
			++pInt;
		}
		++pImp;
	}

	/*导出表*/
	// 获取导出表首地址
	DWORD dwExpTabFoa = rva2foa(pNt, pNt->OptionalHeader.DataDirectory[0].VirtualAddress);
	m_ExportTree.DeleteAllItems();
	if (pNt->OptionalHeader.DataDirectory[0].VirtualAddress)
	{
		// 定位到导出表结构
		IMAGE_EXPORT_DIRECTORY* pExpTab =
			(IMAGE_EXPORT_DIRECTORY*)(dwExpTabFoa + pBuff);
		// 定位函数名称表
		DWORD* pENT = (DWORD*)(rva2foa(pNt, pExpTab->AddressOfNames) + pBuff);
		// 定位函数序号表
		WORD* pEOT = (WORD*)(rva2foa(pNt, pExpTab->AddressOfNameOrdinals) + pBuff);
		for (DWORD i = 0; i < pExpTab->NumberOfNames; i++)
		{
			char* pName = (char*)(rva2foa(pNt, pENT[i]) + pBuff);
			HTREEITEM hItem;
			CString str19;
			str19.Format(L"函数序号:%d", pEOT[i]);
			hItem = m_ExportTree.InsertItem(str19, NULL, TVI_LAST);
			CString str18(pName);
			m_ExportTree.InsertItem(L"函数名称:" + str18, hItem);
		}
	}

	/*资源表*/
	// 定位到第一层目录结构
	m_CtrlTree.DeleteAllItems();
	if (pNt->OptionalHeader.DataDirectory[2].VirtualAddress)
	{
		IMAGE_RESOURCE_DIRECTORY* pResDir = NULL;
		DWORD dwResTabRva = pNt->OptionalHeader.DataDirectory[2].VirtualAddress;
		DWORD dwResTabFoa = rva2foa(pNt, dwResTabRva);
		pResDir = (IMAGE_RESOURCE_DIRECTORY*)(dwResTabFoa + pBuff);
		parseResources((LPBYTE)pResDir, pResDir, m_CtrlTree, 1);
	}

	/*重定位表*/
	// 定位到重定位快的首地址
	m_ReTree.DeleteAllItems();
	if (pNt->OptionalHeader.DataDirectory[5].VirtualAddress)
	{
		DWORD dwRelTabRva = pNt->OptionalHeader.DataDirectory[5].VirtualAddress;
		DWORD dwRelTabFoa = rva2foa(pNt, dwRelTabRva);
		IMAGE_BASE_RELOCATION* pRelTab =
			(IMAGE_BASE_RELOCATION*)(dwRelTabFoa + pBuff);
		while (pRelTab->SizeOfBlock != 0)
		{
			TypeOffset* pTypeOffset = NULL;
			pTypeOffset = (TypeOffset*)(pRelTab + 1);
			DWORD dwCount = (pRelTab->SizeOfBlock - 8) / 2;
			CString str30;
			str30.Format(L"区段RVA:%x", pRelTab->VirtualAddress);
			HTREEITEM hItem;
			hItem = m_ReTree.InsertItem(str30, NULL, TVI_LAST);
			for (DWORD i = 0; i < dwCount; ++i)
			{
				CString str31;
				str31.Format(L"属性:%x", pTypeOffset[i].Type);
				m_ReTree.InsertItem(str31, hItem);
				CString str32;
				str32.Format(L"偏移:%x", pTypeOffset[i].Offset);
				m_ReTree.InsertItem(str32, hItem);
			}
			// 得到下一个重定位快的首地址
			pRelTab = (IMAGE_BASE_RELOCATION*)((LPBYTE)pRelTab + pRelTab->SizeOfBlock);

		}
	}

	/*TLS表*/
	// 定位到TLS的首地址
	m_TLSTree.DeleteAllItems();
	if (pNt->OptionalHeader.DataDirectory[9].VirtualAddress)
	{
		DWORD dwTLSTabRva = pNt->OptionalHeader.DataDirectory[9].VirtualAddress;
		DWORD dwTLSTabFoa = rva2foa(pNt, dwTLSTabRva);
		IMAGE_TLS_DIRECTORY* pTLSTab =
			(IMAGE_TLS_DIRECTORY*)(dwTLSTabFoa + pBuff);
		CString str33;
		str33.Format(L"数据块开始VA:%x", pTLSTab->StartAddressOfRawData);
		m_TLSTree.InsertItem(str33, NULL, TVI_LAST);
		CString str34;
		str34.Format(L"数据块结束VA:%x", pTLSTab->EndAddressOfRawData);
		m_TLSTree.InsertItem(str34, NULL, TVI_LAST);
		CString str35;
		str35.Format(L"回调表VA:%x", pTLSTab->AddressOfCallBacks);
		m_TLSTree.InsertItem(str35, NULL, TVI_LAST);
	}
}

  

原文地址:https://www.cnblogs.com/duxie/p/10857796.html