从自定义 PE 文件中的 dll 导入时,无法找到过程入口点 MessageBoxA
procedure entry point MessageBoxA could not be located when importing from dll in a custom PE file
我一直在努力掌握 PE 文件格式(只是为了自学一些新东西)并尝试创建一个简单的 .exe
它显示一个消息框然后退出,我已经在格式上使用 tinyPE as a base and then built on top of it using stuff from the microsoft docs。
问题是,当我尝试 运行 它时,我得到一个 The procedure entry point MessageBoxA could not be located in the dynamic link library D:\path\to\my\test.exe
弹出窗口(听起来 windows 试图从 exe 本身导入函数,但我不不明白为什么会那样做)
我尝试重新排列内容并尝试 headers 但没有任何帮助。我还使用 PE Explorer 检查了导入,但它似乎正确读取了导入并说它应该按预期从 kernel32.dll
导入
这是我的代码:
bits 32
align 1, db 0
mz_header:
dw "MZ" ; e_magic
dw 0 ; e_cblp
dw 0 ; e_cp
dw 0 ; e_crlc
dw 0 ; e_cparhdr
dw 0 ; e_minalloc
dw 0 ; e_maxalloc
dw 0 ; e_ss
dw 0 ; e_sp
dw 0 ; e_csum
dw 0 ; e_ip
dw 0 ; e_cs
dw 0 ; e_lsarlc
dw 0 ; e_ovno
times 4 dw 0 ; e_res
dw 0 ; e_oemid
dw 0 ; e_oeminfo
times 10 dw 0 ; e_res2
dd pe_header ; e_lfanew
pe_header:
dd "PE"
dw 0x014C ; Machine (Intel 386)
dw 2 ; NumberOfSections
dd 0x4545BE5D ; TimeDateStamp
dd 0 ; PointerToSymbolTable
dd 0 ; NumberOfSymbols
dw pe_optional_header_size ; SizeOfOptionalHeader
dw 0x103 ; Characteristics (no relocations, executable, 32 bit)
pe_optional_header:
dw 0x10B ; Magic (PE32)
db 8 ; MajorLinkerVersion
db 0 ; MinorLinkerVersion
dd text_size ; SizeOfCode
dd 0 ; SizeOfInitializedData
dd 0 ; SizeOfUninitializedData
dd _main ; AddressOfEntryPoint
dd text_begin ; BaseOfCode
dd filesize ; BaseOfData
dd 0x400000 ; ImageBase
dd 1 ; SectionAlignment
dd 1 ; FileAlignment
dw 4 ; MajorOperatingSystemVersion
dw 0 ; MinorOperatingSystemVersion
dw 0 ; MajorImageVersion
dw 0 ; MinorImageVersion
dw 4 ; MajorSubsystemVersion
dw 0 ; MinorSubsystemVersion
dd 0 ; Win32VersionValue
dd filesize ; SizeOfImage
dd header_total_size ; SizeOfHeaders
dd 0 ; CheckSum
dw 2 ; Subsystem (Win32 GUI)
dw 0x400 ; DllCharacteristics
dd 0x100000 ; SizeOfStackReserve
dd 0x1000 ; SizeOfStackCommit
dd 0x100000 ; SizeOfHeapReserve
dd 0x1000 ; SizeOfHeapCommit
dd 0 ; LoaderFlags
dd 4 ; NumberOfRvaAndSizes
rva:
dd 0
dd 0
dd import_dir_table
dd import_dir_table_size
times 12 dd 0, 0 ; This is necessary for a valid executable, probably as padding
pe_optional_header_size equ $ - pe_optional_header
; Section table
text_section:
db ".text", 0, 0, 0 ; Section name
dd text_size ; Size when loaded
dd header_total_size ; Adress when loaded
dd text_size ; Size
dd text_begin ; Points to section beginning
dd 0, 0 ; Pointer to relocations and line numbers
dw 0, 0 ; Count of relocations and line numbers
dd 0x60000020 ; Characteristics
rdata_section:
db ".rdata", 0, 0 ; Section name
dd rdata_size ; Size when loaded
dd rdata_begin ; Adress when loaded
dd rdata_size ; Size
dd rdata_begin ; Points to section beginning
dd 0, 0 ; Pointer to relocations and line numbers
dw 0, 0 ; Count of relocations and line numbers
dd 0x40000040 ; Characteristics
header_total_size equ $ - $$
; .text section
text_begin:
; Entry function
_main:
; try to call the imported function
push dword 0
push dword mbox_message + 0x400000
push dword 0
push dword 1
call [import_adress_table + 0x400000]
mov eax, 42
ret
text_size equ $ - text_begin
; .rdata section
rdata_begin equ $ - $$
import_dir_table:
dd import_lookup_table ; Import lookup table
dd 0, 0 ; Timestamp and forwarder chain, unused
dd kernel32 ; Name of dll
dd import_adress_table ; Import adress table
; Empty entry to signify end of import dir table
dd 0, 0, 0, 0, 0
import_dir_table_size equ $ - import_dir_table
; Like the lookup table, but entries are replaced
; with real adresses of imported functions
import_adress_table:
dd namehint_table
dd 0
; Stores DWORD pointers to Name/Hint tables
import_lookup_table:
dd namehint_table
dd 0
; Stores a hint (?) and a function name to import
namehint_table:
db 0, 0
db "MessageBoxA", 0 ; Function name
; String used to import the kernel32.dll
kernel32:
db "kernel32.dll", 0
; Other .rdata stuff
mbox_message:
db "Hello, World!", 0
rdata_size equ $ - rdata_begin
filesize equ $ - $$
我正在使用 NASM 2.15.5 进行组装:nasm -f bin -o test.exe test.asm
那么我哪里出错了?提前谢谢你
原问题是RbMm在评论中解决的,我错误地导入了kernel32.dll而不是user32.dll(我尝试调用ExitProcess时遗留下来的)
导入正确的库解决了错误,但要使其正常工作并显示消息框,我必须导入 MessageBoxA 调用的所有函数,要找到这些函数,只需创建一个调用 MessageBoxA 的测试程序,然后查看导入MSVC 生成:
#include <winuser.h>
int main()
{
return MessageBoxA(NULL, "Test", NULL, 0);
}
我一直在努力掌握 PE 文件格式(只是为了自学一些新东西)并尝试创建一个简单的 .exe
它显示一个消息框然后退出,我已经在格式上使用 tinyPE as a base and then built on top of it using stuff from the microsoft docs。
问题是,当我尝试 运行 它时,我得到一个 The procedure entry point MessageBoxA could not be located in the dynamic link library D:\path\to\my\test.exe
弹出窗口(听起来 windows 试图从 exe 本身导入函数,但我不不明白为什么会那样做)
我尝试重新排列内容并尝试 headers 但没有任何帮助。我还使用 PE Explorer 检查了导入,但它似乎正确读取了导入并说它应该按预期从 kernel32.dll
导入
这是我的代码:
bits 32
align 1, db 0
mz_header:
dw "MZ" ; e_magic
dw 0 ; e_cblp
dw 0 ; e_cp
dw 0 ; e_crlc
dw 0 ; e_cparhdr
dw 0 ; e_minalloc
dw 0 ; e_maxalloc
dw 0 ; e_ss
dw 0 ; e_sp
dw 0 ; e_csum
dw 0 ; e_ip
dw 0 ; e_cs
dw 0 ; e_lsarlc
dw 0 ; e_ovno
times 4 dw 0 ; e_res
dw 0 ; e_oemid
dw 0 ; e_oeminfo
times 10 dw 0 ; e_res2
dd pe_header ; e_lfanew
pe_header:
dd "PE"
dw 0x014C ; Machine (Intel 386)
dw 2 ; NumberOfSections
dd 0x4545BE5D ; TimeDateStamp
dd 0 ; PointerToSymbolTable
dd 0 ; NumberOfSymbols
dw pe_optional_header_size ; SizeOfOptionalHeader
dw 0x103 ; Characteristics (no relocations, executable, 32 bit)
pe_optional_header:
dw 0x10B ; Magic (PE32)
db 8 ; MajorLinkerVersion
db 0 ; MinorLinkerVersion
dd text_size ; SizeOfCode
dd 0 ; SizeOfInitializedData
dd 0 ; SizeOfUninitializedData
dd _main ; AddressOfEntryPoint
dd text_begin ; BaseOfCode
dd filesize ; BaseOfData
dd 0x400000 ; ImageBase
dd 1 ; SectionAlignment
dd 1 ; FileAlignment
dw 4 ; MajorOperatingSystemVersion
dw 0 ; MinorOperatingSystemVersion
dw 0 ; MajorImageVersion
dw 0 ; MinorImageVersion
dw 4 ; MajorSubsystemVersion
dw 0 ; MinorSubsystemVersion
dd 0 ; Win32VersionValue
dd filesize ; SizeOfImage
dd header_total_size ; SizeOfHeaders
dd 0 ; CheckSum
dw 2 ; Subsystem (Win32 GUI)
dw 0x400 ; DllCharacteristics
dd 0x100000 ; SizeOfStackReserve
dd 0x1000 ; SizeOfStackCommit
dd 0x100000 ; SizeOfHeapReserve
dd 0x1000 ; SizeOfHeapCommit
dd 0 ; LoaderFlags
dd 4 ; NumberOfRvaAndSizes
rva:
dd 0
dd 0
dd import_dir_table
dd import_dir_table_size
times 12 dd 0, 0 ; This is necessary for a valid executable, probably as padding
pe_optional_header_size equ $ - pe_optional_header
; Section table
text_section:
db ".text", 0, 0, 0 ; Section name
dd text_size ; Size when loaded
dd header_total_size ; Adress when loaded
dd text_size ; Size
dd text_begin ; Points to section beginning
dd 0, 0 ; Pointer to relocations and line numbers
dw 0, 0 ; Count of relocations and line numbers
dd 0x60000020 ; Characteristics
rdata_section:
db ".rdata", 0, 0 ; Section name
dd rdata_size ; Size when loaded
dd rdata_begin ; Adress when loaded
dd rdata_size ; Size
dd rdata_begin ; Points to section beginning
dd 0, 0 ; Pointer to relocations and line numbers
dw 0, 0 ; Count of relocations and line numbers
dd 0x40000040 ; Characteristics
header_total_size equ $ - $$
; .text section
text_begin:
; Entry function
_main:
; try to call the imported function
push dword 0
push dword mbox_message + 0x400000
push dword 0
push dword 1
call [import_adress_table + 0x400000]
mov eax, 42
ret
text_size equ $ - text_begin
; .rdata section
rdata_begin equ $ - $$
import_dir_table:
dd import_lookup_table ; Import lookup table
dd 0, 0 ; Timestamp and forwarder chain, unused
dd kernel32 ; Name of dll
dd import_adress_table ; Import adress table
; Empty entry to signify end of import dir table
dd 0, 0, 0, 0, 0
import_dir_table_size equ $ - import_dir_table
; Like the lookup table, but entries are replaced
; with real adresses of imported functions
import_adress_table:
dd namehint_table
dd 0
; Stores DWORD pointers to Name/Hint tables
import_lookup_table:
dd namehint_table
dd 0
; Stores a hint (?) and a function name to import
namehint_table:
db 0, 0
db "MessageBoxA", 0 ; Function name
; String used to import the kernel32.dll
kernel32:
db "kernel32.dll", 0
; Other .rdata stuff
mbox_message:
db "Hello, World!", 0
rdata_size equ $ - rdata_begin
filesize equ $ - $$
我正在使用 NASM 2.15.5 进行组装:nasm -f bin -o test.exe test.asm
那么我哪里出错了?提前谢谢你
原问题是RbMm在评论中解决的,我错误地导入了kernel32.dll而不是user32.dll(我尝试调用ExitProcess时遗留下来的)
导入正确的库解决了错误,但要使其正常工作并显示消息框,我必须导入 MessageBoxA 调用的所有函数,要找到这些函数,只需创建一个调用 MessageBoxA 的测试程序,然后查看导入MSVC 生成:
#include <winuser.h>
int main()
{
return MessageBoxA(NULL, "Test", NULL, 0);
}