;; ; @(#) kill.asm - Task killer resident utility. ; (c) 1997 Ivan Maidanski http://ivmai.chat.ru ; Freeware program source. All rights reserved. ;; ; Language: ASM8086 (for IBM PC/AT, MS-DOS v3.0+, COM file) ; Tested with: Turbo Assembler v3.1, Turbo Link v5.1 ; Last modified: 1997-10-11 14:50:00 GMT+04:00 ;; NAME KillTask ; tasm kill.asm ; tlink /t kill.obj ; Comment: When installed You can abort any program by pressing Ctrl+Alt+Esc .MODEL SMALL .CODE .8086 Null LABEL NEAR ; Program global constants TSR@ActCnt= 3h ; number of sequental hot key pressing to ignore DOS state TSR@SavedIntsCnt= 100h ; number of saved/restored interrupt vectors ; PSP segment ORG 2Ch Main@EnvSeg DW ? ; environment segment ; Resident-part non-initialized valiables ORG 10h Int2Fh@SwStRec DW 9h DUP(?) Int2Fh@InstRec DW 5h DUP(?) ; Resident-part valiables with initialization ORG 6Ch TSR@Data LABEL BYTE TSR@LastIVT DW ? ; last control task segment (with IVTable) TSR@Activated DB ? ; activation required flag TSR@Busy DB ? ; system busy flag (counter) TSR@DataLen= $-TSR@Data ; Resident-part shifted code beginning TSR@Start LABEL NEAR ; Program start point ORG 100h Start: cmp sp,OFFSET StackTop ; check available memory jb Start@Error jmp Main Start@Error: xor ax,ax ; abort program if no memory push es push ax retf ; RAM-resident part code ASSUME ds:NOTHING,es:NOTHING EVEN TSR@Begin LABEL NEAR TSR@Shift= TSR@Begin-TSR@Start EVEN Int08h PROC FAR ; Comment: Timer interrupt handler ; Expects: - ; Returns: - ; Uses: - pushf DB 9Ah ; call far Int08h@Old DD ? cmp cs:[TSR@Activated],0 ; activated ? jne Int08h@Try iret Int08h@Try: cmp cs:[TSR@Activated],TSR@ActCnt ; ignore DOS status ? jae Int08h@Abort push ds ; check DOS status push ax mov ax,0 ; load DS with DOS segment ORG $-2h Int08h@InDOSSeg DW ? mov ds,ax pop ax cmp byte ptr ds:[0],0 ; DOS busy ? ORG $-3h Int08h@InDOSOfs DW ? DB 0 pop ds jne Int08h@Ret Int08h@Abort: call Abort Int08h@Ret: iret Int08h ENDP EVEN Int09h PROC FAR ; Comment: Keyboard interrupt handler ; Expects: - ; Returns: - ; Uses: - inc cs:[TSR@Busy] ; close activation gate push ax in al,60h ; get key scan code cmp al,1h ; [Esc] key ? je Int09h@Check Int09h@FarCall: pop ax pushf DB 9Ah ; call far Int09h@Old DD ? dec cs:[TSR@Busy] ; open activation gate iret Int09h@Check: push ds xor ax,ax mov ds,ax mov al,byte ptr ds:[417h] ; get keyboard flags pop ds and al,0Fh ; Ctrl+Alt ? cmp al,0Ch jne Int09h@FarCall in al,61h ; reset keyboard controller or al,80h out 61h,al and al,7Fh out 61h,al mov al,20h ; reset interrupt controller out 20h,al pop ax inc cs:[TSR@Activated] ; set activation flag dec cs:[TSR@Busy] ; open activation gate iret Int09h ENDP EVEN Int10h PROC FAR ; Comment: BIOS Video service handler ; Expects: - (registers passed to int 10h) ; Returns: - (registers returned by int 10h) ; Uses: - inc cs:[TSR@Busy] ; close activation gate pushf DB 9Ah ; call far Int10h@Old DD ? dec cs:[TSR@Busy] ; open activation gate sti ; simulate IRET without popping flags ret 2h Int10h ENDP EVEN Int13h PROC FAR ; Comment: BIOS disk I/O service handler ; Expects: - (registers passed to int 13h) ; Returns: - (registers returned by int 13h) ; Uses: - inc cs:[TSR@Busy] ; close activation gate pushf DB 9Ah ; call far Int13h@Old DD ? dec cs:[TSR@Busy] ; open activation gate sti ; simulate IRET without popping flags ret 2h Int13h ENDP EVEN Int21h PROC FAR ; Comment: DOS multifunctional handler ; Expects: ax=4B00h, ds:[dx] - ASCIIZ file name, es:[bx] - ExecParamRec ; Returns: ax - error code,... ; Uses: - (ax)/(all) pushf cmp ax,4B00h ; execute new process ? je Int21h@Execute ; cmp ax,4B05h ; set execution state ? ; je Int21h@SetState popf DB 0EAh ; jmp far Int21h@Old DD ? Int21h@Execute: popf inc cs:[TSR@Busy] ; close activation gate sti push ax push bx mov ah,48h ; allocate memory for IVT (and chain pointers) mov bx,((6h+TSR@SavedIntsCnt*4h)+0Fh)/10h pushf call cs:[Int21h@Old-TSR@Shift] pop bx jc Int21h@ErrRet push ds ; chain current table mov ds,ax xchg ax,cs:[TSR@LastIVT] mov word ptr ds:[0],ax pop ds pop ax cld ; save address of the call-point push es push si push di mov es,cs:[TSR@LastIVT] mov di,2h mov si,sp add si,6h movs word ptr es:[di],word ptr ss:[si] movs word ptr es:[di],word ptr ss:[si] push ds ; make copy of the current IV table push cx xor si,si mov ds,si mov cx,TSR@SavedIntsCnt*2h rep movs word ptr es:[di],word ptr ds:[si] pop cx pop ds pop di pop si pop es cli dec cs:[TSR@Busy] ; open activation gate pushf ; execute process call cs:[Int21h@Old-TSR@Shift] inc cs:[TSR@Busy] ; close activation gate jnc Int21h@Restore push ax push es mov es,cs:[TSR@LastIVT] ; unchain current copy mov ax,word ptr es:[0] mov cs:[TSR@LastIVT],ax sti mov ah,49h ; free current IV table copy pushf call cs:[Int21h@Old-TSR@Shift] pop es Int21h@ErrRet: pop ax dec cs:[TSR@Busy] ; open activation gate ret 2h ; simulate IRET without popping flags Int21h@Restore: cli cld ; restore address of the call-point xor si,si mov ds,cs:[TSR@LastIVT] lods word ptr ds:[si] push word ptr ds:[si+2h] push word ptr ds:[si] cmp cs:[TSR@Activated],0 ; TSR activated ? je Int21h@Skip mov cs:[TSR@Activated],0 ; reset activation flag add si,4h ; restore IV table xor di,di mov es,di mov cx,TSR@SavedIntsCnt*2h rep movs word ptr es:[di],word ptr ds:[si] Int21h@Skip: mov cs:[TSR@LastIVT],ax ; unchain current copy sti mov ah,49h ; free current IV table copy push ds pop es pushf call cs:[Int21h@Old-TSR@Shift] clc ; clear error flag dec cs:[TSR@Busy] ; open activation gate ret ; simulate JMP to previous process Int21h ENDP EVEN Int28h PROC FAR ; Comment: DOS Idle handler ; Expects: - ; Returns: - ; Uses: - cmp cs:[TSR@Activated],0 ; activated ? jne Int28h@Act Int28h@FarJump: DB 0EAh ; jmp far Int28h@Old DD ? Int28h@Act: call Abort jmp short Int28h@FarJump Int28h ENDP EVEN Int2Fh PROC FAR ; Comment: Multiplex interrupt handler ; Expects: ah - ID number, al=0 - installation check, ; ax=1605h - identify instance data (Windows 386 API),..., ; ax=4B05h - identify instance data (Task Switcher API),..., ; es=0 & bx=0 (identify) ; Returns: ah - ID number (check), al=1h - installed (check), ; es:[di] - ASCIIZ ID string (check), es:[bx] - SwStRec (identify),... ; Uses: - (al,di,es)/(bx,cx,si,ds,es) cmp ax,1605h ; starting Windows 386 ? je Int2Fh@MultiEnv cmp ax,4B05h ; starting DOS Task Switcher ? je Int2Fh@MultiEnv cmp ah,0 ORG $-1h Int2Fh@IDNumber DB ? je Int2Fh@Check DB 0EAh ; jmp far Int2Fh@Old DD ? Int2Fh@MultiEnv: pushf call cs:[Int2Fh@Old-TSR@Shift] mov cs:[Int2Fh@SwStRec+2h],bx mov bx,OFFSET Int2Fh@InstRec mov word ptr cs:[bx+2h],cs ; make copy of TSR initialized variables mov word ptr cs:[bx],OFFSET TSR@Data mov word ptr cs:[bx+4h],TSR@DataLen mov word ptr cs:[bx+6h],0 ; end of areas definition mov word ptr cs:[bx+8h],0 mov bx,OFFSET Int2Fh@SwStRec mov word ptr cs:[bx+4h],es ; chain to previous list mov word ptr cs:[bx+0Eh],OFFSET Int2Fh@InstRec mov word ptr cs:[bx+10h],cs mov word ptr cs:[bx],3h ; set target Windows version mov word ptr cs:[bx+6h],0 mov word ptr cs:[bx+8h],0 mov word ptr cs:[bx+0Ah],0 mov word ptr cs:[bx+0Ch],0 jmp short Int2Fh@SetSeg Int2Fh@Check: cmp al,0 jne Int2Fh@Ret inc ax ; indicate that ID number taken mov di,OFFSET Int2Fh@IDStr-TSR@Shift Int2Fh@SetSeg: push cs pop es Int2Fh@Ret: iret Int2Fh@IDStr DB 'TaskKill v1.1 (c) 1997',0 Int2Fh@IDStrLen= $-Int2Fh@IDStr Int2Fh ENDP EVEN Abort PROC NEAR ; Comment: Abort current process if possible ; Expects: - ; Returns: - (not applicable if possible) ; Uses: - cmp cs:[TSR@Busy],0 ; system busy ? jne Abort@Ret cmp cs:[TSR@LastIVT],0 ; no executed processes ? push ax je Abort@Reset mov al,0Bh ; interrupt controller busy ? out 20h,al jmp short $+2h in al,20h test al,al jnz Abort@Restore inc cs:[TSR@Busy] ; close activation gate mov ax,3h ; clear screen by setting 80*25 text mode int 10h mov ax,4CFFh ; terminate current process pushf dec cs:[TSR@Busy] ; open activation gate call cs:[Int21h@Old-TSR@Shift] Abort@Reset: mov cs:[TSR@Activated],0 ; reset activation flag Abort@Restore: pop ax Abort@Ret: ret Abort ENDP TSR@CodeLen= $-TSR@Begin TSR@Length= $-TSR@Shift-Null ; Non-resident part code ASSUME ds:@CODE,es:NOTHING Main PROC NEAR ; Comment: - ; Expects: ds=es=cs ; Returns: - (not applicable) ; Uses: - (all) mov sp,OFFSET StackTop mov ax,3000h ; get DOS version int 21h cmp al,3h ; version 3.00 or later ? jae Main@Check Main@Exit: int 20h Main@Check: mov ah,9h ; print program ID information mov dx,OFFSET Main@Msg int 21h call CheckInst ; already installed ? test bh,bh jnz Main@Exit xor ax,ax ; check for presence of PSP xchg ax,ds:[Main@EnvSeg] test ax,ax jz Main@Set mov es,ax ; free PSP mov ah,49h int 21h Main@Set: call SetUpTSR mov ax,3100h ; terminate but stay resident mov dx,(TSR@Length+0Fh)/10h int 21h Main ENDP CheckInst PROC NEAR ; Comment: Check whether TSR already installed ; Expects: ds=cs ; Returns: bh - ID number (or bh=0 if TSR not installed), ; es - TSR segment (if bh>0) ; Uses: ax,bx,cx,dx,si,di,es mov bx,0C001h CheckInst@Loop: xor ax,ax ; check current ID number mov es,ax mov ah,bh push bx int 2Fh pop bx cmp ax,bx ; TSR found ? jne CheckInst@Cont mov ax,es ; No segment ? test ax,ax jz CheckInst@Cont cld mov si,OFFSET Int2Fh@IDStr mov cx,Int2Fh@IDStrLen repe cmps byte ptr ds:[si],byte ptr es:[di] je CheckInst@Ret CheckInst@Cont: inc bh jnz CheckInst@Loop CheckInst@Ret: ret CheckInst ENDP SetUpTSR PROC NEAR ; Comment: initialize all TSR variables and set up new interrupt handlers ; Expects: ds=cs ; Returns: - ; Uses: ax,bx,cx,dx,si,di,es mov bx,0C000h ; get free ID number SetUpTSR@Loop: mov ax,bx ; check current ID number push bx int 2Fh pop bx cmp ax,bx ; ID number reserved ? je SetUpTSR@Init inc bh jnz SetUpTSR@Loop SetUpTSR@Init: mov ds:[Int2Fh@IDNumber],bh mov ds:[TSR@Activated],0 ; reset activation flag mov ds:[TSR@Busy],0 ; reset system busy flag mov ds:[TSR@LastIVT],0 ; set no last task control segment mov ah,34h ; get InDOS flag address int 21h mov ds:[Int08h@InDOSSeg],es mov ds:[Int08h@InDOSOfs],bx mov ax,3509h ; store old int 9h handler address int 21h mov word ptr ds:[Int09h@Old],bx mov word ptr ds:[Int09h@Old+2h],es mov ax,3510h ; store old int 10h handler address int 21h mov word ptr ds:[Int10h@Old],bx mov word ptr ds:[Int10h@Old+2h],es mov ax,3513h ; store old int 13h handler address int 21h mov word ptr ds:[Int13h@Old],bx mov word ptr ds:[Int13h@Old+2h],es mov ax,352Fh ; store old int 2Fh handler address int 21h mov word ptr ds:[Int2Fh@Old],bx mov word ptr ds:[Int2Fh@Old+2h],es mov ax,3521h ; store old int 21h handler address int 21h mov word ptr ds:[Int21h@Old],bx mov word ptr ds:[Int21h@Old+2h],es mov ax,3528h ; store old int 28h handler address int 21h mov word ptr ds:[Int28h@Old],bx mov word ptr ds:[Int28h@Old+2h],es mov ax,3508h ; store old int 8h handler address int 21h mov word ptr ds:[Int08h@Old],bx mov word ptr ds:[Int08h@Old+2h],es cld ; shift resident-part code push ds pop es mov si,OFFSET TSR@Begin mov di,OFFSET TSR@Start mov cx,(TSR@CodeLen+1h)/2h rep movs word ptr es:[di],word ptr ds:[si] mov ax,2509h ; set up new int 09h handler mov dx,OFFSET Int09h-TSR@Shift int 21h mov ax,2510h ; set up new int 10h handler mov dx,OFFSET Int10h-TSR@Shift int 21h mov ax,2513h ; set up new int 13h handler mov dx,OFFSET Int13h-TSR@Shift int 21h mov ax,252Fh ; set up new int 2Fh handler mov dx,OFFSET Int2Fh-TSR@Shift int 21h mov ax,2521h ; set up new int 21h handler mov dx,OFFSET Int21h-TSR@Shift int 21h mov ax,2528h ; set up new int 28h handler mov dx,OFFSET Int28h-TSR@Shift int 21h mov ax,2508h ; set up new int 08h handler mov dx,OFFSET Int08h-TSR@Shift int 21h ret SetUpTSR ENDP ; Program messages Main@Msg DB 'Task Killer Resident Utility v1.1',0Dh,0Ah DB 'Use Ctrl+Alt+Esc to abort any program.',0Dh,0Ah,'$' ; Program stack EVEN DW 80h DUP(?) StackTop LABEL WORD ; End of program END Start