【文章标题】: 谈一下LoadPE的FLC功能的编程实现
【文章作者】: 美丽の破船
【作者邮箱】: juxingting@163.com
【作者主页】: http://hi.baidu.com/juxingting
【编写语言】: C/C++
【操作平台】: XP + VC6.0
【作者声明】: 学PE文件格式的练习程序,发出来供象我一样菜的朋友共同进步!程序实现的算法很笨,往高手指教!
【详细内容】:

    LoadPE的功能强大想必是众所周知的!
    小弟我最近在学习PE文件格式,为了巩固自己的所学,我也在模仿LoadPE的PE编辑器功能!
    昨天,我把它的FLC功能给实现了,个人认为收获不小,颇为激动。
    在失眠了一夜之后,终于耐不住、来发帖子,与大家分享我的所得!(说不定,再让我骗来个精华~ )
    程序用的是最笨的方法,外加笨人比较愚笨,代码写的也罗嗦无比!故高手飘过~~~ 

    闲话不说了,说主题:
    在学习《加密与解密》(第二版)的时候,书里说的根据RVA计算文件偏移的方法如下:
        1、先遍历区段表中每个区段的Virtual Offset得到每个节的起始RVA,并根据SizeOfRawData属性得到每个节的结束RVA
        2、再根据第一步的结果判断要转换的RVA属于哪个区段内
        3、然后根据区段表中相应区段的Virtual Offset和Raw Offset的值来计算出每个区段中,它们两个的差值:△k
        4、最后就可以根据公式转换了!
          RVA = VA - ImageBase;
          File Offset = RVA - △k;
    可是怎么根据File Offset来计算RVA就不知道怎么办了~~

    随着我对PE文件结构的了解越来越深,慢慢的我才知道:节的PointerToRawData属性就是它在文件中的偏移地址! 

    这样一来,它们之间转换的方法就变成了:
        1、先遍历区段表中每个区段的Virtual Offset得到每个节的起始RVA,并根据SizeOfRawData属性得到每个节的结束RVA
        2、再根据第一步的结果判断要转换的RVA属于哪个区段内
        3、然后用要转换的RVA - 它所在的起始RVA 得到 这个RVA位于起始RVA的偏移RVA'
        4、最后取出它所在段的PointerToRawData属性值加上上一步算出来了RVA' 便得到它的文件偏移地址了!
  从文件偏移转换到RVA的方法也可想出来了,只不过是把上面的方法倒过来就可以了~~~ 
   下面我给出我写的代码:

代码:
void CTESTDlg::OnExec() 
{
  UpdateData(TRUE);
  DWORD Temp;
  if(((CButton*)GetDlgItem(IDC_RVA))->GetCheck())
  {
    sscanf(m_RvaCNT,"%X",&Temp);
    m_VaCNT.Format("%.8x",(m_ImgBase + Temp));
    if(Temp <= m_Sections[m_NumberOfSections-1].VirtualAddress + m_Sections[m_NumberOfSections-1].SizeOfRawData)
    {
      for(int a = 0;a < m_NumberOfSections;a++)
      {
        if(Temp >= m_Sections[a].VirtualAddress && Temp <= (m_Sections[a].VirtualAddress + m_Sections[a].SizeOfRawData))
        {
          m_OffCNT.Format("%.8x",(Temp - m_Sections[a].VirtualAddress)+m_Sections[a].PointerToRawData);
          m_SecName.Format("%s",m_Sections[a].Name);
          sscanf(m_OffCNT,"%X",&Temp);
          m_Content = GetHexContent(Temp);
        }
      }
    }
    else
    {
      MessageBox("超出范围了!!!");
      m_VaCNT = "";
      m_RvaCNT = "";
      m_OffCNT = "";
    }
  }
  else if(BST_CHECKED == ((CButton*)GetDlgItem(IDC_VA))->GetCheck())
  {
    sscanf(m_VaCNT,"%X",&Temp);
    m_RvaCNT.Format("%.8x",(Temp - m_ImgBase));
    sscanf(m_RvaCNT,"%X",&Temp);
    if(Temp <= m_Sections[m_NumberOfSections-1].VirtualAddress + m_Sections[m_NumberOfSections-1].SizeOfRawData)
    {
      for(int a = 0;a < m_NumberOfSections;a++)
      {
        if(Temp >= m_Sections[a].VirtualAddress && Temp <= (m_Sections[a].VirtualAddress + m_Sections[a].SizeOfRawData))
        {
          m_OffCNT.Format("%.8x",(m_Sections[a].PointerToRawData + (Temp - m_Sections[a].VirtualAddress)));
          m_SecName.Format("%s",m_Sections[a].Name);
          sscanf(m_OffCNT,"%X",&Temp);
          m_Content = GetHexContent(Temp);
        }
      }
    }
    else
    {
      MessageBox("超出范围了!!!");
      m_VaCNT = "";
      m_RvaCNT = "";
      m_OffCNT = "";
    }
  }
  else if(BST_CHECKED == ((CButton*)GetDlgItem(IDC_OFF))->GetCheck())
  {
    sscanf(m_OffCNT,"%X",&Temp);
    if(Temp <= (m_Sections[m_NumberOfSections-1].PointerToRawData + m_Sections[m_NumberOfSections-1].SizeOfRawData))
    {
      for(int a = 0;a < m_NumberOfSections;a++)
      {
        if(Temp >= m_Sections[a].PointerToRawData && Temp <= (m_Sections[a].PointerToRawData + m_Sections[a].SizeOfRawData))
        {
          m_RvaCNT.Format("%.8x",(m_Sections[a].VirtualAddress + (Temp - m_Sections[a].PointerToRawData)));
          m_VaCNT.Format("%.8x",(m_Sections[a].VirtualAddress + (Temp - m_Sections[a].PointerToRawData) + m_ImgBase));
          m_SecName.Format("%s",m_Sections[a].Name);
          sscanf(m_OffCNT,"%X",&Temp);
          m_Content = GetHexContent(Temp);
        }
      }
    }
    else
    {
      MessageBox("超出范围了!!!");
      m_VaCNT = "";
      m_RvaCNT = "";
      m_OffCNT = "";
    }
  }
  m_RvaCNT.MakeUpper();
  m_VaCNT.MakeUpper();
  m_OffCNT.MakeUpper();

  UpdateData(FALSE);
}
  

具体的代码,大家可以看附件!
希望我这个烂文章能对向我一样梦想自己成为高手的朋友有所帮助!
最后,祝大家成功!!加油~~
【附件下载】:文件地址转换器及VC源码.rar
--------------------------------------------------------------------------------

                                                       2008年07月06日 12:26:35