; BLM ~ BlueOwls Light Meta
; *************************
;
; Details
;
;  Name: BLM (BlueOwls Light Meta)
;  Date: 16 May 2005
;  Size: 412 bytes
;  Morphing power: light
;  Morphing type: non-expansion
;  Compatibility: most common x86 and pentium specific (rdtsc/movzx/..)
;  Platforms: all 32bit (and maybe 16bit) x86 instruction set OSes
;  Used compiler: FASM 1.60
;  Bugs: hopefully none
;
; Morphing
;
;  The following instructions can be morphed:
;
;  1. OP reg, reg -> changing the D bit (2)
;  2. OP (reg,) [(imm32+)reg] -> changing the unused SCALE bits (4)
;  3. OP (reg,) [(imm32+)reg+reg*1] -> swapping the regs (2)
;
;  Any other instruction's size is calculated and skipped.
;
; Usage notes
;
;  BLM can be usefull for any application which would like to do code
;  morphing on its own, or other code. There are however, some things
;  to keep note on:
;
;  - Make sure you don't mix data with code, for example:
;    > CALL _LABEL
;    > DB "some string",0
;    > _LABEL:
;    Would make the meta miscorrectly assume "some string",0 to be
;    code. So make sure that in the codearea you specify is no data.
;  - On input, esi is allowed to equal edi, but it is not recommended
;    if it will cause the meta to morph itself on runtime.
;  - This code does not need any data,  and only needs to be able  to
;    execute. It is completely permutatable.
;
; Agreement
;
;  This  sourcecode  is  meant  to be used  in freeware and  shareware
;  programs, and therefor it is strictly prohibited to add any of this
;  code in binary or source format in  scan strings or other detection
;  methods. If done, it will impact on the sellability of the product,
;  and can result in high fees and/or trials before court.
;  YOU HAVE BEEN WARNED

use32

; 컴컴컴컴컴컴 META SOURCE 컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴

; in:   esi(ecx) = start of code to morph
;       edi(ecx) = start of buffer to put morphed code in
;       ecx = size of code to morph (and buffer)
; out:  esi = esi + ecx
;       edi = edi + ecx
;       other registers are destroyed (except esp)

BLM:		cld
		lea	ebx, [esi+ecx]		; ebx = ptr to end of code to morph
nextcode:	push	ebx
		xor	ecx, ecx
		push	4
		pop	ebx
		call	.innext
		pop	ebx
		rol	edx, 7			; simple RAND function
		neg	dx
		cmp	ebx, esi
		ja	nextcode
		ret

.next:		movsb
.innext:	mov	al, [esi]
		and	al, 11100111b
		cmp	al, 00100110b		; es/cs/ss/ds segment?
		jz	.next			; check if more
		mov	al, [esi]
		and	al, 11111110b
		cmp	al, 01100100b		; fs/gs segment?
		jz	.next			; check if more
		cmp	al, 11110010b		; repz/repnz?
		jz	.next			; check if more
		cmp	al, 01100110b		; WORD?
		jnz	opcode
		mov	bl, 2			; set WORD size
		jmp	.next

; -----------------------------------------------------------------------

opcode: 	mov	al, [esi]
		cmp	al, 0fh
		jnz	branch_start
		movsb
		or	al, [esi]		; ????1111
		cmp	al, 10001111b
		jz	.6byte			; -> jxx label32
		cmp	al, 10111111b
		jz	.3byte			; -> movzx/bt?
		jmp	.done
.6byte: 	movsb
		movsb
		movsb
.3byte: 	movsb
.done:		movsb
		ret
branch_start:	shl	al, 1
		jc	branch_1xxxxxxx
branch_0xxxxxxx:shl	al, 1
		jc	branch_01xxxxxx
branch_00xxxxxx:shl	al, 4
		jnc	op_rmrm_d
op_eax: 	mov	al, [esi]
		shr	al, 1
		jc	.pr32
		movsb
		movsb
		ret				; -> op al, imm8
.pr32:		add	ecx, ebx		; -> op eax, imm32
		rep	movsb
		movsb
		ret
branch_01xxxxxx:cmp	al, 11000000b
		jb	.ncjump
		movsb				; -> jxx label8
.ncjump:	cmp	al, 068h
		jz	do_5byte		; -> push imm32
		cmp	al, 06ah
		jnz	.done			; -> popad/pushad/pop/push/dec/inc (reg)
		stosb				; -> push imm8
.done:		movsb
		ret

op_rmrm_d:	mov	al, [esi+1]		; -> add/or/adc/sbb/and/sub/xor/cmp r/m,r/m
		rcr	edx, 1			; rand true/false
		jc	.nomorph
		cmp	al, 11000000b
.nomorph:	jb	op_rm			; (jc == jb so little optimization)
		lodsb
		xor	al, 00000010b
		stosb
		lodsb
		and	eax, 00111111b		; 00000000 00regreg
		shl	eax, 5			; 00000reg reg00000
		shr	al, 2			; 00000reg 00reg000
		or	al, ah			; 00000xxx 00regreg
		or	al, 11000000b		; 11regreg
		stosb
		ret

branch_1xxxxxxx:shl	al, 1
		jc	branch_11xxxxxx
branch_10xxxxxx:shl	al, 1
		jc	branch_101xxxxx
branch_100xxxxx:shl	al, 1
		jc	branch_01xxxxxx.ncjump	; -> xchg eax,reg/cwde/cdq/pushf/popf/sahf/lahf
branch_1000xxxx:cmp	al, 01000000b
		jae	op_rm			; -> test/xchg/mov/lea/pop r/m(,r/m)
		shl	al, 3
		jc	op_rmimm8		; -> add/or/adc/sbb/and/sub/xor/cmp r/m,imm8
		jmp	op_rmimm32		; -> add/or/adc/sbb/and/sub/xor/cmp r/m,imm32
branch_101xxxxx:shl	al, 1
		jc	branch_1011xxxx
branch_1010xxxx:and	al, 11100000b
		cmp	al, 00100000b
		jb	op_eax			; -> test eax, imm
		cmp	al, 10000000b
		jz	do_5byte		; -> mov mem32, eax
		movsb
		ret				; -> movs/stos/lods/scas
branch_1011xxxx:shl	al, 1
		jnc	branch_1100001x.2byte	; -> mov reg, imm8
		jmp	op_eax.pr32		; -> mov reg, imm32
do_5byte:	movsd
		movsb
		ret
branch_11xxxxxx:shl	al, 1
		jc	branch_111xxxxx
branch_110xxxxx:shl	al, 1
		jc	branch_1101xxxx
branch_1100xxxx:cmp	al, 11010000b
		jz	branch_1100001x.2byte	; -> int imm8
		shl	al, 1
		jc	branch_1100001x.done	; -> leave/int 3
branch_11000xxx:shl	al, 1
		jc	op_rm_w 		; -> mov r/m, imm
branch_110000xx:shl	al, 1
		jc	branch_1100001x
		inc	ecx			; -> rol/ror/rcl/rcr/shl/shr/sal/sar reg, 1
		jmp	op_rm
branch_1100001x:shl	al, 1
		jc	.done
.3byte: 	movsb
.2byte: 	movsb				; -> ret imm16
.done:		movsb
		ret				; -> ret
branch_1101xxxx:shl	al, 2
		jc	branch_1100001x.done	; -> xlatb
branch_1101x0xx:jmp	op_rm			; -> rol/ror/rcl/rcr/shl/shr/sal/sar reg, 1

branch_111xxxxx:shl	al, 1
		jc	branch_1111xxxx
branch_1110xxxx:shl	al, 1
		jnc	branch_11101010 	; -> loop label
branch_11101xxx:cmp	al, 00100000b
		jz	branch_111010x0.done	; -> call label
branch_111010x0:shl	al, 2
		jc	branch_11101010
.done:		movsd				; -> jmp label32
		movsb
		ret
branch_11101010:movsb
		movsb
		ret				; -> jmp label8
branch_1111xxxx:shl	al, 1
		jc	branch_11111xxx
branch_11110xxx:shl	al, 2
		jnc	branch_11111xxx.done	; -> cmc
branch_11111x1x:mov	al, [esi+1]		; al = modr/m
		and	al, 00111000b
		jnz	op_rm			; -> not/mul/div/idiv
		jmp	op_rm_w 		; -> test
branch_11111xxx:shl	al, 1
		jc	.done			; -> clc/stc/cli
		shr	al, 1
		jc	op_rm			; -> inc/dec/call/jmp/push
.done:		movsb
		ret				; -> cld/std

; -----------------------------------------------------------------------

op_rm_w:	mov	al, [esi]
		shr	al, 1
		jnc	op_rmimm8
op_rmimm32:	add	ecx, ebx		; imm length will be 4 or 2
		dec	ecx
op_rmimm8:	inc	ecx			; imm length = 1 byte
op_rm:		movsb
		lodsb
		stosb
		cmp	al, 11000000b		; op reg, reg
		jae	.done
		mov	ah, al
		and	al, 111b
		shr	ah, 6
		jz	.regaddr
		cmp	ah, 00000001b
		jz	.ddone
		add	ecx, 3			; op reg, [reg+dword]
.ddone: 	inc	ecx			; op reg, [reg+byte]
.cmpsib:	cmp	al, 00000100b
		jnz	.done
		xor	ebx, ebx
		mov	eax, ebx
		lodsb				; 00000000 iiregreg
		shl	eax, 2			; 000000ii regreg00
		xchg	bl, ah			; 00000000 regreg00
		shl	eax, 3			; 00000reg reg00000
		shr	al, 5			; 00000reg 00000reg
		cmp	ah, 4
		jz	.randindex
		cmp	al, 4
		jz	.nosib
		or	bl, bl			; index = 1?
		jnz	.nosib
		rcr	edx, 1
		jnc	.nosib			; randomly abort switch
		xchg	al, ah
		jmp	.nosib
.randindex:	mov	bl, dl			; index is random
		and	bl, 00000011b
.nosib: 	shl	al, 5			; 00000reg reg00000
		shr	eax, 3			; 00000000 regreg00
		mov	ah, bl			; 000000ii regreg00
		shr	eax, 2			; 00000000 iiregreg
		stosb
.done:		rep	movsb
		ret
.regaddr:	cmp	al, 00000101b		; op reg, [dword]
		jnz	.cmpsib
		movsd
		jmp	.done

; 컴컴컴컴컴컴 META BINARY 컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴

; in:   esi(ecx) = start of code to morph
;       edi(ecx) = start of buffer to put morphed code in
;       ecx = size of code to morph (and buffer)
; out:  esi = esi + ecx
;       edi = edi + ecx
;       other registers are destroyed (except esp)

BLM:		db 252,141,28,14,83,49,201,106,4,91,232,13,0,0,0,91
		db 193,194,7,102,247,218,57,243,119,234,195,164,138,6,36,231
		db 60,38,116,247,138,6,36,254,60,100,116,239,60,242,116,235
		db 60,102,117,4,179,2,235,227,138,6,60,15,117,19,164,10
		db 6,60,143,116,6,60,191,116,5,235,4,164,164,164,164,164
		db 195,208,224,114,75,208,224,114,20,192,224,4,115,31,138,6
		db 208,232,114,3,164,164,195,1,217,243,164,164,195,60,192,114
		db 1,164,60,104,116,95,60,106,117,1,170,164,195,138,70,1
		db 209,218,114,2,60,192,15,130,179,0,0,0,172,52,2,170
		db 172,131,224,63,193,224,5,192,232,2,8,224,12,192,170,195
		db 208,224,114,52,208,224,114,23,208,224,114,198,60,64,15,131
		db 139,0,0,0,192,224,3,15,130,129,0,0,0,235,124,208
		db 224,114,12,36,224,60,32,114,149,60,128,116,8,164,195,208
		db 224,115,37,235,146,165,164,195,208,224,114,38,208,224,114,27
		db 60,208,116,20,208,224,114,17,208,224,114,73,208,224,114,3
		db 65,235,76,208,224,114,2,164,164,164,195,192,224,2,114,249
		db 235,61,208,224,114,19,208,224,115,12,60,32,116,5,192,224
		db 2,114,3,165,164,195,164,164,195,208,224,114,14,192,224,2
		db 115,17,138,70,1,36,56,117,22,235,10,208,224,114,4,208
		db 232,114,12,164,195,138,6,208,232,115,3,1,217,73,65,164
		db 172,170,60,192,115,76,136,196,36,7,192,236,6,116,70,128
		db 252,1,116,3,131,193,3,65,60,4,117,54,49,219,137,216
		db 172,193,224,2,134,220,193,224,3,192,232,5,128,252,4,116
		db 16,60,4,116,17,8,219,117,13,209,218,115,9,134,196,235
		db 5,136,211,128,227,3,192,224,5,193,232,3,136,220,193,232
		db 2,170,243,164,195,60,5,117,191,165,235,246

; 컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴