写入_IMAGE_FILE_HEADER全部成员 和_IMAGE_OPTIONAL_HEADER部分成员 上一节我们已经学习了这些结构,再复习一下 写入_IMAGE_FILE_HEADER数据: 成员1,占2个字节,表示该文件运行所要求的CPU。对于Intel平台,该值是“4C01”。 成员2,占2个字节,表示该文件中段的总数,我这里计划写3个段(用Pelorder查看参考程序)。(.text(代码段)、.rdata(只读数据段)、 .data(全局变量数据段))。所以此处值是“0300”。 成员3,占4个字节,表示文件创建日期和时间,从1970.1.1 00:00:00以来的秒数,我们这里填“0000”即可。 成员4,占4个字节,表示符号表的指针,主要用于调试,在这里填“0000”。成员5,占4个字节,表示符号的数目,主要用于调试,在这里填“0000” 成员6,占2个字节,表示后面的“PE文件可选头 ”部分所占空间大小。我们来再复习一下这个结构。 我们已经知道“PE文件可选头 ”的大小是 224 byte,转换成十六进制就是E0,所以这里的值为“E000”(这在PE中是不会变的,一定要记住,就像4D5A和5045一样) 成员7,占2个字节,表示关于文件信息的标记,比如文件是exe还是dll。这个值实际上是二进制位进行或运算得到的值。各二进制位表示的意义如下: 我从头文件中复制出来一份可选头结构体,并加了相关解释 成员1,占2个字节,表示文件的格式,值为0x010B表示32位的可选头 成员2,占1个字节,表示链接器的主版本号,此值不会影响程序的执行,我们这里填充零, 此值为“00”。
成员3,占1个字节,表示链接器的幅版本号,此值不会影响程序的执行,我们这里填充零,此值为“00”。
成员4,占4个字节,表示可执行代码的长度,此值不会影响程序的执行,我们这里填充零,此值为“00000000”。
成员5,占4个字节,表示初始化数据的长度(数据段)。此值不会影响程序的执行,我们这里填充零,此值为“00000000”。
成员6,占4个字节,表示未初始化数据的长度(bss段)。此值不会影响程序的执行,我们这里填充零,此值为“00000000”。 成员2到成员6总共占用14个字节 插入14个字节
成员7 ,4个字节,表示代码的入口RVA(文件映射到内存的偏移地址)地址,程序从这儿开始执行。PE装载器准备运行的PE文件的第一个指令的RVA。若您要改变整个执行的流程,可以将该值指定到新的RVA,这样新RVA处的指令首先被执行。 那么这个值我们怎么得到呢?我们知道在文件中有个.text段,他包含了所有的代码,我们可以从中找到我们的入口地址,在这里就是.text段里的第一行代码,也就是.text段的首地址,而在.text段头部就给出了他映射到内存后的首地址的偏移,我们查看已经做好的demo找到他取出添到此处,这里为“00100000”。(此处不理解没关系,我们讲完段结构后自能迎刃而解) 成员8,4个字节,表示可执行代码起始位置。当然就是.text段的首地址,此值不会影响程序的执行,我们这里填充零,此值为“00000000”。
成员9,4个字节,表示初始化数据的起始位置,此值不会影响程序的执行,我们这里填充零,此值为“00000000”。 成员10,4个字节,就是文件映射到内存是的基地址。PE文件的优先装载地址。通常设为“00400000”,PE装载器将尝试把文件装到虚拟地址空间的00400000h处。“优先”表示若该地址区域已被其他模块占用,那PE装载器会选用其他空闲地址。我们这里的值设为“00400000”。
|