Molet

网络安全编程:PE编程实例之地址转换器

Molet 安全防护 2022-12-10 365浏览 0

网络安全编程:PE编程实例之地址转换器

PE文件的3种地址,分别是VA(虚拟地址)、RVA(相对虚拟地址)和FileOffset(文件偏移地址)。这3种地址的转换如果始终使用手动来计算会非常累,因此通常的做法是借助工具来完成。这里编写一个对这3种地址进行转换的工具。该工具如图1所示。

网络安全编程:PE编程实例之地址转换器

图1 地址转换器

这个工具是在前两个工具的基础上完成的。因此,在进行计算的时候,应该先要进行“查看”,再进行“计算”。否则,该获取的指针还没有获取到。

在界面上,左边的3个按钮是“单选框”,单选框的设置方法如图2所示。

网络安全编程:PE编程实例之地址转换器

图2 对单选框的设置

3个单选框中只能有一个是选中状态,为了记录哪个单选框是选中状态,在类中定义一个成员变量m_nSelect。对3个单选框,分别使m_nSelect值为1、2和3。下面来看主要的代码。

在单击“计算”按钮后,响应该按钮的代码如下:

voidCPeParseDlg::OnBtnCalc()
{
//TODO:Addyourcontrolnotificationhandlercodehere
DWORDdwAddr=0;
//获取的地址
dwAddr=GetAddr();
//地址所在的节
intnInNum=GetAddrInSecNum(dwAddr);
//计算其他地址
CalcAddr(nInNum,dwAddr);
}

分别看一下GetAddr()、GetAddrInSecNum()和CalcAddr()的实现。

获取在编辑框中输入的地址内容的代码如下:

DWORDCPeParseDlg::GetAddr()
{
charszAddr[10]={0};
DWORDdwAddr=0;
switch(m_nSelect)
{
case1:
{
GetDlgItemText(IDC_EDIT_VA,szAddr,10);
HexStrToInt(szAddr,&dwAddr);
break;
}
case2:
{
GetDlgItemText(IDC_EDIT_RVA,szAddr,10);
HexStrToInt(szAddr,&dwAddr);
break;
}
case3:
{
GetDlgItemText(IDC_EDIT_FILEOFFSET,szAddr,10);
HexStrToInt(szAddr,&dwAddr);
break;
}
}
returndwAddr;
}

获取该地址所属的第几个节的代码如下:

intCPeParseDlg::GetAddrInSecNum(DWORDdwAddr)
{
intnInNum=0;
intnSecNum=m_pNtHdr->FileHeader.NumberOfSections;
switch(m_nSelect)
{
case1:
{
DWORDdwImageBase=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)
{
returnnInNum;
}
}
break;
}
case2:
{
for(nInNum=0;nInNum<nSecNum;nInNum++)
{
if(dwAddr>=m_pSecHdr[nInNum].VirtualAddress
&&dwAddr<=m_pSecHdr[nInNum].VirtualAddress
+m_pSecHdr[nInNum].Misc.VirtualSize)
{
returnnInNum;
}
}
break;
}
case3:
{
for(nInNum=0;nInNum<nSecNum;nInNum++)
{
if(dwAddr>=m_pSecHdr[nInNum].PointerToRawData
&&dwAddr<=m_pSecHdr[nInNum].PointerToRawData
+m_pSecHdr[nInNum].SizeOfRawData)
{
returnnInNum;
}
}
break;
}
}
return-1;
}

计算其他地址的代码如下:

VOIDCPeParseDlg::CalcAddr(intnInNum,DWORDdwAddr)
{
DWORDdwVa=0;
DWORDdwRva=0;
DWORDdwFileOffset=0;
switch(m_nSelect)
{
case1:
{
dwVa=dwAddr;
dwRva=dwVa-m_pNtHdr->OptionalHeader.ImageBase;
dwFileOffset=m_pSecHdr[nInNum].PointerToRawData
+(dwRva-m_pSecHdr[nInNum].VirtualAddress);
break;
}
case2:
{
dwVa=dwAddr+m_pNtHdr->OptionalHeader.ImageBase;
dwRva=dwAddr;
dwFileOffset=m_pSecHdr[nInNum].PointerToRawData
+(dwRva-m_pSecHdr[nInNum].VirtualAddress);
break;
}
case3:
{
dwFileOffset=dwAddr;
dwRva=m_pSecHdr[nInNum].VirtualAddress
+(dwFileOffset-m_pSecHdr[nInNum].PointerToRawData);
dwVa=dwRva+m_pNtHdr->OptionalHeader.ImageBase;
break;
}
}
SetDlgItemText(IDC_EDIT_SECTION,(constchar*)m_pSecHdr[nInNum].Name);
CStringstr;
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种地址的转换。

继续浏览有关 安全 的文章
发表评论