mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-21 10:56: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
|
|||
|
|