这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;就可以了。这样就更容易
理解了。意思是程序执行第一条指令地址加上代码实际长度就可以了(是虚拟空间里面的地址)。而不用再从磁盘文件的物理地址转换过来了。
不知道作者是不是东拼西凑来的,也不整理一下。而且注释又不清晰。不知道是不是中国人都很喜欢抄袭原著的。