我见过
How to write hello world in assembler under Windows?
和/或
Writing hello,world to console in Fasm with DOS
如何在fasm中写入控制台?
我试过/看到过类似于这个答案中的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
(to我在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”导入
最接近我可以找到没有win32 ax 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本身会这样做,并打印到控制台,不是吗?
5条答案
按热度按时间z5btuh9x1#
有没有什么方法可以做到这一点,而不需要任何外部DLL?
在Windows下:绝对不行!
Windows使用一些方法(可能是
syscall
)进入操作系统,然而,没有官方的入口点。这意味着在当前Windows版本中显示
"Hello world"
消息框的完全相同的程序在下一次Windows更新后会做一些完全不同的事情!因为微软假设每个Windows程序只通过使用与内核版本匹配的
.dll
文件来调用操作系统,所以他们可以这样做。我不知道Windows 10,但较旧的Windows版本(我不记得是XP,Vista还是7)甚至简单地假设如果不使用任何
.dll
文件,.exe
文件会立即返回:在这种情况下,程序甚至没有启动!vkc1a9a22#
事实并非如此,fasm也在使用kernel32 API。
FWIW kernel32被加载到Windows中每个进程的内存空间中,因此使用kernel32 API不会有任何损失或开销。
3lxsmp7m3#
您可能会喜欢€ASM中的这个Windows示例,它没有明确提到任何DLL,也不需要其他外部库。
只需将源代码保存为“bluej.asm”,用
euroasm bluej.asm
组装和链接,并以bluej.exe
运行。然而,如果不使用从默认Windows系统库“kernel32.dll”导入的API函数,您将无法逃脱。
l2osamch4#
对你来说什么是“依赖”?如果你想避免甚至操作系统的DLL的,那么你可能不走运。你不能仅仅依靠系统调用的数字。
**“无依赖关系”**也可以表示“仅使用现有的OS DLL”,如ntdll、kernel32等,但不使用可能不存在的第三方DLL,如C运行时的 * 特定 * 版本。
我想展示的一种方法是从PEB中检索函数指针。这是我写的代码,我个人使用,如果我想有没有导入节的shellcode。
PebGetProcAddress
的工作方式与GetProcAddress
类似,不同之处在于DLL名称和函数名称必须是散列,并且DLL必须使用LoadLibrary
加载。这可能不能完全回答你的问题,但我希望它能让你更接近你的目标,或者帮助其他读到它的人。
PebApi.asm
PebApi.inc
示例
如何生成模块名和函数名的哈希
relj7zay5#
这可能会有所帮助,它读取字符串并打印每个字符,直到NULL: