PE文件的3种地址,分别是VA(虚拟地址)、RVA(相对虚拟地址)和FileOffset(文件偏移地址)。这3种地址的转换如果始终使用手动来计算会非常累,因此通常的做法是借助工具来完成。这里编写一个对这3种地址进行转换的工具。该工具如图1所示。
成都服务器托管,创新互联建站提供包括服务器租用、内江机房主机托管、带宽租用、云主机、机柜租用、主机租用托管、CDN网站加速、域名注册等业务的一体化完整服务。电话咨询:028-86922220
图1 地址转换器
这个工具是在前两个工具的基础上完成的。因此,在进行计算的时候,应该先要进行“查看”,再进行“计算”。否则,该获取的指针还没有获取到。
在界面上,左边的3个按钮是“单选框”,单选框的设置方法如图2所示。
图2 对单选框的设置
3个单选框中只能有一个是选中状态,为了记录哪个单选框是选中状态,在类中定义一个成员变量m_nSelect。对3个单选框,分别使m_nSelect值为1、2和3。下面来看主要的代码。
在单击“计算”按钮后,响应该按钮的代码如下:
- void CPeParseDlg::OnBtnCalc()
- {
- // TODO: Add your control notification handler code here
- DWORD dwAddr = 0;
- // 获取的地址
- dwAddr = GetAddr();
- // 地址所在的节
- int nInNum = GetAddrInSecNum(dwAddr);
- // 计算其他地址
- CalcAddr(nInNum, dwAddr);
- }
分别看一下GetAddr()、GetAddrInSecNum()和CalcAddr()的实现。
获取在编辑框中输入的地址内容的代码如下:
- DWORD CPeParseDlg::GetAddr()
- {
- char szAddr[10] = { 0 };
- DWORD dwAddr = 0;
- switch ( m_nSelect )
- {
- case 1:
- {
- GetDlgItemText(IDC_EDIT_VA, szAddr, 10);
- HexStrToInt(szAddr, &dwAddr);
- break;
- }
- case 2:
- {
- GetDlgItemText(IDC_EDIT_RVA, szAddr, 10);
- HexStrToInt(szAddr, &dwAddr);
- break;
- }
- case 3:
- {
- GetDlgItemText(IDC_EDIT_FILEOFFSET, szAddr, 10);
- HexStrToInt(szAddr, &dwAddr);
- break;
- }
- }
- return dwAddr;
- }
获取该地址所属的第几个节的代码如下:
- int CPeParseDlg::GetAddrInSecNum(DWORD dwAddr)
- {
- int nInNum = 0;
- int nSecNum = m_pNtHdr->FileHeader.NumberOfSections;
- switch ( m_nSelect )
- {
- case 1:
- {
- DWORD dwImageBase = m_pNtHdr->OptionalHeader.ImageBase;
- for ( nInNum = 0; nInNum < nSecNum; nInNum ++ )
- {
- if ( dwAddr >= dwImageBase + m_pSecHdr[nInNum].VirtualAddress
- && dwAddr <= dwImageBase + m_pSecHdr[nInNum].VirtualAddress
- + m_pSecHdr[nInNum].Misc.VirtualSize)
- {
- return nInNum;
- }
- }
- break;
- }
- case 2:
- {
- for ( nInNum = 0; nInNum < nSecNum; nInNum ++ )
- {
- if ( dwAddr >= m_pSecHdr[nInNum].VirtualAddress
- && dwAddr <= m_pSecHdr[nInNum].VirtualAddress
- + m_pSecHdr[nInNum].Misc.VirtualSize)
- {
- return nInNum;
- }
- }
- break;
- }
- case 3:
- {
- for ( nInNum = 0; nInNum < nSecNum; nInNum ++ )
- {
- if ( dwAddr >= m_pSecHdr[nInNum].PointerToRawData
- && dwAddr <= m_pSecHdr[nInNum].PointerToRawData
- + m_pSecHdr[nInNum].SizeOfRawData)
- {
- return nInNum;
- }
- }
- break;
- }
- }
- return -1;
- }
计算其他地址的代码如下:
- VOID CPeParseDlg::CalcAddr(int nInNum, DWORD dwAddr)
- {
- DWORD dwVa = 0;
- DWORD dwRva = 0;
- DWORD dwFileOffset = 0;
- switch ( m_nSelect )
- {
- case 1:
- {
- dwVa = dwAddr;
- dwRva = dwVa - m_pNtHdr->OptionalHeader.ImageBase;
- dwFileOffset = m_pSecHdr[nInNum].PointerToRawData
- + (dwRva - m_pSecHdr[nInNum].VirtualAddress);
- break;
- }
- case 2:
- {
- dwVa = dwAddr + m_pNtHdr->OptionalHeader.ImageBase;
- dwRva = dwAddr;
- dwFileOffset = m_pSecHdr[nInNum].PointerToRawData
- + (dwRva - m_pSecHdr[nInNum].VirtualAddress);
- break;
- }
- case 3:
- {
- dwFileOffset = dwAddr;
- dwRva = m_pSecHdr[nInNum].VirtualAddress
- + (dwFileOffset - m_pSecHdr[nInNum].PointerToRawData);
- dwVa = dwRva + m_pNtHdr->OptionalHeader.ImageBase;
- break;
- }
- }
- SetDlgItemText(IDC_EDIT_SECTION, (const char *)m_pSecHdr[nInNum].Name);
- CString str;
- str.Format("%08X", dwVa);
- SetDlgItemText(IDC_EDIT_VA, str);
- str.Format("%08X", dwRva);
- SetDlgItemText(IDC_EDIT_RVA, str);
- str.Format("%08X", dwFileOffset);
- SetDlgItemText(IDC_EDIT_FILEOFFSET, str);
- }
代码都不复杂,关键就是CalcAddr()中3种地址的转换。
本文题目:网络安全编程:PE编程实例之地址转换器
链接地址:http://www.shufengxianlan.com/qtweb/news18/293068.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联