Tiny PE文件格式程序在Windows 7 64位系统上运行时出现错误

5
我正在尝试在Windows 7 Ultimate 64位系统上运行以下汇编代码(使用Nasm汇编)。
; tiny.asm

BITS 32

;
; MZ header
;
; The only two fields that matter are e_magic and e_lfanew

mzhdr:
    dw "MZ"                       ; e_magic
    dw 0                          ; e_cblp UNUSED
    dw 0                          ; e_cp UNUSED
    dw 0                          ; e_crlc UNUSED
    dw 0                          ; e_cparhdr UNUSED
    dw 0                          ; e_minalloc UNUSED
    dw 0                          ; e_maxalloc UNUSED
    dw 0                          ; e_ss UNUSED
    dw 0                          ; e_sp UNUSED
    dw 0                          ; e_csum UNUSED
    dw 0                          ; e_ip UNUSED
    dw 0                          ; e_cs UNUSED
    dw 0                          ; e_lsarlc UNUSED
    dw 0                          ; e_ovno UNUSED
    times 4 dw 0                  ; e_res UNUSED
    dw 0                          ; e_oemid UNUSED
    dw 0                          ; e_oeminfo UNUSED
    times 10 dw 0                 ; e_res2 UNUSED
    dd pesig                      ; e_lfanew

;
; PE signature
;

pesig:
    dd "PE"

;
; PE header
;

pehdr:
    dw 0x014C                     ; Machine (Intel 386)
    dw 1                          ; NumberOfSections
    dd 0x4545BE5D                 ; TimeDateStamp UNUSED
    dd 0                          ; PointerToSymbolTable UNUSED
    dd 0                          ; NumberOfSymbols UNUSED
    dw opthdrsize                 ; SizeOfOptionalHeader
    dw 0x103                      ; Characteristics (no relocations, executable, 32 bit)

;
; PE optional header
;

filealign equ 1
sectalign equ 1

%define round(n, r) (((n+(r-1))/r)*r)

opthdr:
    dw 0x10B                      ; Magic (PE32)
    db 8                          ; MajorLinkerVersion UNUSED
    db 0                          ; MinorLinkerVersion UNUSED
    dd round(codesize, filealign) ; SizeOfCode UNUSED
    dd 0                          ; SizeOfInitializedData UNUSED
    dd 0                          ; SizeOfUninitializedData UNUSED
    dd start                      ; AddressOfEntryPoint
    dd code                       ; BaseOfCode UNUSED
    dd round(filesize, sectalign) ; BaseOfData UNUSED
    dd 0x400000                   ; ImageBase
    dd sectalign                  ; SectionAlignment
    dd filealign                  ; FileAlignment
    dw 4                          ; MajorOperatingSystemVersion UNUSED
    dw 0                          ; MinorOperatingSystemVersion UNUSED
    dw 0                          ; MajorImageVersion UNUSED
    dw 0                          ; MinorImageVersion UNUSED
    dw 4                          ; MajorSubsystemVersion
    dw 0                          ; MinorSubsystemVersion UNUSED
    dd 0                          ; Win32VersionValue UNUSED
    dd round(filesize, sectalign) ; SizeOfImage
    dd round(hdrsize, filealign)  ; SizeOfHeaders
    dd 0                          ; CheckSum UNUSED
    dw 2                          ; Subsystem (Win32 GUI)
    dw 0x400                      ; DllCharacteristics UNUSED
    dd 0x100000                   ; SizeOfStackReserve UNUSED
    dd 0x1000                     ; SizeOfStackCommit
    dd 0x100000                   ; SizeOfHeapReserve
    dd 0x1000                     ; SizeOfHeapCommit UNUSED
    dd 0                          ; LoaderFlags UNUSED
    dd 16                         ; NumberOfRvaAndSizes UNUSED

;
; Data directories
;

    times 16 dd 0, 0

opthdrsize equ $ - opthdr

;
; PE code section
;

    db ".text", 0, 0, 0           ; Name
    dd codesize                   ; VirtualSize
    dd round(hdrsize, sectalign)  ; VirtualAddress
    dd round(codesize, filealign) ; SizeOfRawData
    dd code                       ; PointerToRawData
    dd 0                          ; PointerToRelocations UNUSED
    dd 0                          ; PointerToLinenumbers UNUSED
    dw 0                          ; NumberOfRelocations UNUSED
    dw 0                          ; NumberOfLinenumbers UNUSED
    dd 0x60000020                 ; Characteristics (code, execute, read) UNUSED

hdrsize equ $ - $$

;
; PE code section data
;

align filealign, db 0

code:

; Entry point

start:
    push byte 42
    pop eax
    ret

codesize equ $ - code

filesize equ $ - $$

代码来源:http://www.phreedom.org/solar/code/tinype/

我使用以下命令创建可执行文件:nasm -f bin -o tiny.exe tiny.asm,但当我尝试运行tiny.exe时,出现错误:应用程序无法正确启动(0xc0000018)。

另一方面,在Windows XP SP3机器上可以无缝运行。有什么想法可能是出了问题?


杀毒软件感到困惑了吗? - Neil
好的观察!我测试过了,虽然禁用了防病毒软件,但仍然出现了相同的错误。所以问题一定是其他方面引起的。 - Ponty
我还没有完全追踪到底是什么问题,但在ntdll!LdrpWx86ProtectImagePages中调用NtProtectVirtualMemory,基地址为0x00400160,NumberOfBytesToProtect = 0x1000,跨越了两个页面(这是一个问题,因为下一页未分配),如果我们将基地址更改为0x00400000,则只有一个页面,它可以加载和执行。因此,PE头中的某些值现在导致了不正确的舍入,或者他们在Win7中修复了XP中曾经存在的错误。 - jcopenha
谢谢您的这个分析。您用了什么工具? - Ponty
只需使用WinDbg和一些恰当的断点。将事件筛选器->创建进程设置为启用,以便在启动时中断,然后在LdrpInitialize中设置一些断点,并开始逐步执行代码,直到出现故障。 - jcopenha
2个回答

8
filealign equ 1
sectalign equ 1

Windows 7加载器不接受小于512的filealign和小于4096的sectionalign。 编辑: 根据counter examples的情况,对齐限制为4/4。

我怀疑这不是正确的。难道 4k 的演示仍然有效吗?其中许多都有 e_lfanew = 4,以重叠 MZ 和 PE 标头,这也会强制将部分对齐到4(因为该字段与e_lfanew重合)。在 corkami 的文档中,我也找不到 Win7 不接受低对齐的 PE-COFFs 的提及。 - user824425
1
4k程序通常将代码段设置为完全重叠标题,并仅使用一个部分,因此低对齐的需求得到缓解。我不知道是否有使用e_lfanew = 4的程序可以工作,但许多曾经工作的程序现在已经无法工作了。我刚刚查看了最近的4k,它使用e_lfanew = 12,sectionalignment = 65536和filealignment = 512。 - Jens Björnhager
经过一番搜索,我找到了这个:Kacce。虽然我不在使用Windows系统,但我希望你能够检查一下它是否有效。 - user824425
@JensBjörnhager:我刚刚找到了一个低对齐二进制的例子(https://code.google.com/p/corkami/source/browse/trunk/src/PE/tinyW7_3264.asm),应该可以在Windows 7上运行。再加上另一个答案是由Ange Albertini本人编写的这一事实,我愿意打赌这个答案是错误的,而他的答案是正确的。 - user824425
Kacce实际上似乎使用4/4作为对齐方式,其他示例也是如此。这与我的经验相悖,但这可能意味着W7接受不低于4/4的对齐方式。需要进一步研究。 - Jens Björnhager
显示剩余6条评论

4

相较于Vista或之后的版本,Windows XP对大小的要求较小:如果OptionalHeader被截断,Windows XP依然接受该文件,而后续的Windows版本则会拒绝该文件。

因此,您只需要添加填充即可在Vista或之后的版本下运行。

详情请参见我的Corkami上的PE页面,其中包含更多详细的说明、示例以及源代码和二进制文件。

(这与对齐无关)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接