📄 keyeval.asm
字号:
MyInt2F proc far
assume ds:nothing
cmp ah, MyTSRID ;Match our TSR identifier?
je YepItsOurs
jmp OldInt2F
; Okay, we know this is our ID, now check for a verify vs. remove call.
YepItsOurs: cmp al, 0 ;Verify Call
jne TryRmv
mov al, 0ffh ;Return success.
lesi IDString
iret ;Return back to caller.
IDString byte "Keypress Logger TSR",0
TryRmv: cmp al, 1 ;Remove call.
jne IllegalOp
call TstRmvable ;See if we can remove this guy.
je CanRemove ;Branch if we can.
mov ax, 1 ;Return failure for now.
iret
; Okay, they want to remove this guy *and* we can remove it from memory.
; Take care of all that here.
assume ds:ResidentSeg
CanRemove: push ds
push es
pusha
cli ;Turn off the interrupts while
mov ax, 0 ; we mess with the interrupt
mov es, ax ; vectors.
mov ax, cs
mov ds, ax
mov ax, word ptr OldInt9
mov es:[9*4], ax
mov ax, word ptr OldInt9+2
mov es:[9*4 + 2], ax
mov ax, word ptr OldInt13
mov es:[13h*4], ax
mov ax, word ptr OldInt13+2
mov es:[13h*4 + 2], ax
mov ax, word ptr OldInt16
mov es:[16h*4], ax
mov ax, word ptr OldInt16+2
mov es:[16h*4 + 2], ax
mov ax, word ptr OldInt1C
mov es:[1Ch*4], ax
mov ax, word ptr OldInt1C+2
mov es:[1Ch*4 + 2], ax
mov ax, word ptr OldInt28
mov es:[28h*4], ax
mov ax, word ptr OldInt28+2
mov es:[28h*4 + 2], ax
mov ax, word ptr OldInt2F
mov es:[2Fh*4], ax
mov ax, word ptr OldInt2F+2
mov es:[2Fh*4 + 2], ax
; Okay, with that out of the way, let's close the file.
; Note: INT 2F shouldn't have to deal with DOS busy because it's
; a passive TSR call.
mov ah, 3Eh ;Close file command
mov bx, FileHandle
int 21h
; Okay, one last thing before we quit- Let's give the memory allocated
; to this TSR back to DOS.
mov ds, PSP
mov es, ds:[2Ch] ;Ptr to environment block.
mov ah, 49h ;DOS release memory call.
int 21h
mov ax, ds ;Release program code space.
mov es, ax
mov ah, 49h
int 21h
popa
pop es
pop ds
mov ax, 0 ;Return Success.
iret
; They called us with an illegal subfunction value. Try to do as little
; damage as possible.
IllegalOp: mov ax, 0 ;Who knows what they were thinking?
iret
MyInt2F endp
assume ds:nothing
; TstRmvable- Checks to see if we can remove this TSR from memory.
; Returns the zero flag set if we can remove it, clear
; otherwise.
TstRmvable proc near
cli
push ds
mov ax, 0
mov ds, ax
cmp word ptr ds:[9*4], offset MyInt9
jne TRDone
cmp word ptr ds:[9*4 + 2], seg MyInt9
jne TRDone
cmp word ptr ds:[13h*4], offset MyInt13
jne TRDone
cmp word ptr ds:[13h*4 + 2], seg MyInt13
jne TRDone
cmp word ptr ds:[16h*4], offset MyInt16
jne TRDone
cmp word ptr ds:[16h*4 + 2], seg MyInt16
jne TRDone
cmp word ptr ds:[1Ch*4], offset MyInt1C
jne TRDone
cmp word ptr ds:[1Ch*4 + 2], seg MyInt1C
jne TRDone
cmp word ptr ds:[28h*4], offset MyInt28
jne TRDone
cmp word ptr ds:[28h*4 + 2], seg MyInt28
jne TRDone
cmp word ptr ds:[2Fh*4], offset MyInt2F
jne TRDone
cmp word ptr ds:[2Fh*4 + 2], seg MyInt2F
TRDone: pop ds
sti
ret
TstRmvable endp
ResidentSeg ends
cseg segment para public 'code'
assume cs:cseg, ds:ResidentSeg
; SeeIfPresent- Checks to see if our TSR is already present in memory.
; Sets the zero flag if it is, clears the zero flag if
; it is not.
SeeIfPresent proc near
push es
push ds
push di
mov cx, 0ffh ;Start with ID 0FFh.
IDLoop: mov ah, cl
push cx
mov al, 0 ;Verify presence call.
int 2Fh
pop cx
cmp al, 0 ;Present in memory?
je TryNext
strcmpl
byte "Keypress Logger TSR",0
je Success
TryNext: dec cl ;Test USER IDs of 80h..FFh
js IDLoop
cmp cx, 0 ;Clear zero flag.
Success: pop di
pop ds
pop es
ret
SeeIfPresent endp
; FindID- Determines the first (well, last actually) TSR ID available
; in the multiplex interrupt chain. Returns this value in
; the CL register.
;
; Returns the zero flag set if it locates an empty slot.
; Returns the zero flag clear if failure.
FindID proc near
push es
push ds
push di
mov cx, 0ffh ;Start with ID 0FFh.
IDLoop: mov ah, cl
push cx
mov al, 0 ;Verify presence call.
int 2Fh
pop cx
cmp al, 0 ;Present in memory?
je Success
dec cl ;Test USER IDs of 80h..FFh
js IDLoop
xor cx, cx
cmp cx, 1 ;Clear zero flag
Success: pop di
pop ds
pop es
ret
FindID endp
Main proc
meminit
mov ax, ResidentSeg
mov ds, ax
mov ah, 62h ;Get this program's PSP
int 21h ; value.
mov PSP, bx
; Before we do anything else, we need to check the command line
; parameters. We must have either a valid filename or the
; command "remove". If remove appears on the command line, then remove
; the resident copy from memory using the multiplex (2Fh) interrupt.
; If remove is not on the command line, we'd better have a filename and
; there had better not be a copy already loaded into memory.
argc
cmp cx, 1 ;Must have exactly 1 parm.
je GoodParmCnt
print
byte "Usage:",cr,lf
byte " KeyEval filename",cr,lf
byte "or KeyEval REMOVE",cr,lf,0
ExitPgm
; Check for the REMOVE command.
GoodParmCnt: mov ax, 1
argv
stricmpl
byte "REMOVE",0
jne TstPresent
call SeeIfPresent
je RemoveIt
print
byte "TSR is not present in memory, cannot remove"
byte cr,lf,0
ExitPgm
RemoveIt: mov MyTSRID, cl
printf
byte "Removing TSR (ID #%d) from memory...",0
dword MyTSRID
mov ah, cl
mov al, 1 ;Remove cmd, ah contains ID
int 2Fh
cmp al, 1 ;Succeed?
je RmvFailure
print
byte "removed.",cr,lf,0
ExitPgm
RmvFailure: print
byte cr,lf
byte "Could not remove TSR from memory.",cr,lf
byte "Try removing other TSRs in the reverse order "
byte "you installed them.",cr,lf,0
ExitPgm
; Okay, see if the TSR is already in memory. If so, abort the
; installation process.
TstPresent: call SeeIfPresent
jne GetTSRID
print
byte "TSR is already present in memory.",cr,lf
byte "Aborting installation process",cr,lf,0
ExitPgm
; Get an ID for our TSR and save it away.
GetTSRID: call FindID
je GetFileName
print
byte "Too many resident TSRs, cannot install",cr,lf,0
ExitPgm
; Things look cool so far, check the filename and open the file.
GetFileName: mov MyTSRID, cl
printf
byte "Keypress logger TSR program",cr,lf
byte "TSR ID = %d",cr,lf
byte "Processing file:",0
dword MyTSRID
puts
putcr
mov ah, 3Ch ;Create file command.
mov cx, 0 ;Normal file.
push ds
push es ;Point ds:dx at name
pop ds
mov dx, di
int 21h ;Open the file
jnc GoodOpen
print
byte "DOS error #",0
puti
print
byte " opening file.",cr,lf,0
ExitPgm
GoodOpen: pop ds
mov FileHandle, ax ;Save file handle.
InstallInts: print
byte "Installing interrupts...",0
; Patch into the INT 9, 13h, 16h, 1Ch, 28h, and 2Fh interrupt vectors.
; Note that the statements above have made ResidentSeg the current data
; segment, so we can store the old values directly into
; the OldIntxx variables.
cli ;Turn off interrupts!
mov ax, 0
mov es, ax
mov ax, es:[9*4]
mov word ptr OldInt9, ax
mov ax, es:[9*4 + 2]
mov word ptr OldInt9+2, ax
mov es:[9*4], offset MyInt9
mov es:[9*4+2], seg ResidentSeg
mov ax, es:[13h*4]
mov word ptr OldInt13, ax
mov ax, es:[13h*4 + 2]
mov word ptr OldInt13+2, ax
mov es:[13h*4], offset MyInt13
mov es:[13h*4+2], seg ResidentSeg
mov ax, es:[16h*4]
mov word ptr OldInt16, ax
mov ax, es:[16h*4 + 2]
mov word ptr OldInt16+2, ax
mov es:[16h*4], offset MyInt16
mov es:[16h*4+2], seg ResidentSeg
mov ax, es:[1Ch*4]
mov word ptr OldInt1C, ax
mov ax, es:[1Ch*4 + 2]
mov word ptr OldInt1C+2, ax
mov es:[1Ch*4], offset MyInt1C
mov es:[1Ch*4+2], seg ResidentSeg
mov ax, es:[28h*4]
mov word ptr OldInt28, ax
mov ax, es:[28h*4 + 2]
mov word ptr OldInt28+2, ax
mov es:[28h*4], offset MyInt28
mov es:[28h*4+2], seg ResidentSeg
mov ax, es:[2Fh*4]
mov word ptr OldInt2F, ax
mov ax, es:[2Fh*4 + 2]
mov word ptr OldInt2F+2, ax
mov es:[2Fh*4], offset MyInt2F
mov es:[2Fh*4+2], seg ResidentSeg
sti ;Okay, ints back on.
; We're hooked up, the only thing that remains is to terminate and
; stay resident.
print
byte "Installed.",cr,lf,0
mov dx, EndResident ;Compute size of program.
sub dx, PSP
mov ax, 3100h ;DOS TSR command.
int 21h
Main endp
cseg ends
sseg segment para stack 'stack'
stk db 1024 dup ("stack ")
sseg ends
zzzzzzseg segment para public 'zzzzzz'
LastBytes db 16 dup (?)
zzzzzzseg ends
end Main
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -