由于论坛字体格式排版和字数限制的原因,这系列教程我主要以图来解释(有的内容会引用书上的原文)
在讲PE之前首先介绍一下WinNT.h这个库文件 这个头文件包含了所有PE相关的结构 首先创建一个小的可执行程序 选择一个小的应用程序 编译好之后,我们看一下他的区段(text是放代码的,rdata段是放导入表的,data用来放全局函数的) 把头文件放到编译的目录下可以精简我们的程序 只要在源码中包含一下这个头文件即可 右键查看头文件 合并区段的部分被注释掉了 加上合并区段的代码 编译出来会发现应用程序更小了,查看一下区段,会发现区段被合并了 这个库文件的部分功能(非常有用)就介绍到这里
下面进入正题 这是PE的整体架构 我们一个一个分开看 为什么要将MZ当做DOS签名呢? 这个是我手写PE程序的DOS头,有64字节(PE只是个参考,有些结构体成员可有可无) 计算一下大小,验证一下 DOS存根的概念 40到4D是16位的汇编指令,在DOS环境下才会执行这些代码,32为的Windows中不会运行。 这是手写PE的DOS存根,总共112字节 我将它的位置留出来方便讲解,也可以不留(DOS存根大小一般为112字节,大小不固定) NT头(包含了文件头和可选头) NT头有4个字节的标识,前面空出的8字节是为了内存对其需要,必须得填充NULL 文件头 文件头是表现文件大致属性的结构体 注意一个特殊的例子:.obj和resource DLL的characteristics值不是0002h,他们都不可执行 手写PE的NT头 可选头(PE头中最大的结构体) 必须有的成员:否则可执行文件会出错
手写PE的可选头 节区头的概念: 节区头结构体: 重要成员: Characterisitics是由下面这些值组合起来的(相加) 手写PE的节区头(区段头) RVA和RAW之间的转换: 文件偏移-文件中节区的起始位置=内存偏移-内存中节区的起始位置 文件偏移=内存偏移-内存中节区的起始位置+文件中节区的起始位置
创建一个文件,用C32打开 认识数据的存储方式: 写好PE签名,然后剩下成员用58个00填充 写好了 参考编译器生成的程序 把存根的位置留出来 把NT头的PE标识写在后面 先写到这里,要不然文章太长了,未完待续····下节课见~ |