问题
I want to build Custom Portable executable using NASM. After getting executable using command nasm -f bin program.asm -o program.exe
it crashes and gives error similar to this
Below you can see the code.
bits 64
%define BASE 400000h
ALIGNMENT equ 512
%define SECTALIGN 8192
STD_OUTPUT_HANDLE equ -11
NULL equ 0
%define ROUND(v, a) (((v + a - 1) / a) * a)
%define ALIGNED(v) (ROUND(v, ALIGNMENT))
%define RVA(obj) (obj - BASE)
section header progbits start=0 vstart=BASE
mz_hdr:
dw "MZ" ; DOS magic
times 0x3a db 0 ; [UNUSED] DOS header
dd RVA(pe_hdr) ; address of PE header
pe_hdr:
dw "PE",0 ; PE magic + 2 padding bytes
dw 0x8664 ; i386 architecture
dw 2 ; two sections
dd 0 ; [UNUSED] timestamp
dd 0 ; [UNUSED] symbol table pointer
dd 0 ; [UNUSED] symbol count
dw OPT_HDR_SIZE ; optional header size
dw 0x0002 ; characteristics: 32-bit, executable
opt_hdr:
dw 0x020b ; optional header magic
db 13,37 ; [UNUSED] linker version
dd ALIGNED(S_TEXT_SIZE) ; [UNUSED] code size
dd ALIGNED(S_IDATA_SIZE) ; [UNUSED] size of initialized data
dd 0 ; [UNUSED] size of uninitialized data
dd RVA(section..text.vstart) ; entry point address
dd RVA(section..text.vstart) ; [UNUSED] base of code
dd RVA(section..idata.vstart) ; [UNUSED] base of data
dd BASE ; image base
dd SECTALIGN ; section alignment
dd ALIGNMENT ; file alignment
dw 4,0 ; [UNUSED] OS version
dw 0,0 ; [UNUSED] image version
dw 4,0 ; subsystem version
dd 0 ; [UNUSED] Win32 version
dd RVA(the_end) ; size of image
dd ALIGNED(ALL_HDR_SIZE) ; size of headers
dd 0 ; [UNUSED] checksum
dw 3 ; subsystem = console
dw 0 ; [UNUSED] DLL characteristics
dd 0x00100000 ; [UNUSED] maximum stack size
dd 0x00001000 ; initial stack size
dd 0x00100000 ; maximum heap size
dd 0x00001000 ; [UNUSED] initial heap size
dd 0 ; [UNUSED] loader flags
dd 16 ; number of data directory entries
dd 0,0 ; no export table
dd RVA(import_table) ; import table address
dd IMPORT_TABLE_SIZE ; import table size
times 14 dd 0,0 ; no other entries in the data directories
OPT_HDR_SIZE equ $ - opt_hdr
sect_hdr_text:
db ".text",0,0,0 ; section name
dd ALIGNED(S_TEXT_SIZE) ; virtual size
dd RVA(section..text.vstart) ; virtual address
dd ALIGNED(S_TEXT_SIZE) ; file size
dd section..text.start ; file position
dd 0,0 ; no relocations or debug info
dw 0,0 ; no relocations or debug info
dd 0x60000020 ; flags: code, readable, executable
sect_hdr_idata:
db ".idata",0,0 ; section name
dd ALIGNED(S_IDATA_SIZE) ; virtual size
dd RVA(section..idata.vstart) ; virtual address
dd ALIGNED(S_IDATA_SIZE) ; file size
dd section..idata.start ; file position
dd 0,0 ; no relocations or debug info
dw 0,0 ; no relocations or debug info
dd 0xC0000040 ; flags: data, readable, writeable
ALL_HDR_SIZE equ $ - $$
;;;;;;;;;;;;;;;;;;;; .text ;;;;;;;;;;;;;;;;;
section .text progbits follows=header align=ALIGNMENT vstart=BASE+SECTALIGN*1
s_text:
; set up stack frame for *lpBytesWritten
; push ebp
; sub esp, 4
; push STD_OUTPUT_HANDLE
; call [GetStdHandle]
; push NULL
; push buffer
; push message_size
; push message
; push eax
; call [WriteConsoleA]
push rbp
mov rbp, rsp
sub rsp, 40
push 0
call [ExitProcess]
mov rsp, rbp
pop rbp
S_TEXT_SIZE equ $ - s_text
;;;;;;;;;;;;;;;;;;;; .idata ;;;;;;;;;;;;;;;;;
section .idata progbits follows=.text align=ALIGNMENT vstart=BASE+SECTALIGN*2
s_idata:
; message db "Hello World!",0
; message_size equ $ - message
; buffer resd 2
; buffer2 resb 32
import_table:
; import of kernel32.dll
dd 0 ; [UNUSED] read-only IAT
dd 0 ; [UNUSED] timestamp
dd 0 ; [UNUSED] forwarder chain
dd RVA(N_kernel32) ; library name
dd RVA(IAT_kernel32) ; IAT pointer
; import of user32.dll
dd 0 ; [UNUSED] read-only IAT
dd 0 ; [UNUSED] timestamp
dd 0 ; [UNUSED] forwarder chain
dd RVA(N_user32) ; library name
dd RVA(IAT_user32) ; IAT pointer
; terminator (empty item)
times 5 dd 0
IMPORT_TABLE_SIZE: equ $ - import_table
IAT_kernel32:
ExitProcess: dd RVA(H_ExitProcess)
GetStdHandle: dd RVA(H_GetStdHandle)
WriteConsoleA: dd RVA(H_WriteConsoleA)
dd 0
IAT_user32:
MessageBoxA: dd RVA(H_MessageBoxA)
dd 0
align 4, db 0
N_kernel32: db "kernel32.dll",0
align 4, db 0
N_user32: db "user32.dll",0
align 2, db 0
H_MessageBoxA: db 0,0,"MessageBoxA",0
align 2, db 0
H_GetStdHandle: db 0,0,"GetStdHandle",0
align 2, db 0
H_WriteConsoleA: db 0,0,"WriteConsoleA",0
align 2, db 0
H_ExitProcess: db 0,0,"ExitProcess",0
S_IDATA_SIZE equ $ - s_idata
align ALIGNMENT, db 0
the_end:
The result is strange because If I use dd
for image base variable in header I get this result which is shifted left by 8 bit and add some irrelevant bits (1). all other variables seems okay.
But if I use dq
for image base, it's value stayed same (2) but other relevant values shifted right. (3)
This is ported from 32 bit assembly example. Do I need to add or change some header values?
回答1:
Since you're using the PE32+ format (identified by the 0x020b magic number), you should not have a BaseOfData
field in your optional header.
Also, the ImageBase
should be a quadword, and so should the Stack/Heap
fields.
See the documentation.
来源:https://stackoverflow.com/questions/64164559/image-base-comes-out-wrong-in-manually-generated-pe-headers-for-a-64-bit-executa