NOJUMPS

calccrc MACRO	start,end
	local	l1
	mov	cx,OFFSET end-OFFSET start
	mov	si,OFFSET start
l1:	add	dl,cs:[si]
	adc	dh,0
	rol	dx,1
	inc	si
	loop	l1
	ENDM
uncryptxor MACRO beg,key
	local	l1
	mov	bx,OFFSET beg
	mov	ax,key
	mov	cx,(OFFSET _unpack_endcrypt-OFFSET beg)/2
l1:	xor	ds:[bx],ax
	add	bx,2
	dec	cx
	jnz	l1
	ENDM
uncryptadd MACRO beg,key ;actually sub, uncrypts add-crypting
	local	l1
	mov	bx,OFFSET beg
	mov	ax,key
	mov	cx,(OFFSET _unpack_endcrypt-OFFSET beg)/2
l1:	sub	ds:[bx],ax
	add	bx,2
	dec	cx
	jnz	l1
	ENDM

unp_text SEGMENT para public 'CODE'
	ASSUME cs:unp_text
	PUBLIC	_unpack_start,_unpack_end
	PUBLIC	_unpack_data,_unpack_dataend,_unpack_data2,_unpack_code
	PUBLIC	_unpack_stack0,_unpack_stack1
	PUBLIC	_unpack_crc0,_unpack_crc1
	PUBLIC	_unpack_crypt1	;add 5f27h - INC
	PUBLIC	_unpack_crypt2	;xor 4493h - INC
	PUBLIC	_unpack_crypt3	;add 0073h - INC
	PUBLIC	_unpack_crypt4	;xor 4536h - none
	PUBLIC	_unpack_crypt10	;xor 0666h - none
	PUBLIC	_unpack_crypt11	;add 0656h - DEC
	PUBLIC	_unpack_crypt12	;xor 0466h - DEC
	PUBLIC	_unpack_crypt13	;add 0663h - none
	PUBLIC	_unpack_crypt14	;add DX - none
	PUBLIC	_unpack_crypt15	;xor 5cach - none
	PUBLIC	_unpack_crypt16	;add 3fach - INC
	PUBLIC	_unpack_endcrypt
_unpack_start LABEL BYTE

	db	'FCP/IV'	;Future Protector IV 

_unpack_code LABEL BYTE
startup	PROC NEAR
	mov	sp,OFFSET _unpack_stack1
io21data LABEL BYTE
	ret
pntds2	LABEL WORd
	jmp	cs:[farjump+2]
startup ENDP
int_iret PROC FAR
	iret
int_iret ENDP

ALIGN 2
_unpack_stack0 LABEL BYTE
	dw	50 dup(5555h)
_unpack_stack1 LABEL BYTE
	dw	OFFSET step1
	dw	0	;popped by step 1 => DS
	dw	OFFSET step2
	dw	OFFSET step3
	dw	OFFSEt step4
stck1:	dw	OFFSET stepx1	;the cracker blew it :-)
	dw	0fff0h,0000h
disk0	dw	0
disk1	dw	0
vram	dw	01234h
hboottxt db	'.;*',13,0
pntds	dw	0

_unpack_crc0 LABEL BYTE

.386P
step1	PROC NEAR
	in	al,21h
	mov	cs:io21data,al
	mov	al,255
	out	21h,al
	cli
	mov	cs:pntds,ds
	pop	ds
	cld
	;disk detect
	mov	ah,08h
	mov	dl,128
	mov	dh,0
	int	13h
	cmp	dh,0
	je	jjj1
	mov	cs:disk0,cx
	mov	cs:disk1,dx
jjj1:	;video detect
	mov	ah,0fh
	int	10h
	cmp	al,7
	je	ismda
	mov	cs:vram,0800h+1234h
ismda:	add	cs:vram,0b000h-01234h
	;processor detect, at return: BP=0=real BP=1=protected mode
	push	sp			; 86/186 will push SP-2;
	pop	ax			; 286/386 will push SP.
	cmp	ax, sp
	jz	not86			; If equal, SP was pushed
	;8086/80186
noprot:	mov	bp,0
	ret
not86:	smsw	cx			; Protected?  Machine status -> CX
	ror	cx,1			; Protection bit -> carry flag
	jnc	noprot			; Real mode if no carry
	mov	bp,1
	ret
step1	ENDP
.8086

step3	PROC	NEAR
	;DS=CS now (in step 2)
	;uncode crap
	mov	byte ptr cs:int1code,40h ;INC AX
	int	3	;clc set at step2's end
	uncryptadd _unpack_crypt1,5f27h
	ret
step3	ENDP

ints	PROC FAR	;SingleStep/DEBUG
int_01:	stc
int_03:	push	bp
	mov	bp,sp
	jnc	int2
	push	bx
	mov	bx,ss:[bp+2] ;ip
	cmp	byte ptr cs:[bx],49h ;inc cx
	jne	int1
int1code: inc	bx
int1:	pop	bx
int3:	pop	bp
	iret
int2:	xor	ss:[bp+6],256
	mov	bp,cs:stck1to
	mov	word ptr cs:[stck1],bp
	jmp	int3
ints000:
ints	ENDP

_unpack_crc1 LABEL BYTE

itable	LABEL WORD
itablelen equ	4
	dw	OFFSET int_iret,0f000h	;int 0
	dw	OFFSET int_01,0f000h	;int 1
	dw	OFFSET int_iret,0f000h	;int 2
	dw	OFFSET int_03,0f000h	;int 3
;Stack contents on ints:
; [bp+6]: flags
; [bp+4]: cs
; [bp+2]: ip
; [bp+0]: bp

_startzeroing LABEL BYTE

step2	PROC NEAR	;WARNING! ROUTINE OVERWRITTEN BY INNER STACK
	mov	cs:hboottxt[0],'b'
	;set interrupts
	mov	bx,'FG'
	mov	si,OFFSET itable
	xor	di,di
	mov	cx,itablelen
	mov	dx,'JM'
	mov	cs:hboottxt[1],'C'
st2a:	segcs
	lodsw
	xchg	ds:[di],ax
	mov	cs:[si-2],ax
	mov	ax,cs
	xchg	ds:[di+2],ax
	mov	cs:[si],ax
	add	si,2
	add	di,4
	loop	st2a
	;carry=0 for di won't rotate
	mov	di,dx	;='JM'
	mov	dx,OFFSET hboottxt
	mov	ax,cs
	mov	ds,ax
	mov	si,bx	;='FG'	;if this enabled, ICE will reboot
	mov	ax,0911h
	ret
step2	ENDP

stepx1	PROC NEAR
	mov	ax,0f000h
	retf	;reboots
stepx1	ENDP

_unpack_crypt1	LABEL BYTE

step4	PROC	NEAR
	;DS=CS
	mov	ax,cs:pntds
	mov	cs:pntds2,ax
	uncryptxor _unpack_crypt2,4493h
_unpack_crypt2 LABEL BYTE
	uncryptadd _unpack_crypt3,0073h
_unpack_crypt3 LABEL BYTE
	jmp	stp4o
stck1to dw	OFFSET step5
hboottxt2 db	'Bc*',13,0
stp4o:	sub	ax,ax
	mov	si,'FG'
	mov	di,'JM'
	mov	ax,0911h
	mov	dx,OFFSET hboottxt2
	clc
	int	3
	uncryptxor _unpack_crypt4,4536h
	ret	;goes to step5
step4	ENDP

_unpack_crypt4 LABEL BYTE

innerstack LABEL BYTE
	dw	OFFSET stepx1

step5	PROC	NEAR
	;enter inner stack
	mov	sp,OFFSET innerstack
	uncryptxor _unpack_crypt10,0666h
_unpack_crypt10 LABEL BYTE
i1c0:	mov	dx,0656h
	sub	ax,ax
	mov	es,ax
	mov	ax,es:[6]
	mov	bx,cs
	cmp	ax,bx
	je	i1c1
	mov	word ptr cs:[i1c0+1],0CA3Fh
	mov	dx,3FC1H
i1c1:	cmp	word ptr es:[4],OFFSET int_01
	je	i1c2
	mov	word ptr cs:[i1c0+1],0CA3Fh
	mov	dx,3CF2H
i1c2:	mov	byte ptr cs:int1code,48h ;DEC AX
	sub	ax,ax
	int	3
	uncryptadd _unpack_crypt11,dx
_unpack_crypt11 LABEL BYTE
	uncryptxor _unpack_crypt12,0466h
_unpack_crypt12 LABEL BYTE
	mov	byte ptr cs:int1code,40h ;INC AX
	sub	ax,ax
	int	3
	uncryptadd _unpack_crypt13,0663h
_unpack_crypt13 LABEL BYTE
	;calc checksum of exe start
	xor	dx,dx
	mov	byte ptr cs:int1code,43h ;INC BX
	calccrc	_unpack_crc0,_unpack_crc1
	uncryptadd _unpack_crypt14,0 ;dx
_unpack_crypt14 LABEL BYTE
	uncryptxor _unpack_crypt15,5CACh
_unpack_crypt15 LABEL BYTE
	mov	byte ptr cs:int1code,40h ;INC AX
	sub	ax,ax
	int	3
	uncryptadd _unpack_crypt16,3FACh
_unpack_crypt16 LABEL BYTE
	mov	word ptr cs:innerstack,OFFSET execute
	sub	ax,ax
	int	3
	ret
step5	ENDP

ALIGN 2

execute	PROC NEAR
	;unpack data
	mov	dx,cs:pntds2
	add	dx,10h
	xor	si,si
	xor	di,di
	cmp	cs:mcrcon,0
	je	exec11
	;calc machine crc
	mov	ax,0ff00h
	mov	ds,ax
	mov	bx,0
	mov	cx,1024
mcrc1:	add	si,ds:[bx]
	add	di,ds:[bx+2]
	rol	si,1
	add	bx,4
	loop	mcrc1
	add	si,cs:disk0
	add	di,cs:disk1
exec11:	add	si,cs:regcs
	add	di,cs:regip
	add	si,cs:regsp
	add	di,cs:regss
	add	si,cs:regkey
	add	di,cs:regkey
	mov	cx,cs:regcs0
exec1:	mov	ds,dx
	sub	ds:[0],si
	sub	ds:[2],di
	xor	si,5354h
	xor	di,1525h
	sub	ds:[4],si
	sub	ds:[6],di
	add	si,1234h
	ror	si,1
	add	di,4321h
	rol	di,1
	sub	ds:[8],si
	sub	ds:[10],di
	xor	si,5354h
	xor	di,1525h
	sub	ds:[12],si
	sub	ds:[14],di
	add	si,1234h
	ror	si,1
	add	di,4321h
	rol	di,1
	inc	dx
	add	si,ds:[0]
	add	di,ds:[8]
	add	si,ds:[2]
	add	di,ds:[10]
	add	si,ds:[4]
	add	di,ds:[12]
	add	si,ds:[6]
	add	di,ds:[14]
	loop	exec1
	mov	bp,OFFSET errormsg1
	cmp	si,cs:keychk0
	jne	error
	cmp	di,cs:keychk1
	jne	error
	cld
_endzeroing LABEL BYTE ;may overflow a byte, but who cares
	mov	dx,cs:pntds2
	mov	ax,cs
	mov	es,ax
	mov	cx,(OFFSET _endzeroing-OFFSET _startzeroing+1)/2
	mov	di,OFFSET _startzeroing
	mov	ax,'..'
	rep	stosw
	call	resetints
	mov	al,cs:io21data
	out	21h,al
	mov	ax,cs
	mov	es,ax
	mov	cx,OFFSET _startzeroing-OFFSET _unpack_code
	mov	di,OFFSET _unpack_code
	mov	al,'.'
	rep	stosb
	;load stack and cs:ip for the actual program and run it.
	mov	ds,dx
	mov	es,dx
	mov	bx,cs
	mov	cx,cs:regcs0
	mov	ax,cs:regss
	add	ax,bx
	sub	ax,cx
	mov	ss,ax
	mov	sp,cs:regsp
	add	cs:regcs,bx
	sub	cs:regcs,cx
	push	cs:regcs
	push	cs:regip
	mov	cs:regcs,ax
	mov	cs:regip,ax
	mov	cs:regss,ax
	mov	cs:regcs0,ax
	mov	cs:keychk1,ax
	mov	cs:regkey,ax
	sti
	jmp	endprg2
	
_endzeroing2 LABEL BYTE
error:	;destroy and exit with error at OFFSET BP
	cld
	mov	dx,cs:pntds2
	mov	ax,cs
	mov	es,ax
	mov	cx,(OFFSET _endzeroing2-OFFSET _startzeroing+1)/2
	mov	di,OFFSET _startzeroing
	mov	ax,'..'
	rep	stosw
	call	resetints
	mov	al,cs:io21data
	out	21h,al
	mov	ax,cs
	mov	es,ax
	mov	di,OFFSET _unpack_code
	mov	cx,OFFSET _startzeroing-OFFSET _unpack_code
	mov	al,'.'
	rep	stosb
	mov	cs:regcs,ax
	mov	cs:regip,ax
	mov	cs:regss,ax
	mov	cs:regcs0,ax
	mov	cs:keychk1,ax
	mov	cs:regkey,ax
	mov	sp,OFFSET _unpack_data
	sti
	jmp	endprg1
execute ENDP

resetints PROC NEAR
	;reset interrupts
	xor	ax,ax
	mov	es,ax
	mov	si,OFFSET itable
	xor	di,di
	mov	cx,itablelen*2
st20a:	segcs
	lodsw
	stosw
	loop	st20a
	ret
resetints ENDP

	ALIGN	2
_unpack_data LABEL BYTE
farjump LABEL DWORD
regcs	dw	0
regip	dw	0
regss	dw	0
regsp	dw	0
regcs0	dw	0
errormsg1 db	'File corrupted!$'
_unpack_data2 LABEL BYTE
regkey	dw	0
mcrcon	dw	0	;1=machine crc enabled
keychk0 dw	0
keychk1 dw	0
_unpack_dataend LABEL BYTE

	ALIGN	2
	
endprg1: ;****************
	mov	dx,bp
	mov	ax,cs
	mov	ds,ax
	mov	ah,9h
	int	21h
	mov	ax,4c03h
	int	21h
endprg2:  ;****************
	retf

	ALIGN	2
_unpack_endcrypt LABEL BYTE
	db	000h,0fch
_unpack_end LABEL BYTE
unp_text ENDS
	END
	