数据部分超过1页时,可执行文件变为无效

时间:2013-09-02 16:34:50

标签: assembly nasm portable-executable corrupt

我一直在尝试使用NASM创建一个PE文件(前一段时间我也在这里询问了与之相关的内容:Create and use sections for PE file in assembly (NASM))。最后,我设法构建了一个非常小的运行可执行文件,在控制台上显示一条消息。那时,.data部分的字节数少于512字节,但是现在,当我添加一些超过512字节的更大变量时,我在尝试执行时遇到“这不是一个有效的Win32应用程序”错误。

首先,我的代码:

BYTES_LAST_PAGE   equ EXE_HEADER - DOS_HEADER
SECTION_ALIGNMENT equ 4096
FILE_ALIGNMENT    equ 512
PREFERRED_ADDRESS equ 4194304
SECTIONS_COUNT    equ 4
HEADERS_SIZE      equ HEADERS_END - DOS_HEADER
CODE_SIZE         equ CODE_END - CODE
DATA_SIZE         equ DATA_END - DATA
IDATA_SIZE        equ IDATA_END - IDATA
ITABLE_SIZE       equ ITABLE_END - ITABLE
BSS_SIZE          equ 531

; Round to the next multiple of the second argument
%define Round(N, M) (N + M - 1)/M * M
; Calculates the RVA to the sections beginning
%define RVA(BaseAddress) (BaseAddress - CODE)/FILE_ALIGNMENT * SECTION_ALIGNMENT + \
                                SECTION_ALIGNMENT
; Calculates the RVA to the specified address
%define RVA(Address, BaseAddress) RVA(BaseAddress) + (Address- BaseAddress)
; The size of the image rounded up to the next multiple of SECTION_ALIGNMENT
%define ImageSize RVA(IMAGE_END) + Round(BSS_SIZE, SECTION_ALIGNMENT)

; Fill with argument 1 argument 2 times
%macro Fill 2
    times %1 db %2
%endmacro

DOS_HEADER:
    db          "MZ"
    dw          BYTES_LAST_PAGE
    dw          1
    dw          4
    dw          4
    dw          0
    dw          65535
    dw          0
    dw          0x00B8
    dw          0
    dw          0
    dw          0
    dw          0x0040
    dw          0
    dq          0
    dw          0
    dw          0
    Fill        20, 0
    dd          EXE_HEADER

DOS_PROGRAM:
    push        cs
    pop         ds
    mov         dx, DOSMessage - DOS_PROGRAM
    mov         ah, 9
    int         21h
    mov         ax, 0x4C01
    int         21h

    DOSMessage :
    db "This program wasn't created for your system!", 0Dh, 0Dh, 0Ah, '$'

 Fill 64-$+DOS_PROGRAM, 0

EXE_HEADER:
    db          "PE", 0, 0
    dw          0x014C
    dw          SECTIONS_COUNT
    dd          1371668450
    dd          0
    dd          0
    dw          SECTIONS_HEADERS_TABLE - OPTIONAL_HEADER
    dw          0x0002|0x0004|0x0008|0x0100|0x0200

OPTIONAL_HEADER:
    dw          0x010B
    db          0
    db          0
    dd          Round(CODE_SIZE, SECTION_ALIGNMENT)
    dd          Round(DATA_SIZE, SECTION_ALIGNMENT)
    dd          Round(BSS_SIZE, SECTION_ALIGNMENT)
    dd          RVA(CODE)
    dd          RVA(CODE)
    dd          RVA(DATA)
    dd          PREFERRED_ADDRESS
    dd          SECTION_ALIGNMENT
    dd          FILE_ALIGNMENT
    dw          4
    dw          0
    dw          0
    dw          0
    dw          3
    dw          10
    dd          0
    dd          ImageSize
    dd          Round(HEADERS_SIZE, FILE_ALIGNMENT)
    dd          0
    dw          3 ; subsys interface
    dw          0 ; no dll
    dd          4096 ; reserved stack
    dd          4096
    dd          65536
    dd          0
    dd          0 
    dd          16
    dd          0
    dd          0
    dd          RVA(ITABLE, IDATA)
    dd          ITABLE_SIZE
    Fill        112, 0

SECTIONS_HEADERS_TABLE:
    CODE_SECTION_HEADER:
        db          ".code", 0, 0, 0
        dd          Round(CODE_SIZE, SECTION_ALIGNMENT)
        dd          RVA(CODE)
        dd          Round(CODE_SIZE, FILE_ALIGNMENT)
        dd          CODE
        dd          0
        dd          0
        dw          0
        dw          0
        dd          0x00000020|0x20000000|0x40000000|0x80000000

    IDATA_SECTION_HEADER:
        db          ".idata", 0, 0
        dd          Round(IDATA_SIZE, SECTION_ALIGNMENT)
        dd          RVA(IDATA)
        dd          Round(IDATA_SIZE, FILE_ALIGNMENT)
        dd          IDATA
        dd          0
        dd          0
        dw          0
        dw          0
        dd          0x00000040|0x40000000|0x80000000 

    DATA_SECTION_HEADER:
        db          ".data", 0, 0, 0
        dd          Round(DATA_SIZE, SECTION_ALIGNMENT)
        dd          RVA(DATA)
        dd          Round(DATA_SIZE, FILE_ALIGNMENT)
        dd          DATA
        dd          0
        dd          0
        dw          0
        dw          0
        dd          0x00000040|0x40000000|0x80000000

    BSS_SECTION_HEADER:
        db          ".bss", 0, 0, 0, 0
        dd          Round(BSS_SIZE, SECTION_ALIGNMENT)
        dd          RVA(BSS)
        dd          0
        dd          0
        dd          0
        dd          0
        dw          0
        dw          0
        dd          0x00000080|0x40000000|0x80000000    

HEADERS_END:

align FILE_ALIGNMENT

use32

; BSS variables relative address
StdHandle     equ RVA(BSS) + 0
WrittenChars  equ RVA(BSS) + 4
BigVar        equ RVA(BSS) + 8

CODE:
    call GetStdHandle

    push dword PREFERRED_ADDRESS + RVA(Message, DATA)
    push dword 6
    call ShowText

    ApplicationEnd:
        mov eax,    0
        ret

    GetStdHandle:
        push -11
        call dword [PREFERRED_ADDRESS + RVA(F_GetStdHandle, IDATA)]
        mov dword [PREFERRED_ADDRESS + StdHandle], eax
        ret

    ShowText:
        push ebp
        mov ebp, esp
        push 0
        push dword PREFERRED_ADDRESS + WrittenChars
        push dword [ebp + 8]
        push dword [ebp + 12]
        push dword [PREFERRED_ADDRESS + StdHandle]
        call dword [PREFERRED_ADDRESS + RVA(F_WriteConsoleW, IDATA)]
        pop ebp
        ret 8

    align FILE_ALIGNMENT
CODE_END:

IDATA:
    KERNEL32 db 'kernel32.dll', 0
    ITABLE:  
        .originalfthk           dd          0
        .datehour               dd          0  
        .forwarder              dd          0
        .module_name            dd          RVA(KERNEL32, IDATA)
        .start                  dd          RVA(IFUNCTIONS, IDATA)

    Fill 20, 0
    ITABLE_END:

    I_WriteConsoleW:    
        dw                  0  
        db                  'WriteConsoleW', 0
        align               2        
    I_GetStdHandle:
        dw                  0  
        db                  'GetStdHandle', 0
        align               2
    I_ExitProcess:
        dw                  0
        db                  'ExitProcess', 0

    IFUNCTIONS:
        F_WriteConsoleW: dd RVA(I_WriteConsoleW, IDATA)
        F_GetStdHandle:  dd RVA(I_GetStdHandle, IDATA)
        F_ExitProcess    dd RVA(I_ExitProcess, IDATA)
    dd          0

    align FILE_ALIGNMENT
IDATA_END:

DATA:
    Message: dw __utf16__("Hello"), 0Ah
    SomeBigVar:
        Fill 512, 11h   ; Make it exceed 512 bytes
   align FILE_ALIGNMENT
DATA_END:

BSS:

IMAGE_END:

如果您将SomeBigVar下方的行更改为Fill 10, 11h,您会看到该消息。因此,由于某些未知原因,只要数据部分变得大到2页,可执行文件就会变为无效。我还用PEInfo分析了这个文件,结果如下:

工作执行:Here
腐败的exe:Here

也许你可以从差异中发现问题。我无法理解为什么。

1 个答案:

答案 0 :(得分:0)

显然BSS段的RVA(虚拟地址)是错误的(0x5000,必须是0x4000)!