为 64 位可执行文件手动生成的 PE 标头中的图像库出错 [英] Image base comes out wrong in manually-generated PE headers for a 64-bit executable

查看:34
本文介绍了为 64 位可执行文件手动生成的 PE 标头中的图像库出错的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用 NASM 构建自定义便携式可执行文件.使用命令 nasm -f bin program.asm -o program.exe 获得可执行文件后,它会崩溃并给出类似于此的错误

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:

结果很奇怪,因为如果我在标题中使用 dd 作为图像基本变量,我会得到这个结果,它左移 8 位并添加一些不相关的位 (1).所有其他变量似乎没问题.

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.

但是如果我使用 dq 作为图像库,它的值保持不变 (2) 但其他相关值右移.(3)

But if I use dq for image base, it's value stayed same (2) but other relevant values shifted right. (3)

这是从 32 位汇编示例移植而来的.我需要添加或更改某些标题值吗?

This is ported from 32 bit assembly example. Do I need to add or change some header values?

推荐答案

由于您使用的是 PE32+ 格式(由 0x020b 幻数标识),您应该不要拥有 BaseOfData 字段在您的可选标题中.

Since you're using the PE32+ format (identified by the 0x020b magic number), you should not have a BaseOfData field in your optional header.

此外,ImageBase 应该是一个四字,Stack/Heap 字段也应该是一个四字.请参阅文档.

Also, the ImageBase should be a quadword, and so should the Stack/Heap fields. See the documentation.

这篇关于为 64 位可执行文件手动生成的 PE 标头中的图像库出错的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆