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("文件不存在!\n");
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格式!\n");
return;
}
// 找到NT头
IMAGE_NT_HEADERS* pNt = NULL;
pNt = (IMAGE_NT_HEADERS*)(pDos->e_lfanew + pBuff);
if (pNt->Signature != IMAGE_NT_SIGNATURE)
{
MessageBox(L"不是有效的PE格式!\n");
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);
}
}
WinPE基础知识之代码解析的更多相关文章
- PHP基础知识测试题及解析
本试题共40道选择题,10道判断题,考试时间1个半小时 一:选择题(单项选择,每题2分): 1. LAMP具体结构不包含下面哪种(A ) A:Windows系统 B:Apache服务器 C:MyS ...
- WinPE基础知识之头部
1.DOS头 // DOS MZ头,大小为64个字节 typedef struct _IMAGE_DOS_HEADER { WORD e_magic; // EXE标志,“MZ”(有用,解析时作为是否 ...
- oracle 基础知识(九)----SQL解析
一,解析过程 二,硬解析,软解析,软软解析 01,硬解析 将SQL语句通过监听器发送到Oracle时, 会触发一个Server process生成,来对该客户进程服务.Server process得到 ...
- WinPE基础知识之重定位表
typedef struct _IMAGE_BASE_RELOCATION { DWORD VirtualAddress; // (重要)需要重定位的位置,这是一个RVA DWORD SizeOfBl ...
- WinPE基础知识之导入表
// 导入表 (结构体数组,以一个全零元素为结尾,每一个数组元素,代表一个PE文件导入信息) // 导入表存储的是从其它PE文件导入过来的函数名.序号,加载到内存之后,还存储这些函数的地址 typed ...
- WinPE基础知识之导出表
// 导出的东西包括函数(变量.类)地址,序号,函数(变量.类)名 typedef struct _IMAGE_EXPORT_DIRECTORY { DWORD Characteristics; // ...
- Struts2入门1 Struts2基础知识
Struts2入门1 Struts2基础知识 20131130 代码下载: 链接: http://pan.baidu.com/s/11mYG1 密码: aua5 前言: 之前学习了Spring和Hib ...
- 浅析C++基础知识
近期想对C++的面试题目进行一下更加详细的整理.事实上认真思考一下C++程序猿的面试,我们能够发现对程序猿的能力的考察总是万变不离当中,这些基础知识主要分为五部分:一. C/C++基础知识 二. C/ ...
- [nRF51822] 11、基础实验代码解析大全 · 实验16 - 内部FLASH读写
一.实验内容: 通过串口发送单个字符到NRF51822,NRF51822 接收到字符后将其写入到FLASH 的最后一页,之后将其读出并通过串口打印出数据. 二.nRF51822芯片内部flash知识 ...
随机推荐
- PAT 甲级 1029 Median (25 分)(思维题,找两个队列的中位数,没想到)*
1029 Median (25 分) Given an increasing sequence S of N integers, the median is the number at the m ...
- laravel5.1设置cookie
Laravel 所建立的 cookie 会加密并且加上认证记号,这代表着被用户擅自更改的 cookie 会失效.从请求中取得Cookie值,你使用cookie方法 $value = $request- ...
- Java连接阿里云HBase示例
使用前要在阿里云的 HBase控制台中点击"修改网络白名单",然后将你的ip地址(会有提示的)添加到网络白名单中,这样以后才能访问. 所需依赖: <dependencies& ...
- PowerShell ISE/文件名解析缺陷远程执行代码漏洞#RCE
基础信息 ID 1337DAY-ID- 32642 类型 zdt Reporter hyp3rlinx 修改后的 2019-05-03 00:00:00 描述 在调试包含数组括号作为文件名一部分的特制 ...
- golang web框架设计5:配置设计
配置信息的解析,实现的是一个key=value,键值对的一个配置文件,类似于ini的配置格式,然后解析这个文件,把解析的数据保存到map中,最后调用的时候通过几个string,int之类的函数返回相应 ...
- RestHighLevelClient 之 Scroll
ES中默认最大查询结果为10000,大于10000时查不出结果,报错超过最大值,如把 from调到大于10000. 针对这个问题,有两种解决办法. 第一种,修改 max_result_window 很 ...
- linux 抓包工具tcpdump和tshark
yum install tcpdump tcpdump -nn -c 100 抓一百条 tcpdump -nn -i eth0 指定网卡 tcpdump -nn port 22 指定端口 tcpdum ...
- Python基础总结之第八天开始【while循环以及for循环,循环嵌套等循环相关的知识点】(新手可相互督促)
ennnnn,年薪20万的梦想是不是又进了一步: 循环,什么是循环,循环就是电池有电,手机屏幕可以循环一整天的使用:循环就是地球不毁灭,太阳日复一日的出现...... 不接受反驳,谢谢!~ 只要条件满 ...
- Vue代码分割懒加载的实现方法
什么是懒加载 懒加载也叫延迟加载,即在需要的时候进行加载,随用随载. 为什么需要懒加载 在单页应用中,如果没有应用懒加载,运用webpack打包后的文件将会异常的大,造成进入首页时,需要加载的内容过多 ...
- MQ解决消息重发--做到幂等性
一.MQ消息发送 1.发送端MQ-client(消息生产者:Producer)将消息发送给MQ-server: 2.MQ-server将消息落地: 3.MQ-server回ACK给MQ-client( ...