x86 程序集,如何在不显示在控制台中的情况下获取用户输入?
x86 Assembly, How to get a user input wihout it being displayed in console?
我对汇编语言很陌生,正在尝试编写一个简单的程序。它获取不应在控制台中显示的用户输入(密码)。
对于正常输入,我是这样使用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
and SetConsoleMode
.
从控制台模式清除 ENABLE_ECHO_INPUT
位
ReadString
在内部使用 ReadConsoleA
,使用 Windows 为控制台子系统的可执行文件自动创建的控制台(即它使用 GetStdHandle
检索控制台输入和输出句柄)。
每当 ReadConsoleA
是否回显读取的字符取决于 控制台模式。
具体来说,标志 ENABLE_ECHO_INPUT
(值 0x4)清除后将阻止回显字符。
要获得当前的控制台模式,请使用 GetConsoleMode
,清除 ENABLE_ECHO_INPUT
位和模式与 ENABLE_ECHO_INPUT
的取反(即 [=69 中的 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 的 [=51] 一起 link 编辑=]link。使其适应您的工具。
DisableEcho
returns 您必须传递给 EnableEcho
的原始控制台模式(根据 Irvine 的调用约定,在 edx
中)。
喜欢:
call DisableEcho
;Here echo is disabled when calling ReadXXX
mov edx, eax ;Assuming eax has been preserved
call EnableEcho
根据您的需要调整代码,我没有使用全局变量,因为与 Irvine 相反,我更喜欢尽可能使用纯函数。
有些人发现缺少全局变量更难理解。
这是一个完整的程序,它将读取用户名、密码和 OTP 代码(只是为了表明 echo 已启用 before 和 after 密码提示)然后将打印所有这些。
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, 10, 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, strCRLF
call _WriteString@0
mov edx, myOTP
call _WriteString@0
;-- Exit --
push 0
call _ExitProcess@4
;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
我对汇编语言很陌生,正在尝试编写一个简单的程序。它获取不应在控制台中显示的用户输入(密码)。
对于正常输入,我是这样使用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
and SetConsoleMode
.
ENABLE_ECHO_INPUT
位
ReadString
在内部使用 ReadConsoleA
,使用 Windows 为控制台子系统的可执行文件自动创建的控制台(即它使用 GetStdHandle
检索控制台输入和输出句柄)。
每当 ReadConsoleA
是否回显读取的字符取决于 控制台模式。
具体来说,标志 ENABLE_ECHO_INPUT
(值 0x4)清除后将阻止回显字符。
要获得当前的控制台模式,请使用 GetConsoleMode
,清除 ENABLE_ECHO_INPUT
位和模式与 ENABLE_ECHO_INPUT
的取反(即 [=69 中的 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 的 [=51] 一起 link 编辑=]link。使其适应您的工具。
DisableEcho
returns 您必须传递给 EnableEcho
的原始控制台模式(根据 Irvine 的调用约定,在 edx
中)。
喜欢:
call DisableEcho
;Here echo is disabled when calling ReadXXX
mov edx, eax ;Assuming eax has been preserved
call EnableEcho
根据您的需要调整代码,我没有使用全局变量,因为与 Irvine 相反,我更喜欢尽可能使用纯函数。
有些人发现缺少全局变量更难理解。
这是一个完整的程序,它将读取用户名、密码和 OTP 代码(只是为了表明 echo 已启用 before 和 after 密码提示)然后将打印所有这些。
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, 10, 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, strCRLF
call _WriteString@0
mov edx, myOTP
call _WriteString@0
;-- Exit --
push 0
call _ExitProcess@4
;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