Author Topic: Accepting keyboard input to implement 'Password' program  (Read 30793 times)

Offline S Mahen

  • Jr. Member
  • *
  • Posts: 21
Accepting keyboard input to implement 'Password' program
« on: September 15, 2013, 01:10:40 AM »
I want to implement a code to accept password from user.
Code should not display the accepted characters.
It should display only '*'
If password is correct program should display message 'Lagged In'
else 'Wrong Password'

I tried using
.
.
mov eax,03h
mov ebx,0
mov ecx,pwbuff
mov edx,pwbuff_len
int 80h
.
.
But this is with echo.

I am finding it difficult to accept input from user through keyboard without echo.
Please help.

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Accepting keyboard input to implement 'Password' program
« Reply #1 on: September 15, 2013, 02:47:35 AM »
Are you guys all taking the same class?

http://forum.nasm.us/index.php?topic=1710.0

There's been a similar question over at Stack Overflow recently, too. Someone over there linked to a paper by Karsten Schiebler(?) on the issue of "raw" keyboard input at http://asm.sf.net . I'll see if I can find that...

Later,
Frank

Here 'tis:
http://asm.sourceforge.net/articles/rawkb.html

« Last Edit: September 15, 2013, 03:03:28 AM by Frank Kotler »

Offline S Mahen

  • Jr. Member
  • *
  • Posts: 21
Re: Accepting keyboard input to implement 'Password' program
« Reply #2 on: September 17, 2013, 05:29:47 AM »
Thanks Frank for the reference.  :)

We (Me and Sandeep) are not taking the same class. We are working on same type of problem statements, hence multiple queries.

I worked on the reference code mentioned in the reply.

'getc' procedure works nicely to accept single char without echo and returns the accepted char in AL.

I checked the returned value with '0Ah' ASCII of 'Enter Key' if not I stored in a buffer and incremented count of accepted password and displayed '*'. And repeated the same till Enter Key.

After Enter Key, I compared length of Original password with length of accepted Password if mismatched I displayed 'Access not Granted' Message.
If length is same then I compared both the passwords.
If matched I displayed 'Access Granted' message, else displayed 'Access not Granted' Message.

From the day one I joined the forum, I got good support from you for developing ALPs using NASM.

Thank you very much Frank for your support.

_start:
   print entmsg,emsg_len
   mov esi,0
accpw:
   call getc
   cmp al,0ah
   je conti
   mov [pwbuff+esi],al
   inc esi
   print astrix,1
   jmp accpw
conti:
   cmp esi,pw_len      ;match length of password
   jne wrpw      ;if not equal wrong password

   mov ecx,esi      ;else load length in ecx to compare number of char.
   mov esi,pwbuff      ;point esi to accepted password buffer
   mov edi,password   ;point edi to actual password
   repe cmpsb      ;compare both strings char by char
   jne wrpw      ;if not equal wrong password

okaypw:   print accessmsg,amsg_len ;else password is correct & display access grant message
   jmp exit      ;jump to exit
wrpw:   print noaccessmsg,nmsg_len ;display access not granted message when password is wrong
exit:

Offline Gunner

  • Jr. Member
  • *
  • Posts: 74
  • Country: us
    • Gunners Software
Re: Accepting keyboard input to implement 'Password' program
« Reply #3 on: September 18, 2013, 02:55:26 AM »
Using "C" functions is not any fun, we are using Assembly, let's do it the right way!

Linux terminal programs start in "Cooked" mode, to do this properly, you need to change to "raw" mode.  Here is some code to get you going:

Code: [Select]

    ICANON      equ 1<<1
    ECHO        equ 1<<3

    sys_exit    equ 1
    sys_read    equ 3
    sys_write   equ 4
    stdin       equ 0
    stdout      equ 1
 
    global _start
   
    section     .data
    szAsterisk  db  "*"
    szLF        db  10
   
    section     .bss
    lpBufIn     resb    2
    lpPassIn    resb    24
    termios     resb    36

    section .text
    _start:
       
        call    echo_off
        call    canonical_off

        xor     esi, esi
    .GetCode:   
        cmp     esi, 24
        je      .PassTooBig
       
        call    GetKeyCode
        mov     al, byte[lpBufIn]
        cmp     al, "Q"
        je      .Done
        cmp     al, 10
        je      .Continue

        mov     byte [lpPassIn + esi], al
        call    PrintAsterisk
        inc     esi
        jmp     .GetCode
   
    .Continue:
        mov     byte [lpPassIn + esi], 10    ; change 10 to 0 to null terminate
       
        ;~ for testing purposes
        ;~ #####################################
        inc esi                             ;~ #
                                            ;~ #
        mov     edx, 1                      ;~ #
        mov     ecx, szLF                   ;~ #
        mov     eax, sys_write              ;~ #
        mov     ebx, stdout                 ;~ #
        int     80H                         ;~ #
                                            ;~ #
        mov     edx, esi                    ;~ #
        mov     ecx, lpPassIn               ;~ #
        mov     eax, sys_write              ;~ #   
        mov     ebx, stdout                 ;~ #
        int     80H                         ;~ #
        ;~ #####################################
             
        ;~ Compare passowrds here!!!
        jmp     .Done
       
    .PassTooBig:
        ;~ Entered password too big!
       
    .Done:
        call    echo_on
        call    canonical_on

        mov     eax, sys_exit
        xor     ebx, ebx
        int     80H
       
    ;~ #########################################
    GetKeyCode:
        mov     eax, sys_read
        mov     ebx, stdin
        mov     ecx, lpBufIn
        mov     edx, 1
        int     80h
        ret
   
    ;~ #########################################
    PrintAsterisk:
        mov     edx, 1
        mov     ecx, szAsterisk
        mov     eax, sys_write
        mov     ebx, stdout
        int     80H     
        ret        
       
    ;~ #########################################
    canonical_off:
            call read_stdin_termios

            ; clear canonical bit in local mode flags
            mov eax, ICANON
            not eax
            and [termios+12], eax

            call write_stdin_termios
            ret
           
    ;~ #########################################
    echo_off:
            call read_stdin_termios

            ; clear echo bit in local mode flags
            mov eax, ECHO
            not eax
            and [termios+12], eax

            call write_stdin_termios
            ret

    ;~ #########################################
    canonical_on:
            call read_stdin_termios

            ; set canonical bit in local mode flags
            or dword [termios+12], ICANON

            call write_stdin_termios
            ret

    ;~ #########################################
    echo_on:
            call read_stdin_termios

            ; set echo bit in local mode flags
            or dword [termios+12], ECHO

            call write_stdin_termios
            ret

    ;~ #########################################
    read_stdin_termios:
            mov eax, 36h
            mov ebx, stdin
            mov ecx, 5401h
            mov edx, termios
            int 80h
            ret

    ;~ #########################################
    write_stdin_termios:
            mov eax, 36h
            mov ebx, stdin
            mov ecx, 5402h
            mov edx, termios
            int 80h
            ret

At program start, we turn off character echo by calling echo_off and to enter raw mode, call canonical_off 

*** VERY IMPORTANT ***
Before you exit your program, turn echo back on, and cooked mode back on!!!
Code: [Select]
        call    echo_on
        call    canonical_on

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Accepting keyboard input to implement 'Password' program
« Reply #4 on: September 18, 2013, 04:42:10 AM »
I think the "getc" that S Mahen is using is my homemade "getc" from the link above, not the C "getc". I should have called it something else to avoid confusion. It does about what you do, only turns canonical and echo off, gets the key, and turns 'em back on, all in the same function. Not very efficient, but we've gotta wait for the human to get his clumsy thumb off the key anyway, and it avoids the problem you mention at the end. I once turned echo and canonical off and made stdin non-blocking... then crashed my program. What a mess! Had to use the Big Red Switch.

Something that you do that S Mahen probably should do is check for the number of characters we're putting in the buffer, so as not to overflow it. We don't want to reinvent "gets()"! Leave that to the C guys! :)

Best,
Frank


Offline S Mahen

  • Jr. Member
  • *
  • Posts: 21
Re: Accepting keyboard input to implement 'Password' program
« Reply #5 on: January 29, 2021, 12:41:04 AM »
Hi,
Now I want to work on 64-bit code.
Using syscall "ioctl" (16).

The objective is same...

Please guide me.

Offline fredericopissarra

  • Full Member
  • **
  • Posts: 373
  • Country: br
Re: Accepting keyboard input to implement 'Password' program
« Reply #6 on: January 29, 2021, 01:59:18 PM »
Hi,
Now I want to work on 64-bit code.
Using syscall "ioctl" (16).

Here's the same excellent code from Gunner, but for x86-64 (with tiny corrections):
Code: [Select]
  bits        64
  default     rel

ICANON      equ 1<<1
ECHO        equ 1<<3

; NOTE: syscalls #s are different for SysV x86-64 ABI.
sys_exit    equ 60
sys_read    equ 0
sys_write   equ 1
sys_ioctl   equ 16
stdin       equ 0
stdout      equ 1

  ; CHANGE: don't need to keep these bytes in a writable section!
  section .rodata

szAsterisk  db  "*"
szLF        db  `\n`

  ; NOTE: Beware that .bss isn't zeroed automatically, as in C.
  section     .bss

lpBufIn     resb    2
lpPassIn    resb    24
termios     resb    36

  section .text

  global _start
_start:
  call    echo_off
  call    canonical_off

  ; NOTE: Changed from edi to ebx because SysV ABI for x86-64 uses RSI.
  xor     ebx, ebx
.GetCode:   
  cmp     ebx, 24
  je      .PassTooBig
   
  call    GetKeyCode

  mov     al, byte [lpBufIn]
  cmp     al, "Q"
  je      .Done
  cmp     al, 10
  je      .Continue

  mov     byte [lpPassIn + rbx], al
  call    PrintAsterisk
  inc     ebx
  jmp     .GetCode
 
.Continue:
  mov     byte [lpPassIn + rbx], 0    ; FIX
   
  ;~ for testing purposes
  ;~ #####################################
  inc ebx                             ;~ #
                                      ;~ #
  mov     edx, 1                      ;~ #
  lea     rsi, [szLF]                 ;~ #
  mov     eax, sys_write              ;~ #
  mov     esi, stdout                 ;~ #
  syscall                             ;~ #
                                      ;~ #
  mov     edx, ebx                    ;~ #
  lea     rsi, [lpPassIn]             ;~ #
  mov     eax, sys_write              ;~ #   
  mov     esi, stdout                 ;~ #
  syscall                             ;~ #
  ;~ #####################################
       
  ;~ Compare passowrds here!!!
  jmp     .Done
   
.PassTooBig:
  ;~ Entered password too big!
   
.Done:
  call    echo_on
  call    canonical_on

  mov     eax, sys_exit
  xor     edi, edi
  syscall
   
;~ #########################################
GetKeyCode:
  mov     eax, sys_read
  mov     edi, stdin
  lea     rsi, [lpBufIn]
  mov     edx, 1
  syscall
  ret
 
;~ #########################################
PrintAsterisk:
  mov     edx, 1
  lea     rsi, [szAsterisk]
  mov     eax, sys_write
  mov     edi, stdout
  syscall     
  ret        
   
;~ #########################################
canonical_off:
  call read_stdin_termios

  ; clear canonical bit in local mode flags
  and dword [termios+12], ~ICANON

  call write_stdin_termios
  ret
     
;~ #########################################
echo_off:
  call read_stdin_termios

  ; clear echo bit in local mode flags
  and dword [termios+12], ~ECHO

  call write_stdin_termios
  ret

;~ #########################################
canonical_on:
  call read_stdin_termios

  ; set canonical bit in local mode flags
  or dword [termios+12], ICANON

  call write_stdin_termios
  ret

;~ #########################################
echo_on:
  call read_stdin_termios

  ; set echo bit in local mode flags
  or dword [termios+12], ECHO

  call write_stdin_termios
  ret

;~ #########################################
read_stdin_termios:
  mov eax, sys_ioctl
  mov edi, stdin
  mov esi, 0x5401
  lea rdx, [termios]
  syscall
  ret

;~ #########################################
write_stdin_termios:
  mov eax, sys_ioctl
  mov edi, stdin
  mov esi, 0x5402
  lea rdx, [termios]
  syscall
  ret

Offline S Mahen

  • Jr. Member
  • *
  • Posts: 21
Re: Accepting keyboard input to implement 'Password' program
« Reply #7 on: January 30, 2021, 01:42:29 AM »
Thank you so much for the sample code... I am modifying the same as per problem statement. Will share the modified code...