Всем привет! Столкнулся в ассемблере с такой проблемой.. В виндовой консоли нужно обработать каждое нажатие клавиш. Возможно-ли такое средствами API ? Задача: зашифровать на-лету каждый символ юзерского ввода (пароль). Испробовал несколько стандартных функций типа "WriteConsole/Scanf/_lread", но они/все пишут в буфер и ждут маркера конца "Enter". Причём если передать им в качестве параметра счётчик макс.символов например(8), то при вводе бОльшего кол-ва символов - хвост символов остаётся в буфере клавиатуры, и при повторном вызове этой-же функции, записывается в указанный буфер функции. Например в досе можно выставить СХ=8 и сервисом DOS AH=1 про'LOOP'ить ввод, и благополучно выйти из цикла. Как такое организовать под виндой? Считать один символ с клавы в регистр, и закончить ввод без "Enter". Был-бы признателен..
вот сорец кейлоггера, посмотри как в нем реализовано. ( в винде сразу много задач выполняется, поэтому работа с клавиатурой реализуется иначе. into the rabbit hole -> http://opensecuritytraining.info/Keylogging_files/The Adventures of a Keystroke.pdf )
_edge спасибо! Но чёт не получается заточить код под себя Делаю так. Подправь, если не в лом.. Код (ASM): format PE console include 'win32ax.inc' .code start: mov esi,7 @go: invoke Sleep, cmp esi,255 je start inc esi invoke GetAsyncKeyState,esi or eax,eax jnz @jop jmp @go @jop: invoke MapVirtualKey,esi,2 ; mov bl,al ; sub bl,30h ; cmp bl,9 ; ja @go xor al,[key] add [pass],al dec byte[key] dec byte[len] jnz @go ; cinvoke printf, form, pass ; cinvoke scanf invoke ExitProcess,0 ;********************************************** .data key db 0DAh pass db 9 dup(0) len db 8 form db '%c',0 ;********************************************** section '.idata' import data readable writeable library kernel, 'KERNEL32.DLL',\ user, 'USER32.DLL',\ msvcrt, 'msvcrt.dll' import kernel,\ Sleep, 'Sleep',\ ExitProcess, 'ExitProcess' import user,\ GetAsyncKeyState, 'GetAsyncKeyState',\ MapVirtualKey, 'MapVirtualKeyA' import msvcrt,\ printf, 'printf',\ scanf, 'scanf'
Коцит, к сожалению, пока не могу помочь работающим кодом, но вот что обнаружил - вызов, к примеру, printf портит регистры. Это может изменять поведение программы, если printf используется где-нибудь в цикле. То есть имеет смысл обрамлять вызовы printf командами pusha / popa.
renibowot, там единичка не скопировалась с исходника в пост. _edge, >> printf портит регистры. 'printf' я туда добавил чисто для наглядности, чтоб видеть результат. Поэтому я его закоментировал, и результат тот-же. Цикл организовал через переменную, но код возвращает или несколько нажатий за одну итерацию цикла, или вообще тупо тормозит. И вообще, от куда внутри цикла попадает в ESI код клавиши? При вызове 'MapVirtualKey' в мл.байте ESI уже лежит код нажатой клавиши, и думаю это API вообще в моём случае не нужна. Правда отлаживал код в "Оле", а она не возвращает нажатие, пока не сравняешь/нажмёшь клавишу, которая в данный момент равна счётчику(ESI). Например, если нажать в Оле на пробел, когда ESI внутри цикла станет 20h, то срабатывает 'GetAsyncKeyState' и EAX становится единицей. В этот момент в ESI уже лежит код нажатой клавиши, который передаётся в 'MapVirtualKey'. Здесь я и забуксовал.. Orbit, мне не нужна готовая софтина, т.к. это чисто в багаж личных знаний, на будующее.
https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms686033(v=vs.85).aspx?f=255&MSPPError=-2147217396 SetConsoleMode со сброшенным флагом ENABLE_LINE_INPUT подойдёт?
Argogo, чёто у меня не получается задать режим со-сброшеным флагом "ENABLE_LINE_INPUT" Оля выдаёт ошибку: "ERROR_INVALID_PARAMETER (00000057)" может я неправильно что-то делаю? Был-бы рад примеру на FASM'e.. Пытаюсь сделать так: Код (ASM): ;.... section '.text' code readable executable start: invoke GetStdHandle, -11 ; дескрипторы консоли mov [stdOut], eax ; монитор invoke GetStdHandle, -10 ; ..и клава mov [stdIn], eax ; invoke SetConsoleMode,[stdIn],0F5h ;.... И почему-то мой Фасм в упор не воспринимает параметры в текстовом виде. Если задаю константы, то всё компилит нормально. Сначала считал режим через "GetConsoleMode", который вернул мне моду со-значением(F7h). Опытным путём в окне отладчика получил такие значения флагов: Код (Text): Mode(FF) = 1111 1111 ----------------------------- ENABLE_PROCESSED_INPUT/OUTPUT = бит(0) ENABLE_LINE_INPUT/WRAP_AT_EOL = бит(1) ENABLE_ECHO_INPUT = бит(2) ENABLE_WINDOW_INPUT = бит(3) ENABLE_MOUSE_INPUT |E0 = бит(4) По сути, старшие 3-бита погоду не делают, и 1Fh возвращает такую-же моду. Теперь, сбрасываю биты(1-3) и Ольга показывает, что "ENABLE_LINE_INPUT" исчез из списка, но 'SetConsoleMode' возвращает ошибку: Код (Text): Mode(F5) = 1111 0101 ----------------------------- ENABLE_PROCESSED_INPUT/OUTPUT = бит(0) ENABLE_ECHO_INPUT = бит(2) ENABLE_MOUSE_INPUT |E0 = бит(4) Остальные все флаги сбрасываются без ошибки, только 'Line_Input' глючит. И вообще подозреваю, что эта функция тоже будет писАть в буфер (а не в регистр), только по одному символу за-раз. Хотя, нужно проверить.. Спасибо за идею!
Коцит, в FASM'е я не копенгаген, вот мой пример для MASM'а, ожидание нажатия клавиши: Код (Text): ;================================\ ConsolePause PROC NEAR push ebp mov ebp, esp push STD_INPUT_HANDLE call GetStdHandle push eax @@dHinp equ [ebp-1*4] push 0 push @@dHinp call SetConsoleMode push @@dHinp call FlushConsoleInputBuffer push 0 @@dReaded equ [ebp-2*4] push 0 @@bBuffer equ [ebp-3*4] push 0 lea eax, @@dReaded push eax push 1 lea eax, @@bBuffer push eax push @@dHinp call ReadConsoleA leave ret nop ConsolePause ENDP ;================================\