mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-19 18:06:10 +00:00
247 lines
7.0 KiB
NASM
247 lines
7.0 KiB
NASM
; 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
|
||
|