这节课的重点是:模拟PE加载过程,按照运行的要求给FileBuffer拉伸放到内存当中,从 FileBuffer 到 ImageBuffer 再到 运行Buffer。
PE 加载 过程:
-
根据sizeofImage 分配空间
-
根据sizeofheader copy头
-
按照节表, 根据VaSize,RawSize,SizeOfRawData copy节
一,介绍FileBuffer
sizeofHeanders(位于可选PE头中) 它是 所有头+所有节表 按照 文件对齐以后的大小
节表和节的关系:节表是节的目录。
Misc 未初始化,没对齐的节 代表在内存中映射完的大小
SizeOfRawData 对应的节里面的数据按照文件对齐后的大小
PointerToRawData 文件的偏移 (在文件中离DOS头有多远)
二,FileBuffer call到ImageBuffer中
先call SizeOfHeaders ,然后call节的数据(节表已经交代了节的大小内容)
ImageBuffer中的地址对应FileBuffer的地址:
VirtualAddress 代表虚拟的偏移 也就是离DOS头的距离,如何确定在第几个节?
① 501234-50000=1234
②1234 > VirtualAddress 123456 < VirtualAddress+misc.VirtualSize
③1234-1000=234
④400+234=我们想要的地址
附:
RVA 相对偏移地址 例如1234就是RVA ,离开始头有多远!注!RVA不是VirtualAddress!!!
FOA就是上面的 400+234 F是 File 文件 OA就是 offset 偏移
主要就是要学会把FileBuffer拉伸成为ImageBuffer后 再写成运行Buffer,以后方便把自己的代码塞进去。
例题、编写一个函数,能够将RVA的值转换成FOA. //函数声明 //************************************************************************** //ReadPEFile:将文件读取到缓冲区 //参数说明: //lpszFile 文件路径 //pFileBuffer 缓冲区指针 //返回值说明: //读取失败返回0 否则返回实际读取的大小 //******************************************************DWORD ReadPEFile(IN LPSTR lpszFile,OUT LPVOID* pFileBuffer); //****************************************************** //CopyFileBufferToImageBuffer:将文件从FileBuffer复制到ImageBuffer //参数说明: //pFileBuffer FileBuffer指针 //pImageBuffer ImageBuffer指针 //返回值说明: //读取失败返回0 否则返回复制的大小 //****************************************************** DWORD CopyFileBufferToImageBuffer(IN LPVOID pFileBuffer,OUT LPVOID* pImageBuffer); //****************************************************** //CopyImageBufferToNewBuffer:将ImageBuffer中的数据复制到新的缓冲区 //参数说明: //pImageBuffer ImageBuffer指针 //pNewBuffer NewBuffer指针 //返回值说明: //读取失败返回0 否则返回复制的大小 //******************************************************DWORD CopyImageBufferToNewBuffer(IN LPVOID pImageBuffer,OUT LPVOID* pNewBuffer); //****************************************************** //MemeryTOFile:将内存中的数据复制到文件 //参数说明: //pMemBuffer 内存中数据的指针 //size 要复制的大小 //lpszFile 要存储的文件路径 //返回值说明: //读取失败返回0 否则返回复制的大小 //******************************************************BOOL MemeryTOFile(IN LPVOID pMemBuffer,IN size_t size,OUT LPSTR lpszFile); //****************************************************** //RvaToFileOffset:将内存偏移转换为文件偏移 //参数说明: //pFileBuffer FileBuffer指针 //dwRva RVA的值 //返回值说明: //返回转换后的FOA的值 如果失败返回0 //****************************************************** DWORD RvaToFileOffset(IN LPVOID pFileBuffer,IN DWORD dwRva);