呵呵,看得出,你对pe文件格式还是不太了解。
ImageBase对于EXE文件来说,由于每个文件总是使用独立的虚拟地址空间,EXE总是能够按照这个地址装入。通常是0x00400000,imagebase指向的内容是DOS文件头。对于内存中pe文件代码段的起始地址是ImageBase + BaseOfCode;对于磁盘文件中代码段的起始地址是相对于文件头偏移PointerToRawData的位置。
假设要在磁盘文件中的代码段缝隙中添加代码,则首先需要查看磁盘文件代码段缝隙大小,是否容的下插入的代码,如果能容下,则根据文件对齐的原则,首先将原来的磁盘文件中代码段按照文件对齐,找出起始插入代码的位置。例如:
// 此段的真实长度.
dwVirtSize=header->section_header[0].Misc.VirtualSize;
// 此段的物理偏移.
dwPhysAddress=header->section_header[0].PointerToRawData;
// 此段的物理长度.
dwPhysSize=header->section_header[0].SizeOfRawData;
// 得到代码段的可用空间,用以判断可不可以写入我们的代码
// 用此段的物理长度减去此段的真实长度就可以得到.
dwSpace=dwPhysSize-dwVirtSize;
if(dwSpace < viruslength) return;
// 代码写入的物理偏移.
dwEntryWrite=header->section_header[0].PointerToRawData+header->
section_header[0].Misc.VirtualSize;
//对齐边界.
mods=dwEntryWrite%16;
if(mods!=0)
{
dwEntryWrite+=(16-mods);
}
//计算加载到内存中的代码段与文件中的代码段的差。
dwCodeOffset=header->opt_head.BaseOfCode-dwPhysAddress;
这里的dwEntryWrite就是对齐后要插入代码的位置。现在有了物理文件中的位置,需要找出加载到内存中的位置。根据我在上面贴子中讲的“对于code代码段,在内存中存在的形式和硬盘中存储的形式是一样的,都是以二进制方式存在”,可以有公式:
内存中位置 - (ImageBase + BaseOfCode) = dwEntryWrite - dwPhysAddress;
由于pe中使用的都是PVA,因此假设内存中对应位置的RVA是dwNewEntryAddress,
则上面公式中: 内存中位置 = ImageBase + dwNewEntryAddress;
把这个代入上面公式就是:
ImageBase + dwNewEntryAddress - (ImageBase + BaseOfCode) = dwEntryWrite - dwPhysAddress
于是:dwNewEntryAddress = dwEntryWrite - dwPhysAddress + BaseOfCode;
dwNewEntryAddress = dwEntryWrite + (BaseOfCode - dwPhysAddress );
而前面dwCodeOffset=header->opt_head.BaseOfCode-dwPhysAddress;
所以:
dwNewEntryAddress = dwEntryWrite + dwCodeOffset;
到此为止,就推断出了你开头 计算新的程序入口地址的公式了。
哈哈,如果我的回答你能明白,那么别忘了给我加点声望值