MalwareSourceCode/MSDOS/K-Index/Virus.MSDOS.Unknown.key-fake.asm

247 lines
6.8 KiB
NASM
Raw Normal View History

2022-08-21 09:07:57 +00:00
; KEY-FAKE.ASM -- Fakes keystrokes from internal keyboard buffer.
; ============
CSEG Segment
Assume CS:CSEG
Org 0100h
Entry: Jmp Initialize
; Most Resident Data
; ------------------
db 'KEY-FAKE (C) Copyright Charles Petzold, 1985'
SearchLabelEnd Label Byte
OldInterrupt16 dd 0
Pointer dw Offset KeyStrokeBuffer
Counter db 0
; New Interrupt 16 (Keyboard)
; ---------------------------
NewInterrupt16 Proc Far
Sti ; Allow futher interrupts
Cmp CS:[Counter],0 ; See if characters in buffer
Jz DoOldInterrupt ; If not, just do regular interrupt
Or AH,AH ; Check if AH is zero
Jz GetCharacter ; If so, call is to get character
Cmp AH,1 ; Check if AH is one
Jz GetStatus ; If so, call is for status
DoOldInterrupt: Jmp CS:[OldInterrupt16] ; Otherwise, go away
GetCharacter: Push BX
Mov BX,CS:[Pointer] ; BX points to current buffer position
Mov AX,CS:[BX] ; Get ASCII code and scan code
Inc BX ; Move buffer pointer ahead
Inc BX
Mov CS:[Pointer],BX ; Save new pointer
Dec CS:[Counter] ; One less character in counter
Pop BX
Or AX,AX ; See if 0 returned
Jz NewInterrupt16 ; If so, take it from the top again
IRet ; Return to calling program
GetStatus: Push BX
Mov BX,CS:[Pointer] ; BX points to current buffer position
Mov AX,CS:[BX] ; Get ASCII code and scan code
Pop BX
Or AX,AX ; See if special 0 keystroke
Jnz StatusReturn ; If not, return non-zero flag
Add CS:[Pointer],2 ; If so, skip over it
Dec CS:[Counter] ; One less character
Or AX,AX ; Will set zero flag
StatusReturn: Ret 2 ; Do not pop flags
NewInterrupt16 EndP
; Beginning of Key Stroke Buffer
; ------------------------------
KeyStrokeBuffer Label Byte ; 256 Byte Buffer for keystrokes
; Initialization -- Search through Memory and see if label matches
; ----------------------------------------------------------------
;
; If so, use the loaded program; if not, create a new interrupt
Assume DS:CSEG, ES:CSEG, SS:CSEG
Initialize: Mov Word Ptr [Entry],0 ; Slightly modify search label
Mov Byte Ptr [Entry + 2],0 ; so no false matches
Cld
Mov DX,CS ; This segment
Sub AX,AX ; Beginning of search
Mov ES,AX ; Search segment
SearchLoop: Mov SI,100h ; Address to search
Mov DI,SI ; Set pointers to same address
Mov CX,Offset SearchLabelEnd - Offset Entry
Repz Cmpsb ; Check for match
Jz ReadyForDecode ; If label matches
Inc AX ; Still the search segment
Mov ES,AX ; ES to next segment
Cmp AX,DX ; Check if it's this segment
Jnz SearchLoop ; Try another compare
Mov Byte Ptr DS:[1],27h ; Since no match found,
; set up PSP for Terminate &
; remain resident.
; Save and Set Interupt 16 if Staying Resident
; --------------------------------------------
Sub AX,AX ; Set AX to zero
Mov DS,AX ; To access vector segment
Assume DS:Nothing ; Tell the assembler
Mov AX,Word Ptr DS:[16h * 4] ; Get vector offset
Mov Word Ptr CS:[OldInterrupt16],AX ; Save it
Mov AX,Word Ptr DS:[16h * 4 + 2] ; Get vector segment
Mov Word Ptr CS:[OldInterrupt16 + 2],AX ; and save it
Cli ; Don't interrupt me
Mov DS:[16h * 4],Offset NewInterrupt16 ; Store new
Mov DS:[16h * 4 + 2],CS ; address
Sti ; Now you can talk
Push CS
Pop DS ; Restore DS
Assume DS:CSEG
; Parameter decoding when program segment has been found
; ------------------------------------------------------
;
; ES = segment of loaded program (could be CS)
ReadyForDecode: Mov SI,80h ; SI points to parameter area
Mov DI,Offset KeyStrokeBuffer
Mov ES:[Pointer],DI ; ES:DI points to buffer area
Mov ES:[Counter],0 ; Set keystroke counter to zero
Lodsb ; Get parameter count
Cbw ; Convert to word
Mov CX,AX ; CX = parameter count
Inc CX ; So catch last delimiter (0D)
Or AX,AX ; Check if parameter present
Jnz GoDecodeLoop ; If so, continue
Jmp EndDecode ; If not, cut out
GoDecodeLoop: Jmp DecodeLoop
; End of Residence is end of Key Stroke Buffer
; --------------------------------------------
Org 256 + Offset KeyStrokeBuffer
EndResidence Label Byte
; Data for Parameter Decoding
; ---------------------------
QuoteSign db 0 ; Flag for quoted strings
DoingNumber db 0 ; Flag for doing a number
DoingExtended db 0 ; Flag for doing extended ASCII
CalcNumber db 0 ; A calculated number
Ten db 10 ; For MUL convenience
; Routine for doing quoted text
; -----------------------------
DecodeLoop: Lodsb ; Get character
Cmp [QuoteSign],0 ; Check if doing quoted text
Jz NotDoingQuote ; If not, continue checks
Cmp AL,[QuoteSign] ; Check first if character is quote
Jz EndQuote ; If so, finish quoted text
Sub AH,AH ; Set scan code to zero
Stosw ; Save it in buffer
Inc ES:[Counter] ; One more character
Jmp DoNextCharacter ; Go to bottom of routine
EndQuote: Mov [QuoteSign],0 ; End of quoted text
Jmp DoNextCharacter ; Get the next character
; Routine for Extended Ascii Character (@)
; ----------------------------------------
NotDoingQuote: Cmp AL,'@' ; See if character is for extended
Jnz NotExtended ; If not, hop over a little code
Mov [DoingExtended],1 ; Flag for extended ASCII
Jmp Delimiter ; To possibly dump number
; Routine for Quote Sign ' or "
; -----------------------------
NotExtended: Cmp AL,'"' ; Check for a double quote sign
Jz Quote
Cmp AL,"'" ; Check for a single quote sign
Jnz NotAQuote
Quote: Mov [QuoteSign],AL ; Save the quote sign
Jmp Delimiter ; To possibly dump number
; Routine for decimal number
; --------------------------
NotAQuote: Cmp AL,'0' ; See if character >= 0
Jb Delimiter
Cmp AL,'9' ; See if character <= 9
Ja Delimiter
Mov [DoingNumber],1 ; If so, doing number
Sub AL,'0' ; Convert to binary
Xchg AL,[CalcNumber] ; Get previously calculated
Mul [Ten] ; Multiply by 10
Add [CalcNumber],AL ; Add it to new digit
Jmp DoNextCharacter ; And continue
; Anything else is considered a delimiter
; ---------------------------------------
Delimiter: Cmp [DoingNumber],1 ; Check if doing a number
Jnz DoNextCharacter ; If not, do not dump
Mov AL,[CalcNumber] ; Set AX to ASCII number
Sub AH,AH ; Zero out scan code part
Cmp [DoingExtended],1 ; Check if doing scan code
Jnz NumberOK
Xchg AL,AH ; Switch ASCII and scan code
NumberOK: Stosw ; Store the two codes
Inc ES:[Counter] ; One more character in buffer
Mov [DoingNumber],0 ; Clear out all flags
Mov [DoingExtended],0
Mov [CalcNumber],0
DoNextCharacter:Dec CX ; One less character to do
Jz EndDecode ; If no more, we're done
Jmp DecodeLoop ; Otherwise, get next one
; End Decode -- Ready to terminate (and possibly stay resident)
; -------------------------------------------------------------
EndDecode: Mov DX,Offset EndResidence ; End of resident part
Ret ; Int 20h or 27h
CSEG EndS
End Entry
2021-01-12 23:47:04 +00:00