面朝大海,春暖花开

C++/C

研究PE文件格式(二)

这2天一直再研究PE文件格式,其实别的不是很难,就RVA,物理地址,物理偏移弄得糊涂了。
现在才有点明白。
就是就是磁盘上的文件地址与进程虚拟空间中的地址或者偏移转换。
又再取看看应用程序捆绑编程,越看越迷惑,感觉作者写的一点都不负责任。比如贴处一段代码出来:
  // 此段的真实长度.
  dwVirtSize=header->section_header[0].Misc.VirtualSize;

  // 此段的物理偏移.
  dwPhysAddress=header->section_header[0].PointerToRawData;

  // 此段的物理长度.
  dwPhysSize=header->section_header[0].SizeOfRawData;
  
  // 得到PE文件头的开始偏移.
  dwPeAddress=dos_head->e_lfanew;
  
  // 得到代码段的可用空间,用以判断可不可以写入我们的代码
  // 用此段的物理长度减去此段的真实长度就可以得到.
  dwSpace=dwPhysSize-dwVirtSize;

  // 得到程序的装载地址,一般为0x400000.
  dwProgRAV=header->opt_head.ImageBase;

  // 得到代码偏移,用代码段起始RVA减去此段的物理偏移
  // 应为程序的入口计算公式是一个相对的偏移地址,计算公式为:
  // 代码的写入地址+dwCodeOffset.
 dwCodeOffset=header->opt_head.BaseOfCode-dwPhysAddress;
  
  // 代码写入的物理偏移.
  dwEntryWrite=header->section_header[0].PointerToRawData+header->section_header[0].Misc.VirtualSize;

  //对齐边界.
  mods=dwEntryWrite%16;

  if(mods!=0)
  {
   dwEntryWrite+=(16-mods);
  }
  
  // 保存旧的程序入口地址.
  dwOldEntryAddress=header->opt_head.AddressOfEntryPoint;

  // 计算新的程序入口地址.       
  dwNewEntryAddress=dwEntryWrite+dwVirtSize;
对于最后的计算新的程序入口地址,我看不懂,为什么先要计算代码物理偏移,然后再把磁盘文件入口地址转换为虚拟空间地址
也是是就要加上一个代码偏移。这还是我花了以上午的时间理解了,是作者的注释误导了我。其实何必这么麻烦呢~
一句代码就解决问题了,dwNewEntryAddress=head->opt_head.BaseOfCode+dwVirtSize;就可以了。这样就更容易
理解了。意思是程序执行第一条指令地址加上代码实际长度就可以了(是虚拟空间里面的地址)。而不用再从磁盘文件的物理地址转换过来了。
不知道作者是不是东拼西凑来的,也不整理一下。而且注释又不清晰。不知道是不是中国人都很喜欢抄袭原著的。

posted on 2007-10-24 18:44 随风只幻 阅读(276) 评论(0)  编辑 收藏 引用


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理