MalwareSourceCode/MSDOS/Virus.MSDOS.Unknown.key-fake.asm
2021-01-12 17:47:04 -06:00

247 lines
7.0 KiB
NASM
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

; 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