【发布时间】:2020-12-02 22:20:09
【问题描述】:
我见过
How to write hello world in assembler under Windows?
和
Writing hello,world to console in Fasm with DOS
How to write to the console in fasm?
我已经从this answer 尝试/看到了类似这个 MASM 示例的代码
;---ASM Hello World Win64 MessageBox
extrn MessageBoxA: PROC
extrn ExitProcess: PROC
.data
title db 'Win64', 0
msg db 'Hello World!', 0
.code
main proc
sub rsp, 28h
mov rcx, 0 ; hWnd = HWND_DESKTOP
lea rdx, msg ; LPCSTR lpText
lea r8, title ; LPCSTR lpCaption
mov r9d, 0 ; uType = MB_OK
call MessageBoxA
add rsp, 28h
mov ecx, eax ; uExitCode = MessageBox(...)
call ExitProcess
main endp
End
(我在 Windows 64 位 extrn MessageBoxA:PROC 上收到错误“非法指令”,因为 FASM 不理解该 MASM 指令。)
还有这个 FASM 示例 from this question
; Example of 64-bit PE program
format PE64 GUI
entry start
section '.text' code readable executable
start:
sub rsp,8*5 ; reserve stack for API use and make stack dqword aligned
mov r9d,0
lea r8,[_caption]
lea rdx,[_message]
mov rcx,0
call [MessageBoxA]
mov ecx,eax
call [ExitProcess]
section '.data' data readable writeable
_caption db 'Win64 assembly program',0
_message db 'Hello World!',0
section '.idata' import data readable writeable
dd 0,0,0,RVA kernel_name,RVA kernel_table
dd 0,0,0,RVA user_name,RVA user_table
dd 0,0,0,0,0
kernel_table:
ExitProcess dq RVA _ExitProcess
dq 0
user_table:
MessageBoxA dq RVA _MessageBoxA
dq 0
kernel_name db 'KERNEL32.DLL',0
user_name db 'USER32.DLL',0
_ExitProcess dw 0
db 'ExitProcess',0
_MessageBoxA dw 0
db 'MessageBoxA',0
但它会显示一个消息框,并且还具有外部依赖项“kernel32.dll”和“user32.dll”
也试过这个例子from the FASM forum
format pe console
include 'win32ax.inc'
entry main
section '.data!!!' data readable writeable
strHello db 'Hello World !',13,10,0
strPause db 'pause',0
section '.txt' code executable readable
main:
; you can use crt functions or windows API.
cinvoke printf,strHello
cinvoke system,strPause; or import getc()
; or
; invoke printf,srtHello
; add esp, 4
; or use WriteFile and GetStdHandle APIs
push 0
call [ExitProcess]
section '.blah' import data readable
library kernel32,'kernel32.dll',\
msvcrt,'msvcrt.dll' ;; C-Run time from MS. This is always on every windows machine
import kernel32,\
ExitProcess,'ExitProcess'
import msvcrt,\
printf,'printf',\
system,'system'
但这取决于win32ax.inc 和其他导入
还有
format PE console
include 'win32ax.inc'
.code
start:
invoke WriteConsole,<invoke GetStdHandle,STD_OUTPUT_HANDLE>,"Hello World !",13,0
invoke Sleep,-1
.end start
但需要“win32ax.inc”导入
没有 win32ax 我能找到的最接近的from the FASM forum:
format pe64 console
entry start
STD_OUTPUT_HANDLE = -11
section '.text' code readable executable
start:
sub rsp,8*7 ; reserve stack for API use and make stack dqword aligned
mov rcx,STD_OUTPUT_HANDLE
call [GetStdHandle]
mov rcx,rax
lea rdx,[message]
mov r8d,message_length
lea r9,[rsp+4*8]
mov qword[rsp+4*8],0
call [WriteFile]
mov ecx,eax
call [ExitProcess]
section '.data' data readable writeable
message db 'Hello World!',0
message_length = $ - message
section '.idata' import data readable writeable
dd 0,0,0,RVA kernel_name,RVA kernel_table
dd 0,0,0,0,0
kernel_table:
ExitProcess dq RVA _ExitProcess
GetStdHandle dq RVA _GetStdHandle
WriteFile dq RVA _WriteFile
dq 0
kernel_name db 'KERNEL32.DLL',0
user_name db 'USER32.DLL',0
_ExitProcess db 0,0,'ExitProcess',0
_GetStdHandle db 0,0,'GetStdHandle',0
_WriteFile db 0,0,'WriteFile',0
但仍需要 kernel32.dll 和 user32.dll
没有任何外部 DLL 的任何方法都可以做到这一点?我只知道程序 fasm 本身会执行此操作,并打印到控制台,不是吗?
【问题讨论】:
-
您可以通过
syscall直接使用未记录/不受支持的系统调用,系统调用号和参数取决于 Windows 内核版本。 j00ru.vexillium.org/syscalls/nt/64 / Windows system calls。或者,也许有一些受支持的方式仍然可以通过 DLL 使用稳定的 ABI,但您不会算作“外部”? -
@Peter 系统调用的想法听起来不错,但它完全没有记录吗?我该怎么做才能找到与
dd 0,0,0,RVA kernel_name,RVA kernel_table和user_name部分相同的效果? -
您如何知道 FASM 本身“会”?您是否使用了一些工具来检查
fasm.exe以查看它链接的 DLL,或者您是否检查了它的源代码和/或构建脚本?是的,DLL 内部用于与内核通信的系统调用 ABI 完全没有被 Microsoft 记录。如果您不相信或不理解我刚才所说的话,请阅读我给您的链接。 -
我知道它是开源的,但我自己没有阅读源代码。你?如果是这样,您究竟在寻找什么来验证它没有使用任何 DLL 中的任何函数?显然,它确实按照 dxiv 的回答使用 DLL 函数,就像任何理智的 Windows 程序一样。目前尚不清楚您是否只是在寻找复制
win32ax.inc中任何内容的 FASM 语法(如果您愿意,您可以复制/粘贴)以便您可以尽可能手动使用 winapi dll 函数,或者如果您真的想要尝试构建一个真正不引用任何 DLL 的“静态”可执行文件(使用未记录的系统调用)。 -
你在这里的意图是什么?如果你想达到更低的级别,那就是:Windows 上的 DLL 和 Linux/BSD 上的系统调用。如果您不想导入 PE(无论出于何种原因),那么您可以从 PEB 获得对 NTDLL.DLL 的引用。始终加载此 DLL(但对于 picoprocesses)。请注意,即使在 Linux/BSD 下,UI 也是由用户空间库完成的,就像在 Windows 中一样。当你得到一个操作系统时,汇编和 C 之间并没有太大区别:它们都只是调用函数。
标签: windows assembly x86-64 system-calls fasm