我一直在尝试使用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分析了这个文件,结果如下:
也许你可以从差异中发现问题。我无法理解为什么。
答案 0 :(得分:0)
显然BSS段的RVA(虚拟地址)是错误的(0x5000,必须是0x4000)!