关于使用masm编译器产生的PE文件"data段"与"data?段"结构的思考与试验

最近在学习分解PE文件,第一步便是熟悉pe文件的结构。在看到了罗云杉的win32汇编教程的第17章的PEInfo例子时,运行了一下,顺便根据提示做了一定的试验。结果发现了一定的问题。这些问题主要集中在对win32汇编中的.data段和.data?段上。

首先,按照书中(大概是第三章)的说法,.data?段在磁盘上不会预留空间,只有当PE文件被装载(注意是装载,而不是简单的内存映射)的时候,.data?段才会被填充为真正的占有内存的节。于是,我编写了一个非常简单的程序,如下:

 

代码
        .386
        .model flat, stdcall
        option casemap :none

include        windows.
inc
include        user32.
inc
includelib    user32.lib
include        kernel32.
inc
includelib    kernel32.lib



    .data?
number    dd    ?

    .const
text    db    
'hello',0

    .code
start:
    invoke    MessageBox, NULL, addr    text, addr    text, MB_OK
    invoke    ExitProcess, 
0
end    start

 

使用PEInfo程序(书中所带代码,基本上就是查看PE文件内容的程序)查看到如下信息

----------------------------------------------------------
节区名称  节区大小  虚拟地址  Raw_尺寸  Raw_偏移  节区属性
----------------------------------------------------------
.text     00000026  00001000  00000200  00000400  60000020
.rdata    0000009A  00002000  00000200  00000600  40000040
.data     00000004  00003000  00000000  00000000  C0000040
.rsrc     00000010  00004000  00000200  00000800  40000040

 

简单解释一下,“Raw_尺寸”表示该节在磁盘中以磁盘粒度调整后的所占大小,“节区大小”是没有经过对齐调整的,正真所占空间的大小。

 

很显然,.const段被解释位.rdata,.data?也被解释为.data(注意区别程序结果中的.data和程序中的.data其实所带意义不同,根据以后的试验可知,在PE文件中,被命名为.data的节实际上是源程序中的.data和.data?的统称), 而程序里由于没有.data,所以Raw_尺寸为0。

当我修改程序如下之后(只是简单的加了一个.data段),程序如下

 

代码
       .386
        .model flat, stdcall
        option casemap :none

include        windows.
inc
include        user32.
inc
includelib    user32.lib
include        kernel32.
inc
includelib    kernel32.lib



    .data?
number    dd    ?

    .data
number2   dd    0


    .const
text    db    
'hello',0

    .code
start:
    invoke    MessageBox, NULL, addr    text, addr    text, MB_OK
    invoke    ExitProcess, 
0
end    start

 

再次查看,可以看到如下结果,

----------------------------------------------------------
节区名称  节区大小  虚拟地址  Raw_尺寸  Raw_偏移  节区属性
----------------------------------------------------------
.text     00000026  00001000  00000200  00000400  60000020
.rdata    0000009A  00002000  00000200  00000600  40000040
.data     00000008  00003000  00000200  00000800  C0000040
.rsrc     00000010  00004000  00000200  00000A00  40000040

 

再次修改程序,将number2的定义改成2*16*16个byte大小,即

    .data
number2   db    2*16*16 dup(0)

得到结果

----------------------------------------------------------
节区名称  节区大小  虚拟地址  Raw_尺寸  Raw_偏移  节区属性
----------------------------------------------------------
.text     00000026  00001000  00000200  00000400  60000020
.rdata    0000009A  00002000  00000200  00000600  40000040
.data     00000204  00003000  00000200  00000800  C0000040
.rsrc     00000010  00004000  00000200  00000A00  40000040

 

如果在上次修改的那个程序里再在.data中再加一个number3 db 0 ,即

    .data
number2   db    2*16*16 dup(0)
number3   db 0

----------------------------------------------------------
节区名称  节区大小  虚拟地址  Raw_尺寸  Raw_偏移  节区属性
----------------------------------------------------------
.text     00000026  00001000  00000200  00000400  60000020
.rdata    0000009A  00002000  00000200  00000600  40000040
.data     00000208  00003000  00000400  00000800  C0000040
.rsrc     00000010  00004000  00000200  00000C00  40000040

 

总结:

有上面的一系列的测试结果可知,

1. 在PE文件中,被命名为.data的节实际上是源程序中的.data和.data?的统称,只是.data?不占用磁盘,而.data却实实在在地占用了磁盘

2. 从"节区大小"这里可以看出来,源程序中在没有.data,但是有.data?的情况下,确实在磁盘上没有预留空间,但是在PE文件被装载进内存之后,就会被扩展出来

3. 磁盘的对齐粒度是200h,这其实是一笔不小的开销。远远高于内存的4h的对齐粒度。

 

posted @ 2010-08-12 11:41  aicro  阅读(590)  评论(0编辑  收藏  举报