5.1 Windows的二进制文件格式PE/COFF

PE文件格式事实上与ELF同根同源,它们都是由COFF格式发展而来。

5.2 PE前身——COFF

在win下,Command Prompt for vs 2017,cd命令进入源代码所在目录:

运行命令:

“cl”是VISUAL C++的编译器。/c参数表示只编译,不链接,只会生成obj文件,不会生成exe文件。如下:

如果不加这个参数,那么cl会在编译源代码后,再调用link链接器将生产的obj文件与默认的C运行库链接,生成exe文件。
“/Za”参数禁用这些C和C++的专有扩展。
可以使用下面命令查看obj的结构:

/ALL参数将打印输出目标文件的所有相关信息,包括文件头,每个段的属性和段的原始数据及符号表。
下面是打印出来的所有相关信息:

Microsoft (R) COFF/PE Dumper Version 14.10.25019.0
Copyright (C) Microsoft Corporation. All rights reserved. Dump of file SimpleSection.obj File Type: COFF OBJECT FILE HEADER VALUES
14C machine (x86)
number of sections
5960849C time date stamp Sat Jul ::
1F4 file pointer to symbol table
number of symbols
size of optional header
characteristics SECTION HEADER #
.drectve name
physical address
virtual address
size of raw data
DC file pointer to raw data (000000DC to 000000F3)
file pointer to relocation table
file pointer to line numbers
number of relocations
number of line numbers
100A00 flags
Info
Remove
byte align RAW DATA #
: 2F 4C 4C 3A /DEFAULTLIB:"
: 4C 4D LIBCMT" Linker Directives
-----------------
/DEFAULTLIB:LIBCMT SECTION HEADER #
.debug$S name
physical address
virtual address
size of raw data
F4 file pointer to raw data (000000F4 to )
file pointer to relocation table
file pointer to line numbers
number of relocations
number of line numbers
flags
Initialized Data
Discardable
byte align
Read Only RAW DATA #
: F1 ....?...g...)...
: 3A 5C 6D 6C ....D:\SimpleSec
: 6F 6E 5C 6D 6C tion\SimpleSecti
: 6F 6E 2E 6F 6A 3A 3C on.obj.:.<.."...
: 0A BB 0A BB .....?a......?a.
: 4D 6F 6F 4F .Microsoft (R) O
: 6D 7A 6E 6F 6D 6C ptimizing Compil
: er.. SECTION HEADER #
.data name
physical address
virtual address
C size of raw data
file pointer to raw data ( to )
file pointer to relocation table
file pointer to line numbers
number of relocations
number of line numbers
C0300040 flags
Initialized Data
byte align
Read Write RAW DATA #
: 0A T...%d..U... SECTION HEADER #
.text$mn name
physical address
virtual address
4E size of raw data
file pointer to raw data ( to 000001C1)
1C2 file pointer to relocation table
file pointer to line numbers
number of relocations
number of line numbers
flags
Code
byte align
Execute Read RAW DATA #
: 8B EC 8B E8 U.ì.E.Ph....è...
: C4 5D C3 CC CC CC CC CC CC CC CC CC CC ..?.]?ìììììììììì
: 8B EC EC C7 FC A1 U.ì.ì.?Eü....?..
: FC F8 E8 .........Eü.E?Pè
: C4 8B FC 8B E5 5D C3 .....?..Eü.?]? RELOCATIONS #
Symbol Symbol
Offset Type Applied To Index Name
-------- ---------------- ----------------- -------- ------
DIR32 A $SG1535
0000000D REL32 F _printf
0000002E DIR32 B ?static_var@???main@@@ (`main'::`2'::static_var)
DIR32 ?static_var2@???main@@@ (`main'::`2'::static_var2)
REL32 E _func SECTION HEADER #
.bss name
physical address
virtual address
size of raw data
file pointer to raw data
file pointer to relocation table
file pointer to line numbers
number of relocations
number of line numbers
C0300080 flags
Uninitialized Data
byte align
Read Write COFF SYMBOL TABLE
010461BB ABS notype Static | @comp.id
ABS notype Static | @feat.
SECT1 notype Static | .drectve
Section length , #relocs , #linenums , checksum
SECT2 notype Static | .debug$S
Section length , #relocs , #linenums , checksum
SECT3 notype Static | .data
Section length C, #relocs , #linenums , checksum AC5AB941
SECT3 notype External | _global_init_var
UNDEF notype External | _global_uninit_var
00A SECT3 notype Static | $SG1535
00B SECT3 notype Static | ?static_var@???main@@@ (`main'::`2'::static_var)
00C SECT4 notype Static | .text$mn
Section length 4E, #relocs , #linenums , checksum CC61DB94
00E SECT4 notype () External | _func
00F UNDEF notype () External | _printf
SECT4 notype () External | _main
SECT5 notype Static | .bss
Section length , #relocs , #linenums , checksum
SECT5 notype Static | ?static_var2@???main@@@ (`main'::`2'::static_var2) String Table Size = 0x5D bytes Summary .bss
C .data
.debug$S
.drectve
4E .text$mn
COFF文件结构

COFF的文件头部包括两部分,一个是描述文件总体结构和属性的映像头,另一个是描述该文件中包含的段属性的段表
映像:因为PE文件再装载时被直接映射到进程的虚拟空间中运行,它时进程的虚拟空间的映像。所以PE可执行文件很多时候被叫做映像文件

文件头里描述COFF文件总体属性的映像头是一个”IMAGE_FILE_HEADER”的结构,相当于ELF中”Elf32_Ehdr”结构。

上面目标文件中这部分与这个结构对应:

File Type: COFF OBJECT

FILE HEADER VALUES
14C machine (x86)//目标机器类型
number of sections//PE中所含段的数量
5960849C time date stamp Sat Jul :: //PE文件创建时间
1F4 file pointer to symbol table//符号表在PE文件中的位置
number of symbols
size of optional header//optional header的大小,这个结构只存在PE可执行文件中,COFF文件中不存在
characteristics

COFF OBJECT也就是COFF目标文件格式。
映像头后面就是COFF文件的段表,它是一个类型”IMAGE_SECTION_HEADER”结构数组,数组里面每一个元素代表一个段,这个结构和ELF文件中的”Elf32——Shdr”很相似。

5.3 链接指示信息

上面目标文件中”.drectve”内容:

SECTION HEADER #
.drectve name
physical address
virtual address
size of raw data
DC file pointer to raw data (000000DC to 000000F3)
file pointer to relocation table
file pointer to line numbers
number of relocations
number of line numbers
100A00 flags //标准位,即"IMAGE_SECTION_HEADERS"里面的Characteristics成员。
Info
Remove
byte align//这三个组合属性表示该段时信息段,并非程序数据 RAW DATA #//该段在文件中的原始数据
: 2F 4C 4C 3A /DEFAULTLIB:"
: 4C 4D LIBCMT" //dumpbin对该段进行解析后的结果,它就是"cl"编译器希望传递给"link"链接器的参数,它表示VC的静态链接的多线程C库。 Linker Directives
-----------------
/DEFAULTLIB:LIBCMT

它的内容时编译器传给链接器的指令。

5.4 调试信息

COFF文件中所有以”.debug”开始的段都包含着调试信息。

  • “.debug$S”表示包含的是符号相关的调试信息。
  • “.debug$P”表示包含的是预编译头文件相关的调试信息。
  • “.debug$T”表示包含的是类型相关的调试信息。

调试信息段具体格式被定义在PE格式文件标准中。

SECTION HEADER #
.debug$S name
physical address
virtual address
size of raw data
F4 file pointer to raw data (000000F4 to )
file pointer to relocation table
file pointer to line numbers
number of relocations
number of line numbers
flags
Initialized Data
Discardable
byte align
Read Only RAW DATA #
: F1 ....?...g...)...
: 3A 5C 6D 6C ....D:\SimpleSec
: 6F 6E 5C 6D 6C tion\SimpleSecti
: 6F 6E 2E 6F 6A 3A 3C on.obj.:.<.."...
: 0A BB 0A BB .....?a......?a.
: 4D 6F 6F 4F .Microsoft (R) O
: 6D 7A 6E 6F 6D 6C ptimizing Compil
:

5.5 符号表

COFF符号表的内容基本和ELF文件的符号表一样,主要是符号名。符号的类型,所在的位置

COFF SYMBOL TABLE //符号编号 符号大小 符号所在位置 符号类型,只有两种notype和notype() 符号可见范围 符号名
010461BB ABS notype Static | @comp.id //ABS表示符号是个绝对值,不存在任何段中
ABS notype Static | @feat. //notype 变量和其他符号
SECT1 notype Static | .drectve //表示符号所表示的对象定义在本COFF文件的第一个段中
Section length , #relocs , #linenums , checksum
SECT2 notype Static | .debug$S //Static局部变量,只有目标文件中可见
Section length , #relocs , #linenums , checksum
SECT3 notype Static | .data
Section length C, #relocs , #linenums , checksum AC5AB941
SECT3 notype External | _global_init_var //External全局变量,可以被其他目标文件引用
UNDEF notype External | _global_uninit_var //表示符号未定义,即这个符号被定义在其他目标文件中
00A SECT3 notype Static | $SG1535
00B SECT3 notype Static | ?static_var@???main@@@ (`main::`::static_var)
00C SECT4 notype Static | .text$mn
Section length 4E, #relocs , #linenums , checksum CC61DB94
00E SECT4 notype () External | _func1 //notype ()函数
00F UNDEF notype () External | _printf
SECT4 notype () External | _main
SECT5 notype Static | .bss
Section length , #relocs , #linenums , checksum
SECT5 notype Static | ?static_var2@???main@@@ (`main::`::static_var2)

5.6 Windows下的ELF——PE

PE文件是基于COFF的扩展,它比COFF文件多几个结构,最主要变化:

  • 文件最开始的部分不是COFF文件头,而是DOS MZ可执行文件格式的文件头和桩代码
  • 原来的COFF文件头中的”IMAGE_FILE_HEADER”部分扩展成PE文件文件头结构”IMAGE_NT_HEADERS”,这个结构包括原来的”Image Header”及新增的PE扩展头部结构

程序员的自我修养五Windows PE/COFF的更多相关文章

  1. 程序员的自我修养九Windows下的动态链接

    9.1 DLL简介 DLL即动态链接库的缩写,它相对于Linux下的共享对象. Windows下的DLL文件和EXE文件实际上是一个概念,它们都是有PE格式的二进制文件. 微软希望通过DLL机制加强软 ...

  2. pwn学习日记Day21 《程序员的自我修养》读书笔记

    Linux内核装载ELF过程 (1)bash进程调用fork()系统调用创建一个新的进程 (2)新的进程调用execve()系统调用执行指定的ELF文件,原先的bash进程继续返回等待刚才启动的新进程 ...

  3. pwn学习日记Day19 《程序员的自我修养》读书笔记

    windows PE/COFF章总结 本章学习了windows下的可执行文件和目标文件格式PE/COFF.PE/COFF文件与ELF文件非常相似,它们都是基于段的结构的二进制文件格式.Windows下 ...

  4. pwn学习日记Day20 《程序员的自我修养》读书笔记

    可执行文件的装载与进程 覆盖装入和页映射是两种典型的动态装载方法 进程建立的三步 1.创建一个独立的虚拟地址空间 2.读取可执行文件头,并且建立虚拟空间与可执行文件的映射关系. 3.将CPU的指令寄存 ...

  5. 程序员的自我修养(2)——计算机网络(转) good

    相关文章:程序员的自我修养——操作系统篇 几乎所有的计算机程序,都会牵涉到网络通信.因此,了解计算机基础网络知识,对每一个程序员来说都是异常重要的. 本文在介绍一些基础网络知识的同时,给出了一些高质量 ...

  6. gcc ld 链接器相关知识,调试指令(程序员的自我修养----链接、装载与库)

    最近解决一个动态链接上的问题,因为以前从来没有接触过这方面的知识,所以恶补了一下,首先要了解gcc编译指令(makefile),ld链接器的选项(还有连接脚本section指定内存位置),熟悉查看连接 ...

  7. 第八周读书笔记(人月神话X月亮与六便士)——到底什么才是一个程序员的自我修养?

    写了这么久的读书笔记,涉及到问题大多是一些如何把软件工程做好,如何把自己的职业生涯做好.但总感觉逻辑链上缺了一环,亦即:我们为什么要把软件工程做好,我们成为一名优秀的职业生涯的意义到底在于什么?我觉得 ...

  8. pwn学习日记Day18 《程序员的自我修养》读书笔记

    知识杂项 obj文件:当前源代码编译成二进制目标文件 exe文件:将.obj文件与库文件.lib等文件链接生成的可执行文件 一个现代编译器的主要工作流程如下: 源程序(source code)→ 预处 ...

  9. Java程序员的自我修养

    一.自我修养路线图 如图,这是笔者所走的路.且不论这路走的对不对,这个过程中行业环境会影响到你,大可不必钻牛角尖.附上这张图的目的是为了说,如果你想成为一个优秀的程序员,那么你一定要有规划.当然,别想 ...

随机推荐

  1. 【学习笔记】C# 封装和继承

    封装 封装是实现面向对象程序设计的第一步 封装就是将数据.方法等集合在一个个单元中,我们称之为类 封装的意义在于保护代码/数据,屏蔽复杂性 继承 继承是所有面向对象语言不可缺少的部分 继承是为了实现类 ...

  2. Hibernate 实体映射类的状态值自动转换

    经常会遇到有些字段在数据库只是一个 byte 值,但是取出数据后需要转换为真实的状态名称. 举个栗子:一个图书管理系统,书籍有一个属性 stat(借出状态),在库中只需要保存一个 0/1/2/3/4 ...

  3. 第三篇:RESTful介绍

    在介绍restful之前先放一张从之前文章评论里看到的图,我觉得它把soap和rest之间的一些区别形容地非常形象. 在第一篇和第二篇中我们也介绍过,soap协议传递的报文要基于xml格式的soap消 ...

  4. DL4NLP——词表示模型(三)word2vec(CBOW/Skip-gram)的加速:Hierarchical Softmax与Negative Sampling

    上篇博文提到,原始的CBOW / Skip-gram模型虽然去掉了NPLM中的隐藏层从而减少了耗时,但由于输出层仍然是softmax(),所以实际上依然“impractical”.所以接下来就介绍一下 ...

  5. ffmpeg.exe下载

    下载链接:http://pan.baidu.com/s/1cGTe6y

  6. 基于FPGA的VGA显示静态图片

    终于熬到暑假了,记过三四周的突击带考试,终于为我的大二画上了一个完整的句号,接下来终于可以静心去做自己想做的事情了,前一阵子报了一个线上培训班,学学Sobel边缘检测,之前一直在学习图像处理,但是因为 ...

  7. vue项目优化之按需加载组件-使用webpack require.ensure

    require-ensure和require-amd的区别: require-amd 说明: 同AMD规范的require函数,使用时传递一个模块数组和回调函数,模块都被下载下来且都被执行后才执行回调 ...

  8. CentOS 下mysql ERROR&n…

    CentOS 下mysql ERROR 1045: Access denied for user: 'root@localhost' (Using password: NO) 描述:在操作数据库时会出 ...

  9. 【mock.js】后端不来过夜半,闲敲mock落灯花 ——南宋·赵师秀

      mock的由来[假]   赵师秀:南宋时期的一位前端工程师 诗词背景:在一个梅雨纷纷的夜晚,正值产品上线的紧张时期,书童却带来消息:写后端的李秀才在几个时辰前就赶往临安度假去了,  赵师秀非常生气 ...

  10. H5入门——HTML部分

    一.HTML的基本构成 1.<!DOCTYPE html>文档类型声明 <!--HTML的文档类型声明.声明这个文件是HTML5文件,让浏览器按照HTML5准备进行解析显示.文档类型 ...