• 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);
    	}
    }
    

      

  • 相关阅读:
    提出的问题
    2020软件工程作业02
    2020软件工程作业01
    我当社畜这些年-1
    Electron-vue实现后台多进程(二)
    Electron-vue实现后台多进程(一)
    pytorch自定义loss函数的几种方法
    XGBoost原理
    transformers的bert预训练模型的返回值简要描述
    sklearn下的ROC与AUC原理详解
  • 原文地址:https://www.cnblogs.com/duxie/p/10857796.html
Copyright © 2020-2023  润新知