//---------------------------------------------------------------- // noncanon64.s (A revision of our 'noncanon.s' demo) // // This program was written in order to develop the assembly // code needed by an application that could allow a password // to be typed in by the user and that would provide instant // visual 'feedback' as each keystroke is typed, but without // showing to any observers which key had just been pressed. // // to assemble: $ as noncanon.s -o noncanon.o // and to link: $ ld noncanon.o -o noncanon // and execute: $ ./noncanon // // programmer: ALLAN CRUSE // written on: 12 JUL 2011 -- for the x86_64 linux kernel //---------------------------------------------------------------- # well-known device-file ID-numbers .equ DEV_STDIN, 0 .equ DEV_STDOUT, 1 # From 'unistd_64.h' in kernel 2.6.26 .equ SYS_READ, 0 .equ SYS_WRITE, 1 .equ SYS_IOCTL, 16 .equ SYS_EXIT, 60 # From 'include/asm-x86/ioctls.h' in kernel 2.6.26 .equ TCGETS, 0x5401 .equ TCSETSF, 0x5404 .section .data msg: .ascii "The 'struct termios' data-structure is shown below: \n" buf: .ascii "xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx " .ascii "xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx" .ascii "\n" .ascii "xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx " .ascii "xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx " .ascii "\n" len: .int . - msg inch: .quad 0 inlen: .int . - inch .align 16 tty_orig: .space 64, 0xFF tty_work: .space 64, 0x00 .section .text _start: # get the kernel's existing 'struct termios' data-structure # by emulating 'tcgetattr( STDIN_FILENO, &tty_orig );' mov $SYS_IOCTL, %rax mov $DEV_STDIN, %edi mov $TCGETS, %rsi lea tty_orig, %edx syscall # make a working copy of the 'struct termios' data-structure lea tty_orig, %esi lea tty_work, %edi cld mov $16, %ecx rep movsl # modify the copied 'struct termios' data-structure mov $3, %ebx mov tty_work(,%ebx,4), %eax and $~0xF, %eax mov %eax, tty_work(,%ebx,4) # install the modified 'struct termios' data-structure by # emulating 'tcsetattr( STDIN_FILENO, TCSAFLUSH, &tty_work );' mov $SYS_IOCTL, %rax mov $DEV_STDIN, %rdi mov $TCSETSF, %rsi lea tty_work, %rdx syscall while: # test 'non-canonical' keyboard input mov $SYS_READ, %rax mov $DEV_STDIN, %rdi lea inch, %rsi mov inlen, %edx syscall # check for -key cmpq $0x0A, inch je finis # otherwise display an asterick character movq $'*', inch mov $SYS_WRITE, %eax mov $DEV_STDOUT, %rdi lea inch, %rsi mov $1, %edx syscall jmp while finis: # output a newline control-code movq $'\n', inch mov $SYS_WRITE, %rax mov $DEV_STDOUT, %rdi lea inch, %rsi mov $1, %edx syscall # reinstall the original 'struct termios' data-structure by # emulating 'tcsetattr( STDIN_FILENO, TCSAFLUSH, &tty_orig );' mov $SYS_IOCTL, %rax mov $DEV_STDIN, %rdi mov $TCSETSF, %rsi lea tty_orig, %rdx syscall # format a hex-dump of the 'struct termios' data-structure xor %esi, %esi lea buf, %edi mov $16, %ecx nxlong: mov tty_work(%esi), %eax call eax2hex add $9, %edi add $4, %esi loop nxlong # display the original 'struct termios' data-structure to # assure that it didn't overrun the 64-bytes we allocated mov $SYS_WRITE, %rax mov $DEV_STDOUT, %rdi lea msg, %rsi mov len, %edx syscall exit: # terminate this program mov $SYS_EXIT, %rax xor %rdi, %rdi syscall hex: .ascii "0123456789ABCDEF" eax2hex: push %rax push %rbx push %rcx push %rdx push %rdi mov $8, %ecx nxnyb: rol $4, %eax mov %al, %bl and $0xF, %ebx mov hex(%ebx), %dl mov %dl, (%edi) inc %edi loop nxnyb pop %rdi pop %rdx pop %rcx pop %rbx pop %rax ret .global _start .end