关于IMAGE_OPTIONAL_HEADER.SectionAlignment与IMAGE_OPTIONAL_HEADER.FileAlignment 以及内存映射的字节对齐

关于IMAGE_OPTIONAL_HEADER.SectionAlignment与IMAGE_OPTIONAL_HEADER.FileAlignment 以及内存映射的字节对齐
的关系.

一. PE格式(包括文件中和内存中)是怎么分块对齐的?
PE的大概格式是:
IMAGE_DOS_HEADER +
Stub +
IMAGE_NT_HEADERS +
IMAGE_SECTION_HEADER * n
Section 0
Section 1
...
Section n


分块对齐是这样分的:
------Block 1---------------------
IMAGE_DOS_HEADER +
Stub +
IMAGE_NT_HEADERS +
IMAGE_SECTION_HEADER * n
------Block 2---------------------
Section 0
------Block 3---------------------
Section 1
------Block 4---------------------
...
------Block 5---------------------
Section n
----------------------------------

从Block1 到 Block5都要按指定大小对齐.
其中, PE文件存储在磁盘的对齐是按照IMAGE_OPTIONAL_HEADER.FileAlignment对齐;
PE文件运行的时候再内存中是按照IMAGE_OPTIONAL_HEADER.SectionAlignment对齐.

用VC6生成一个Exe文件, 查看FileAlignment和SectionAlignment, 默认都是0x1000(4k).
一般Block 1比0x1000小的, 所以Block 2的ROF为0x1000.
而运行装载后, Block 2 的RVA一般为0x401000. (PE从0x400000开始装载的).

用VC2008生成一个Exe文件, 查看FileAlignment默认是0x200, SectionAlignment默认都是0x1000.
所以, 假设Block 1大小为0x2E6, 那么, 所以Block 2的ROF为0x400.
而运行装载后, Block 2 的RVA为0x401000. (PE从0x400000开始装载的).

而我们用CreateFileMapping打开一个文件时, 也是把文件加载到内存, 这个也是要对齐的,
但是这种对齐是针对整个文件的(这个也是基于0x1000对齐的).
区别是CreateFileMapping的对齐是针对这个文件的, 而PE文件运行装载的内存对齐是针对块的, 例如上面说的Block 1 ---- Block 5,

http://bbs.pediy.com/archive/index.php?t-90067.html


/ALIGN指定节的内存对齐属性,要更改节的文件对齐,
可以指定一个未公开的链接器选项"/FILEALIGN:#"来指定,例如"/FILEALIGN:0x1000"
#pragma comment(linker, "/ALIGN:0x1000")
#pragma comment(linker, "/FILEALIGN:0x1000")  // 验证了, 写在代码里没效
在 VC2008 中这样写就说第2行是无效指令,只能在项目属性的|连接器|命令行|附加选项里写.

我用VC2008修改如下
(FileAlignment默认是0x200, SectionAlignment默认是0x1000)
1.
SectionAlignment(/ALIGN:0x1000)
FileAlignment(/FILEALIGN:0x1000)
可以运行(其实这个配置就VC6的默认配置)

2.
SectionAlignment(/ALIGN:0x200)
FileAlignment(/FILEALIGN:0x1000)
报不是Win32应用程序.

3.
/ALIGN指定节的内存对齐属性,要更改节的文件对齐,就是用/OPT:WIN98,可以指定4k对齐,如果是OPT:NOWIN98,就是512字节对齐.
vs 2008 已经不支持了。


在VC6.0下
FileAlignment和SectionAlignment, 默认都是0x1000(4k).
1.
SectionAlignment(/ALIGN:0x200)
可以运行(只改SectionAlignment, FileAlignment自动变成了0x200)
(有这个警告LINK : warning LNK4108: /ALIGN specified without /DRIVER or /VXD; image may not run)

2.
SectionAlignment(/ALIGN:0x200)
FileAlignment(/FILEALIGN:0x1000)
可以运行(FileAlignment自动变成了0x200)(也就是说再VC6.0中/FILEALIGN:0x1000是无效的)
(有这个警告LINK : warning LNK4108: /ALIGN specified without /DRIVER or /VXD; image may not run)

3.
SectionAlignment(/ALIGN:0x1000)
FileAlignment(/OPT:WIN98)
可以运行(SectionAlignment 0x1000, FileAlignment 0x200)
(有这个警告LINK : warning LNK4108: /ALIGN specified without /DRIVER or /VXD; image may not run)

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
将PE文件格式逆向解析成汇编语言是一个非常复杂的任务,需要对PE文件格式有深入的了解,并且需要具备较强的反汇编技能。以下是一个简单的示例,演示如何将PE文件头部信息逆向解析成汇编语言: ``` ; 定义IMAGE_DOS_HEADER结构体 IMAGE_DOS_HEADER struct e_magic dw ? e_cblp dw ? e_cp dw ? e_crlc dw ? e_cparhdr dw ? e_minalloc dw ? e_maxalloc dw ? e_ss dw ? e_sp dw ? e_csum dw ? e_ip dw ? e_cs dw ? e_lfarlc dw ? e_ovno dw ? e_res dw 4 dup(?) e_oemid dw ? e_oeminfo dw ? e_res2 dw 10 dup(?) e_lfanew dd ? IMAGE_DOS_HEADER ends ; 定义IMAGE_NT_HEADERS结构体 IMAGE_NT_HEADERS struct Signature dd ? FileHeader IMAGE_FILE_HEADER <> OptionalHeader IMAGE_OPTIONAL_HEADER32 <> IMAGE_NT_HEADERS ends ; 定义IMAGE_FILE_HEADER结构体 IMAGE_FILE_HEADER struct Machine dw ? NumberOfSections dw ? TimeDateStamp dd ? PointerToSymbolTable dd ? NumberOfSymbols dd ? SizeOfOptionalHeader dw ? Characteristics dw ? IMAGE_FILE_HEADER ends ; 定义IMAGE_OPTIONAL_HEADER32结构体 IMAGE_OPTIONAL_HEADER32 struct Magic dw ? MajorLinkerVersion db ? MinorLinkerVersion db ? SizeOfCode dd ? SizeOfInitializedData dd ? SizeOfUninitializedData dd ? AddressOfEntryPoint dd ? BaseOfCode dd ? BaseOfData dd ? ImageBase dd ? SectionAlignment dd ? FileAlignment dd ? MajorOperatingSystemVersion dw ? MinorOperatingSystemVersion dw ? MajorImageVersion dw ? MinorImageVersion dw ? MajorSubsystemVersion dw ? MinorSubsystemVersion dw ? Win32VersionValue dd ? SizeOfImage dd ? SizeOfHeaders dd ? CheckSum dd ? Subsystem dw ? DllCharacteristics dw ? SizeOfStackReserve dd ? SizeOfStackCommit dd ? SizeOfHeapReserve dd ? SizeOfHeapCommit dd ? LoaderFlags dd ? NumberOfRvaAndSizes dd ? DataDirectory dd 16 dup(?) IMAGE_OPTIONAL_HEADER32 ends ; 定义节表结构体 IMAGE_SECTION_HEADER struct Name db 8 dup(?) VirtualSize dd ? VirtualAddress dd ? SizeOfRawData dd ? PointerToRawData dd ? PointerToRelocations dd ? PointerToLinenumbers dd ? NumberOfRelocations dw ? NumberOfLinenumbers dw ? Characteristics dd ? IMAGE_SECTION_HEADER ends ; 定义变量 dos_header IMAGE_DOS_HEADER <> nt_headers IMAGE_NT_HEADERS <> section_headers IMAGE_SECTION_HEADER 16 dup(?) ; 读取PE文件 filename db 'test.exe', 0 handle dw ? buffer db 512 dup(?) bytes_read dw ? section_table_offset dd ? size_of_section_table dd ? ; 打开文件 mov ah, 3dh mov al, 0 ; 只读模式 mov dx, offset filename int 21h mov handle, ax ; 读取DOS头部信息 mov ah, 3fh mov bx, handle mov cx, sizeof IMAGE_DOS_HEADER mov dx, offset dos_header int 21h ; 获取PE头部偏移地址 mov ax, word ptr [dos_header+0x3c] mov bx, handle mov cx, sizeof IMAGE_NT_HEADERS mov dx, offset nt_headers add dx, ax int 21h ; 解析PE头部信息 mov ax, word ptr [nt_headers.Signature] cmp ax, 'PE' jne exit_program ; 解析文件头部信息 mov ax, word ptr [nt_headers.FileHeader.NumberOfSections] mov section_table_offset, dx mov size_of_section_table, ax * sizeof IMAGE_SECTION_HEADER add dx, sizeof IMAGE_FILE_HEADER mov cx, sizeof IMAGE_FILE_HEADER mov si, offset nt_headers.FileHeader mov di, dx rep movsb ; 解析可选头部信息 mov ax, word ptr [nt_headers.OptionalHeader.Magic] cmp ax, IMAGE_NT_OPTIONAL_HDR32_MAGIC jne exit_program mov cx, sizeof IMAGE_OPTIONAL_HEADER32 mov si, offset nt_headers.OptionalHeader mov di, dx rep movsb ; 解析节表信息 mov ah, 3fh mov bx, handle mov cx, size_of_section_table mov dx, offset section_headers add dx, section_table_offset int 21h exit_program: ; 关闭文件 mov ah, 3eh mov bx, handle int 21h ``` 以上代码仅为示例,实际上解析PE文件格式的过程要比这个更加复杂,需要对不同的结构体进行不同的解析方式,并且需要处理一些特殊情况。同时,反汇编的过程中还需要考虑一些优化问题,例如去除无用代码、还原函数调用等,以确保反汇编的代码正确、可读性强。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值