如何解决x86 程序集,如何在不显示在控制台中的情况下获取用户输入?
我对汇编语言真的很陌生,正在尝试编写一个简单的程序。它获取不应显示在控制台中的用户输入(密码)。
对于普通输入,我像这样使用 Irvine32 库。但是这个方法显示用户输入的输入,对于像密码这样的输入,这应该是隐藏的,我不知道该怎么做。
INCLUDE Irvine32.inc
.data
idPromptStr byte "Please enter ID : ",13,10,0
id DWORD ?
.code
main proc
mov edx,OFFSET idPromptStr
call WriteString
call ReadInt ;Reads the integer value from console and moves it to eax.
mov id,eax ;Input value is taken in eax.
main endp
end main
解决方法
TL;DR 您需要使用 GetConsoleMode
和 SetConsoleMode
从控制台模式清除 ENABLE_ECHO_INPUT
位。
ReadString
在内部使用 ReadConsoleA
,使用 Windows 自动为控制台子系统为可执行文件创建的控制台(即它使用 GetStdHandle
检索控制台输入和输出句柄)。>
ReadConsoleA
何时回显读取的字符取决于控制台模式。
具体来说,标志 ENABLE_ECHO_INPUT
(值 0x4)在清除后将阻止回显字符。
要获取当前控制台模式,请使用 GetConsoleMode
,清除 ENABLE_ECHO_INPUT
位和带有否定 ENABLE_ECHO_INPUT
的模式(即 NASM 中的 and rm32,~ENABLE_ECHO_INPUT
)。
然后使用这个新值设置控制台模式。
这是禁用和重新启用回声的功能:
;No args,return the console mode to pass to EnableEcho
DisableEcho:
push esi
push edi
;-- Get console input handle ---
push STD_INPUT_HANDLE
call _GetStdHandle@4
mov esi,eax
;-- Clear the ENABLE_ECHO_INPUT bit --
sub esp,04
push esp
push eax
call _GetConsoleMode@8
pop eax
mov edi,eax
and eax,~ENABLE_ECHO_INPUT
push eax
push esi
call _SetConsoleMode@8
mov eax,edi
pop edi
pop esi
ret
;edx = value returned from DisableEcho
EnableEcho:
;-- Get console input handle ---
push STD_INPUT_HANDLE
call _GetStdHandle@4
;-- Set mode --
push edx
push eax
call _SetConsoleMode@8
ret
注意此代码是为 NASM 编写的,并与 Microsoft 的链接相关联。使其适应您的工具。
DisableEcho
返回您必须传递给 EnableEcho
的原始控制台模式(根据 Irvine 的调用约定,在 edx
中)。
喜欢:
call DisableEcho
;Here echo is disabled when calling ReadXXX
mov edx,eax ;Assuming eax has been preserved
call EnableEcho
根据您的需要调整代码,我没有使用全局变量,因为与 Irvine 不同,我尽可能喜欢纯函数。
有些人发现缺少全局变量更难理解。
这是一个完整的程序,它将读取用户名、密码和 OTP 代码(只是为了显示在密码提示之前和之后启用了回显)和然后将打印所有这些。
BITS 32
GLOBAL _start
%define STD_INPUT_HANDLE -10
%define ENABLE_ECHO_INPUT 4
%define STRLEN 82
EXTERN _ReadString@0
EXTERN _ExitProcess@4
EXTERN _SetConsoleMode@8
EXTERN _GetConsoleMode@8
EXTERN _GetStdHandle@4
EXTERN _WriteString@0
SECTION .bss
myUsername resb STRLEN
myPassword resb STRLEN
myOTP resb STRLEN
SECTION .data
strUsername db "Username: ",0
strPassword db "Password:",0
strOTP db 13,10,"OTP code: ",0
strCRLF db 13,0
SECTION .text
_start:
;-- Read the username --
mov edx,strUsername
call _WriteString@0
mov edx,myUsername
mov ecx,STRLEN
call _ReadString@0
;-- Disable echo --
call DisableEcho
mov esi,eax
;-- Read the password --
mov edx,strPassword
call _WriteString@0
mov edx,myPassword
mov ecx,STRLEN
call _ReadString@0
;-- Restore the echo ---
mov edx,esi
call EnableEcho
;-- Read the otp --
mov edx,strOTP
call _WriteString@0
mov edx,myOTP
mov ecx,STRLEN
call _ReadString@0
;-- Show --
mov edx,myUsername
call _WriteString@0
mov edx,strCRLF
call _WriteString@0
mov edx,myPassword
call _WriteString@0
mov edx,myOTP
call _WriteString@0
;-- Exit --
push 0
call _ExitProcess@4
;No args,edi
pop edi
pop esi
ret
;edx = value returned from DisableEcho
EnableEcho:
;-- Get console input handle ---
push STD_INPUT_HANDLE
call _GetStdHandle@4
;-- Set mode --
push edx
push eax
call _SetConsoleMode@8
ret
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。