错误的库在手动生成的 PE 64 位可执行文件中加载了错误的函数
Wrong library loads wrong function in manually-generated PE 64-bit executable
我有 64 位手动生成的 PE 可执行文件。我需要加载两个库 kernel32.dll
和 user.dll
。它给出了第一个错误。
如果我只有一个库(这就是 kernel32.dll
),我会得到第二个错误。有没有办法得到另一个错误。
有没有办法让所有的库都正确?请记住,代码是从 32 位可执行文件移植而来的。你可以看下面的代码。
bits 64
BASE equ 400000h
ALIGNMENT equ 512
%define SECTALIGN 4096
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 __POSIX_TIME__ ; [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
dq 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
dq 0x0010000000000000 ; [UNUSED] maximum stack size
dq 0x0000100000000000 ; initial stack size
dq 0x0010000000000000 ; maximum heap size
dq 0x0000100000000000 ; [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 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
ret
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 4
; buffer2 resb 64
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:
@user2426998 - 你显然遇到了比加载错误的 .dll 更大的问题。
建议:
请更新您的 post 并说明您要做什么。
问:这个项目的“目标”是什么?
不是“使用自定义 PE32+ 可执行文件构建程序”。 为什么 您确实需要“自定义 PE32+ 可执行文件”(相对于例如,只需为 64 位重新编译旧的 .c/.cpp 程序)? code/binary 你从哪里开始?您的 PE32+ 映像与任何“普通”64 位 Windows .exe 有何“不同”之处? 64 位 Windows .exe 实际上是您的目标吗?还是您需要完成“其他事情”?
我假设你有 Microsoft Visual Studio。
尽可能多地使用它:如果你可以在 MSVS 中做某事,那么你可能应该在 MSVS 中做。
它会让你的生活变得更加轻松:)
肯定编写一些.c“测试模块”的代码,然后使用“/Fa”在 MSVS 中构建它们。
这将为您提供一个“模板”,用于手动编写您自己的汇编代码。
特别是,它将向您展示如何正确传递参数:)
绝对使用像dumpbin or 3rd party tools like PE Internals这样的MSVS工具。将“您的代码”与“其他有效示例”进行比较和对比。
'希望对您有所帮助...
答案:
功能分配部分需要调整。应该使用四字而不是双字。
IAT_kernel32:
ExitProcess: dq RVA(H_ExitProcess)
GetStdHandle: dq RVA(H_GetStdHandle)
WriteConsoleA: dq RVA(H_WriteConsoleA)
dq 0
IAT_user32:
MessageBoxA: dq RVA(H_MessageBoxA)
dq 0
应根据此示例更正对齐方式
align 16, db 0
N_kernel32: db "kernel32.dll",0
align 16, db 0
N_user32: db "user32.dll",0
align 8, db 0
H_ExitProcess: db 0,0,"ExitProcess",0
align 8, db 0
H_GetStdHandle: db 0,0,"GetStdHandle",0
align 8, db 0
H_WriteConsoleA: db 0,0,"WriteConsoleA",0
align 8, db 0
H_MessageBoxA: db 0,0,"MessageBoxA",0
我有 64 位手动生成的 PE 可执行文件。我需要加载两个库 kernel32.dll
和 user.dll
。它给出了第一个错误。
如果我只有一个库(这就是 kernel32.dll
),我会得到第二个错误。有没有办法得到另一个错误。
有没有办法让所有的库都正确?请记住,代码是从 32 位可执行文件移植而来的。你可以看下面的代码。
bits 64
BASE equ 400000h
ALIGNMENT equ 512
%define SECTALIGN 4096
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 __POSIX_TIME__ ; [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
dq 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
dq 0x0010000000000000 ; [UNUSED] maximum stack size
dq 0x0000100000000000 ; initial stack size
dq 0x0010000000000000 ; maximum heap size
dq 0x0000100000000000 ; [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 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
ret
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 4
; buffer2 resb 64
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:
@user2426998 - 你显然遇到了比加载错误的 .dll 更大的问题。
建议:
请更新您的 post 并说明您要做什么。
问:这个项目的“目标”是什么?
不是“使用自定义 PE32+ 可执行文件构建程序”。 为什么 您确实需要“自定义 PE32+ 可执行文件”(相对于例如,只需为 64 位重新编译旧的 .c/.cpp 程序)? code/binary 你从哪里开始?您的 PE32+ 映像与任何“普通”64 位 Windows .exe 有何“不同”之处? 64 位 Windows .exe 实际上是您的目标吗?还是您需要完成“其他事情”?我假设你有 Microsoft Visual Studio。
尽可能多地使用它:如果你可以在 MSVS 中做某事,那么你可能应该在 MSVS 中做。 它会让你的生活变得更加轻松:)肯定编写一些.c“测试模块”的代码,然后使用“/Fa”在 MSVS 中构建它们。 这将为您提供一个“模板”,用于手动编写您自己的汇编代码。 特别是,它将向您展示如何正确传递参数:)
绝对使用像dumpbin or 3rd party tools like PE Internals这样的MSVS工具。将“您的代码”与“其他有效示例”进行比较和对比。
'希望对您有所帮助...
答案: 功能分配部分需要调整。应该使用四字而不是双字。
IAT_kernel32:
ExitProcess: dq RVA(H_ExitProcess)
GetStdHandle: dq RVA(H_GetStdHandle)
WriteConsoleA: dq RVA(H_WriteConsoleA)
dq 0
IAT_user32:
MessageBoxA: dq RVA(H_MessageBoxA)
dq 0
应根据此示例更正对齐方式
align 16, db 0
N_kernel32: db "kernel32.dll",0
align 16, db 0
N_user32: db "user32.dll",0
align 8, db 0
H_ExitProcess: db 0,0,"ExitProcess",0
align 8, db 0
H_GetStdHandle: db 0,0,"GetStdHandle",0
align 8, db 0
H_WriteConsoleA: db 0,0,"WriteConsoleA",0
align 8, db 0
H_MessageBoxA: db 0,0,"MessageBoxA",0